forked from trealla-prolog/trealla
-
Notifications
You must be signed in to change notification settings - Fork 1
/
js_toplevel.pl
105 lines (92 loc) · 2.46 KB
/
js_toplevel.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/*
This is a JSON toplevel that WASM ports can use to grab answers from Trealla programmatically.
Very experimental and not in the upstream.
Current format:
ASCII START OF TEXT (0x02), stdout text as-is, then ASCII END OF TEXT (0x03), then a JSON response
{
"result": "success" | "failure" | "error",
"answers": [{ "X": "<substitution for X>", ... }, ...],
"error": "<throw/1 exception term>"
}
*/
:- module(js_toplevel, [js_toplevel/0, js_ask/1]).
:- use_module(library(lists)).
:- use_module(library(dcgs)).
:- use_module(library(json)).
js_toplevel :-
getline(Line),
js_ask(Line).
js_ask(Input) :-
catch(
read_term_from_chars(Query, [variable_names(Vars)], Input),
Error,
(
write('\x2\\x3\'),
write_result(error, Error),
flush_output
)
),
query(Query, Vars, Status, Solution),
write_result(Status, Solution),
flush_output.
write_result(success, Solution0) :-
solution_json(Solution0, Solution),
once(phrase(json_chars(pairs([
string("result")-string("success"),
string("answer")-Solution
])), JSON)),
maplist(write, JSON), nl.
write_result(failure, _) :-
once(phrase(json_chars(pairs([
string("result")-string("failure")
])), JSON)),
maplist(write, JSON), nl.
write_result(error, Error0) :-
term_json(Error0, Error),
once(phrase(json_chars(pairs([
string("result")-string("error"),
string("error")-Error
])), JSON)),
maplist(write, JSON), nl.
query(Query, Vars, Status, Solution) :-
write('\x2\'),
( catch(call(Query), Error, true)
*-> OK = true
; OK = false
),
write('\x3\'), % END OF TEXT
query_status(OK, Error, Status),
( nonvar(Error)
-> Solution = Error
; Solution = Vars
).
query_status(_OK, Error, error) :- nonvar(Error), !.
query_status(true, _, success).
query_status(false, _, failure).
solution_json(Vars0, pairs(Vars)) :- maplist(var_json, Vars0, Vars).
var_json(Var0=Value0, string(Var)-Value) :-
atom_chars(Var0, Var),
term_json(Value0, Value).
term_json(Value0, string(Value)) :-
atom(Value0),
atom_chars(Value0, Value),
!.
term_json(Value, string(Value)) :-
string(Value),
!.
term_json(Value, number(Value)) :-
number(Value),
!.
term_json(Value0, list(Value)) :-
is_list(Value0),
maplist(term_json, Value0, Value),
!.
term_json(Value, pairs([string("functor")-string(Functor), string("args")-list(Args)])) :-
compound(Value),
Value =.. [Functor0|Args0],
atom_chars(Functor0, Functor),
maplist(term_json, Args0, Args),
!.
term_json(Value, pairs([string("var")-string("_")])) :-
var(Value),
!.