From 1400d60b66e14c6ec4017a12e3985c80ec8b9af3 Mon Sep 17 00:00:00 2001 From: Douglas R Miles Date: Wed, 7 Feb 2024 17:26:55 -0800 Subject: [PATCH] MeTTa --compile=full examples/baseline_compat/hyperon-mettalog_sanity/fibo_hang.metta runs !(fibo 80) in 2.24 milliseconds --- MeTTa | 7 +- .../c3_pln_stv.metta.answers | 4 +- .../hyperon-mettalog_sanity/fibo_hang.metta | 29 ++ .../gpt2-like/language_models/pllm_drs.pl | 24 +- .../understanding_performance/naive-fib.metta | 19 +- metta_vspace/pyswip-want/metta_server.pl | 293 +++++++++++++++--- metta_vspace/pyswip/metta_compiler.pl | 13 +- metta_vspace/pyswip/metta_convert.pl | 54 +++- metta_vspace/pyswip/metta_interp.pl | 22 +- metta_vspace/pyswip/metta_printer.pl | 246 +++++++++++---- metta_vspace/pyswip/metta_python.pl | 9 +- metta_vspace/pyswip/metta_space.pl | 124 -------- metta_vspace/pyswip/swi_support.pl | 2 + scripts/test_in_metta.sh | 39 ++- 14 files changed, 603 insertions(+), 282 deletions(-) create mode 100644 examples/baseline_compat/hyperon-mettalog_sanity/fibo_hang.metta diff --git a/MeTTa b/MeTTa index 54feb4d7..e5224781 100755 --- a/MeTTa +++ b/MeTTa @@ -473,8 +473,9 @@ if [[ $should_compile -eq 1 ]]; then #else rm -f $reference_file if [[ "$never_compile" -eq 0 ]]; then - DEBUG "Compiling $reference_file" - # swipl -l metta_vspace/$PYSWIP_VERSION/metta_interp.pl -g qcompile_mettalog -- --exeout=$reference_file + : + #DEBUG "Compiling $reference_file" + #swipl -l metta_vspace/$PYSWIP_VERSION/metta_interp.pl -g qcompile_mettalog -- --exeout=$reference_file fi fi @@ -484,7 +485,7 @@ if [[ -z "$reference_file" ]]; then fi if [[ -f "$reference_file" ]]; then - rm -f $reference_file + : # rm -f $reference_file fi if [[ -f "$reference_file" ]]; then diff --git a/examples/baseline_compat/hyperon-experimental_scripts/c3_pln_stv.metta.answers b/examples/baseline_compat/hyperon-experimental_scripts/c3_pln_stv.metta.answers index f8652655..2351c815 100644 --- a/examples/baseline_compat/hyperon-experimental_scripts/c3_pln_stv.metta.answers +++ b/examples/baseline_compat/hyperon-experimental_scripts/c3_pln_stv.metta.answers @@ -4,5 +4,5 @@ Doing: timeout --foreground --kill-after=5 --signal=SIGINT 61 time metta /opt/lo [()] [()] [()] -0.09user 0.00system 0:00.10elapsed 99%CPU (0avgtext+0avgdata 33140maxresident)k -0inputs+0outputs (0major+3619minor)pagefaults 0swaps +0.10user 0.02system 0:00.14elapsed 83%CPU (0avgtext+0avgdata 33204maxresident)k +27928inputs+0outputs (185major+3553minor)pagefaults 0swaps diff --git a/examples/baseline_compat/hyperon-mettalog_sanity/fibo_hang.metta b/examples/baseline_compat/hyperon-mettalog_sanity/fibo_hang.metta new file mode 100644 index 00000000..31cdd56d --- /dev/null +++ b/examples/baseline_compat/hyperon-mettalog_sanity/fibo_hang.metta @@ -0,0 +1,29 @@ + +(= (fib $n) + (if (== $n 0) + 0 + (if (== $n 1) + 1 + (+ (fib (- $n 1)) (fib (- $n 2)))))) + +(= (fib1 $a $b $n $i) + (if (< $n 3) + (fib $n) + (if (== $i (- $n 2)) + (+ $a $b) + (fib1 $b (+ $a $b) $n (+ $i 1))))) + + +!(println! (fib 12)) + +!(fib1 0 1 100 0) + +!(println! (fib1 0 1 80 0)) + +!(fib 80) + + +!(println! (fib 20)) + + + diff --git a/examples/performance/gpt2-like/language_models/pllm_drs.pl b/examples/performance/gpt2-like/language_models/pllm_drs.pl index 99a80913..9fe0bca4 100755 --- a/examples/performance/gpt2-like/language_models/pllm_drs.pl +++ b/examples/performance/gpt2-like/language_models/pllm_drs.pl @@ -1,2 +1,24 @@ - +% eval_80/6: Evaluates a Python function call within MeTTa. +% Parameters: +% - Eq: denotes get-type, match, or interpret call. +% - RetType: Expected return type of the MeTTa function. +% - Depth: Recursion depth or complexity control. +% - Self: Context or environment for the evaluation. +% - [MyFun|More]: List with MeTTa function and additional arguments. +% - RetVal: Variable to store the result of the Python function call. +eval_80(Eq, RetType, Depth, Self, [MyFun|More], RetVal) :- + % MyFun as a registered Python function with its module and function name. + metta_atom(Self, ['registered-python-function', PyModule, PyFun, MyFun]), + % Tries to fetch the type definition for MyFun, ignoring failures. + (( get_operator_typedef(Self, MyFun, Params, RetType), + try_adjust_arg_types(RetType, Depth, Self, [RetType|Params], [RetVal|More], [MVal|Adjusted]) + )->true; (maplist(as_prolog, More , Adjusted), MVal=RetVal)), + % Constructs a compound term for the Python function call with adjusted arguments. + compound_name_arguments(Call, PyFun, Adjusted), + % Optionally prints a debug tree of the Python call if tracing is enabled. + if_trace(host;python, print_tree(py_call(PyModule:Call, RetVal))), + % Executes the Python function call and captures the result in MVal which propagates to RetVal. + py_call(PyModule:Call, MVal), + % Checks the return value against the expected type and criteria. + check_returnval(Eq, RetType, RetVal). diff --git a/examples/performance/understanding_performance/naive-fib.metta b/examples/performance/understanding_performance/naive-fib.metta index b2a607b2..0489fc56 100644 --- a/examples/performance/understanding_performance/naive-fib.metta +++ b/examples/performance/understanding_performance/naive-fib.metta @@ -1,10 +1,14 @@ -;; Takes Rust MeTTa 10.166 seconds -;; Takes HVM Regular 0.0009 seconds -;; Takes Rust Regular 0.0009 seconds -;; Takes MeTTaLog Regular 15.017 seconds -;; Takes MeTTaLog Tableing 0.017 seconds +;; Takes HVM Regular 0.0009 seconds ;; Guessed +;; Takes Rust Regular 0.0009 seconds ;; Guessed +;; Takes Rust MeTTa 10.166 seconds ;; Tested +;; Takes MeTTaLog Regular 90.6667 seconds ;; Tested +;; Takes MeTTaLog Compiled-Tabling 0.017 seconds ;; Tested +;; Takes MeTTaLog Compiled 2.017 seconds ;; Guessed -;;; !(pragma! tabling true) +;; MeTTaLog only: +;!(pragma! tabling true) +;; MeTTaLog only: +;!(pragma! compiler full) (= (fib $n) @@ -18,9 +22,10 @@ (fib (- $n 2)))))) +!(fib 10) !(fib 20) -!(fib 50) +!(fib 80) diff --git a/metta_vspace/pyswip-want/metta_server.pl b/metta_vspace/pyswip-want/metta_server.pl index 94bee387..ac44b38e 100755 --- a/metta_vspace/pyswip-want/metta_server.pl +++ b/metta_vspace/pyswip-want/metta_server.pl @@ -4,92 +4,283 @@ call_wdet(Goal,WasDet):- call(Goal),deterministic(WasDet). % Helper to parse Server and Port -parse_server_port(ServerPort,DefaultPort, Server, Port) :- - ( ServerPort = Server:Port -> true - ; integer(ServerPort) -> Server = localhost, Port = ServerPort - ; Server = ServerPort, Port = DefaultPort % Default port if none specified +parse_service_port(Peer,DefaultPort, Server, Port) :- + ( Peer = Server:Port -> true + ; integer(Peer) -> Server = localhost, Port = Peer + ; Server = Peer, Port = DefaultPort % Default port if none specified ). -start_vspace_server(Port) :- - thread_create(run_vspace_server(Port),_,[detached(true),alias(vspace_server)]). -run_vspace_server(Port) :- - tcp_socket(Socket), tcp_bind(Socket, Port), tcp_listen(Socket, 5), tcp_open_socket(Socket, ListenFd), - fbug(run_vspace_server(Port)), - accept_vspace_connections(ListenFd). +service_running(Alias):- thread_property(VSS,TS),VSS=Alias,TS=status(running),!. -accept_vspace_connections(ListenFd) :- - tcp_accept(ListenFd, ClientFd, ClientAddr), - format(atom(ThreadAlias), 'client_~w', [ClientAddr]), +% Start interpreter service with MSpace = &self +start_vspace_service(Port):- + current_self(MSpace), start_vspace_service(MSpace,Port). +% see amples of using this https://github.com/logicmoo/vspace-metta/blob/main/examples/features/distributed-processing/create-server.metta +start_vspace_service(MSpace,Port):- + atomic_list_concat([vspace_service,MSpace,Port],'_',Alias), + start_vspace_service(Alias,MSpace,Port). + +start_vspace_service(Alias,_Space,_Port):- service_running(Alias),!. +start_vspace_service(Alias,MSpace,Port):- + thread_create(run_vspace_service(MSpace,Port),_,[detached(true),alias(Alias)]). + + +:- dynamic(was_vspace_port_in_use/2). + +handle_port_in_use(MSpace,Port):- + assert(was_vspace_port_in_use(MSpace,Port)), + Port100 is Port +100,run_vspace_service(MSpace,Port100). + + +run_vspace_service(MSpace,Port):- + catch( + run_vspace_service_unsafe(MSpace,Port), + error(socket_error(eaddrinuse,_),_), + handle_port_in_use(MSpace,Port)). + +run_vspace_service_unsafe(MSpace,Port) :- + tcp_socket(Socket), + tcp_bind(Socket, Port), + tcp_listen(Socket, 5), tcp_open_socket(Socket, ListenFd), + fbugio(run_vspace_service(MSpace,Port)), + retractall(vspace_port(_)), + assert(vspace_port(Port)), + accept_vspace_connections(MSpace,ListenFd). + +accept_vspace_connections(MSpace,ListenFd) :- + tcp_accept(ListenFd, RemoteFd, RemoteAddr), + nb_setval(self_space,MSpace), + format(atom(ThreadAlias0), 'peer_~w_~w_~w_', [RemoteAddr,RemoteFd,MSpace]), + gensym(ThreadAlias0,ThreadAlias), thread_create(setup_call_cleanup( - tcp_open_socket(ClientFd, Stream), - ignore(handle_vspace_client(Stream)), + tcp_open_socket(RemoteFd, Stream), + ignore(handle_vspace_peer(Stream)), catch(close(Stream),_,true)), _, [detached(true), alias(ThreadAlias)] ), - accept_vspace_connections(ListenFd). + accept_vspace_connections(MSpace,ListenFd). -handle_vspace_client(Stream) :- - read_term(Stream, Goal,[]), +handle_vspace_peer(Stream) :- + recv_term(Stream, Goal), ( Goal \= end_of_file -> ( catch(call_wdet(Goal,WasDet), Error, true) *-> ( var(Error) -> send_term(Stream, success(Goal,WasDet)) ; send_term(Stream,error(Error))) ;send_term(Stream, 'failed'))), - handle_vspace_client(Stream). + handle_vspace_peer(Stream). -% Start the server automatically on a default port or a specified port +any_to_i(A,I):- integer(A),I=A. +any_to_i(A,I):- format(atom(Ay),'~w',[A]),atom_number(Ay,I). +% Start the service automatically on a default port or a specified port :- dynamic vspace_port/1. -start_vspace_server:- ( vspace_port(Port) -> start_vspace_server(Port); start_vspace_server(3023) ). +get_vspace_port(Port):- current_prolog_flag('argv',L),member(AA,L),atom_concat('--service=',P,AA),atom_number(P,Port),!,set_prolog_flag('port',Port). +get_vspace_port(Port):- current_prolog_flag('port',P),any_to_i(P,Port),!. +get_vspace_port(Port):- vspace_port(Port),!. +get_vspace_port(Port):- Port = 3023. +start_vspace_service:- is_compiling,!. +start_vspace_service:- get_vspace_port(Port), start_vspace_service(Port),!. -:- initialization(start_vspace_server). -% Connects to the server and sends the goal -remote_call(ServerPort, Goal) :- - setup_call_cleanup( - (connect_to_server(ServerPort, Stream),send_term(Stream, Goal)), - read_response(Stream,Goal), - close(Stream)). % Helper to establish connection -connect_to_server(HostPort, Stream) :- - parse_server_port(HostPort, 3023, Host, Port), +connect_to_service(HostPort, Stream) :- + parse_service_port(HostPort, 3023, Host, Port), tcp_socket(Socket), tcp_connect(Socket, Host:Port), tcp_open_socket(Socket, Stream). % Helper to send goal and receive response -send_term(Stream, Goal) :- write_canonical(Stream, Goal),writeln(Stream, '.'), flush_output(Stream). +send_term(Stream, MeTTa) :- write_canonical(Stream, MeTTa),writeln(Stream, '.'), flush_output(Stream). +recv_term(Stream, MeTTa) :- read_term(Stream, MeTTa, []). -% Read and process the server's response +% Read and process the service's response read_response(Stream,Goal) :- flush_output(Stream), - repeat, read_term(Stream,Response,[]), + repeat, recv_term(Stream,Response), (Response == failed -> (!,fail) ; (Response = error(Throw) -> throw(Throw) ; ((Response = success(Goal,WasDet)), (WasDet==true-> (!, true) ; true)))). -% Example usage +% Connects to the service and sends the goal % ?- remote_call('localhost', member(X, [1,2,3])). +remote_call(Peer, Goal) :- + setup_call_cleanup( + (connect_to_service(Peer, Stream),send_term(Stream, Goal)), + read_response(Stream,Goal), + close(Stream)). + +remote_eval(Peer, MeTTa, Result) :- + remote_call(Peer, eval(MeTTa,Result)). + +/* +;; Example usage (from MeTTa) + +metta> !(remote-eval! localhost (add-atom &self (A b b))) +metta> !(remote-eval! localhost (add-atom &self (A b c))) +metta> !(remote-eval! localhost (match &self $Code $Code)) + +*/ + + +:- dynamic remote_code/4. % Maps MeTTa-Space and function to Service address + +our_address(Host:Port):- gethostname(Host),vspace_port(Port). +we_exist(Addr):- our_address(Addr). + +they_exist(Addr):- + our_address(Ours), + diff(Addr,Ours), + execute_goal(we_exist(Addr)), \+ our_address(Addr). + +% tell the services that took our place about us. +register_ready:- + our_address(Ours), + forall(was_vspace_port_in_use(MSpace,Port), + remote_call(Port,register_remote_code(MSpace,we_exist(_),true,Ours))). + +% before we terminate we should call this +:- at_halt(register_gone). +register_gone:- \+ service_running(_),!. +register_gone:- + ignore(( + fail, + our_address(Ours), + forall(they_exist(Addr), + remote_call(Addr,unregister_peer(Ours))))). + +unregister_peer(Who):- + forall(remote_code(MSpace,EntryPoint, _, Who), + unregister_remote_code(MSpace,EntryPoint,Who)). + +% Registers a predicate to a service +register_remote_code(MSpace,EntryPoint, NonDet, Server) :- + unregister_remote_code(MSpace,EntryPoint, Server), + assertz(remote_code(MSpace,EntryPoint, NonDet, Server)). +unregister_remote_code(MSpace,EntryPoint, Server) :- + retractall(remote_code(MSpace,EntryPoint, _, Server)). + -:- dynamic predicate_server/2. % Maps predicate to server -% Registers a predicate to a server -register_predicate_server(Predicate, Server) :- assertz(predicate_server(Predicate, Server)). +execute_goal(Goal):- + current_self(MSpace), + execute_goal(MSpace,Goal, IsDet), + (was_t(IsDet) -> ! ; true). +execute_goal(_Self,true, _) :- !. % Meta-interpreter with cut handling -execute_goal(Goal, IsCut) :- - predicate_server(Goal, Server), !, - remote_call(Server, Goal), % If the goal is registered for a server, call remotely - IsCut = _. -execute_goal(!, IsCut) :- !, IsCut = cut. % Handle cuts -execute_goal(Goal, IsCut) :- predicate_property(Goal,numberr_of_clauses(_)),!, +execute_goal(MSpace,Goal, IsDet) :- + remote_code(MSpace,Goal, NonDet, Peer), % If the goal is registered for a service, call remotely + (was_t(NonDet) -> true ; !), + remote_call(Peer, execute_goal(MSpace,Goal,IsDet)). + +execute_goal(_Self,!, IsDet) :- !, IsDet = true. % Handle cuts +execute_goal(_Self,fail, IsDet) :- !, (was_t(IsDet)->throw(cut_fail); fail). +execute_goal(MSpace,Goal, _) :- predicate_property(Goal,number_of_clauses(_)),!, clause(Goal, Body), % Retrieve the clause body for the goal - execute_goal(Body, IsCut), - (nonvar(IsCut)->!;true). -execute_goal((SubGoal1, SubGoal2), IsCut) :- !, execute_goal(SubGoal1, IsCut), execute_goal(SubGoal2, IsCut). -execute_goal((SubGoal1; SubGoal2), IsCut) :- !, (execute_goal(SubGoal1, IsCut); execute_goal(SubGoal2, IsCut)). -execute_goal((SubGoal1 -> SubGoal2), IsCut) :- !, (execute_goal(SubGoal1, IsCut) -> execute_goal(SubGoal2, IsCut)). -execute_goal(findall(X, Y, Z), _) :- !, findall(X, execute_goal(Y, _), Z). -execute_goal(forall(X, Y), _) :- !, forall(execute_goal(X, _), execute_goal(Y, _)). -execute_goal(SubGoal, _IsCut) :- call_wdet(SubGoal, _WasDet). + catch(execute_goal(MSpace,Body, IsDet),cut_fail,(!,fail)), + (was_t(IsDet)-> !; true). +execute_goal(MSpace,call(Cond), _ ) :- !, execute_goal(MSpace,Cond, IsDet), (was_t(IsDet)->!;true). +execute_goal(MSpace,(Cond, Then), IsDet) :- !, execute_goal(MSpace,Cond, IsDet), execute_goal(MSpace,Then, IsDet). +execute_goal(MSpace,(Cond; Else), IsDet) :- !, (execute_goal(MSpace,Cond, IsDet); execute_goal(MSpace,Else, IsDet)). +execute_goal(MSpace,(Cond *-> Then; Else), IsDet) :- !, (execute_goal(MSpace,Cond, IsDet) *-> execute_goal(MSpace,Then, IsDet) ; execute_goal(MSpace,Else, IsDet)). +execute_goal(MSpace,(Cond *-> Then), IsDet) :- !, (execute_goal(MSpace,Cond, IsDet) *-> execute_goal(MSpace,Then, IsDet)). +execute_goal(MSpace,(Cond -> Then; Else), IsDet) :- !, (execute_goal(MSpace,Cond, IsDet) -> execute_goal(MSpace,Then, IsDet) ; execute_goal(MSpace,Else, IsDet)). +execute_goal(MSpace,(Cond -> Then), IsDet) :- !, (execute_goal(MSpace,Cond, IsDet) -> execute_goal(MSpace,Then, IsDet)). +execute_goal(MSpace,catch(X, E, Z), IsDet) :- !, catch(execute_goal(MSpace,X, IsDet) , E, execute_goal(MSpace,Z, _)). +execute_goal(MSpace,findall(X, Y, Z), _) :- !, findall(X, execute_goal(MSpace,Y, _), Z). +execute_goal(MSpace,forall(X, Y), _) :- !, forall(execute_goal(MSpace,X, _), execute_goal(MSpace,Y, _)). +execute_goal(_Self,SubGoal, _IsCut) :- call_wdet(SubGoal, WasDet), (was_t(WasDet)->!;true). + +was_t(T):- T == true. + + +ccml_nth:attr_unify_hook(_Nth,_Var). + +metta_hyperpose_v0(P2, InList, OutList) :- + current_prolog_flag(cpu_count,Count), + length(InList,Len), length(OutList,Len), + max_min(Count,Len,_,Procs), + findall(thread(Goal, OutputVar), + (nth1(N, InList, InputVar), Goal = call(P2, InputVar, OutputVar), put_attr(OutputVar,ccml_nth,N)), + GoalsWithOutputs), + separate_goals_and_outputs(GoalsWithOutputs, Goals, OutList), + concurrent(Procs, Goals, []). + +separate_goals_and_outputs([], [], []). +separate_goals_and_outputs([thread(Goal, OutputVar)|GoalsWithOutputs], [Goal|Goals], [OutputVar|Outputs]) :- + separate_goals_and_outputs(GoalsWithOutputs, Goals, Outputs). + + + + + +%:- use_module(library(concurrent)). + +% Meta predicate that combines concurrent processing and result gathering +metta_concurrent_maplist(P2, InList, OutList) :- InList=[_,_|_],!, % only use extra threads iof 2 or more + setup_call_cleanup( + concurrent_assert_result(P2, InList, Tag), + gather_results_in_order(Tag, InList, OutList), + cleanup_results(Tag)). +metta_concurrent_maplist(P2, InList, OutList):- maplist(P2, InList, OutList). + +% Meta predicate that combines concurrent processing and result gathering +metta_hyperpose(Eq,RetType,Depth,MSpace,InList,Res) :- fail, InList=[_,_|_],!, % only use extra threads iof 2 or more + setup_call_cleanup( + concurrent_assert_result(eval_20(Eq,RetType,Depth,MSpace), InList, Tag), + each_result_in_order(Tag, InList, Res), + cleanup_results(Tag)). +metta_hyperpose(Eq,RetType,Depth,MSpace,ArgL,Res):- eval_20(Eq,RetType,Depth,MSpace,['superpose',ArgL],Res). + + +% Concurrently applies P2 to each element of InList, results are tagged with a unique identifier +concurrent_assert_result(P2, InList, Tag) :- + current_prolog_flag(cpu_count,Count), + length(InList,Len), max_min(Count,Len,_,Procs), + gensym(counter, Tag), % Generate a unique identifier + concurrent_forall( nth1(Index, InList, InputVar),assert_result_after_computation(P2, Tag, Index, InputVar), [threads(Procs)]). + %findall(assert_result_after_computation(P2, Tag, Index, InputVar), nth1(Index, InList, InputVar), Goals), + %concurrent(Procs, Goals, []). + +% Asserts the output of applying P2 to Input +assert_result_after_computation(P2, Tag, Index, Input) :- + catch( + (call(P2, Input, Output)*-> assert(result(Tag, Index, Input, Output)) ; assert(result(Tag, Index, Input, failed(Tag)))), + E, (assert(result(Tag, Index, Input, error(E))))). + + +% Gathers results in order, matching them with the corresponding inputs +gather_results_in_order(Tag, InList, OrderedResults) :- + gather_results_in_order(Tag, InList, 0, OrderedResults). + +use_result( IInput, RResult, Input, Result):- var(RResult),!,IInput=Input,Result=RResult. +use_result( IInput, error(E), Input, _Result):- ignore(IInput=Input),!, throw(E). +use_result( IInput, failed(_), Input, _Result):- ignore(IInput=Input),!,fail. +use_result( IInput, RResult, Input, Result):- IInput=Input,Result=RResult. + +gather_results_in_order(_, [], _, []). +gather_results_in_order(Tag, [Input|RestInputs], Index, [Result|OrderedResults]) :- + ( result(Tag, Index, IInput, RResult) + *-> (use_result( IInput, RResult, Input, Result),NextIndex is Index + 1,gather_results_in_order(Tag, RestInputs, NextIndex, OrderedResults)) + ; % Wait for 75 milliseconds before retrying + ( sleep(0.075), gather_results_in_order(Tag, [Input|RestInputs], Index, [Result|OrderedResults]))). + + +each_result_in_order(Tag, InList, OrderedResults) :- + each_result_in_order(Tag, InList, 0, OrderedResults). +each_result_in_order(_, [], _,_):-!,fail. +each_result_in_order(Tag, [Input|RestInputs], Index,Result) :- + ( result(Tag, Index, IInput, RResult) + *-> (use_result( IInput, RResult, Input, Result); + (NextIndex is Index + 1,each_result_in_order(Tag, RestInputs, NextIndex, Result))) + ; % Wait for 75 milliseconds before retrying + ( sleep(0.075), each_result_in_order(Tag, [Input|RestInputs], Index,Result))). + + +% Cleanup predicate to remove asserted results from the database +cleanup_results(Tag) :- + retractall(result(Tag, _, _, _)). + + +:- initialization(start_vspace_service). diff --git a/metta_vspace/pyswip/metta_compiler.pl b/metta_vspace/pyswip/metta_compiler.pl index e430db0a..c8cf31f5 100755 --- a/metta_vspace/pyswip/metta_compiler.pl +++ b/metta_vspace/pyswip/metta_compiler.pl @@ -242,14 +242,14 @@ nop(ignore(Result = '$VAR'('HeadRes'))))),!. compile_for_assert(HeadIs, AsBodyFn, Converted) :- - AsFunction = HeadIs, + AsFunction = HeadIs, must_det_ll(( Converted = (HeadC :- NextBodyC), % Create a rule with Head as the converted AsFunction and NextBody as the converted AsBodyFn /*funct_with_result_is_nth_of_pred(HeadIs,AsFunction, Result, _Nth, Head),*/ f2p(HeadIs,HResult,AsFunction,HHead), (var(HResult) -> (Result = HResult, HHead = Head) ; funct_with_result_is_nth_of_pred(HeadIs,AsFunction, Result, _Nth, Head)), - verbose_unify(Converted), + %verbose_unify(Converted), f2p(HeadIs,Result,AsBodyFn,NextBody), %RetResult = Converted, %RetResult = _, @@ -545,11 +545,18 @@ ValueResultRValueResult = (ValueResultR=ValueResult), combine_code(CodeForValue,ValueResultRValueResult,Converted). +compile_flow_control(HeadIs,RetResult,Convert,Converted) :- + Convert =~ ['println!',Value],!, + Converted = (ValueCode,eval_args('println!'(ValueResult), RetResult)), + f2p(HeadIs,ValueResult,Value,ValueCode). + + compile_flow_control(HeadIs,RetResult,Convert, Converted) :- Convert =~ ['case',Value,PNil],[]==PNil,!,Converted = (ValueCode,RetResult=[]), f2p(HeadIs,_ValueResult,Value,ValueCode). + compile_flow_control(HeadIs,RetResult,Convert, (ValueCode, Converted)) :- Convert =~ ['case',Value|Options], \+ is_ftVar(Value),!, cname_var('CASE_EVAL_',ValueResult), @@ -1369,7 +1376,7 @@ format(TempFileStream, ':- multifile((~q)/~w).~n', [PredName, Arity]), format(TempFileStream, ':- dynamic((~q)/~w).~n', [PredName, Arity]), %if_t( \+ option_value('tabling',false), - if_t(option_value('tabling',true),format(TempFileStream,':- ~q.~n',[table(PredName/Arity)])), + if_t(option_value('tabling','True'),format(TempFileStream,':- ~q.~n',[table(PredName/Arity)])), maplist(write_clause(TempFileStream), PredClauses), % Close the temporary file close(TempFileStream), diff --git a/metta_vspace/pyswip/metta_convert.pl b/metta_vspace/pyswip/metta_convert.pl index 3c9ca194..bc4ec872 100755 --- a/metta_vspace/pyswip/metta_convert.pl +++ b/metta_vspace/pyswip/metta_convert.pl @@ -230,18 +230,19 @@ p2m(_OC,NC, NC) :- var(NC), !. % If NC is a variable, do not translate. p2m(_OC,NC, NC) :- is_ftVar(NC), !. % If NC is a free term variable, do not translate. - +p2m(_OC,[], 'Nil'). % empty list p2m(_OC,M:I, with_self(N,O)):- p2m(OC,M,N),p2m(I,O). % Conversion for lists -p2m(_OC,[], 'Nil'). % empty list p2m(OC,[H|T],['::'|L]):- is_list([H|T]),maplist(p2m(OC),[H|T],L). p2m(OC,[H|T], 'Cons'(OH, OT)):- p2m(OC,H, OH), p2m(OC,T, OT). p2m(OC,NC, OO) :- % If NC is a list, map each element of the list from Prolog to MeTTa is_list(NC),!, maplist(p2m(OC), NC, OO). +p2m(_OC,!, ['set-det']). % Translate the cut operation directly. p2m(_OC,!, '!'). % Translate the cut operation directly. p2m(_OC,false, 'False'). +p2m([progn|_], (!,fail), [empty]). % Translate Prolog’s fail to MeTTa’s False. % p2m(_OC,fail, 'False'). % Translate Prolog’s fail to MeTTa’s False. p2m(_OC,true, 'True'). % Translate Prolog’s true to MeTTa’s True. % p2m(_OC,prolog, meTTa). % Translate the atom prolog to meTTa. @@ -255,7 +256,7 @@ % Conversion for any atomic term p2m(_OC,A, A):- string(A),!. -%p2m([progn|_],A, [H]):- atom(A),into_hyphens(A,H),!. +p2m([progn|_],A, [H]):- atom(A),into_hyphens(A,H),!. p2m(_,A, H):- atom(A),into_hyphens(A,H),!. p2m(_OC,A, A):- atomic(A). @@ -337,31 +338,49 @@ % Entry point for printing to Metta format. It clears the screen, sets the working directory, % expands the filenames with a specific extension, and processes each file. print_to_metta :- - cls, % Clears the screen (assumes a custom or system-specific implementation). + % cls, % Clears the screen (assumes a custom or system-specific implementation). % with_pwd( % '/opt/logicmoo_workspace/packs_sys/logicmoo_opencog/MeTTa/vspace-metta/examples/gpt2-like/language_models/', - Filt = '/opt/logicmoo_workspace/packs_sys/logicmoo_opencog/MeTTa/vspace-metta/examples/gpt2-like/language_models/*.pl', - expand_file_name(Filt, Files), - % Finds all Prolog files in the specified directory. - print_to_metta(Files), - MC = '/opt/logicmoo_workspace/packs_sys/logicmoo_opencog/MeTTa/vspace-metta/metta_vspace/pyswip/metta_convert.pl', - print_to_metta(MC). % Processes each found file. + %Filt = 'examples/gpt2-like/language_models/*.pl', + Filt = '/opt/logicmoo_workspace/packs_sys/logicmoo_opencog/MeTTa/vspace-metta/examples/performance/clasic_unification/*.pl', + % Finds all Prolog files in the specified directory. + print_to_metta(Filt), % Processes each found file. + % MC = '/opt/logicmoo_workspace/packs_sys/logicmoo_opencog/MeTTa/vspace-metta/metta_vspace/pyswip/metta_convert.pl', + % print_to_metta(MC), % Processes each found file. + !. % Example of a no-operation (nop) call for a specific file path, indicating a placeholder or unused example. %$nop(print_to_metta('/opt/logicmoo_workspace/packs_sys/logicmoo_opencog/MeTTa/vspace-metta/metta_vspace/pyswip/metta_convert.pl')). % Processes a list of filenames, applying 'print_to_metta' to each. -print_to_metta(Filenames):- is_list(Filenames),!,maplist(print_to_metta,Filenames). +with_file_lists(P1,FileSpec):- is_list(FileSpec),!,maplist(with_file_lists(P1),FileSpec). +with_file_lists(P1,Directory):- atom(Directory), exists_directory(Directory), + findall(File,directory_source_files(Directory, File, [recursive(true),if(true)]),Files), + maplist(with_file_lists(P1),Files). +with_file_lists(P1,Mask):- atom(Mask), \+ exists_file(Mask), + expand_file_name(Mask, Files), Files\==[],!,maplist(with_file_lists(P1),Files). +with_file_lists(P1,Filename):- ignore(call(P1,Filename)). + -% Processes a single filename by opening the file, translating its content, and then closing the file. print_to_metta(Filename):- + ignore(print_to_metta_file(Filename)), + ignore(print_to_metta_console(Filename)),!. + + +% Processes a list of filenames, applying 'print_to_metta' to each. +print_to_metta_console(FileSpec):- with_file_lists(print_to_metta_now(user_output),FileSpec). +print_to_metta_file(FileSpec):- with_file_lists(print_to_metta_now(_Create),FileSpec). + +% Processes a single filename by opening the file, translating its content, and then closing the file. +print_to_metta_now(OutputIn,Filename):- atom(Filename), % Verifies that the filename is an atom. % Generate the new filename with .metta extension. file_name_extension(Base, _OldExt, Filename), file_name_extension(Base, metta, NewFilename), % Setup step: open both the input and output files. format('~N~n~w~n', [print_to_metta(Filename,NewFilename)]), % Prints the action being performed. - Output = user_output, + %Output = user_output, + copy_term(OutputIn,Output), setup_call_cleanup( open(Filename, read, Input, [encoding(utf8)]), % Call step: perform the translation and write to the output file. @@ -419,7 +438,8 @@ term_position(Pos), subterm_positions(RawLayout), syntax_errors(error), - comments(Comments)], + comments(Comments), + module(trans_mod)], read_term(Stream, Term, Options), ( Term == end_of_file -> true @@ -443,12 +463,16 @@ process_term(end_of_file):- !. process_term(Term):- is_directive(Term), + ignore(maybe_call_directive(Term)), !, print_directive(Term). process_term(Term):- - p2m(Term,STerm), + expand_to_hb(Term,H,B), + p2m((H:-B),STerm), push_term_ctx(Term), write_src(STerm). +maybe_call_directive((:- op(X,F,Y))):- trans_mod:op(X,F,Y). + % Checks if a term is a directive. is_directive((:- _)). diff --git a/metta_vspace/pyswip/metta_interp.pl b/metta_vspace/pyswip/metta_interp.pl index 83788c4a..d7963ad5 100755 --- a/metta_vspace/pyswip/metta_interp.pl +++ b/metta_vspace/pyswip/metta_interp.pl @@ -87,8 +87,9 @@ option_value_def('prolog',false). option_value_def('compat',auto). option_value_def('compatio',auto). -option_value_def('compile',false). -option_value_def('table',false). +option_value_def('compile',false). % true false and full +option_value_def('tabling',true). +option_value_def('optimize',true). option_value_def(no_repeats,false). option_value_def('time',true). option_value_def('exec',true). @@ -98,11 +99,11 @@ %option_value_def('halt',false). option_value_def('doing_repl',false). option_value_def('test-retval',false). -option_value_def('trace-length',100). -option_value_def('stack-max',100). +option_value_def('trace-length',10_000). +option_value_def('stack-max',10_000). option_value_def('trace-on-overtime',20.0). option_value_def('trace-on-overflow',false). -option_value_def('exeout','./Sav.godlike.MeTTaLog'). +option_value_def('exeout','./Sav.gitlab.MeTTaLog'). @@ -147,7 +148,7 @@ %set_option_value_interp('trace-on-load',TF), set_option_value_interp('trace-on-exec',TF), set_option_value_interp('trace-on-eval',TF), - + if_t( \+ TF , set_prolog_flag(debug_on_interrupt,true)). !. fake_notrace(G):- tracing,!,notrace(G). @@ -1769,9 +1770,12 @@ print_var(Name=Var) :- print_var(Name,Var). %print_var(Name,_Var) :- atom_concat('Num',Rest,Name),atom_number(Rest,_),!. -print_var(Name,Var):- var(Name),!,write_src(Name), write(' = '), write_asrc(Var), nl. -print_var('$VAR'(Name),Var):-!, print_var(Name,Var). -print_var(Name,Var):- write('$'), write(Name), write(' = '), write_asrc(Var), nl. + +write_var(V):- var(V), !, write_dvar(V),!. +write_var('$VAR'(S)):- !, write_dvar(S),!. +write_var(V):- write_dvar(V),!. + +print_var(Name,Var):- write_var(Name), write(' = '), write_asrc(Var), nl. write_asrc(Var):- copy_term(Var,Copy,Goals),Var=Copy,write_asrc(Var,Goals). write_asrc(Var,[]):- write_src(Var). diff --git a/metta_vspace/pyswip/metta_printer.pl b/metta_vspace/pyswip/metta_printer.pl index 70ed5d82..ac34bc56 100755 --- a/metta_vspace/pyswip/metta_printer.pl +++ b/metta_vspace/pyswip/metta_printer.pl @@ -44,6 +44,186 @@ % 'pp_metta' rule is responsible for pretty-printing metta terms. pp_metta(P):- pretty_numbervars(P,PP),with_option(concepts=false,pp_fb(PP)). + + + +pp_sax(V) :- is_final_write(V),!. +pp_sax(S) :- \+ allow_concepts,!, write_src(S). +pp_sax(S) :- is_englishy(S),!,print_concept("StringValue",S). +pp_sax(S) :- symbol_length(S,1),symbol_string(S,SS),!,print_concept("StringValue",SS). +pp_sax(S) :- is_an_arg_type(S,T),!,print_concept("TypeNode",T). +pp_sax(S) :- has_type(S,T),!,format('(~wValueNode "~w")',[T,S]). +pp_sax(S) :- sub_atom(S,0,4,Aft,FB),flybase_identifier(FB,Type),!,(Aft>0->format('(~wValueNode "~w")',[Type,S]);format('(TypeNode "~w")',[Type])). +pp_sax(S) :- print_concept("ConceptNode",S). + +print_concept( CType,V):- allow_concepts, !, write("("),write(CType),write(" "),ignore(with_concepts(false,write_src(V))),write(")"). +print_concept(_CType,V):- ignore(write_src(V)). +write_val(V):- number(V),!, write_src(V). +write_val(V):- compound(V),!, write_src(V). +write_val(V):- write('"'),write(V),write('"'). + + +% Handling the final write when the value is a variable or a '$VAR' structure. +is_final_write(V):- var(V), !, write_dvar(V),!. +is_final_write('$VAR'(S)):- !, write_dvar(S),!. +is_final_write([VAR,V|T]):- '$VAR'==VAR, T==[], !, write_dvar(V). +is_final_write([]):- write('Nil'). +is_final_write('[|]'):- write('Cons'). + + +write_dvar(S):- S=='_', !, write_dname(S). +write_dvar(S):- S=='__', !, write('$'). +write_dvar(S):- var(S), get_var_name(S,N),write_dname(N),!. +write_dvar(S):- var(S), !, format('$~p',[S]). +write_dvar(S):- atom(S), atom_concat('_',N,S),write_dname(N). +write_dvar(S):- string(S), atom_concat('_',N,S),write_dname(N). +%write_dvar(S):- number(S), write_dname(S). +write_dvar(S):- write_dname(S). +write_dname(S):- write('$'),write(S). + +pp_as(V) :- \+ \+ pp_sex(V),flush_output. +pp_sex_nc(V):- with_no_quoting_symbols(true,pp_sex(V)),!. +write_src(V):- notrace(pp_sex(V)),!. +pp_sex(V):- pp_sexi(V),!. +% Various 'write_src' and 'pp_sex' rules are handling the writing of the source, +% dealing with different types of values, whether they are lists, atoms, numbers, strings, compounds, or symbols. +pp_sexi(V):- is_final_write(V),!. +pp_sexi(V):- allow_concepts,!,with_concepts('False',pp_sex(V)),flush_output. +pp_sexi('') :- !, writeq(''). +% Handling more cases for 'pp_sex', when the value is a number, a string, a symbol, or a compound. +%pp_sex('') :- format('(EmptyNode null)',[]). +pp_sexi(V):- number(V),!, writeq(V). +pp_sexi(V):- string(V),!, writeq(V). +pp_sexi(S):- string(S),!, print_concept('StringValue',S). +pp_sexi(V):- symbol(V), should_quote(V),!, symbol_string(V,S), write("'"),write(S),write("'"). +% Base case: atoms are printed as-is. +%pp_sexi(S):- symbol(S), always_dash_functor(S,D), D \=@= S, pp_sax(D),!. +pp_sexi(V):- symbol(V),!,write(V). +pp_sexi(V) :- (number(V) ; is_dict(V)), !, print_concept('ValueAtom',V). +%pp_sex((Head:-Body)) :- !, print_metta_clause0(Head,Body). +%pp_sex(''):- !, write('()'). + +% Continuing with 'pp_sex', 'write_mobj', and related rules, +% handling different cases based on the value’s type and structure, and performing the appropriate writing action. +% Lists are printed with parentheses. +pp_sexi(V) :- \+ compound(V), !, format('~p',[V]). +pp_sexi(V):- \+ is_list(V),!, pp_sex_c(V). +%pp_sex(V) :- (symbol(V),symbol_number(V,N)), !, print_concept('ValueAtom',N). +%pp_sex(V) :- V = '$VAR'(_), !, format('$~p',[V]). +pp_sexi(V) :- no_src_indents,!,pp_sex_c(V). + +pp_sexi(V) :- w_proper_indent(2,w_in_p(pp_sex_c(V))). + +write_mobj(H,_):- \+ symbol(H),!,fail. +write_mobj('$VAR',[S]):- write_dvar(S). +write_mobj(exec,[V]):- !, write('!'),write_src(V). +write_mobj('$OBJ',[_,S]):- write('['),write_src(S),write(' ]'). +write_mobj('{}',[S]):- write('{'),write_src(S),write(' }'). +write_mobj('{...}',[S]):- write('{'),write_src(S),write(' }'). +write_mobj('[...]',[S]):- write('['),write_src(S),write(' ]'). +write_mobj('$STRING',[S]):- !, writeq(S). +write_mobj(F,Args):- fail, mlog_sym(K),!,pp_sex_c([K,F|Args]). +%write_mobj(F,Args):- pp_sex_c([F|Args]). + +pp_sex_l(V):- pp_sexi_l(V),!. +pp_sexi_l(V) :- is_final_write(V),!. +pp_sexi_l([F|V]):- symbol(F), is_list(V),write_mobj(F,V),!. +pp_sexi_l([H|T]):-T ==[],!,write('('), pp_sex_nc(H),write(')'). +pp_sexi_l([H,S]):-H=='[...]', write('['),print_items_list(S),write(' ]'). +pp_sexi_l([H,S]):-H=='{...}', write('{'),print_items_list(S),write(' }'). +%pp_sex_l(X):- \+ compound(X),!,write_src(X). +%pp_sex_l('$VAR'(S))):- +pp_sexi_l([=,H,B]):- + write('(= '), with_indents(false,write_src(H)), nl, write(' '), + with_indents(true,write_src(B)),write(')'). +pp_sexi_l([H|T]) :- \+ no_src_indents, symbol(H),member(H,['If','cond','let','let*']),!, + with_indents(true,w_proper_indent(2,w_in_p(pp_sex_c([H|T])))). + +pp_sexi_l([H|T]) :- is_list(T), length(T,Args),Args =< 2, fail, + wots(SS,((with_indents(false,(write('('), pp_sex_nc(H), write(' '), print_list_as_sexpression(T), write(')')))))), + ((atom_length(SS,Len),Len < 20) ->write(SS); + with_indents(true,w_proper_indent(2,w_in_p(pp_sex_c([H|T]))))),!. +/* + +pp_sexi_l([H|T]) :- is_list(T),symbol(H),upcase_atom(H,U),downcase_atom(H,U),!, + with_indents(false,(write('('), pp_sex_nc(H), write(' '), print_list_as_sexpression(T), write(')'))). + +%pp_sex([H,B,C|T]) :- T==[],!, +% with_indents(false,(write('('), pp_sex(H), print_list_as_sexpression([B,C]), write(')'))). +*/ +pp_sexi_l([H,H2]):- write('('), pp_sex_nc(H), write(' '), with_indents(false,print_list_as_sexpression([H2])), write(')'). +pp_sexi_l([H|T]):- write('('), pp_sex_nc(H), write(' '), print_list_as_sexpression(T), write(')'). + +print_items_list(X):- is_list(X),!,print_list_as_sexpression(X). +print_items_list(X):- write_src(X). + +pp_sex_c(V):- pp_sexi_c(V),!. +pp_sexi_c(V) :- is_final_write(V),!. +pp_sexi_c([H|T]) :- is_list(T),!,pp_sex_l([H|T]). +pp_sexi_c(=(H,B)):- !, pp_sex_l([=,H,B]). +pp_sexi_c(V):- compound_name_list(V,F,Args),write_mobj(F,Args),!. +% Compound terms. +%pp_sex(Term) :- compound(Term), Term =.. [Functor|Args], write('('),format('(~w ',[Functor]), write_args_as_sexpression(Args), write(')'). +%pp_sex(Term) :- Term =.. ['=',H|Args], length(Args,L),L>2, write('(= '), pp_sex(H), write('\n\t\t'), maplist(pp_sex(2),Args). +pp_sexi_c(V):- ( \+ compound(V) ; is_list(V)),!, pp_sex(V). +pp_sexi_c(listOf(S,_)) :- !,write_mobj(listOf(S)). +pp_sexi_c(listOf(S)) :- !,format('(ListValue ~@)',[pp_sex(S)]). +pp_sexi_c('!'(V)) :- write('!'),!,pp_sex(V). +%pp_sex_c('exec'(V)) :- write('!'),!,pp_sex(V). +pp_sexi_c('='(N,V)):- allow_concepts, !, format("~N;; ~w == ~n",[N]),!,pp_sex(V). +%pp_sex_c(V):- writeq(V). + +pp_sexi_c(Term) :- compound_name_arity(Term,F,0),!,pp_sex_c([F]). +pp_sexi_c(Term) :- Term =.. [Functor|Args], always_dash_functor(Functor,DFunctor), format('(~w ',[DFunctor]), write_args_as_sexpression(Args), write(')'),!. +pp_sexi_c(Term) :- allow_concepts, Term =.. [Functor|Args], format('(EvaluationLink (PredicateNode "~w") (ListLink ',[Functor]), write_args_as_sexpression(Args), write('))'),!. +pp_sexi_c(Term) :- + Term =.. [Functor|Args], + always_dash_functor(Functor,DFunctor), format('(~w ',[DFunctor]), + write_args_as_sexpression(Args), write(')'),!. + +pp_sexi(2,Result):- write('\t\t'),pp_sex(Result). + + +current_column(Column) :- current_output(Stream), line_position(Stream, Column),!. +current_column(Column) :- stream_property(current_output, position(Position)), stream_position_data(column, Position, Column). +min_indent(Sz):- current_column(Col),Col>Sz,nl,indent_len(Sz). +min_indent(Sz):- current_column(Col),Need is Sz-Col,indent_len(Need),!. +min_indent(Sz):- nl, indent_len(Sz). +indent_len(Need):- forall(between(1,Need,_),write(' ')). + +w_proper_indent(N,G):- + flag(w_in_p,X,X), %(X==0->nl;true), + XX is (X*2)+N,setup_call_cleanup(min_indent(XX),G,true). +w_in_p(G):- setup_call_cleanup(flag(w_in_p,X,X+1),G,flag(w_in_p,_,X)). + + +always_dash_functor(A,B):- once(dash_functor(A,B)),A\=@=B,!. +always_dash_functor(A,A). + +dash_functor(A,C):- \+ symbol(A),!,C=A. +%dash_functor(A,C):- p2m(A,B),A\==B,!,always_dash_functor(B,C). +dash_functor(Functor,DFunctor):- + symbol(Functor), atomic_list_concat(L,'-',Functor), L\=[_],maplist(always_dash_functor,L,LL), + atomic_list_concat(LL,'-',DFunctor). +dash_functor(Functor,DFunctor):- fail, + symbol(Functor), atomic_list_concat(L,'_',Functor), L\=[_],maplist(always_dash_functor,L,LL), + atomic_list_concat(LL,'-',DFunctor). +dash_functor(Functor,DFunctor):- + symbol(Functor), atomic_list_concat(L,'_',Functor), L\=[_],maplist(always_dash_functor,L,LL), + atomic_list_concat(LL,'_',DFunctor). + +% Print arguments of a compound term. +write_args_as_sexpression([]). +write_args_as_sexpression([H|T]) :- write(' '), pp_sex(H), write_args_as_sexpression(T). + +% Print the rest of the list. +print_list_as_sexpression([]). +print_list_as_sexpression([H]):- pp_sex(H). +%print_list_as_sexpression([H]):- w_proper_indent(pp_sex(H)),!. +print_list_as_sexpression([H|T]):- pp_sex(H), write(' '), print_list_as_sexpression(T). + + + % The predicate with_indents/2 modifies the src_indents option value during the execution of a goal. % The first argument is the desired value for src_indents, % and the second argument is the Goal to be executed with the given src_indents setting. @@ -51,6 +231,17 @@ % Set the value of the `src_indents` option to TF and then execute the Goal with_option(src_indents, TF, Goal). + +no_src_indents:- option_else(src_indents,TF,true),!,TF=='False'. + + + +no_quoting_symbols:- option_else(no_quoting_symbols,TF,true),!,TF=='True'. + +with_no_quoting_symbols(TF, Goal) :- + % Set the value of the `no_src_indents` option to TF and then execute the Goal + with_option(no_quoting_symbols, TF, Goal). + % The predicate allow_concepts/0 checks whether the use of concepts is allowed. % It does this by checking the value of the concepts option and ensuring it is not false. allow_concepts :- !, fail, @@ -65,63 +256,14 @@ % Set the value of the `concepts` option to TF and then execute the Goal with_option(concepts, TF, Goal). - -% Various 'write_src' and 'write_src0' rules are handling the writing of the source, -% dealing with different types of values, whether they are lists, atoms, numbers, strings, compounds, or symbols. -write_src(V):- notrace(write_src0(V)). -write_src0(V):- V ==[],!,write('()'). -write_src0(V):- allow_concepts,!,with_concepts('False',write_src1(V)),flush_output. -write_src0(V):- is_list(V),!,pp_sexi(V). -write_src0(V):- write_src1(V),!. - -% Handling the final write when the value is a variable or a '$VAR' structure. -is_final_write(V):- var(V), !, format('$~p',[V]). -is_final_write('$VAR'(S)):- S=='_', !, write('$'),write(S). -is_final_write('$VAR'(S)):- S=='__', !, write('$'). -is_final_write('$VAR'(S)):- var(S), write('$'),write(S). -is_final_write('$VAR'(S)):- number(S), write('$'),write(S). -is_final_write('$VAR'(S)):- atom(S), atom_concat('_',N,S),write('$'),write(N). -is_final_write('$VAR'(S)):- string(S), atom_concat('_',N,S),write('$'),write(N). - - -% Handling more cases for 'write_src1', when the value is a number, a string, a symbol, or a compound. -write_src1(V) :- is_final_write(V),!. -write_src1([F|V]):- atom(F), is_list(V),write_mobj(F,V),!. -write_src1((Head:-Body)) :- !, print_metta_clause0(Head,Body). -write_src1(''):- !, write('()'). -write_src1(V):- number(V),!, writeq(V). -write_src1(V):- string(V),!, writeq(V). - -% Continuing with 'write_src1', 'write_mobj', and related rules, -% handling different cases based on the value’s type and structure, and performing the appropriate writing action. -write_src1(V):- symbol(V), should_quote(V),!, - symbol_string(V,S),writeq(S). -write_src1(V):- symbol(V),!,write(V). -write_src1(V):- compound(V), \+ is_list(V),!,write_mobj(V). -write_src1(V):- pp_sex(V),!. - -write_mobj(V) :- is_final_write(V),!. -write_mobj(V):- ( \+ compound(V) ; is_list(V)),!, write_src0(V). - -write_mobj(V):- compound_name_list(V,F,Args),write_mobj(F,Args),!. -write_mobj(V):- writeq(V). -write_mobj(exec,[V]):- !, write('!'),write_src(V). -write_mobj('$OBJ',[_,S]):- write('['),write_src(S),write(' ]'). -write_mobj('{}',[S]):- write('{'),write_src(S),write(' }'). -write_mobj('{...}',[S]):- write('{'),write_src(S),write(' }'). -write_mobj('[...]',[S]):- write('['),write_src(S),write(' ]'). -write_mobj('$STRING',[S]):- !, writeq(S). -write_mobj(F,Args):- fail, mlog_sym(K),!,pp_sexi([K,F|Args]). -write_mobj(F,Args):- pp_sexi([F|Args]). - % Rules for determining when a symbol needs to be quoted in metta. dont_quote(Atom):- atom_length(Atom,1), !, char_type(Atom,punct). -dont_quote(Atom):- atom(Atom),upcase_atom(Atom,Atom),downcase_atom(Atom,Atom). +dont_quote(Atom):- symbol(Atom),upcase_atom(Atom,Atom),downcase_atom(Atom,Atom). -should_quote(Atom) :- \+ atom(Atom), \+ string(Atom),!,fail. +should_quote(Atom) :- \+ symbol(Atom), \+ string(Atom),!,fail. should_quote(Atom) :- \+ dont_quote(Atom), - % atom(Atom), % Ensure that the input is an atom + % symbol(Atom), % Ensure that the input is an symbol atom_chars(Atom, Chars), once(should_quote_chars(Chars);should_quote_atom_chars(Atom,Chars)). diff --git a/metta_vspace/pyswip/metta_python.pl b/metta_vspace/pyswip/metta_python.pl index 4c585c94..bebce642 100755 --- a/metta_vspace/pyswip/metta_python.pl +++ b/metta_vspace/pyswip/metta_python.pl @@ -2,6 +2,10 @@ :- flush_output. :- setenv('RUST_BACKTRACE',full). %:- '$set_source_module'('user'). +:- set_prolog_flag(py_backtrace_depth,10). +:- set_prolog_flag(py_backtrace, true). +:- set_prolog_flag(py_argv,[]). +%:- set_prolog_flag(argv,[]). /* # Core in Rust In the original version, the core logic and functionalities of the MeTTa system are implemented in Rust. Rust is known for its performance and safety features, making it a suitable choice for building robust, high-performance systems. @@ -333,12 +337,9 @@ setenv('PYTHONPATH', NewPythonPath). -:- set_prolog_flag(py_backtrace_depth,10). -:- set_prolog_flag(py_backtrace, true). %:- initialization(on_restore1,restore). %:- initialization(on_restore2,restore). -%:- set_prolog_flag(argv,[]). -:- set_prolog_flag(py_argv,[]). + % py_initialize(, +Argv, +Options) diff --git a/metta_vspace/pyswip/metta_space.pl b/metta_vspace/pyswip/metta_space.pl index b4e675ca..fbb15ffc 100755 --- a/metta_vspace/pyswip/metta_space.pl +++ b/metta_vspace/pyswip/metta_space.pl @@ -428,121 +428,6 @@ % is a quine 'AtomDef'(X,['AtomDef',X]). -% =============================== -% PRINTERS -% =============================== - - -pp_sax(V) :- is_final_write(V),!. -pp_sax(S) :- \+ allow_concepts,!, write_src(S). -pp_sax(S) :- is_englishy(S),!,print_concept("StringValue",S). -pp_sax(S) :- symbol_length(S,1),symbol_string(S,SS),!,print_concept("StringValue",SS). -pp_sax(S) :- is_an_arg_type(S,T),!,print_concept("TypeNode",T). -pp_sax(S) :- has_type(S,T),!,format('(~wValueNode "~w")',[T,S]). -pp_sax(S) :- sub_atom(S,0,4,Aft,FB),flybase_identifier(FB,Type),!,(Aft>0->format('(~wValueNode "~w")',[Type,S]);format('(TypeNode "~w")',[Type])). -pp_sax(S) :- print_concept("ConceptNode",S). - -print_concept( CType,V):- allow_concepts, !, write("("),write(CType),write(" "),ignore(with_concepts(false,write_src(V))),write(")"). -print_concept(_CType,V):- ignore(write_src(V)). -write_val(V):- number(V),!, write_src(V). -write_val(V):- compound(V),!, write_src(V). -write_val(V):- write('"'),write(V),write('"'). - -% Base case: atoms are printed as-is. -pp_as(V) :- \+ \+ pp_sex(V),flush_output. -pp_sex(V) :- is_final_write(V),!. -pp_sex('!'(V)) :- write('!'),!,pp_sex(V). -pp_sex('exec'(V)) :- write('!'),!,pp_sex(V). -%pp_sex('') :- format('(EmptyNode null)',[]). -pp_sex('') :- !, format('""',[]). -pp_sex([]):- !, write('()'). -pp_sex('='(N,V)):- allow_concepts, !, format("~N;; ~w == ~n",[N]),!,pp_sex(V). -pp_sex(V) :- (number(V) ; is_dict(V)), !, print_concept('ValueAtom',V). -%pp_sex(V) :- (symbol(V),symbol_number(V,N)), !, print_concept('ValueAtom',N). -pp_sex(S) :- symbol(S), always_dash_functor(S,D), pp_sax(D),!. -pp_sex(S) :- string(S),!, print_concept('StringValue',S). -% Lists are printed with parentheses. -pp_sex(V) :- \+ compound(V), !, format('~p',[V]). -pp_sex(V) :- V = '$VAR'(_), !, format('$~p',[V]). -pp_sex('!'(V)) :- write('!'),!,pp_sex(V). -pp_sex(listOf(S,_)) :- !,pp_sex(listOf(S)). -pp_sex(listOf(S)) :- !,format('(ListValue ~@)',[pp_sex(S)]). - -pp_sex([H|T]) :- \+ no_src_indents, atom(H),member(H,['If','cond','let','let*']),!, - with_indents(true,w_proper_indent(2,w_in_p(pp_sexi([H|T])))). - -pp_sex([H|T]) :- is_list(T), length(T,Args),Args =< 2, fail, - wots(SS,((with_indents(false,(write('('), pp_sex(H), write(' '), print_list_as_sexpression(T), write(')')))))), - ((atom_length(SS,Len),Len < 20) ->write(SS); - with_indents(true,w_proper_indent(2,w_in_p(pp_sexi([H|T]))))),!. -/* - -pp_sex([H|T]) :- is_list(T),atom(H),upcase_atom(H,U),downcase_atom(H,U),!, - with_indents(false,(write('('), pp_sex(H), write(' '), print_list_as_sexpression(T), write(')'))). - -%pp_sex([H,B,C|T]) :- T==[],!, -% with_indents(false,(write('('), pp_sex(H), print_list_as_sexpression([B,C]), write(')'))). -*/ -pp_sex(V) :- no_src_indents,!,pp_sexi(V). - -pp_sex(V) :- w_proper_indent(2,w_in_p(pp_sexi(V))). - -no_src_indents:- option_else(src_indents,TF,true),!,TF=='False'. - -pp_sexi_l([H,S]):-H=='[...]', write('['),print_items_list(S),write(' ]'). -pp_sexi_l([H,S]):-H=='{...}', write('{'),print_items_list(S),write(' }'). -pp_sexi_l(Decl):- '=~'(Decl , (=(H,B))), - write('(= '), with_indents(false,write_src(H)), nl, write(' '), - with_indents(true,write_src(B)),write(')'). - -pp_sexi_l([H,H2]):- write('('), pp_sex(H), write(' '), with_indents(false,print_list_as_sexpression([H2])), write(')'). -pp_sexi_l([H|T]):-write('('), pp_sex(H), write(' '), print_list_as_sexpression(T), write(')'). - -print_items_list(X):- is_list(X),!,print_list_as_sexpression(X). -print_items_list(X):- write_src(X). - -pp_sexi(Term) :- Term==[],!,write('()'). -pp_sexi(V) :- is_final_write(V),!. -pp_sexi([H|T]) :- is_list(T),!,pp_sexi_l([H|T]). -% Compound terms. -%pp_sex(Term) :- compound(Term), Term =.. [Functor|Args], write('('),format('(~w ',[Functor]), write_args_as_sexpression(Args), write(')'). -%pp_sex(Term) :- Term =.. ['=',H|Args], length(Args,L),L>2, write('(= '), pp_sex(H), write('\n\t\t'), maplist(pp_sex(2),Args). -pp_sexi(Term) :- compound_name_arity(Term,F,0),!,pp_sexi([F]). -pp_sexi(Term) :- Term =.. [Functor|Args], always_dash_functor(Functor,DFunctor), format('(~w ',[DFunctor]), write_args_as_sexpression(Args), write(')'),!. -pp_sexi(Term) :- allow_concepts, Term =.. [Functor|Args], format('(EvaluationLink (PredicateNode "~w") (ListLink ',[Functor]), write_args_as_sexpression(Args), write('))'),!. -pp_sexi(Term) :- Term =.. [Functor|Args], - always_dash_functor(Functor,DFunctor), format('(~w ',[DFunctor]), write_args_as_sexpression(Args), write(')'),!. - -pp_sex(2,Result):- write('\t\t'),pp_sex(Result). - - -current_column(Column) :- current_output(Stream), line_position(Stream, Column),!. -current_column(Column) :- stream_property(current_output, position(Position)), stream_position_data(column, Position, Column). -min_indent(Sz):- current_column(Col),Col>Sz,nl,indent_len(Sz). -min_indent(Sz):- current_column(Col),Need is Sz-Col,indent_len(Need),!. -min_indent(Sz):- nl, indent_len(Sz). -indent_len(Need):- forall(between(1,Need,_),write(' ')). - -w_proper_indent(N,G):- - flag(w_in_p,X,X), %(X==0->nl;true), - XX is (X*2)+N,setup_call_cleanup(min_indent(XX),G,true). -w_in_p(G):- setup_call_cleanup(flag(w_in_p,X,X+1),G,flag(w_in_p,_,X)). - - -always_dash_functor(A,B):- once(dash_functor(A,B)),A\=@=B,!. -always_dash_functor(A,A). - -dash_functor(A,C):- \+ symbol(A),!,C=A. -dash_functor(A,C):- p2m(A,B),A\==B,!,always_dash_functor(B,C). -dash_functor(Functor,DFunctor):- - symbol(Functor), atomic_list_concat(L,'-',Functor), L\=[_],maplist(always_dash_functor,L,LL), - atomic_list_concat(LL,'-',DFunctor). -dash_functor(Functor,DFunctor):- fail, - symbol(Functor), atomic_list_concat(L,'_',Functor), L\=[_],maplist(always_dash_functor,L,LL), - atomic_list_concat(LL,'-',DFunctor). -dash_functor(Functor,DFunctor):- - symbol(Functor), atomic_list_concat(L,'_',Functor), L\=[_],maplist(always_dash_functor,L,LL), - atomic_list_concat(LL,'_',DFunctor). sort_on(C,R,A,B):- (A==B-> R= (=) ; must_det_ll((call(C,A,AA),call(C,B,BB),!,compare(R,AA+A,BB+B)))),!. tokens(X,VL):- unaccent_atom(X,A),!, findall(E,(is_tokenizer(T),call(T,A,E)),L),predsort(sort_on(length_fw_len),L,S),last(S,VL). @@ -571,15 +456,6 @@ is_an_arg_type(S,T):- flybase_identifier(S,T),!. has_type(S,Type):- sub_atom(S,0,4,Aft,FB),flybase_identifier(FB,Type),!,Aft>0. -% Print arguments of a compound term. -write_args_as_sexpression([]). -write_args_as_sexpression([H|T]) :- write(' '), pp_sex(H), write_args_as_sexpression(T). - -% Print the rest of the list. -print_list_as_sexpression([]). -print_list_as_sexpression([H]):- pp_sex(H). -%print_list_as_sexpression([H]):- w_proper_indent(pp_sex(H)),!. -print_list_as_sexpression([H|T]):- pp_sex(H), write(' '), print_list_as_sexpression(T). call_sexpr(S):- writeln(call=S). %call_sexpr(Space,Expr,Result):- diff --git a/metta_vspace/pyswip/swi_support.pl b/metta_vspace/pyswip/swi_support.pl index ef6289e8..9159994b 100755 --- a/metta_vspace/pyswip/swi_support.pl +++ b/metta_vspace/pyswip/swi_support.pl @@ -50,8 +50,10 @@ option_else0(_N,V, Else):- !,V=Else. %option_value( N,V):- var(V), !, (was_option_value( N,V)->true;trace). +option_value(N,V):- V==true,option_value0(N,'True'),!. option_value(N,V):- notrace(option_value0(N,V)). option_value0( N,V):- var(V), !, was_option_value( N,V). + option_value0( N,V):- nonvar(V), option_value0( N,VV), !, p2m(VV,V1),p2m(V,V2),!,V1=V2.%equal_enough(V1,V2). option_value0( N,V):- option_else0( N,V ,[]). diff --git a/scripts/test_in_metta.sh b/scripts/test_in_metta.sh index c1a7dea8..3c924faa 100755 --- a/scripts/test_in_metta.sh +++ b/scripts/test_in_metta.sh @@ -27,7 +27,8 @@ export METTALOG_MAX_TIME export all_test_args="${@}" run_tests_auto_reply="" generate_report_auto_reply="" -UNITS_DIR="examples/" +METTALOG_OUTPUT="examples" +UNITS_DIR="$METTALOG_OUTPUT/" passed_along_to_mettalog=() METTALOG_MAX_TIME=75 clean=0 # 0 means don't clean, 1 means do clean @@ -46,10 +47,11 @@ while [ "$#" -gt 0 ]; do -y|--yes) run_tests_auto_reply="y" ;; -n|--no) run_tests_auto_reply="n" ;; --timeout=*) METTALOG_MAX_TIME="${1#*=}" ;; + --output=*) METTALOG_OUTPUT="${1#*=}";; --report=*) generate_report_auto_reply="${1#*=}" ;; --clean) clean=1; if_failures=0 ;; --regres*) clean=0; if_failures=0; if_regressions=1 ;; - --cont*) clean=0; if_failures=0 ;; + --cont*) clean=0; if_failures=0 ;; --fail*) clean=0; if_failures=1 ;; --explain) explain_only=1 ;; --test) explain_only=0 ;; @@ -90,8 +92,8 @@ if [ "$show_help" -eq 1 ]; then echo " extra args Optional command-line arguments passed to MeTTaLog" echo "" echo "Examples:" - echo " # Run under '${SCRIPT_DIR}/examples/baseline_compat/hyperon-pln_metta/sumo' with a 60 second timeout per test" - echo " $0 examples/ --include \"*sumo/\" --timeout=60" + echo " # Run under '${SCRIPT_DIR}/$METTALOG_OUTPUT/baseline_compat/hyperon-pln_metta/sumo' with a 60 second timeout per test" + echo " $0 $METTALOG_OUTPUT/ --include \"*sumo/\" --timeout=60" echo "" echo " # Automatically (chooses 'y') cleans up and runs all tests in default '${SCRIPT_DIR}/examples' directory with a 180 second timeout per test" echo " $0 -y --clean --timeout=180" @@ -108,6 +110,20 @@ IF_REALLY_DO() { fi } +if [[ "$METTALOG_OUTPUT" != "" ]]; then + # Create the directory if it doesn't exist + + NEW_UNITSDIR="${METTALOG_OUTPUT}/${UNITS_DIR#*/}" + + IF_REALLY_DO mkdir -p "$NEW_UNITSDIR" + + IF_REALLY_DO \cp -an "$UNITS_DIR"/* "$NEW_UNITSDIR/" + + UNITS_DIR="$NEW_UNITSDIR" +else + METTALOG_OUTPUT=examples +fi + function delete_html_files() { if [ -n "${UNITS_DIR}" ]; then # Check if UNITS_DIR is not empty @@ -234,6 +250,7 @@ function run_tests() { # Main execution block function main() { + cd "$SCRIPT_DIR" # Prompt user to rerun all tests if run_tests_auto_reply is not set @@ -438,10 +455,10 @@ function generate_final_MeTTaLog() { { echo "| STATUS | TEST NAME | TEST CONDITION | ACTUAL RESULT | EXPECTED RESULT |" echo "|--------|-----------|----------------|---------------|-----------------|" cat /tmp/SHARED.UNITS | awk -F'\\(|\\) \\| \\(' '{ print $2 " " $0 }' | sort | cut -d' ' -f2- | tac | awk '!seen[$0]++' | tac - } > ./examples/PASS_FAIL.md + } > ./$METTALOG_OUTPUT/PASS_FAIL.md - ./scripts/pass_fail_totals.sh examples/ > ./examples/TEST_LINKS.md + ./scripts/pass_fail_totals.sh $METTALOG_OUTPUT/ > $METTALOG_OUTPUT/TEST_LINKS.md } @@ -451,10 +468,10 @@ function PreCommitReports() { cd "$SCRIPT_DIR" echo "Executing Tasks..." - rsync -avm --include='*.metta.html' -f 'hide,! */' examples/ reports/ \ - && echo "1) Synced HTML files from examples/ to reports/ and deleted the original HTML files in examples/" - \cp -f examples/PASS_FAIL.md reports/PASS_FAIL.md - \cp -f examples/TEST_LINKS.md reports/TEST_LINKS.md + rsync -avm --include='*.metta.html' -f 'hide,! */' $METTALOG_OUTPUT/ reports/ \ + && echo "1) Synced HTML files from $METTALOG_OUTPUT/ to reports/ and deleted the original HTML files in $METTALOG_OUTPUT/" + \cp -f $METTALOG_OUTPUT/PASS_FAIL.md reports/PASS_FAIL.md + \cp -f $METTALOG_OUTPUT/TEST_LINKS.md reports/TEST_LINKS.md #mv final_MeTTaLog.md MeTTaLog.md \ #&& echo "2) Renamed final_MeTTaLog.md to MeTTaLog.md" @@ -554,7 +571,7 @@ function compare_test_files() { rm -f "$sorted1" "$sorted2" new_tests.md missing_tests.md } -main +( main )