-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathbuiltins.ml
More file actions
156 lines (139 loc) · 3.71 KB
/
builtins.ml
File metadata and controls
156 lines (139 loc) · 3.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
open Sexp
open Environment
let tee = (Atom "#T")
let nil = cons Null Null
let fn_car args _ = car (car args)
let fn_cdr args _ = cdr (car args)
let fn_quote args _ = car args
let fn_cons args _ =
let lst = cons (car args) Null in
let rec loop a =
match a with
Cons (_) ->
begin
append lst (car a) ;
loop (cdr a)
end
| _ -> lst
in
loop (car (cdr args))
let fn_setcar args _ =
let first = car args in
let second = car (cdr args) in
(match first with
Cons (c) ->
c.car <- second
| _ -> invalid_arg "First argument to setcar must be a Cons") ;
tee
let fn_setcdr args _ =
let first = car args in
let second = car (cdr args) in
(match first with
Cons (c) ->
c.cdr <- second
| _ -> invalid_arg "First argument to setcdr must be a Cons") ;
tee
let fn_equal args _ =
let first = car args in
let second = car (cdr args) in
if (name first) = (name second) then
tee
else
nil
let fn_atom args _ =
match (car args) with
Atom (_) -> tee
| _ -> nil
let rec fn_lambda args env =
let lambda = (car args) in
let rest = (cdr args) in
match lambda with
Lambda (largs, lsexp) ->
let lst = interleave largs rest in
let sexp = replace_atom lsexp lst in
eval sexp env
| _ -> invalid_arg "Argument to lambda must be a Lambda"
and eval sexp env =
match sexp with
Null -> nil
| Cons (_) ->
(match (car sexp) with
Atom ("LAMBDA") ->
let largs = car (cdr sexp) in
let lsexp = car (cdr (cdr sexp)) in
Lambda (largs, lsexp)
| _ ->
let acc = cons (eval (car sexp) env) Null in
let rec loop s =
match s with
Cons (_) ->
append acc (eval (car s) env) ;
loop (cdr s)
| _ -> ()
in
loop (cdr sexp) ;
eval_fn acc env)
| _ ->
let v = Symtab.lookup env (name sexp) in
match v with
Null -> sexp
| _ -> v
and eval_fn sexp env =
let symbol = car sexp in
let args = cdr sexp in
match symbol with
Lambda (_) ->
fn_lambda sexp env
| Func (fn) ->
(fn args env)
| _ -> sexp
let fn_cond args env =
let rec loop a =
match a with
Cons (_) ->
begin
let lst = car a in
let pred = (if (car lst) != nil then
eval (car lst) env
else
nil)
in
let ret = car (cdr lst) in
if pred != nil then
eval ret env
else
loop (cdr a)
end
| _ -> nil
in
loop args
let fn_label args env =
Symtab.add env (name (car args))
(car (cdr args)) ;
tee
let rec lisp_print sexp =
match sexp with
Null -> ()
| Cons (_) ->
begin
print_string "(" ;
lisp_print (car sexp) ;
let rec loop s =
match s with
Cons (_) ->
print_string " " ;
lisp_print (car s) ;
loop (cdr s)
| _ -> ()
in
loop (cdr sexp) ;
print_string ")" ;
end
| Atom (n) ->
print_string n
| Lambda (largs, lsexp) ->
print_string "#" ;
lisp_print largs ;
lisp_print lsexp
| _ ->
print_string "Error."