; YourDSL - How to rewrite closures and primitives
; ------------------------------
; The Little Lisper 3rd Edition
; Chapter 10
; Exercise 5
; Common Lisp
; http://t...content-available-to-author-only...r.com/thelittlelisper
; http://t...content-available-to-author-only...t.com/2010/06/little-lisper-chapter-10-what-is-value.html
; http://t...content-available-to-author-only...t.com/2010/06/little-lisper.html
; ------------------------------
(defun build (a b)
(cons a (cons b '())))
(setf e4
'(3 (quote a)(quote b)))
(defun list-to-action (e)
(cond
((atom (car e))
(cond
((eq (car e) (quote quote))
'*quote)
((eq (car e) (quote lambda))
'*lambda)
((eq (car e) (quote cond))
'*cond)
(t '*application)))
(t '*application)))
(defun atom-to-action (e)
(cond
((numberp e) '*self-evaluating)
(t '*identifier)))
(defun expression-to-action (e)
(cond
((atom e) (atom-to-action e))
(t (list-to-action e))))
(defun meaning (e table)
(funcall (expression-to-action e) e table))
(defun value_ (e)
(meaning e (quote ())))
(defun *self-evaluating (e table)
e)
(defun *quote (e table)
(text-of-quotation e))
(defun text-of-quotation (l)
(second l))
(defun *identifier (e table)
(lookup-in-table
e table 'initial-table))
(defun initial-table (name)
(cond
((eq name (quote t)) t)
((eq name (quote nil)) nil)
(t (build
(quote primitive)
name))))
(defun lookup-in-table (name table table-f)
(cond
((null table) (funcall table-f name))
(t (lookup-in-entry
name
(car table)
(lambda (name)
(lookup-in-table
name
(cdr table)
table-f))))))
(defun lookup-in-entry (name entry entry-f)
(lookup-in-entry-help
name
(first entry)
(second entry)
entry-f))
(defun lookup-in-entry-help (name names values entry-f)
(cond
((null names) (funcall entry-f name))
((eq (car names) name)
(car values))
(t (lookup-in-entry-help
name
(cdr names)
(cdr values)
entry-f))))
(defun *application (e table)
(apply_
(meaning (function-of e) table)
(evlis (arguments-of e) table)))
(defun evcon (lines table)
(cond
((meaning
(question-of (car lines)) table)
(meaning
(answer-of (car lines)) table))
(t (evcon (cdr lines) table))))
(defun question-of (l)
(first l))
(defun answer-of (l)
(second l))
(defun *cond (e table)
(evcon (cond-lines e) table))
(defun cond-lines (l)
(cdr l))
(defun apply_ (fun vals)
(cond
((primitive? fun)
(apply-primitive
(second fun) vals))
((non-primitive? fun)
(apply-closure
(second fun) vals))))
(defun primitive? (l)
(eq
(first l)
(quote primitive)))
(defun non-primitive? (l)
(eq
(first l)
(quote non-primitive)))
(defun add1 (n)
(+ 1 n))
(defun apply-primitive (name vals)
(cond
((eq name (quote car))
(car (first vals)))
((eq name (quote cdr))
(cdr (first vals)))
((eq name (quote cons))
(cons (first vals) (second vals)))
((eq name (quote eq))
(eq (first vals) (second vals)))
((eq name (quote atom))
(atom (first vals) ))
((eq name (quote not))
(not (first vals) ))
((eq name (quote null))
(null (first vals) ))
((eq name (quote number))
(numberp (first vals) ))
((eq name (quote zero))
(zero (first vals) ))
((eq name (quote add1))
(add1 (first vals) ) )
((eq name (quote sub1))
(sub1 (first vals) )) ))
(defun function-of (l)
(car l))
(defun arguments-of (l)
(cdr l))
(defun evlis (args table)
(cond
((null args) (quote ()))
(t (cons (meaning (car args) table)
(evlis (cdr args) table)))))
(defun apply-closure (closure vals)
(meaning (body-of closure)
(extend-table
(new-entry
(formals-of closure) vals)
(table-of closure))))
(defun body-of (l)
(third l))
(defun extend-table (a b)
(cons a b))
(defun new-entry (a b)
(build a b))
(defun formals-of (l)
(second l))
(defun table-of (l)
(first l))
(defun *lambda (e table)
(build (quote non-primitive)
(cons table (cdr e))))
; ------------------------------
(initial-table 'bob)
; (primitive bob)
; hint from 10.6 that initial-table needs to be represented as functions...
(defun initial-table (name)
(cond
((eq name (quote t)) t)
((eq name (quote nil)) nil)
(t (build
(quote primitive)
name))))
(initial-table 'bob)
; (primitive bob)
; possible to rewrite this to be a stream of functions
;1. value
(print (value_ '(add1 1)) )
;=> 2
;2. -meaning
(meaning '(add1 1) '())
; 2
;3. -meaning
(expression-to-action '(add1 1))
; *application
;4.-meaning
(funcall '*application '(add1 1) '())
; 2
;5 -application
(function-of '(add1 1))
; ADD1
;6. -application
(meaning 'add1 '())
; (primitive add1)
;7. -application
(arguments-of '(add1 1))
; (1)
;8. -application
(evlis '(1) '())
; (1)
;9. -application
(apply_ '(primitive add1) '(1))
; 2
(print (value_ '((lambda (x) (add1 x)) 2)))
; 3
;(print (value_ e3))
; 6
(setf e3_
'((lambda (x)
(add1 4))
6))
(print (value_ e3_) )
; 5
(setf e3__
'((lambda (x)
(add1 x))
6))
(print (value_ e3__))
; 7
;1. value
(print (value_ '((lambda (x) (add1 x)) 6)))
; 7
;2. meaning
(meaning '((lambda (x) (add1 x)) 6) '())
; 7
;3. -meaning
(expression-to-action '((lambda (x) (add1 x)) 6))
; *application
;4.-meaning
(funcall '*application '((lambda (x) (add1 x)) 6) '())
; 7
;5 -application
(function-of '((lambda (x) (add1 x)) 6))
; (LAMBDA (X) (ADD1 X))
;6. -application
(meaning '(LAMBDA (X) (ADD1 X)) '())
;(NON-PRIMITIVE (NIL (X) (ADD1 X)))
;7. -application
(arguments-of '((lambda (x) (add1 x)) 6))
; (6)
;8. -application
(evlis '(6) '())
; (6)
;9. -application
(apply_ '(NON-PRIMITIVE (NIL (X) (ADD1 X))) '(6))
; 7
(meaning '(lambda) '())
;1. Basically the goal is to rewrite the __apply__ function so that the primitive and
;non-primitive tags are no longer needed
;2. The tags come from the __meaning__ function inside the __application__ function
;3. Need to rewrite the __initial-table__ function with the __meaning__ function to stop adding primitive and non-primitive flags
;4. Need to rewrite __apply__ so that it simply applies 'non-primitive to lambda functions
; and applies primitive to everything else
;5. And change __*lambda__ function not to return non-pritimive
;So __initial-table__ changes from
(defun initial-table (name)
(cond
((eq name (quote t)) t)
((eq name (quote nil)) nil)
(t (build
(quote primitive)
name))))
;to
(defun initial-table5 (name)
(cond
((eq name (quote t)) t)
((eq name (quote nil)) nil)
(t (cons name '()))))
(initial-table 'bob)
;(PRIMITIVE BOB)
(initial-table5 'bob)
;(BOB)
;and lambda becomes
(defun *lambda (e table)
(build (quote non-primitive)
(cons table (cdr e))))
(defun *lambda5 (e table)
(cons (cons table (cdr e)) '()))
(*lambda '(boris) '())
; (NON-PRIMITIVE (NIL))
(*lambda5 '(boris) '())
; ((NIL))
(defun list-to-action5 (e)
(cond
((atom (car e))
(cond
((eq (car e) (quote quote))
'*quote)
((eq (car e) (quote lambda))
'*lambda5)
((eq (car e) (quote cond))
'*cond)
(t '*application5)))
(t '*application5)))
(defun expression-to-action5 (e)
(cond
((atom e) (atom-to-action5 e))
(t (list-to-action5 e))))
(defun meaning5 (e table)
(funcall (expression-to-action5 e) e table))
(defun value5 (e)
(meaning5 e (quote ())))
(defun *identifier5 (e table)
(lookup-in-table
e table 'initial-table5))
(defun atom-to-action5 (e)
(cond
((numberp e) '*self-evaluating)
(t '*identifier5)))
(defun apply5 (fun vals)
(cond
((not (eq 'lambda (car fun)))
(apply-primitive
(second fun) vals))
((eq 'lambda (car fun))
(apply-closure
(second fun) vals))))
(defun *application5 (e table)
(apply5
(meaning (function-of e) table)
(evlis (arguments-of e) table)))
(print (value5 '(add1 1)))
;2
(print (value5 '((lambda (x) (add1 x)) 6)))
; NIL