%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% A Prolog implementation of the natural semantics 
%% for the While language (arithmetic expressions, really).                            


%%%%%%%%%%%%%%%%%%%%%
%% State operations

% lookup_state(State, Variable, Value)

lookup_state([(X,V)|_], X, V).
lookup_state([(Y,_)|S], X, V) :-
	Y \= X,
	lookup_state(S, X, V).

% update_state(State, Variable, Value, NewState)

update_state([], X, V, [(X,V)]).
update_state([(X,_)|S], X, V, [(X,V)|S]).
update_state([(Y,U)|S], X, V, [(Y,U)|S1]) :-
	Y \= X,
	update_state(S, X, V, S1).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Natural semantics of arithmetic expressions

% aexp_ns(Aexp, State, Number)

aexp_ns(num(N), _, N).

aexp_ns(var(X), S, N) :-
	lookup_state(S, X, N).

aexp_ns(add(A1,A2), S, N) :-
	aexp_ns(A1, S, N1),
	aexp_ns(A2, S, N2),
	N is N1 + N2.

aexp_ns(sub(A1,A2), S, N) :-
	aexp_ns(A1, S, N1),
	aexp_ns(A2, S, N2),
	N is N1 - N2.

aexp_ns(mul(A1,A2), S, N) :-
	aexp_ns(A1, S, N1),
	aexp_ns(A2, S, N2),
	N is N1 * N2.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Adding some syntactic sugar

% State

:- op(80, xfx, @).
(S,V) @ X :-
	lookup_state(S, X, V).

% Aexp

:- op(120, yfx, :+:).
:- op(120, yfx, :-:).
:- op(100, yfx, :*:).

% Semantics

:- op(180, xfx, --->).

(N, S) ---> N :-
	number(N).

(X, S) ---> N :-
	atom(X),
	(S,N) @ X.

(A1 :+: A2, S) ---> N :-
        (A1, S) ---> N1,
	(A2, S) ---> N2,
	N is N1 + N2.

(A1 :-: A2, S) ---> N :-
        (A1, S) ---> N1,
	(A2, S) ---> N2,
	N is N1 - N2.

(A1 :*: A2, S) ---> N :-
        (A1, S) ---> N1,
	(A2, S) ---> N2,
	N is N1 * N2.

%%%%%%%%
%% Eof
