python
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
|
||||
|
||||
|
||||
#include "py4yap.h"
|
||||
#include <VFS.h>
|
||||
|
||||
@@ -27,7 +26,8 @@ PyObject *py_ModDict;
|
||||
|
||||
VFS_t pystream;
|
||||
|
||||
static void *py_open(VFS_t *me, int sno, const char *name, const char *io_mode) {
|
||||
static void *py_open(VFS_t *me, int sno, const char *name,
|
||||
const char *io_mode) {
|
||||
#if HAVE_STRCASESTR
|
||||
if (strcasestr(name, "//python/") == name)
|
||||
name += strlen("//python/");
|
||||
@@ -35,56 +35,57 @@ static void *py_open(VFS_t *me, int sno, const char *name, const char *io_mode)
|
||||
if (strstr(name, "//python/") == name)
|
||||
name += strlen("//python/");
|
||||
#endif
|
||||
StreamDesc *st = YAP_RepStreamFromId(sno);
|
||||
StreamDesc *st = YAP_RepStreamFromId(sno);
|
||||
// we assume object is already open, so there is no need to open it.
|
||||
PyObject *stream = string_to_python(name, true, NULL);
|
||||
if (stream == Py_None)
|
||||
return NULL;
|
||||
Py_INCREF(stream);
|
||||
st->u.private_data = stream;
|
||||
st->vfs = me;
|
||||
st->status = Append_Stream_f | Output_Stream_f;
|
||||
Yap_DefaultStreamOps(st);
|
||||
return stream;
|
||||
Py_INCREF(stream);
|
||||
st->u.private_data = stream;
|
||||
st->vfs = me;
|
||||
st->status = Append_Stream_f | Output_Stream_f;
|
||||
Yap_DefaultStreamOps(st);
|
||||
return stream;
|
||||
}
|
||||
|
||||
static bool py_close(int sno) {
|
||||
return true;
|
||||
StreamDesc *s = YAP_GetStreamFromId(sno);
|
||||
StreamDesc *s = YAP_GetStreamFromId(sno);
|
||||
PyObject *fclose = PyObject_GetAttrString(s->u.private_data, "close");
|
||||
PyObject *rc = PyObject_CallObject(fclose, NULL);
|
||||
bool v = (rc == Py_True);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
static int py_put(int sno, int ch) {
|
||||
// PyObject *pyw; // buffer
|
||||
//int pyw_kind;
|
||||
//PyObject *pyw_data;
|
||||
// int pyw_kind;
|
||||
// PyObject *pyw_data;
|
||||
|
||||
char s[2];
|
||||
StreamDesc *st = YAP_GetStreamFromId(sno);
|
||||
// PyUnicode_WRITE(pyw_kind, pyw_data, 0, ch);
|
||||
PyObject *err,*fput = PyObject_GetAttrString(st->u.private_data, "write");
|
||||
char s[2];
|
||||
StreamDesc *st = YAP_GetStreamFromId(sno);
|
||||
// PyUnicode_WRITE(pyw_kind, pyw_data, 0, ch);
|
||||
PyObject *err, *fput = PyObject_GetAttrString(st->u.private_data, "write");
|
||||
s[0] = ch;
|
||||
s[1] = '\0';
|
||||
PyObject_CallFunctionObjArgs(fput, PyUnicode_FromString(s), NULL);
|
||||
if ((err = PyErr_Occurred())) {
|
||||
PyErr_SetString(err, "Error in put\n");// %s:%s:%d!\n", __FILE__, __FUNCTION__, __LINE__);
|
||||
}
|
||||
s[1] = '\0';
|
||||
PyObject_CallFunctionObjArgs(fput, PyBytes_FromString(s), NULL);
|
||||
if ((err = PyErr_Occurred())) {
|
||||
PyErr_SetString(
|
||||
err,
|
||||
"Error in put\n"); // %s:%s:%d!\n", __FILE__, __FUNCTION__, __LINE__);
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
||||
static int py_get(int sno) {
|
||||
StreamDesc *s = YAP_GetStreamFromId(sno);
|
||||
StreamDesc *s = YAP_GetStreamFromId(sno);
|
||||
PyObject *fget = PyObject_GetAttrString(s->u.private_data, "read");
|
||||
PyObject *pyr = PyObject_CallFunctionObjArgs(fget, PyLong_FromLong(1), NULL);
|
||||
return PyUnicode_READ_CHAR(pyr, 0);
|
||||
}
|
||||
|
||||
static int64_t py_seek(int sno, int64_t where, int how) {
|
||||
StreamDesc *s = YAP_GetStreamFromId(sno);
|
||||
StreamDesc *s = YAP_GetStreamFromId(sno);
|
||||
PyObject *fseek = PyObject_GetAttrString(s->u.private_data, "seek");
|
||||
PyObject *pyr = PyObject_CallFunctionObjArgs(fseek, PyLong_FromLong(where),
|
||||
PyLong_FromLong(how), NULL);
|
||||
@@ -92,7 +93,7 @@ static int64_t py_seek(int sno, int64_t where, int how) {
|
||||
}
|
||||
|
||||
static void py_flush(int sno) {
|
||||
StreamDesc *s = YAP_GetStreamFromId(sno);
|
||||
StreamDesc *s = YAP_GetStreamFromId(sno);
|
||||
PyObject *flush = PyObject_GetAttrString(s->u.private_data, "flush");
|
||||
PyObject_CallFunction(flush, NULL);
|
||||
}
|
||||
@@ -111,9 +112,9 @@ static void python_output(void) {
|
||||
#endif
|
||||
|
||||
static bool init_python_stream(void) {
|
||||
//pyw = PyUnicode_FromString("x");
|
||||
//pyw_kind = PyUnicode_KIND(pyw);
|
||||
//pyw_data = PyUnicode_DATA(pyw);
|
||||
// pyw = PyUnicode_FromString("x");
|
||||
// pyw_kind = PyUnicode_KIND(pyw);
|
||||
// pyw_data = PyUnicode_DATA(pyw);
|
||||
|
||||
pystream.name = "python stream";
|
||||
pystream.vflags =
|
||||
@@ -227,6 +228,6 @@ X_API bool do_init_python(void) {
|
||||
install_pl2pl();
|
||||
// PyGILState_Release(gstate);
|
||||
add_modules();
|
||||
// python_output();
|
||||
// python_output();
|
||||
return true;
|
||||
}
|
||||
|
@@ -61,13 +61,13 @@ argi(N,I,I1) :-
|
||||
I1 is I+1.
|
||||
|
||||
python_query( Self, String ) :-
|
||||
yap_flag(typein_module, Mod),
|
||||
atomic_to_term( String, Goal, VarNames ),
|
||||
query_to_answer( Mod:Goal, VarNames, Status, Bindings),
|
||||
maplist(in_dict(Self.bindings), Bindings),
|
||||
query_to_answer( Goal, VarNames, Status, Bindings),
|
||||
Self.port := Status,
|
||||
write_query_answer( Bindings ),
|
||||
nl( user_error ),
|
||||
Self.port := Status.
|
||||
nl(user_error),
|
||||
Self.bindings := {},
|
||||
maplist(in_dict(Self.bindings), Bindings).
|
||||
|
||||
in_dict(Dict, var([V0,V|Vs])) :- !,
|
||||
Dict[V] := V0,
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import os
|
||||
import sys
|
||||
import abc
|
||||
import math
|
||||
|
||||
import yap4py.yapi
|
||||
from IPython.core import interactiveshell
|
||||
@@ -14,6 +15,7 @@ from pygments import highlight
|
||||
from pygments.lexers.prolog import PrologLexer
|
||||
from pygments.formatters import HtmlFormatter
|
||||
|
||||
import pdb
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -87,7 +89,7 @@ class YAPCompleter:
|
||||
|
||||
class YAPInteractive(InteractiveShell):
|
||||
"""An enhanced, interactive shell for YAP."""
|
||||
|
||||
|
||||
def init_yap_completer(self):
|
||||
"""Initialize the completion machinery.
|
||||
|
||||
@@ -110,9 +112,9 @@ class YAPInteractive(InteractiveShell):
|
||||
self.yapeng.goal(use_module(library("jupyter")))
|
||||
self.q = None
|
||||
self.run = False
|
||||
self.os = ""
|
||||
self.port = None
|
||||
self.init_yap_completer()
|
||||
self.init_syntax_highlighting()
|
||||
|
||||
def init_syntax_highlighting(self, changes=None):
|
||||
# Python source parser/formatter for syntax highlighting
|
||||
@@ -169,7 +171,7 @@ class YAPInteractive(InteractiveShell):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def run_cell(self, raw_cell, store_history=True, silent=False,
|
||||
shell_futures=True):
|
||||
"""Run a complete IPython cell.
|
||||
@@ -206,9 +208,9 @@ class YAPInteractive(InteractiveShell):
|
||||
# vs is the list of variables
|
||||
# you can print it out, the left-side is the variable name,
|
||||
# the right side wraps a handle to a variable
|
||||
# pdb.set_trace()
|
||||
# #pdb.set_trace()
|
||||
# atom match either symbols, or if no symbol exists, strings, In this case
|
||||
pdb.set_trace()
|
||||
# import pdb; pdb.set_trace()
|
||||
# atom match either symbols, or if no symbol ex b pl nvists, strings, In this case
|
||||
# variable names should match strings
|
||||
# ask = True
|
||||
# launch the query
|
||||
@@ -222,6 +224,7 @@ class YAPInteractive(InteractiveShell):
|
||||
store_history = False
|
||||
|
||||
if store_history:
|
||||
self.execution_count = self.execution_count+1
|
||||
result.execution_count = self.execution_count
|
||||
|
||||
def error_before_exec(value):
|
||||
@@ -237,13 +240,14 @@ class YAPInteractive(InteractiveShell):
|
||||
# prefilter_manager) raises an exception, we store it in this variable
|
||||
# so that we can display the error after logging the input and storing
|
||||
# it in the history.
|
||||
# preprocessing_exc_tuple = None
|
||||
# try:
|
||||
# # Static input transformations
|
||||
# cell = raw_cell #self.input_transformer_manager.transform_cell(raw_cell)
|
||||
# except SyntaxError:
|
||||
# preprocessing_exc_tuple = sys.exc_info()
|
||||
cell = raw_cell # cell has to exist so it can be stored/logged
|
||||
preprocessing_exc_tuple = None
|
||||
try:
|
||||
# Static input transformations
|
||||
cell = raw_cell.strip(" \n\t").rstrip(" \n\t") #self.input_transformer_manager.transform_cell(raw_cell.strip(" \n\t").rstrip(" \n\t"))
|
||||
except SyntaxError:
|
||||
preprocessing_exc_tuple = sys.exc_info()
|
||||
#
|
||||
# cell = raw_cell # cell has to exist so it can be stored/logged
|
||||
# else:
|
||||
# # import pdb; pdb.set_trace()
|
||||
# if False and len(cell.splitlines()) == 1:
|
||||
@@ -277,6 +281,8 @@ class YAPInteractive(InteractiveShell):
|
||||
# compiler
|
||||
# compiler = self.compile if shell_futures else CachingCompiler()
|
||||
|
||||
pdb.set_trace()
|
||||
|
||||
cell_name = str( self.execution_count)
|
||||
|
||||
if cell[0] == '%':
|
||||
@@ -308,7 +314,7 @@ class YAPInteractive(InteractiveShell):
|
||||
has_raised = False
|
||||
try:
|
||||
self.bindings = dict = {}
|
||||
state = self.jupyter_query(cell)
|
||||
state = self.jupyter_query(raw_cell)
|
||||
if state:
|
||||
self.last_execution_succeeded = True
|
||||
result.result = (True, dict)
|
||||
@@ -341,7 +347,7 @@ class YAPInteractive(InteractiveShell):
|
||||
def prolog_cell(self,s):
|
||||
""""
|
||||
Trasform a text into program+query. A query is the
|
||||
last line if the last line is non-empty and does not terminate
|
||||
last line if the last line is non-empty and does not terminate
|
||||
on a dot. You can also finish with
|
||||
|
||||
- `*`: you request all solutions
|
||||
@@ -349,33 +355,48 @@ class YAPInteractive(InteractiveShell):
|
||||
- '?'[N]: you want an answer; optionally you want N answers
|
||||
|
||||
If the line terminates on a `*/` or starts on a `%` we assume the line
|
||||
is a comment.
|
||||
is a comment.
|
||||
"""
|
||||
s = s.rstrip()
|
||||
take = 0
|
||||
its = 0
|
||||
[program,x,query] = s.partition('\n')
|
||||
if query == '':
|
||||
query = program
|
||||
while take < len(query):
|
||||
take += 1
|
||||
ch = query[-take]
|
||||
if ch.isdigit():
|
||||
its = its + ord(ch) - ord('0')
|
||||
elif ch == '*' and take == 1:
|
||||
return program, query[:-take], -1
|
||||
elif ch == '.' and take == 1:
|
||||
return s, '', 1
|
||||
elif ch == '/' and query[-2] == '*' and take == 1:
|
||||
return program, query[:-take], -1
|
||||
elif ch == '^' and take == 1:
|
||||
return program, query[:-take], 1
|
||||
elif ch == '?':
|
||||
return program, query[:-take], its+1
|
||||
s = s.rstrip().strip()
|
||||
l = s.split("\n")
|
||||
while not l[0]:
|
||||
l = l[1:]
|
||||
rl = []
|
||||
for h in l:
|
||||
if h and h[0] == '%':
|
||||
if h[1] == '%':
|
||||
break
|
||||
else:
|
||||
return program, query, 1
|
||||
return s, '', 1
|
||||
|
||||
rl = [h] + rl
|
||||
if not rl:
|
||||
return '','',1
|
||||
query = rl[0]
|
||||
program = ''
|
||||
i=0
|
||||
for h in rl:
|
||||
if h and not h.isspace():
|
||||
break
|
||||
i += 1
|
||||
rl = rl[i:]
|
||||
if not rl:
|
||||
return '','',1
|
||||
take = 1
|
||||
ch = query[-take]
|
||||
if ch == '*' and take == 1:
|
||||
query = l[:-1]
|
||||
sols = -1
|
||||
if ch == '.':
|
||||
return s, '', 1
|
||||
rl = rl[1:]
|
||||
while True:
|
||||
h = rl[0]
|
||||
if h and not h.isspace():
|
||||
query = h + '\n'+ query
|
||||
rl = rl[1:]
|
||||
break
|
||||
for l in rl:
|
||||
program = l + '\n'+ program
|
||||
return program,query,take
|
||||
|
||||
def jupyter_query(self, s):
|
||||
# import pdb; pdb.set_trace()
|
||||
@@ -383,15 +404,19 @@ class YAPInteractive(InteractiveShell):
|
||||
# construct a self.query from a one-line string
|
||||
# self.q is opaque to Python
|
||||
self.bindings = {}
|
||||
self.port = "call"
|
||||
iterations=1
|
||||
if self.q and s != self.os:
|
||||
self.q.close()
|
||||
self.q = None
|
||||
if not self.q:
|
||||
import pdb; pdb.set_trace()
|
||||
program,query,self.iterations = self.prolog_cell(s)
|
||||
#import pdb; pdb.set_trace()
|
||||
self.port = "call"
|
||||
program,query,iterations = self.prolog_cell(s)
|
||||
self.q = self.yapeng.query(jupyter_query(self, program, query))
|
||||
self.os = s
|
||||
self.solutions = []
|
||||
if not self.q:
|
||||
return True, []
|
||||
self.os = s
|
||||
# vs is the list of variables
|
||||
# you can print it out, the left-side is the variable name,
|
||||
# the right side wraps a handle to a variable
|
||||
@@ -406,23 +431,34 @@ class YAPInteractive(InteractiveShell):
|
||||
# ask = True
|
||||
# launch the query
|
||||
# run the new commbnand using the given tracer
|
||||
solutions = []
|
||||
while self.iterations > 0:
|
||||
self.iterations -= 1
|
||||
rc = self.answer(self.q)
|
||||
if rc:
|
||||
# deterministic = one solution
|
||||
if self.port == "exit":
|
||||
# done
|
||||
self.q.close()
|
||||
self.q = None
|
||||
self.os = ""
|
||||
print("yes")
|
||||
solutions += [self.bindings]
|
||||
if iterations <0:
|
||||
while self.answer( self.q):
|
||||
self.solutions += [self.bindings]
|
||||
self.q.close()
|
||||
self.q = None
|
||||
self.os = ""
|
||||
if not self.solutions:
|
||||
print("no solutions found")
|
||||
return True
|
||||
|
||||
rc = self.answer(self.q)
|
||||
if rc:
|
||||
# deterministic = one solution
|
||||
#Dict = {}
|
||||
#engine.goal(show_answer( q.namedVars(), Dict))
|
||||
self.solutions += [self.bindings]
|
||||
if self.port == "exit":
|
||||
# done
|
||||
self.q.close()
|
||||
self.q = None
|
||||
self.os = ""
|
||||
return True
|
||||
else:
|
||||
print("No (more) answers")
|
||||
self.q.close()
|
||||
self.q = None
|
||||
return True, solutions
|
||||
self.os = ''
|
||||
return False
|
||||
|
||||
def answer(self, q):
|
||||
try:
|
||||
@@ -430,7 +466,7 @@ class YAPInteractive(InteractiveShell):
|
||||
except Exception as e:
|
||||
print(e.args[1])
|
||||
self.yapeng.goal(exit_cell(self))
|
||||
return False, None
|
||||
return e
|
||||
|
||||
|
||||
class YAPInteractiveABC(metaclass=abc.ABCMeta):
|
||||
|
@@ -1,4 +1,14 @@
|
||||
|
||||
/**
|
||||
* @file jupyter.yap
|
||||
*
|
||||
* @brief allow interaction between Jupyter and YAP.
|
||||
*
|
||||
* @long The code in here:
|
||||
* - establishes communication between Prolog and Python Streams
|
||||
* - inputs Prolog code and queries
|
||||
* - supports completion of Prolog programs.
|
||||
* -
|
||||
*/
|
||||
:- use_module(library(yapi)).
|
||||
:- use_module(library(lists)).
|
||||
:- use_module(library(maplist)).
|
||||
@@ -6,33 +16,50 @@
|
||||
|
||||
:- python_import(sys).
|
||||
|
||||
:- start_low_level_trace.
|
||||
|
||||
user:jupyter_query(Self, Cell, Line ) :-
|
||||
setup_call_cleanup(
|
||||
enter_cell(Self),
|
||||
jupyter_cell(Self, Cell, Line),
|
||||
exit_cell(Self) ).
|
||||
exit_cell(Self)
|
||||
).
|
||||
|
||||
jupyter_cell(_Self, Cell, _) :-
|
||||
open_mem_read_stream( Cell, Stream),
|
||||
load_files(['jupyter cell'],[stream(Stream)]),
|
||||
close( Stream ),
|
||||
stop_low_level_trace,
|
||||
jupyter_consult(Cell),
|
||||
fail.
|
||||
jupyter_cell( _Self, _, Line ) :-
|
||||
blank( Line ),
|
||||
!.
|
||||
jupyter_cell( Self, _, Line ) :-
|
||||
start_low_level_trace,
|
||||
python_query( Self, Line ).
|
||||
|
||||
jupyter_consult(Text) :-
|
||||
blank( Text ),
|
||||
!.
|
||||
jupyter_consult(Cell) :-
|
||||
open_mem_read_stream( Cell, Stream),
|
||||
load_files(user:'jupyter cell',[stream(Stream)]).
|
||||
%should load_files close?
|
||||
|
||||
blank(Text) :-
|
||||
atom_codes(Text, L),
|
||||
maplist( blankc, L).
|
||||
|
||||
blankc(' ').
|
||||
blankc('\n').
|
||||
blankc('\t').
|
||||
|
||||
enter_cell(_Self) :-
|
||||
%open('//python/sys.stdin', read, _Input, []),
|
||||
open('//python/sys.stdout', append, _Output, []),
|
||||
open('//python/sys.stdout', append, _Error, []),
|
||||
%set_prolog_flag(user_input, _Input),
|
||||
set_prolog_flag(user_output, _Output),
|
||||
set_prolog_flag(user_error, _Error),
|
||||
writeln(hello),
|
||||
format(user_error,'h~n',[]),
|
||||
:= print("py"),
|
||||
:= sys.stderr.write("ok\n").
|
||||
set_prolog_flag(user_error, _Error).
|
||||
|
||||
exit_cell(_Self) :-
|
||||
%close( user_input),
|
||||
close( user_output),
|
||||
close( user_error).
|
||||
|
||||
|
Reference in New Issue
Block a user