combo(branch, [T, F, Expr|S], S, Ei, Eo) :- \+ Expr = true, \+ Expr = false, catch( % Try Expr and do one or the other, (Expr -> append(T, Ei, Eo) ; append(F, Ei, Eo)), _, % If Expr don't grok, try both branches. (append(T, Ei, Eo) ; append(F, Ei, Eo)) ). combo(loop, [B, Expr|S], S, Ei, Eo) :- \+ Expr = true, \+ Expr = false, catch( % Try Expr and do one or the other, (Expr -> append(B, [B, loop|Ei], Eo) ; Ei=Eo), _, % If Expr don't grok, try both branches. (Ei=Eo ; append(B, [B, loop|Ei], Eo)) ). /* To handle comparision operators the possibility of exceptions due to insufficiently instantiated arguments must be handled. First try to make the comparison and set the result to a Boolean atom. If an exception happens just leave the comparison expression as the result and some other function or combinator will deal with it. Example: func(>, [A, B|S], [C|S]) :- catch( (B > A -> C=true ; C=false), _, C=(B>A) % in case of error. ). To save on conceptual overhead I've defined a term_expansion/2 that sets up the func/3 for each op. */ term_expansion(comparison_operator(X), (func(X, [A, B|S], [C|S]) :- F =.. [X, B, A], catch((F -> C=true ; C=false), _, C=F))). % I don't use Prolog-compatible op symbols in all cases. term_expansion(comparison_operator(X, Y), (func(X, [A, B|S], [C|S]) :- F =.. [Y, B, A], catch((F -> C=true ; C=false), _, C=F))). % Likewise for math operators, try to evaluate, otherwise use the % symbolic form. term_expansion(math_operator(X), (func(X, [A, B|S], [C|S]) :- F =.. [X, B, A], catch(C is F, _, C=F))). term_expansion(math_operator(X, Y), (func(X, [A, B|S], [C|S]) :- F =.. [Y, B, A], catch(C is F, _, C=F))). % Symbolic math expressions are literals. literal(_+_). literal(_-_). literal(_*_). literal(_/_). literal(_ mod _). % Symbolic comparisons are literals. literal(_>_). literal(_<_). literal(_>=_). literal(_=<_). literal(_=:=_). literal(_=\=_). % Symbolic math. Compute the answer, or derivative, or whatever, later. math_operator(+). math_operator(-). math_operator(*). math_operator(/). math_operator(mod). % Attempt to calculate the value of a symbolic math expression. func(calc, [A|S], [B|S]) :- B is A. func(sqrt, [A|S], [sqrt(A)|S]). comparison_operator(>). comparison_operator(<). comparison_operator(>=). comparison_operator(<=, =<). comparison_operator(=, =:=). comparison_operator(<>, =\=).