/* Evaluation of arithmetic expressions */
evalA(_, X, X) :- integer(X).
evalA(S, Var, Val) :-
	atom(Var),
	get(S, Var, Val).
evalA(S, Aexp1 - Aexp2, Val) :-
	evalA(S, Aexp1, Val1),
	evalA(S, Aexp2, Val2),
	Val is Val1 - Val2.
evalA(S, Aexp1 * Aexp2, Val) :-
	evalA(S, Aexp1, Val1),
	evalA(S, Aexp2, Val2),
	Val is Val1 * Val2.

/* Evaluation of boolean expressions. */
:- op(700, xfx, <=).
evalB(_, true, tt).
evalB(S, Aexp1 <= Aexp2, B) :-
	evalA(S, Aexp1, Val1),
	evalA(S, Aexp2, Val2),
	intLeq(Val1,Val2,B).
evalB(S, not(Bexp), B) :-
	evalB(S, Bexp, B1),
        boolNot(B1,B).
evalB(S, and(Bexp1,Bexp2), B) :-
	evalB(S, Bexp1, B1),
	evalB(S, Bexp2, B2),
	boolAnd(B1,B2,B).

/* Utility functions to work with tt and ff as the semantic true and false */
intLeq(Val1,Val2,tt) :- Val1 =< Val2.
intLeq(Val1,Val2,ff) :- Val1 > Val2.

boolNot(tt,ff).
boolNot(ff,tt).

boolAnd(ff,ff,ff).
boolAnd(ff,tt,ff).
boolAnd(tt,ff,ff).
boolAnd(tt,tt,tt).


/* Helper functions to use lists of tuples as associative lists. The get function always finds some value! */
set(S1, Var, Val, S2) :-
	list_to_assoc(S1, L1),
	put_assoc(Var, L1, Val, L2),
	assoc_to_list(L2, S2).

get(S1, Var, Val) :-
	list_to_assoc(S1, L1),
	get_assoc(Var, L1, Val),
	!.
get(_, _, 42).
