From 9fb8a9b69bcd94256345000d0a500564ada03df8 Mon Sep 17 00:00:00 2001 From: logicmoo Date: Sun, 1 Dec 2024 02:52:55 -0800 Subject: [PATCH] output_language --- hyperon-wam.vpj | 4 +- src/canary/metta_compiler.pl | 52 +++++++++++++-- src/canary/metta_compiler_lib.pl | 3 + src/canary/metta_debug.pl | 63 ++++++++++++++++++ src/canary/metta_interp.pl | 106 ++++++++++++++++++++++++++++--- src/canary/metta_parser.pl | 38 ++++++++--- src/canary/metta_pfc_base.pl | 18 +++--- src/canary/metta_repl.pl | 40 +++++++----- src/canary/metta_runtime.pl | 80 +---------------------- 9 files changed, 274 insertions(+), 130 deletions(-) diff --git a/hyperon-wam.vpj b/hyperon-wam.vpj index ed6837cb7f3..bfe652142cf 100755 --- a/hyperon-wam.vpj +++ b/hyperon-wam.vpj @@ -67,6 +67,8 @@ Name="Other Files" Filters=""> + + @@ -279,6 +281,4 @@ Recurse="1" Excludes=".git/;*.metta.html;*.bak;build/;.*/;*~*/"/> - - diff --git a/src/canary/metta_compiler.pl b/src/canary/metta_compiler.pl index 1530975f58c..3bf992241ac 100755 --- a/src/canary/metta_compiler.pl +++ b/src/canary/metta_compiler.pl @@ -140,7 +140,7 @@ % ?- compile_for_exec(RetResult, is(pi+pi), Converted). compile_for_exec(Res,I,O):- - %ignore(Res='$VAR'('RetResult')), + %ignore(Res='$VAR'('RetResult')),` compile_for_exec0(Res,I,O),!. compile_for_exec0(Res,I,eval_args(I,Res)):- is_ftVar(I),!. @@ -180,10 +180,25 @@ %(var(HResult) -> (Result = HResult, HHead = Head) ; % funct_with_result_is_nth_of_pred(HeadIs,AsFunction, Result, _Nth, Head)), ast_to_prolog_aux([FnName/LenArgsPlus1],[assign,HResult,[call(FnName)|Args]],HeadC), - format("~w",[NextBody]), - ast_to_prolog([FnName/LenArgsPlus1],NextBody,NextBodyC) + + output_language( ast, (( + \+ \+ (( no_conflict_numbervars(HeadC + NextBody), + %write_src_wi([=,HeadC,NextBody]), + print_tree_nl([=,HeadC,NextBody]), + true))))), + + + ast_to_prolog([FnName/LenArgsPlus1],NextBody,NextBodyC), + output_language(prolog, (print_pl_source(Converted))), + true )). + +no_conflict_numbervars(Term):- + findall(N,(sub_term(E,Term),compound(E), '$VAR'(N)=E, integer(N)),NL),!, + max_list([-1|NL],Max),Start is Max + 1,!, + numbervars(Term,Start,_,[attvar(skip),singletons(true)]). + %compile_for_assert(HeadIs, AsBodyFn, Converted) :- % format("compile_for_assert: ~w ~w\n",[HeadIs, AsBodyFn]), % HeadIs=[FnName|Args], @@ -426,7 +441,7 @@ findall(Atom1, (between(1, Am1, I1), Atom1='$VAR'(I1)), AtomList1), B=..[u_assign,[F|AtomList1],'$VAR'(A)], (enable_interpreter_calls -> G=true;G=fail), - create_and_consult_temp_file(Space,Fp/A,[H:-(format("######### warning: using stub for:~w\n",[F]),G,B)]))). + create_and_consult_temp_file(Space,Fp/A,[H:-(format("; % ######### warning: using stub for:~w\n",[F]),G,B)]))). % Predicate to create a temporary file and write the tabled predicate create_and_consult_temp_file(Space,F/A, PredClauses) :- @@ -434,6 +449,10 @@ % Generate a unique temporary memory buffer tmp_file_stream(text, TempFileName, TempFileStream), % Write the tabled predicate to the temporary file + format(TempFileStream, ':- multifile((~q)/~w).~n', [metta_compiled_predicate, 3]), + format(TempFileStream, ':- dynamic((~q)/~w).~n', [metta_compiled_predicate, 3]), + format(TempFileStream, '~N~q.~n',[metta_compiled_predicate(Space,F,A)]), + format(TempFileStream, ':- multifile((~q)/~w).~n', [F, A]), format(TempFileStream, ':- dynamic((~q)/~w).~n', [F, A]), %if_t( \+ option_value('tabling',false), @@ -444,16 +463,26 @@ % Consult the temporary file % abolish(F/A), /*'&self':*/ + % sformat(CAT,'cat ~w',[TempFileName]), shell(CAT), consult(TempFileName), - listing(F/A), + % listing(F/A), % Delete the temporary file after consulting %delete_file(TempFileName), - asserta(metta_compiled_predicate(Space,F,A)), current_predicate(F/A), - listing(metta_compiled_predicate/3), + %listing(metta_compiled_predicate/3), true)). + +write_to_streams(StreamList, Format, Args) :- + % Write to each stream in the list + forall(member(Stream, StreamList), + format(Stream, Format, Args)), + % Write to stdout + format(user_output, Format, Args), + flush_output(user_output). % Ensure output is displayed immediately + + %metta_compiled_predicate(_,F,A):- metta_compiled_predicate(F,A). % Helper predicate to write a clause to the file @@ -523,6 +552,15 @@ atom(Fn), compile_flow_control(HeadIs,RetResult,Convert, Converted),!. +f2p(HeadIs,RetResult, Convert, Converted) :- HeadIs\=@=Convert, + Convert=[Fn|_], \+ atom(Fn), + Args = Convert, + maplist(f2p(HeadIs),NewArgs, Args, NewCodes), + append(NewCodes,CombinedNewCode), + Code=[assign,RetResult,list(NewArgs)], + append(CombinedNewCode,[Code],Converted). + + f2p(HeadIs,RetResult, Convert, Converted) :- HeadIs\=@=Convert, Convert=[Fn|Args], atom(Fn),!, diff --git a/src/canary/metta_compiler_lib.pl b/src/canary/metta_compiler_lib.pl index 3ea786ff7dd..59f6cf8c093 100644 --- a/src/canary/metta_compiler_lib.pl +++ b/src/canary/metta_compiler_lib.pl @@ -44,3 +44,6 @@ mc__assertEqualToResult(A, B, C) :- u_assign([assertEqualToResult, A, B], C). + + +mc__empty(_):-!,fail. diff --git a/src/canary/metta_debug.pl b/src/canary/metta_debug.pl index 4999ccaf425..261001debec 100755 --- a/src/canary/metta_debug.pl +++ b/src/canary/metta_debug.pl @@ -762,6 +762,69 @@ is_showing(Flag) :- is_verbose(Flag), !. is_showing(Flag) :- fast_option_value(Flag, 'show'), !. + +log_file_type(X):- nonvar(X),!,log_file_type(Is),!,Is=X. +log_file_type(metta):- fast_option_value(compile, full),!. +log_file_type(prolog):- fast_option_value(compile, save),!. +log_file_type(markdown):- fast_option_value(format, markdown),!. +log_file_type(metta):- fast_option_value(compile, false),!. +log_file_type(prolog). + + +into_blocktype(InfoType,Goal):- !, + enter_markdown(InfoType),!, + Goal. + %setup_call_cleanup(format('~N```~w~n',[InfoType]),Goal, format('~N```~n',[])). + +into_blocktype(InfoType,Goal):- log_file_type(markdown), !, + setup_call_cleanup(format('~N```~w~n',[InfoType]),Goal, format('~N```~n',[])). + +into_blocktype(InfoType,Goal):- log_file_type(prolog), !, + setup_call_cleanup(format('~N```~w~n',[InfoType]),Goal, format('~N```~n',[])). + +into_blocktype(InfoType,Goal):- log_file_type(prolog), !, + setup_call_cleanup(format('~N/*~n```~w~n*/~n',[InfoType]),Goal, format('~N/*~n```~n*/~n',[])). + +output_language( InfoType, Goal ) :- log_file_type(Lang), !, % (Lang==prolog; Lang==metta),!, + ((InfoType == Lang -> (must_det_ll((enter_markdown(Lang),leave_comment)),call(Goal)) ; (must_det_ll(enter_comment),into_blocktype(InfoType,Goal)))). + +output_language( InfoType, Goal ) :- log_file_type(markdown), !, into_blocktype(InfoType,Goal). +output_language( comment, Goal ) :- log_file_type(markdown), !, call(Goal). +output_language( comment, Goal ) :- log_file_type(prolog), !, format('~N:- q.~n', [output_language( comment, Goal)]). +output_language( comment, Goal ) :- log_file_type(metta), !, in_cmt(Goal). + + +:- dynamic(inside_comment/0). +leave_comment:- inside_comment,!, format('~N*/~n~n'),retract(inside_comment). +leave_comment. +enter_comment:- inside_comment,!. +enter_comment:- format('~N~n/*~n'),assert(inside_comment). +:- enter_comment. + +:- at_halt(leave_markdown(_)). +:- at_halt(leave_comment). + + +:- dynamic(inside_markdown/1). +leave_markdown(_):- \+ inside_markdown(_),!. +leave_markdown(Lang):- inside_markdown(Lang),!, format('~N```~n'),retract(inside_markdown(Lang)). +leave_markdown(_):- !. % inside_markdown(Other),!,leave_markdown(Other). +leave_markdown(_Lang):- !. %format('~N```~n'),!. +enter_markdown(Lang):- inside_markdown(Lang),!. +enter_markdown(Lang):- inside_markdown(Other),!,leave_markdown(Other),!,enter_markdown(Lang). +enter_markdown(Lang):- log_file_type(Us),Us=Lang,inside_comment,!,format('~N```~w~n',[Lang]),asserta(inside_markdown(Lang)),leave_comment. +enter_markdown(Lang):- format('~N```~w~n',[Lang]),asserta(inside_markdown(Lang)). + + +pick_quote(String, '"'):- \+ string_contains(String,'"'),!. +pick_quote(String, '\''):- \+ string_contains(String,'\''),!. +pick_quote(String, '`'):- \+ string_contains(String,'`'),!. + +banner_writeln(Msg):- + writeln('/*===='), + writeln(Msg), + writeln('====*/'),!. + %! if_show(+Flag, :Goal) is nondet. % % Conditionally execute a goal if showing is enabled for the given flag. diff --git a/src/canary/metta_interp.pl b/src/canary/metta_interp.pl index f25d993c210..c026977df81 100755 --- a/src/canary/metta_interp.pl +++ b/src/canary/metta_interp.pl @@ -652,7 +652,9 @@ redo_call_cleanup(set_prolog_IO(user_input, Out,user_error), G, set_prolog_IO(user_input,COut,user_error)). - not_compatio(G):- if_t(once(is_mettalog;is_testing),user_err(G)). +not_compatio(G):- nb_current(in_not_compatio, true),!,call(G). +not_compatio(G):- if_t(once(is_mettalog;is_testing; (\+ is_compatio )), + user_err( locally(nb_setval(in_not_compatio, true), G))). extra_answer_padding(_). @@ -1287,7 +1289,7 @@ assert_preds(Self,Load,Preds):- expand_to_hb(Preds,H,_B), functor(H,F,A), %trace, - if_t((show_transpiler), + if_t((false,show_transpiler), color_g_mesg_ok('#005288',( ignore(( % \+ predicate_property(H,defined), @@ -1527,10 +1529,11 @@ metta_anew(Load,_Src,OBO):- silent_loading,!,metta_anew1(Load,OBO). metta_anew(Load,Src,OBO):- not_compat_io(( - if_show(load,color_g_mesg('#ffa500', ((format('~N '), write_src(Src))))), + output_language( metta, (if_show(load, color_g_mesg('#ffa500', ((format('~N '), write_src(Src))))))), % format('~N'), - if_verbose(load,color_g_mesg('#0f0f0f',(write(' ; Action: '),writeq(Load=OBO),nl))))), - metta_anew1(Load,OBO),not_compat_io((format('~N'))). + output_language( Load, (if_verbose(load,color_g_mesg('#4f4f0f', (( (write('; Action: '),writeq(Load=OBO),nl))))))), + true)), + metta_anew1(Load,OBO),not_compat_io((format('~N'))). subst_vars_not_last(A,B):- functor(A,_F,N),arg(N,A,E), @@ -1574,7 +1577,7 @@ wots(S,write_src(exec(Exec))), nb_setval(exec_src,Exec), format('~N'), - ignore((notrace((color_g_mesg('#0D6328',writeln(S)))))). + output_language(metta,ignore((notrace((color_g_mesg('#0D6328',writeln(S))))))). %!(let* (( ($a $b) (collapse (get-atoms &self)))) ((bind! &stdlib $a) (bind! &corelib $b))) @@ -1777,7 +1780,7 @@ do_metta_exec(From,Self,TermV,FOut):- Output = X, %format("########################X0 ~w ~w ~w\n",[Self,TermV,FOut]), - (catch(((not_compatio(write_exec(TermV)), + (catch(((output_language(metta,write_exec(TermV)), notrace(into_metta_callable(Self,TermV,Term,X,NamedVarsList,Was)),!, %format("########################X1 ~w ~w ~w ~w\n",[Term,X,NamedVarsList,Output]), user:interactively_do_metta_exec(From,Self,TermV,Term,X,NamedVarsList,Was,Output,FOut))), @@ -1811,7 +1814,10 @@ subst_vars(Res+ExecGoal,Res+Term,NamedVarsList), copy_term_g(NamedVarsList,Was), term_variables(Term,Vars), - notrace((color_g_mesg('#114411',print_pl_source(answer(Res):-ExecGoal)))), + + + Call = do_metta_runtime(Res, ExecGoal), + output_language(prolog, notrace((color_g_mesg('#114411', print_pl_source(:- Call ))))), %nl,writeq(Term),nl, ((\+ \+ (( @@ -1846,6 +1852,8 @@ current_self(SelfS),SelfS==Self,!, do_metta(true,exec,Self,Form,_Out). eval_H(Term,X):- catch_metta_return(eval_args(Term,X),X). + +eval_H(StackMax,Self,Term,X):- fast_option_value(compile, save),!. eval_H(StackMax,Self,Term,X):- catch_metta_return(eval_args('=',_,StackMax,Self,Term,X),X). /* eval_H(StackMax,Self,Term,X). @@ -2231,6 +2239,9 @@ :- ensure_loaded(metta_python). :- ensure_loaded(metta_corelib). %:- ensure_loaded(metta_help). + +:- enter_comment. + :- initialization(use_corelib_file). :- initialization(use_metta_ontology). @@ -2255,7 +2266,86 @@ %:- initialization(loon(program),program). %:- initialization(loon(default)). +% Flush any pending output to ensure smooth runtime interactions +flush_metta_output :- + with_output_to(user_error, (write_answer_output, ttyflush)). + +% Write out answers in hyperon-experimental format to user_error +metta_runtime_write_answers(List) :- + with_output_to(user_error, (write('['), write_answers_aux(List), write(']'))). + +% Helper predicate to manage answer formatting to user_error +write_answers_aux([]) :- !. +write_answers_aux([H|T]) :- + with_output_to(user_error, (write_src_woi(H), (T == [] -> true ; write(', '), write_answers_aux(T)))). + +% Dynamically describe the current file or an actively reading file, providing context for runtime sessions +file_desc(Message) :- + prolog_load_context(file, CurrentFile), + ( stream_property(Stream, mode(read)), + stream_property(Stream, file_name(File)), + \+ at_end_of_stream(Stream), + File \= CurrentFile, + !, + sformat(Message, 'File(~w)', [File]) + ; sformat(Message, 'File(~w)', [CurrentFile]) + ). + +:- dynamic(runtime_session/4). + +% Begin a runtime session with detailed time recording, output to user_error +begin_metta_runtime :- + file_desc(Description), + current_times(WallStart, CPUStart), + asserta(runtime_session(start, WallStart, CPUStart, Description)), + with_output_to(user_error, format('~w started.~n', [Description])). + +% End a runtime session, calculate and print elapsed times, output to user_error +end_metta_runtime :- + file_desc(Description), + ( retract(runtime_session(start, WallStart, CPUStart, Description)) + -> calculate_elapsed_time(WallStart, CPUStart, WallElapsedTime, CPUElapsedTime), + print_elapsed_time(WallElapsedTime, CPUElapsedTime, Description) + ; with_output_to(user_error, format('Error: No runtime session start information found for "~w".~n', [Description])) + ). + +% Wall and CPU time +current_times(WallStart, CPUStart) :- + get_time(WallStart), + statistics(cputime, CPUStart). + +% Calculate elapsed times +calculate_elapsed_time(WallStart, CPUStart, WallElapsedTime, CPUElapsedTime) :- + current_times(WallEnd, CPUEnd), + WallElapsedTime is WallEnd - WallStart, + CPUElapsedTime is CPUEnd - CPUStart. + +% Print the elapsed wall and CPU time with a description, output to user_error +print_elapsed_time(WallElapsedTime, CPUElapsedTime, Description) :- + with_output_to(user_error, + format(' % Walltime: ~9f seconds, CPUtime: ~9f seconds for ~w~n', + [WallElapsedTime, CPUElapsedTime, Description])). + +% Execute a Prolog query and handle output, performance logging, and time measurements to user_error +do_metta_runtime(_Var,_Call) :- fast_option_value(compile, save),!. +do_metta_runtime( Var, Call) :- + functor(Call, Func, _), + atom_concat('Testing ', Func, Description), + current_times(WallStart, CPUStart), + % Execute the query and collect results + with_output_to(user_error, findall(Var, Call, List)), + % Record stop time + calculate_elapsed_time(WallStart, CPUStart, WallElapsedTime, CPUElapsedTime), + % Show results + with_output_to(user_error, metta_runtime_write_answers(List)), + % Print elapsed time + print_elapsed_time(WallElapsedTime, CPUElapsedTime, Description), + flush_metta_output. + + + :- set_prolog_flag(metta_interp,ready). +%:- ensure_loaded(metta_runtime). %:- set_prolog_flag(gc,false). :- use_module(library(clpr)). % Import the CLP(R) library diff --git a/src/canary/metta_parser.pl b/src/canary/metta_parser.pl index d2f35f4666f..002c7b656b6 100644 --- a/src/canary/metta_parser.pl +++ b/src/canary/metta_parser.pl @@ -195,12 +195,17 @@ svar_fixvarname(SVAR, UP) :- % If the name is already bound, throw an error. nonvar(UP), !, trace_or_throw(nonvar_svar_fixvarname(SVAR, UP)). +% svar_fixvarname(SVAR, UP) :- % Fix the name if it follows certain conventions. svar_fixname(SVAR, UP), !. svar_fixvarname(SVAR, UP) :- % If fixing fails, throw an error. fail, trace_or_throw(svar_fixname(SVAR, UP)). +svar_fixvarname(SVAR, UP):- integer(SVAR),!,sformat(SUP,'~w',['$VAR'(SVAR)]), svar_fixvarname(SUP, UP). +svar_fixvarname(SVAR, UP):- integer(SVAR),UP=SVAR,!. +svar_fixvarname(SVAR, UP):- svar(SVAR,UP),!. +svar_fixvarname(SVAR, UP):- n_to_vn(UP,SVAR),!. %! svar_fixname(?Var, ?NameO) is det. % @@ -274,6 +279,9 @@ fix_varcase(Word, Word) :- % If the word starts with '_', leave it unchanged. atom_concat_or_rtrace('_', _, Word), !. + +fix_varcase(Word, WordC) :- string(Word),atom_string(Atom,Word),!,fix_varcase(Atom, WordC). +fix_varcase(Word, WordC) :- atom(Word),downcase_atom(Word, UC),Word=UC,atom_concat('_',UC,WordC),!. fix_varcase(Word, WordC) :- % Convert the first letter to uppercase. !, atom_codes(Word, [F | R]), to_upper(F, U), atom_codes(WordC, [U | R]). @@ -818,15 +826,19 @@ maybe_name_vars(List):- \+ is_list(List), !. maybe_name_vars([]):-!. maybe_name_vars([N=Var|List]):- - ignore((n_to_vn(N,NN),Var = '$VAR'(NN))), + must_det_ll((n_to_vn(N,NN), ignore((Var = '$VAR'(NN))))), maybe_name_vars(List). -n_to_vn(N,NN):- var(N),!,sformat(NN,'~p',[N]). -n_to_vn(N,NN):- number(N),sformat(NN,'~p',['$VAR'(N)]). -n_to_vn(N,NN):- \+ atom(N),!,sformat(NN,'~p',[N]). -n_to_vn('_','_'):-!. -n_to_vn(N,NN):-atom_concat('$',N1,N),!,sformat(NN,'~w',[N1]). -n_to_vn(N,NN):-atom_concat('_',N1,N),!,sformat(NN,'~w',[N1]). -n_to_vn(N,NN):-!,sformat(NN,'~w',[N]). + +n_to_vn(N,NN):- n_to_vn0(N,NNS),name(NN,NNS). +n_to_vn0(N,NN):- var(N),!,sformat(NN,'~p',[N]). +n_to_vn0(N,NN):- integer(N),sformat(NN,'~p',['$VAR'(N)]). +n_to_vn0(N,NN):- number(N),sformat(NN,'~p',['$VAR'(N)]). +n_to_vn0(N,NN):- string(N),!,atom_string(A,N),!,n_to_vn0(A,NN). +n_to_vn0(N,NN):- \+ atom(N),!,sformat(NN,'_~p',[N]). +n_to_vn0('_','_'):-!. +n_to_vn0(N,NN):-atom_concat('$',N1,N),!,sformat(NN,'~w',[N1]). +n_to_vn0(N,NN):-atom_concat('_',N1,N),!,sformat(NN,'_~w',[N1]). +n_to_vn0(N,NN):-!,sformat(NN,'_~w',[N]). better_typename(TypeName1,TypeName2,array):- var(TypeName1),var(TypeName2),!. better_typename(TypeName1,TypeName2,TypeName1):- var(TypeName2),!. @@ -1198,6 +1210,10 @@ ; Symbolic = Symbol). % Otherwise, keep the symbol as is. + +% ast_to_prolog_aux(_,A,O) :- compound(A), A='$VAR'(String),svar_fixvarname(String,UP),O='$VAR'(UP),!. +% ast_to_prolog_aux(DontStub,[assign,A,E],OO):- compound(A), A='$VAR'(String),svar_fixvarname(String,UP),String\=UP,O='$VAR'(UP),!,ast_to_prolog_aux(DontStub,[assign,O,E],OO). + %! classify_and_convert_charseq_(+Chars:list, -Symbolic:term) is det. % % Helper predicate that attempts to classify the character sequence. @@ -1207,9 +1223,11 @@ % @param Symbolic The resultant Prolog term or symbol. % Case 1: If the character sequence starts with '$', treat it as a variable. -classify_and_convert_charseq_(['$'| RestChars], '$VAR'(Symbolic)) :- +classify_and_convert_charseq_(['$'| RestChars], '$VAR'(SymbolicVar)) :- !, - atom_chars(Symbolic, ['_'|RestChars]). % Convert the rest of the characters into a variable name. + atom_chars(Symbolic, RestChars), % Convert the rest of the characters into a variable name. + svar_fixvarname(Symbolic,SymbolicVar). + % Case 2: Attempt to interpret the characters as a Prolog term using `read_from_chars/2`. % This handles more complex syntaxes like numbers, dates, etc. classify_and_convert_charseq_(Chars, Symbolic) :- diff --git a/src/canary/metta_pfc_base.pl b/src/canary/metta_pfc_base.pl index 33c6a3e4389..556bb69e0ac 100755 --- a/src/canary/metta_pfc_base.pl +++ b/src/canary/metta_pfc_base.pl @@ -2194,12 +2194,12 @@ %! pfcAddTrigger(+Trigger, +Support) is det. % -% Adds a trigger (positive, negative, or bidirectional) to the system, +% Adds a trigger (positive, negative, or backward) to the system, % asserting it with the provided support and evaluating it if applicable. % Unrecognized triggers result in a warning message. % % @arg Trigger The trigger to be added, which can be a positive (`$pt$`), -% negative (`$nt$`), or bidirectional (`$bt$`) trigger. +% negative (`$nt$`), or backward (`$bt$`) trigger. % @arg Support The support context for asserting the trigger. % % @example @@ -2225,7 +2225,7 @@ \+ pfc_call(Test), with_current_why(\+ pfc_call(Test), fcEvalLHS(Body, ((\+Trigger), '$nt$'(TriggerCopy, Test, Body)))). pfcAddTrigger('$bt$'(Trigger, Body), Support) :- - % Add a bidirectional trigger. + % Add a backward trigger. !, pfcAssert('$bt$'(Trigger, Body), Support), pfcBtPtCombine(Trigger, Body, Support). @@ -2235,16 +2235,16 @@ %! pfcBtPtCombine(+Head, +Body, +Support) is det. % -% Combines a bidirectional trigger (`$bt$`) with any positive triggers +% Combines a backward trigger (`$bt$`) with any positive triggers % (`$pt$`) that have unifying heads. For each unifying positive trigger, -% the instantiated body of the bidirectional trigger is evaluated. +% the instantiated body of the backward trigger is evaluated. % -% @arg Head The head of the bidirectional trigger. -% @arg Body The body of the bidirectional trigger. +% @arg Head The head of the backward trigger. +% @arg Body The body of the backward trigger. % @arg Support The support context for the combination. % % @example -% % Combine a bidirectional trigger with matching positive triggers. +% % Combine a backward trigger with matching positive triggers. % ?- pfcBtPtCombine(my_head, my_body, support_context). % pfcBtPtCombine(Head, Body, Support) :- @@ -3135,7 +3135,7 @@ %! fc_rule_check(+P) is nondet. % % Performs special built-in forward chaining if the input `P` is a rule. -% It processes both unidirectional (`==>`) and bidirectional (`<==>`) rules. +% It processes unidirectional (`==>`), bidirectional (`<==>`) and backward (`<-`) rules. % % @arg P The rule to process. % diff --git a/src/canary/metta_repl.pl b/src/canary/metta_repl.pl index fed77b48e4d..dc4b5fd04b2 100755 --- a/src/canary/metta_repl.pl +++ b/src/canary/metta_repl.pl @@ -921,7 +921,7 @@ % Execute the form and generate the output using do_metta/5. do_metta(true, exec, Self, Form, Out), % Write the result to the source. - write_src(Out). + output_language(metta_answers, write_src(Out)). %! eval(+Form, -Out) is det. % Evaluates a form and returns the output. @@ -1205,21 +1205,23 @@ nb_setarg(1,Prev,Output))), - if_t(ResNum=(not_compatio(format('~N~nDeterministic: ', [])), !); %or Nondet + output_language(answers,(if_t(ResNum=(old_not_compatio(format('~N~nDeterministic: ', [])), !); %or Nondet /* previously: handle deterministic result output */ - (Complete==true -> (not_compatio(format('~N~nLast Result(~w): ',[ResNum])),! ); - not_compatio(format('~N~nNDet Result(~w): ',[ResNum]))))), - ignore((( - not_compatio(if_t( \+ symbolic(Output), nop(nl))), + (Complete==true -> (old_not_compatio(format('~N~nLast Result(~w): ',[ResNum])),! ); + old_not_compatio(format('~N~nNDet Result(~w): ',[ResNum]))))), + ignore((( + if_t( \+ symbolic(Output), not_compatio(nop(nl))), %if_t(ResNum==1,in_answer_io(format('~N['))), - user_io(with_indents(is_mettalog, - color_g_mesg_ok(yellow, - \+ \+ + % user_io + (with_indents(is_mettalog, + color_g_mesg_ok(yellow, + \+ \+ (maybe_name_vars(NamedVarsList), - not_compatio(write_bsrc(Output)), - true)))) )) ))), - in_answer_io(write_asrc(Output)), + old_not_compatio(write_bsrc(Output)), + true)))) )) ))))), + in_answer_io(write_asrc((Output))), not_compatio(extra_answer_padding(format('~N'))), % Just in case, add some virt space between answers @@ -1237,8 +1239,8 @@ maplist(print_var,NamedVarsListR), nop(nl)))) ; true))))), ( (Stepping==true) -> - (write("~npress ';' for more solutions "),get_single_char_key(C), - not_compatio((writeq(key=C),nl)), + (old_not_compatio(write("~npress ';' for more solutions ")),get_single_char_key(C), + old_not_compatio((writeq(key=C),nl)), (C=='b' -> (once(repl),fail) ; (C=='m' -> make ; (C=='t' -> (nop(set_debug(eval,true)),rtrace) ; @@ -1254,10 +1256,11 @@ (((Complete==true ->! ; true))))), not_compatio(extra_answer_padding(format('~N~n'))))) *-> (ignore(Result = res(FOut)),ignore(Output = (FOut))) ; (flag(result_num,ResNum,ResNum),(ResNum==0-> - (in_answer_io(nop(write('['))),not_compatio(format('~N~n~n')),!,true);true))), + (in_answer_io(nop(write('['))),old_not_compatio(format('~N~n~n')),!,true);true))), in_answer_io(write(']\n')), ignore(Result = res(FOut)). +old_not_compatio(G):- call(G),ttyflush. %! maybe_assign(+N_V) is det. % @@ -1787,7 +1790,10 @@ % Compile the goal for execution and store the result in Res. compile_for_exec(Res, Exec, Goal), % Print the compiled goal with formatting. - notrace((color_g_mesg('#114411', print_pl_source(answer2(Res) :- Goal)))). + Call = do_metta_runtime(Res, Goal), + output_language(prolog, notrace((color_g_mesg('#114411', print_pl_source(:- Call))))), + call(Call). + %! verbose_unify(+Term) is det. % diff --git a/src/canary/metta_runtime.pl b/src/canary/metta_runtime.pl index 3b96ec6d38a..37911819261 100644 --- a/src/canary/metta_runtime.pl +++ b/src/canary/metta_runtime.pl @@ -26,82 +26,8 @@ % Uncomment the next line if 'metta_compiler_lib' needs to be loaded as well % :- user:ensure_loaded(metta_compiler_lib),!, -:- user:ensure_loaded(metta_interp),!, - % Start interpreter code - user:loon. +:- user:ensure_loaded(metta_interp),!. -% Flush any pending output to ensure smooth runtime interactions -flush_metta_output :- - with_output_to(user_error, (write_answer_output, ttyflush)). - -% Write out answers in hyperon-experimental format to user_error -metta_runtime_write_answers(List) :- - with_output_to(user_error, (write('['), write_answers_aux(List), write(']'))). - -% Helper predicate to manage answer formatting to user_error -write_answers_aux([]) :- !. -write_answers_aux([H|T]) :- - with_output_to(user_error, (write_src_woi(H), (T == [] -> true ; write(', '), write_answers_aux(T)))). - -% Dynamically describe the current file or an actively reading file, providing context for runtime sessions -file_desc(Message) :- - prolog_load_context(file, CurrentFile), - ( stream_property(Stream, mode(read)), - stream_property(Stream, file_name(File)), - \+ at_end_of_stream(Stream), - File \= CurrentFile, - !, - sformat(Message, 'File(~w)', [File]) - ; sformat(Message, 'File(~w)', [CurrentFile]) - ). - -:- dynamic(runtime_session/4). - -% Begin a runtime session with detailed time recording, output to user_error -begin_metta_runtime :- - file_desc(Description), - current_times(WallStart, CPUStart), - asserta(runtime_session(start, WallStart, CPUStart, Description)), - with_output_to(user_error, format('~w started.~n', [Description])). - -% End a runtime session, calculate and print elapsed times, output to user_error -end_metta_runtime :- - file_desc(Description), - ( retract(runtime_session(start, WallStart, CPUStart, Description)) - -> calculate_elapsed_time(WallStart, CPUStart, WallElapsedTime, CPUElapsedTime), - print_elapsed_time(WallElapsedTime, CPUElapsedTime, Description) - ; with_output_to(user_error, format('Error: No runtime session start information found for "~w".~n', [Description])) - ). - -% Wall and CPU time -current_times(WallStart, CPUStart) :- - get_time(WallStart), - statistics(cputime, CPUStart). - -% Calculate elapsed times -calculate_elapsed_time(WallStart, CPUStart, WallElapsedTime, CPUElapsedTime) :- - current_times(WallEnd, CPUEnd), - WallElapsedTime is WallEnd - WallStart, - CPUElapsedTime is CPUEnd - CPUStart. - -% Print the elapsed wall and CPU time with a description, output to user_error -print_elapsed_time(WallElapsedTime, CPUElapsedTime, Description) :- - with_output_to(user_error, - format(' % Walltime: ~9f seconds, CPUtime: ~9f seconds for ~w~n', - [WallElapsedTime, CPUElapsedTime, Description])). - -% Execute a Prolog query and handle output, performance logging, and time measurements to user_error -do_metta_runtime(Var, Call) :- - functor(Call, Func, _), - atom_concat('Testing ', Func, Description), - current_times(WallStart, CPUStart), - % Execute the query and collect results - with_output_to(user_error, findall(Var, Call, List)), - % Record stop time - calculate_elapsed_time(WallStart, CPUStart, WallElapsedTime, CPUElapsedTime), - % Show results - with_output_to(user_error, metta_runtime_write_answers(List)), - % Print elapsed time - print_elapsed_time(WallElapsedTime, CPUElapsedTime, Description), - flush_metta_output. +% Start interpreter code +:- user:loon.