module 'emop.top' [Impl] { main :- 'top':assertz( dynamic_emop_call(M, F, Args) :- static_emop_call(M, F, Args) ), 'top':asserta( emop_call(M, F, Args) :- !, dynamic_emop_call(M, F, Args) ), 'top':asserta( emop_call(M, F, Args) :- var(M), throw(error(instantiation_error(emop_call/3))) ), Impl:loop('data.record':{}, true, 0) }, module Impl [Impl] { to_term(T, Env) = ToTerm:do(T) :- AnonEnv = 'data.record':{}, module ToTerm [ToTerm, Env, AnonEnv] { do(callable(F, Args)) = 'data.term':make(F, 'data.list':iter(Args, ToTerm)). do(number(N)) = N. do(var(V), Term) :- ( V = '_' -> true ; 'data.atom':sub(V, 0, 1, _, '_') -> Term = AnonEnv:{V} ; Term = Env:{V} ). }. read_line(Level, Clauses, Goal) :- catch( ( 'io.std':format('(~d) ?- ', [Level]), 'io.stream':backtrackable('io.std', Backtrackable), 'io.stream':text_position(Backtrackable, '', Positionable), 'emop.lexer':lex(Positionable, Lexems), module LexemsProtect [Lexems] { read(Lexem) :- catch( Lexems:read(Lexem), E, ( repeat, ( 'io.std':read(C) -> ( C \= '\n', C \= end_of_file -> fail ; true ) ; true ) -> throw(E) ) ). }, 'emop.parser':parse( LexemsProtect, toplevel, _Fid, _FidPos, Ast0 ), ( Ast0 = callable('.', unescaped, [Ast, empty(_, _)], _, _) -> true ; Ast = Ast0 ), ( ( Ast = empty(eos, eos), 'data.number':(Level > 0), 'io.std':print_endline(backtrack) ; Ast = callable('.', unescaped, [], _, _) ; Ast = callable('backtrack', unescaped, [], _, _) ) -> throw(intern(backtrack('data.number':pred(Level)))) ; Ast = callable('backtrack', unescaped, [number(Target)], _, _) -> throw(intern(backtrack(Target))) ; ( Ast = empty(eol, eol), 'io.std':print_endline(other) ; Ast = callable(';', unescaped, [], _, _) ; Ast = callable('other', unescaped, [], _, _) ) -> throw(intern(other)) ; Ast = empty(eos, eos) -> 'sys.process':halt ; true ), 'data.atom':new(Fid), % Trick to import io.null! 'io.null':endline, 'emop.expand':expand_file( toplevel(Fid), 'io.null', Ast, Clauses, _Deps, Goal, _ ) ), E, ( ( E = intern(_) -> throw(E) ; 'emop.message':error(E), fail ) ) ). execute(Clauses, Goal, Vars, Deterministic) :- module Assert [Impl] { do(clause(F, _, Args, B)) :- 'top':asserta( Impl:to_term( callable(':-', [callable(F, Args), B]), 'data.record':{} ) ). }, 'data.list':iter(Clauses, Assert), 'top':call_det(Impl:to_term(Goal, Vars), Deterministic). display_store(Vars) :- ( 'data.atom':new(VarName), module NameVar [Vars, VarName] { do(Var, _) :- Value = Vars:{Var}, ( 'data.var':pure(Value) -> Value = 'data.term':make(VarName, [Var]) ; true ). }, Vars:iter(NameVar), module DisplayValue [DisplayValue, Vars, VarName] { make_var_name(Index, Term) :- Name = 'data.atom':format('X~d', [Index]), Var = Vars:{Name}, ( 'data.var':pure(Var) -> Var = 'data.term':make(VarName, [Name]), Term = Name ; DisplayValue:make_var_name('data.number':succ(Index), Term) ). make_term(Value, Depth, Term) :- ( 'data.var':pure(Value) -> Term = DisplayValue:make_var_name(0), Value = 'data.term':make(VarName, [Term]) ; Value = 'data.term':make(VarName, [Term]) -> true ; 'data.fd':check(Value) -> Term = 'data.fd':pretty(Value) ; 'data.number':check(Value) -> Term = Value ; 'data.module':check(Value) -> ( 'data.module':predicate(Value, pretty/1) -> ( catch( Value:pretty(Pretty), E, ( 'emop.message':error(E), Pretty = '' ) ) -> DisplayValue:make_term(Pretty, Depth, Term) ; Term = '' ) ; Term = '' ) ; 'data.term':check(Value) -> 'data.term':decomposition(Value, [F | Args0]), ( Args0 = [] -> Args1 = [] ; Depth = 0 -> ( Value = [_ | _] -> Args1 = ['...', []] ; Args1 = ['...'] ) ; SubDepth = 'data.number':pred(Depth), module MakeArg [SubDepth, DisplayValue] { do(Arg0, Arg1) :- DisplayValue:make_term(Arg0, SubDepth, Arg1). }, 'data.list':iter(Args0, MakeArg, Args1) ), Term = 'data.term':make(F, Args1) ). do(Var, Value) :- ( ( Value = 'data.term':make(VarName, [Var]) ; 'data.atom':sub(Var, 0, _, _, '_') ) -> true ; 'io.std':format( '~a = ~p\n', [Var, DisplayValue:make_term(Value, 20)] ) ). }, Vars:iter(DisplayValue), fail ; true ). result(Deterministic) :- ( Deterministic = 'true' -> 'io.std':print_endline('yes') ; 'io.std':print_endline( 'yes (there may be other solutions)' ) ). loop(Vars, Deterministic, Level) :- catch( ( ( Impl:read_line(Level, Clauses, Goal) -> catch( ( Impl:( execute(Clauses, Goal, Vars, Deterministic0), 'io.std':endline, result(Deterministic0), display_store(Vars) ), Level0 = 'data.number':succ(Level) ; 'io.std':endline, 'io.std':print_endline('no'), Impl:display_store(Vars), Deterministic = Deterministic0, Level = Level0 ), E, ( 'emop.message':error(E), Deterministic = Deterministic0, Level = Level0 ) ), Impl:loop( Vars, Deterministic0, Level0 ) ; Impl:loop(Vars, Deterministic, Level) ) ), intern(Command), ( ( Command = backtrack(Target) -> ( Level = Target -> Impl:( result(Deterministic), display_store(Vars), loop(Vars, Deterministic, Level) ) ; throw(intern(backtrack(Target))) ) ; Command = other -> ( Deterministic = false -> fail ; 'io.std':print_endline('there is no more solution'), Impl:loop(Vars, true, Level) ) ; throw(unknown_command(Command)) ) ) ). }