94 lines
2.6 KiB
Plaintext
94 lines
2.6 KiB
Plaintext
|
|
|
|
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(<>, =\=).
|
|
|
|
|
|
|