代码拉取完成,页面将自动刷新
写一个主流语言的编译器非常困难,仅仅前端Parser的工作量就很大。直到看到 这个项目rui314/minilisp 。
用Java实现一个这样的Lisp解释器应该很有趣。
目前的版本包含了如下特性,
(+ 1 2) ;; -> 3
cons组成一个cell
(define pair (cons 'a 'b))
(println pair) ;; -> (a . b)
(println (car pair)) ;; -> a
(println (cdr pair)) ;; -> b
define关键字定义一个变量,println打印结果。
(if (= 1 1)
(println 'yes)
(println 'no)) ;; -> yes
(define i 0)
(define array ())
(while (<= i 3)
(setq array (cons i array))
(setq i (+ i 1)))
(println array) ;; -> (3 2 1 0)
用defun关键字定义函数
(defun add (x y)
(+ x y))
(println (add 1 2)) ;; -> 3
可以进行参数的匹配,因为 (1 2) <=> (1 . (2))
, 所以当形参是 (x . y)
的时候,
x 为 1,y 为 (2)。
(defun list (x . y)
(println x)
(println y)
(cons x y))
(define arr (list 1 2))
;;x -> 1
;;y -> (2)
(println arr) ;; -> (1 2)
再看一个例子,形参是(x . (y z))
匹配 (1 2 3)
的话,结果是 x -> 1,y -> 2, z -> 3
(defun match ( x . ( y z ))
(println x)
(println y)
(println z))
(match 1 2 3)
;; x -> 1
;; y -> 2
;; z -> 3
每次执行都有结果返回,但是默认不打印。所以需要调用println来对返回的结果进行打印。
;; A countup function. We use lambda to introduce local variables because we
;; do not have "let" and the like.
(define counter
((lambda (count)
(lambda ()
(setq count (+ count 1))
count)) ;;
0))
(println (counter)) ; -> 1
(println (counter)) ; -> 2
;; This will not return 12345 but 3. Variable "count" in counter function
;; is resolved based on its lexical context rather than dynamic context.
(println ((lambda (count) (counter)) 12345)) ; -> 3
defmacro关键字定义一个宏。unless是一个宏。list是一个工具函数,会生成一个list expression。macroexpand是一个函数,实现对宏的扩展。
(defun list (x . y)
(cons x y))
(defmacro unless (condition expr)
(list 'if condition () expr))
(define x 0)
(println (unless (= x 0) '(x is not 0))) ; -> ()
(println (unless (= x 1) '(x is not 1))) ; -> (x is not 1)
(println (macroexpand '(unless (= x 1) '(x is not 1))))
;; -> (if (= x 1) () '(x is not 1))
该项目是基于Java8和maven的,所以环境要首先支持。
进入项目根目录,运行如下命令
~/work/minilisp/$ ./bin/package.sh
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< com.threelambda:minilisp >----------------------
[INFO] Building minilisp 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
......
......
~/work/minilisp/$ ./bin/hello.sh
(hello word)
~/work/minilisp/$ ./bin/run.sh
(println 'hello)
hello
nqueens.lisp来自于rui314/minilisp 。 但是我修改了几个地方,因为实现的有点不同。以下是4皇后的解法。
~/work/minilisp/$ ./bin/run.sh < examples/nqeens.lisp
start
(x @ x x)
(x x x @)
(@ x x x)
(x x @ x)
$
(x x @ x)
(@ x x x)
(x x x @)
(x @ x x)
$
done
(define name 'ym)
(define put println)
(put name) ;; -> ym
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。