Skip to content

Instantly share code, notes, and snippets.

@abruzzi
Forked from Liutos/gist:3726523
Created October 7, 2015 12:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save abruzzi/6d936b6a8a56d41dac01 to your computer and use it in GitHub Desktop.
Save abruzzi/6d936b6a8a56d41dac01 to your computer and use it in GitHub Desktop.
照着垠神的λ-calculus解释器用CommonLisp写的
(defpackage :com.liutos.del0-interp
(:use :cl)
(:nicknames :del0-interp
:interp))
(in-package :interp)
(defvar *env0* '())
(defun ext-env (x v env)
(cons `(,x . ,v) env))
(defun lookup (x env)
(let ((p (assoc x env)))
(cond ((not p) x)
(t (cdr p)))))
(defclass closure ()
((f :initarg :f ;关键字符号:initarg是一个选项,它对应了后面的
;符号:f,意思是当使用make-instance实例化一个
;对象时,可以用:f来作为关键字参数给f这个成员变量
;设定一个值,如后面的make-instance调用所示。
:reader closure-f
;; :reader也是一个选项,它对应的符号是closure-f。这个选项的作用是让Lisp自动帮我们定义
;; 一个函数,它的名字是closure-f。把这个函数作用在closure类的实例上就可以得到成员变量
;; f的值了,所以后面写(closure-f v1)的意思是取出v1所指向的对象中的f这个成员变量的值。
)
(env :initarg :env
:reader closure-env)))
(defun interp1 (exp env)
(cond ((symbolp exp) (lookup exp env))
((numberp exp) exp)
((and (consp exp)
(eq 'lambda (car exp))
(consp (cadr exp)))
(make-instance 'closure :f exp :env env))
((and (consp exp)
(null (cddr exp)))
(destructuring-bind (e1 e2) exp
(let ((v1 (interp1 e1 env))
(v2 (interp1 e2 env)))
(if (typep v1 'closure)
(let ((e (caddr (closure-f v1)))
(x (caadr (closure-f v1)))
(env1 (closure-env v1)))
(interp1 e (ext-env x v2 env1)))))))
((and (consp exp)
(cddr exp)
(null (cdddr exp)))
(destructuring-bind (op e1 e2) exp
(let ((v1 (interp1 e1 env))
(v2 (interp1 e2 env)))
(case op
(+ (+ v1 v2))
(- (- v1 v2))
(* (* v1 v2))
(/ (/ v1 v2))))))))
(defun interp (exp)
(interp1 exp *env0*))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment