:- use_module(library(plammar)). :- use_module(library(http/http_unix_daemon)). :- use_module(library(http/thread_httpd)). :- use_module(library(http/http_dispatch)). :- use_module(library(http/http_json)). :- use_module(library(http/http_client)). :- use_module(library(http/http_cors)). :- set_setting(http:cors, [*]). :- set_prolog_flag(report_error,true). :- http_handler(/, handle, [spawn(for_fresh_variables)]). server(Port) :- http_server(http_dispatch,[port(Port)]), format(user_output,"Started server on port ~p.~n",[Port]). handle(Request) :- cors_enable, member(method(Method), Request), handle(Method, Request). handle(post, Request) :- !, http_read_data(Request, Data, []), % format(user_output, "Data is: ~p~n", [Data]), atom_chars(Data, Chars), Options = [ targets([swi]), infer_operators(no) ], ( % format(user_output, "Data is: ~p~n", [string_tree(Data,'Tree')]), % with_output_to(string(S), string_tree(Data, Tree)), % format(user_output, "Output is: ~p~n", [S]) catch( call_with_time_limit(1.0, ( prolog_parsetree(chars(Chars), AST, Options) )), _Catcher, reply_error ), % log(AST), reply_by(Request, AST) ; reply_error ). reply_error(Msg) :- nonvar(Msg), format(user_output, 'There has been an error: ~w~n', [Msg]), reply_json_dict(_{ type: error, message: 'Unexpected Error', error: Msg }). reply_error :- reply_json_dict(_{ message: 'Program could not be parsed.', type: error }). reply_by(Request, Tree) :- member(accept(Accept), Request), member(media(application/json,_,_,_), Accept), !, reply_tree(json, Tree). reply_by(Request, Tree) :- member(accept(Accept), Request), member(media(text/'x-prolog',_,_,_), Accept), !, reply_tree(prolog, Tree). reply_tree(json, Tree) :- tree_to_dict(Tree, Dict), with_output_to(string(S), print_term(Tree, [indent_arguments(2),tab_width(0),output(current_output)])), reply_json_dict(Dict.put('__source', S)). reply_tree(prolog, Tree) :- format('Content-Type: text/x-prolog~n~n', []), print_term(Tree, [indent_arguments(2),tab_width(0),output(current_output)]). tree_to_dict(Tree, Dict) :- is_list(Tree), !, maplist(tree_to_dict, Tree, Dict). tree_to_dict(end_of_file, Dict) :- !, Dict = _{ type: end_of_file }. tree_to_dict(Tree, Dict) :- Tree =.. [Name, Inner], is_list(Inner), !, maplist(tree_to_dict, Inner, Inner_Dicts), Dict = _{ type: Name, elements: Inner_Dicts }. tree_to_dict(Tree, Dict) :- Tree =.. [Name, Inner], compound(Inner), !, tree_to_dict(Inner, InnerDict), InnerName = InnerDict.type, Dict = _{ type: Name }.put(InnerName, InnerDict). tree_to_dict(Tree, Dict) :- Tree =.. [Name, Inner], atomic(Inner), !, Dict = _{ type: Name, value: Inner }. tree_to_dict(term(Op,List), Dict) :- !, tree_to_dict(List, ListDict), Dict = _{ type: term, op: Op, elements: ListDict }. tree_to_dict(Token, Dict) :- Token =.. [Token_Name, Token_Atom, Inner], atom_concat(_, '_token', Token_Name), !, tree_to_dict(Inner, InnerDict), Dict = _{ type: term, token: Token_Atom, value: InnerDict }. tree_to_dict(comment_text(Text,List), Dict) :- !, tree_to_dict(List, ListDict), Dict = _{ type: comment_text, text: Text, elements: ListDict }. add_types_to_tree(List, Typed) :- is_list(List), !, maplist(add_types_to_tree, List, Typed). add_types_to_tree(Tree, Tree) :- is_dict(Tree), dict_pairs(Tree, Tag, _), member(Tag, [pos, range]), !. add_types_to_tree(Tree, Typed) :- is_dict(Tree), !, dict_pairs(Tree, Type, Pairs), maplist(add_types_to_tree, Pairs, Typed_Pairs), dict_pairs(Typed, Type, [type-Type|Typed_Pairs]). add_types_to_tree(Key-Value, Key-Typed) :- !, add_types_to_tree(Value, Typed). add_types_to_tree(Value, Value) :- atom(Value), !. log(Term) :- open('/tmp/plammar-server.log', append, Stream), writeq(Stream, Term), nl, close(Stream).