Skip to content

Commit eb736af

Browse files
committed
Define defmacro to eval.l
1 parent bf7c0d8 commit eb736af

File tree

5 files changed

+60
-6
lines changed

5 files changed

+60
-6
lines changed

README.md

+17
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,23 @@ Lisp. You can run the FizzBuzz program like:
118118

119119
This takes very long time. For me, it took 45 minutes.
120120

121+
Though sedlisp.sed does not support defmacro, eval.l also defines
122+
defmacro:
123+
124+
$ ./evalify.rb | sed -f sedlisp.sed
125+
(defmacro let (l e) (cons (cons lambda (cons (cons (car l) nil) (cons e nil))) (cons (car (cdr l)) nil)))
126+
(let (x 42) (+ x 7)) ; Hit ^d after this.
127+
...
128+
49
129+
$ ./evalify.rb | sed -f sedlisp.sed
130+
(defun list0 (a) (cons a nil))
131+
(defun cadr (a) (car (cdr a)))
132+
(defmacro cond (l) (if l (cons if (cons (car (car l)) (cons (cadr (car l)) (cons (cons (quote cond) (list0 (cdr l))))))) nil))
133+
(defun fb (n) (cond (((eq (mod n 5) 0) "Buzz") ((eq (mod n 3) 0) "Fizz") (t n))))
134+
(fb 18) ; Hit ^d after this. This will take about one minute.
135+
...
136+
Fizz
137+
121138
Unfortunately, you cannot nest the eval one more time. This is
122139
probably a limitation of eval.l.
123140

eval.l

+17-3
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,14 @@
1818
(defun eval-val-1 (v s) (if (eq v NOT-FOUND) (eval-gval s) v))
1919
(defun eval-val (s) (eval-val-1 (table-get val-table s) s))
2020

21-
(defun eval-if (o s) (if (eq o if) (run-if s) (eval-defun o s)))
21+
(defun eval-if (o s) (if (eq o if) (run-if s) (eval-defmacro o s)))
22+
(defun eval-defmacro (o s) (if (eq o defmacro) (run-defmacro s) (eval-defun o s)))
2223
(defun eval-defun (o s) (if (eq o defun) (run-defun s) (eval-lambda o s)))
2324
(defun eval-lambda (o s) (if (eq o lambda) (run-lambda s) (eval-quote o s)))
2425
(defun eval-quote (o s) (if (eq o quote) (run-quote s) (eval-define o s)))
25-
(defun eval-define (o s) (if (eq o define) (run-define s) (eval-func (eval o) s)))
26+
(defun eval-define (o s) (if (eq o define) (run-define s) (eval-macro (eval o) s)))
27+
(defun is-macro (o) (if (atom o) nil (eq (car o) macro)))
28+
(defun eval-macro (o s) (if (is-macro o) (run-macro (cdr o) s) (eval-func o s)))
2629
(defun is-func (o) (if (atom o) nil (eq (car o) lambda)))
2730
(defun eval-func (o s) (if (is-func o) (run-func (cdr o) s) (eval-add o s)))
2831
(defun eval-add (o s) (if (eq o +) (run-add s) (eval-sub o s)))
@@ -40,6 +43,7 @@
4043
(defun undefined-func (o) (print (cons o (quote (undefined func)))))
4144

4245
(defun run-if (s) (if (eval (car s)) (eval (cadr s)) (eval (car (cddr s)))))
46+
(defun run-defmacro (s) (gval-table-add (car s) (cons macro (cdr s))))
4347
(defun run-defun (s) (gval-table-add (car s) (run-lambda (cdr s))))
4448
(defun run-lambda (s) (cons lambda s))
4549
(defun run-quote (s) (car s))
@@ -50,9 +54,16 @@
5054

5155
(defun run-func-2 (a b c) b)
5256
(defun run-func-1 (v l s) (run-func-2 (set-vals (car l) s) (eval (cadr l)) (define val-table v)))
53-
;(defun run-func-1 (v l s) (run-func-2 (set-vals (car l) s) (eval (cadr l)) (define val-table v)))
5457
(defun run-func (l s) (run-func-1 val-table l s))
5558

59+
(defun create-val-table-m (a p) (if a (cons (car a) (cons (car p) (create-val-table-m (cdr a) (cdr p)))) ()))
60+
(defun set-vals-m (a p) (define val-table (create-val-table-m a p)))
61+
62+
(defun run-macro-2 (a b c) b)
63+
(defun run-macro-1 (v l s) (run-macro-2 (set-vals-m (car l) s) (eval (cadr l)) (define val-table v)))
64+
65+
(defun run-macro (l s) (eval (run-macro-1 val-table l s)))
66+
5667
(defun run-add (s) (+ (eval (car s)) (eval (cadr s))))
5768
(defun run-sub (s) (- (eval (car s)) (eval (cadr s))))
5869
(defun run-mul (s) (* (eval (car s)) (eval (cadr s))))
@@ -122,3 +133,6 @@
122133
;(eval (quote (defun func2 (b) (+ (func) b))))
123134
;(eval (quote (defun func2 (b) (+ b (func 99)))))
124135
;(eval (quote (func2 42)))
136+
137+
(eval (quote (defmacro let (l e) (cons (cons lambda (cons (cons (car l) nil) (cons e nil))) (cons (car (cdr l)) nil)))))
138+
(eval (quote (let (x 42) x)))

purelisp.rb

+2-1
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,9 @@ def eval_sexpr(sexpr, vals)
118118
when 'print'
119119
raise "invalid print: #{stringify_sexpr(sexpr)}" if args.size != 1
120120
puts "PRINT: #{stringify_sexpr(args[0])}"
121-
p vals
122121
args[0]
122+
else
123+
raise "undefined function: #{op}"
123124
end
124125
end
125126

test.l

+12-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
;(- 34 7)
4545

4646
;(if 1 2 3)
47-
47+
1
4848
(+ 1(+ 1 1))
4949

5050
(+(- 9 2) 1)
@@ -145,3 +145,14 @@ foo
145145
(defun func (a b) b) ;cont
146146
(defun func2 (a b) (+ (func 2 3) b)) ;cont
147147
(func2 99 42)
148+
149+
; TEST EVAL
150+
151+
(defmacro let (l e) (cons (cons lambda (cons (cons (car l) nil) (cons e nil))) (cons (car (cdr l)) nil))) ;cont
152+
(let (x 42) (+ x 7))
153+
154+
(defun list0 (a) (cons a nil)) ;cont
155+
(defun cadr (a) (car (cdr a))) ;cont
156+
(defmacro cond (l) (if l (cons if (cons (car (car l)) (cons (cadr (car l)) (cons (cons (quote cond) (list0 (cdr l))))))) nil)) ;cont
157+
(defun fb (n) (cond (((eq (mod n 5) 0) Buzz) ((eq (mod n 3) 0) Fizz) (t n)))) ;cont
158+
(fb 18)

test.rb

+12-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
if ARGV[0] == '-e'
77
$evalify = true
88
ARGV.shift
9+
elsif ARGV[0] == '-E'
10+
$evalify = true
11+
$eval_test_only = true
12+
ARGV.shift
913
end
1014

1115
ref_lisp = ARGV[0] || 'purelisp.rb'
@@ -38,10 +42,17 @@ def getResult(cmd, line)
3842
if (/TEST LAMBDA/ =~ line &&
3943
(ref_lisp == 'rblisp.rb' || test_lisp == 'rblisp.rb'))
4044
break
45+
elsif /TEST EVAL/ =~ line
46+
$eval_test = true
47+
if !$evalify
48+
break
49+
end
4150
end
4251
next
4352
end
4453

54+
next if !$eval_test && $eval_test_only
55+
4556
while line =~ /;cont/
4657
line.sub!(/;cont/, '')
4758
line += lines[lineno += 1]
@@ -52,7 +63,7 @@ def getResult(cmd, line)
5263
line = evalify(line)
5364
end
5465

55-
expected = getResult(COMMANDS[ref_lisp], orig)
66+
expected = getResult(COMMANDS[ref_lisp], $eval_test ? line : orig)
5667
expected = expected.lines[-1].chomp
5768
output = getResult(COMMANDS[test_lisp], line)
5869
actual = output.lines[-1].chomp

0 commit comments

Comments
 (0)