; This file provides some concrete Lisp implementations for Tennent-style
; denotational definitions, as discussed in Notes 10.
;

; Here's a definition of a store as the kind of alist we use in Assignment 6.
;
(setq store-as-alist '( (x 10) (y 20) (z 30) ))


; Here's an equivalent definition of a store, Tennent-style as a function.
;
(defun store-as-function (ident)
    (cond ( (eq ident 'x) 10 )
	  ( (eq ident 'y) 20 )
	  ( (eq ident 'z) 30 )
	  ( t 'error )
    )
)


; Here's an equality check to demonstrate that the two stores are equivalent.
;
(eq (cadr (assoc 'y store-as-alist))
    (store-as-function 'y))

; In Lisp, the preceding definition of store-as-function cannot be "perturbed"
; to add new bindings, as Tennent does with his functions.  This is easy enough
; to fix, by defining the functional store as follows.
;
(setq store-as-perturbable-function
  '(lambda (ident)
    (cond ( (eq ident 'x) 10 )
	  ( (eq ident 'y) 20 )
	  ( (eq ident 'z) 30 )
	  ( t 'error )
    )
  )
)


; Here's another equality check to show that this perturbable function store is
; equivalent to the previous two store representations.  Notice that we must
; use Lisp apply, since Common Lisp does not allow us to apply a lambda form
; directly to its arguments.  This is just a mild syntactic weakness of
; (Common) Lisp.
;
(eq (cadr (assoc 'y store-as-alist))
    (apply store-as-perturbable-function '(y)))


; Now, here's a concrete implementation of Tennent's perturb operation.  Using
; this function, an application of Tennent's perturb function like this
;
;    s [ w |-> 40 ]
;
; looks like this in Lisp
;
;    (perturb s 'w 40).
;
(defun perturb (f arg val)
    (let ((arg-name (caadr f))
	  (func-body (cdaddr f)))
	(list 'lambda (list arg-name)
	      (cons 'cond
		    (cons (cons (list 'eq arg-name (list 'quote arg))
				(list val))
			  func-body
		    )
	      )
	)
    )
)

; Here's an equality check to show that looking up in a modified alist store is
; equivalent to applying a perturbed functional store.
;
(eq (cadr (assoc 'w (cons '(w 40) store-as-alist)))
    (apply (perturb store-as-perturbable-function 'w 40) '(w)))


; Based on the preceding definitions, here are partial definitions for
; Tennent's command execution (script C) and expression evaluation (script E)
; functions.  These definitions work for execution of assignment statements and
; evaluation of identifiers.  The Lisp definitions are very close
; transliterations of Tennent's definitions in Notes 10.
;

; Here's script C for the assignment statement case.
;
(defun command-exec (cmd u s)
    (cond ((is-assmnt cmd)
	   (let ((d (apply u (list (car cmd))))
		 (e (expr-eval (caddr cmd) u s)))
	       (if (and (question-mark d 'L) (question-mark e 'R))
		   (perturb s (car d) (list 'quote e))
		   'error
	       )
	    ) )
	  (t 'whatever)
    )
)	 
		   
; Here's script E for the identifier case.
;
(defun expr-eval (expr u s)
    (cond ( (is-ident expr)
	    (let ((d (apply u (list expr))))
		(if (question-mark d 'L)
		    (apply s (list (car d)))
		    (if (question-mark d 'R)
			d
			'error
		    )
		 )
	     ) )
	  ( (is-basic-val expr)
	    (list expr 'R) )
	  (t 'whatever)
    )
)

; Here's the tag-checking question mark operator.
;
(defun question-mark (binding type)
    (eq (cadr binding) type)
)

; Here are a couple functions to do a little bit of what Tennent's' double
; bracket operators do.  We don't need much given the limited syntax we're
; dealing with.
;
(defun is-assmnt (cmd)
    (eq (cadr cmd) ':=)
)
(defun is-ident (expr)
    (symbolp expr)
)
(defun is-basic-val (expr)
    (or (numberp expr) (eq expr t) (eq expr nil))
)

; To test the preceding defs, here are sample environment and store values.
; They represent an environment with integer variables x, y, and z declared,
; and a store with x assigned the value 10, and y and z unused.
(setq env
  '(lambda (ident)
    (cond ( (eq ident 'x) '(loc-0 L) )
	  ( (eq ident 'y) '(loc-1 L) )
	  ( (eq ident 'z) '(loc-2 L) )
	  ( t 'error )
    )
  )
)

(setq store
  '(lambda (loc)
    (cond ( (eq loc 'loc-0) '(10 R) )
	  ( (eq loc 'loc-1) 'unused )
	  ( (eq loc 'loc-2) 'unused )
	  ( t 'error )
    )
  )
)


; Here's what the evaluation of "y := x" looks like.
;
(command-exec '(y := x) env store)


; Since (command-exec '(y := x) env store) returns a store, if we apply it
; to 'loc-1 as follows, we get (10 R).
;
(apply (command-exec '(y := x) env store) '(loc-1))

;
; This is as cool as it gets in semantic definitions.  It is the fully formal
; juncture of operational and denotational semantics.  And it's achievable to
; this degree of simplicity and elegance nowhere but in Lisp.  If you
; understand what's going on here, then you understand the fundamental
; semantics of programming languages, and you hold in your hands the key to the
; deep understanding of any programming language yet invented by humankind.
;