Please note, this is a STATIC archive of website www.tutorialspoint.com from 11 May 2019, cach3.com does not collect or store any user information, there is no "phishing" involved.
Tutorialspoint

Execute LISP Online

;; A simple LISP interpreter written by Dr Klefstad for ICS 141 at UCI
;; Of course, I deleted lots of it to let you learn more about evaluation.

;; my-assoc returns the association (binding) of a variable in the association
;; list.  An alist is a list of this form:
;; ((var1 . val1) (var2 . val2) ... (varN . valN))
;; where each vari is a symbol representing a variable (or parameter) name
;; and each vali is the value of the variable.
;; assoc returns the association of a given symbol, e.g,
;; (assoc 'myvar '((a . 10)(b a b c)(myvar d e f)))
;; returns (myvar d e f) and you take the cdr of that to get myvar's value
;; (d e f)
;; We will use alists for the stack of variables and their values.  Assoc
;; always finds the first association of a variable, and this is how we
;; implement dynamic scoping.  New defintions of a variable will hide older
;; definitions, but the older definitions will come back into scope when
;; recursive evaluation unwinds.
;; setq and defun will push a new association on the global-alist.
;; whenever we apply a function, we will bind the formals to the evaluated
;; actuals pushing these new bindings onto the local alist and then
;; evaluate the body of the function in that new scoping context.

;; You need to write this one.
(defun my-assoc (v alist)
    (cond
        ((null alist) nil)
        ((eq v (car (car alist))) (car alist))
        (t (my-assoc v (cdr alist)))
    )
)

;; This one is done
(defun my-eval (e alist)
    ; (write " in my-eval ")
    (cond ((atom e) (my-eval-atom e alist))
          (t (my-apply (car e) (cdr e) alist))
    )
)

(defun my-eval-atom (e alist)
    (cond
        ((null e) nil)
        ((symbolp e) (cdr (my-assoc e alist)))
        (t e)
    )
)

;; This one is done, but you must write the functions it calls
(defun my-apply (fn args alist)
    ; (write "in my-apply")
    (cond ((atom fn) (my-apply-atom fn args alist))
          ( t (my-apply-lambda fn args alist)))
)

(defun my-eval-list (l alist)
    (cond
        ((null (cdr l)) (my-eval (car l) alist))
        (t (my-eval (car l) alist) (my-eval-list (cdr l) alist))
    )
)

;; You need to write this one.
(defun my-apply-lambda (fn args alist)
    ; (write "in lambda!")
    (write fn)
    (write args)
    (write alist)
    (write-line "")
    (my-eval-list fn (my-bind-formals fn alist) args alist)
;; bind the formals to the evaluated actuals then evaluate the body in that
;; new scoping context (i.e., that becomes the new alist for recursive
;; evaluation of the function body.  Return the value of the last 
;; expression in the body (using eval-list).
)

;; You need to write this one.
(defun my-bind-formals (formals actuals alist)
    (cond
        ((null (car formals)) alist)
        ((null (car actuals)) alist)
        (t (my-bind-formals (cdr formals) (cdr actuals) (cons (cons (car formals) (my-eval (car actuals) alist)) alist)))
    )
;; This takes a list of formals and unevaluated actuals.  It should evaluate
;; each actual and bind it to its corresponding formal placing them all on
;; the front of the alist.  It should return the alist with the new bindings
;; on the front.  This will be used to evaluate calls to functions defined
;; via defun.
;; e.g., (my-bind-formals '(a) '((add 1 b)) '((b . 10)))
;; will return ((a . 11) (b . 10))
;; Note there will be one actual parameter for each formal parameter.
)

(defun my-apply-atom (fn args alist)
    ; (write "in my-apply-atom")
    (write args)
    (cond 
        ((eq fn 'eq)
           (eq (my-eval (car args) alist) (my-eval (cadr args) alist)))
          ;; I wrote the first one, eq, for you, you write the rest
          ((eq fn 'car)
            (car args)
          )
          ((eq fn 'cdr)
            (cdr args)
          )
          ((eq fn 'cons)
            (cons (car args) (cdr args))
          )
          ((eq fn 'quote)
            args
          )
          ((eq fn 'setq) (my-eval-setq (car args) (cadr args)))
          ;; these are (nearly) done, but you must write the sub-functions
          ((eq fn 'cond) (my-eval-cond args alist))
          ((eq fn 'defun) (my-eval-defun args alist))
          ((eq fn 'eval) (my-eval (my-eval (car args) alist) alist))
          (T (my-apply (my-assoc fn alist) args alist))
    )
)

(defun my-eval-setq (var val)
   (setq global-alist (cons (cons var val) global-alist))
)

;; You need to write this one.  You should know how cond works at this point.
(defun my-eval-cond (clauses alist)
    (write "in cond")
)

;; You need to write this one.
(defun my-eval-defun (body alist)
    (write "in defun")
    (my-eval-setq (car body) (cdr body))
;; just push the function body onto the global alist.  It is already an
;; association, e.g., (equal (L1 L2) (cond (...))) and (assoc 'equal in
;; the global alist will return this.  You can then take the cdr and you
;; have a list containing the formal parameters and the expressions in
;; the function body.
)

;; This one is done, it just initializes the global alist where global
;; settings, like those defined via setq and defun, go.
(setq global-alist nil)
;; to push a new value, (setq global-alist (cons (cons 'newvar 'newval) global-alist))

;; This one is done, it will become the new top-level for LISP.  After you
;; load this file, call (my-top) and then you can type in expressions and
;; define and call functions to test your my-eval.
(defun my-top ()
    (prog ()
        top (print (my-eval (read) global-alist))
            (terpri) ;; prints a newline
            (go top) ;; loops forever
    )
)


; (setq x 4)
; (write x)
(my-top)
; (defun X (A) A)
(defun X (A) A)
( X ' B )

; (write (MY-APPLY-LAMBDA 'X '((QUOTE B)) '((A . B) (X (A) A)) ))
; (write (MY-EVAL-LIST '(A) '((A . B) (X (A) A))))
; (write (my-eval '(eq 10 b) '((b . 10))))
; (write (my-bind-formals '(a) '((eq 10 b)) '((b . 10))))
; (write (my-eval-list '(10 x 8) global-alist))
; (write (my-eval-setq 'A 10))
; (write (my-apply-atom 'setq '(A 10) '(a )))
; (write (my-apply-atom 'quote '(a b c) '(a)))

Advertisements
Loading...

We use cookies to provide and improve our services. By using our site, you consent to our Cookies Policy.