-
Notifications
You must be signed in to change notification settings - Fork 0
/
lisp.ml
145 lines (122 loc) · 3.22 KB
/
lisp.ml
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
type atom = Symbol of string | Float of float | Int of int
| String of string
type lispval = Atom of atom | List of cons
and cons = Cons of lispval * lispval | Nil
exception Impossible of string
exception Type_mismatch
exception Sequence_expected
exception Void_function of string
exception Void_variable of string
exception Eval_error of string
exception Argument_mismatch
exception Setting_constant of string
let __dynlink_init_called = ref false
let load_library path =
if !__dynlink_init_called then
Dynlink.loadfile path
else
begin
Dynlink.init();
Dynlink.allow_unsafe_modules true;
__dynlink_init_called := true;
Dynlink.loadfile path
end
let quote v =
List(Cons(Atom(Symbol "quote"), List(Cons(v, List Nil))))
let rec iter_cons f cons =
match cons with
Cons(v, List c) -> (f v; iter_cons f c)
| Cons(v, Atom a) -> failwith "iter_cons: Can't iterate over a pair"
| Nil -> ()
let rec map_cons f cons =
match cons with
(* 'let' used to make f execute in the right order over the
elements of cons *)
Cons(v, List c) -> let result = f v in Cons(result, List(map_cons f c))
| Cons(v, Atom a) -> failwith "map_cons: Can't iterate over a pair"
| Nil -> Nil
let rec fold_left_cons f (init:lispval) cons =
match cons with
Cons(v, List c) ->
if c = Nil then
f init v
else
fold_left_cons f (f init v) c
| Cons(v, Atom a) -> failwith "fold_left_cons: Can't iterate over a pair"
| Nil -> init
(* car and cdr of nil are nil *)
let car c =
match c with
Cons(car, cdr) -> car
| Nil -> List Nil
let cdr c =
match c with
Cons(car, cdr) -> cdr
| Nil -> List Nil
let cdrlist c =
match c with
Cons(car, List cdr) -> cdr
| Nil -> Nil
| _ -> raise Sequence_expected
(* helper for returning a Lisp value from an OCaml boolean
expression *)
let generalised_bool b =
if b then
Atom(Symbol "t")
else
List Nil
let atomp v =
match v with
Atom _ -> true
| _ -> false
let symbolp v =
match v with
Atom(Symbol _) -> true
| _ -> false
let numberp v =
match v with
Atom(Int _) -> true
| Atom(Float _) -> true
| _ -> false
let consp v =
match v with
List(Cons(_, _)) -> true
| _ -> false
let listp v =
match v with
List(Cons(_, List _)) -> true
| _ -> false
let stringp v =
match v with
Atom(String _) -> true
| _ -> false
let nullp v =
match v with
List Nil -> true
| _ -> false
let truep v = not (nullp v)
let compatible_numbers_from_lispvals a b =
match a with
Atom(Int a_value) ->
begin
match b with
Atom(Int b_value) -> `Ints(a_value, b_value)
| Atom(Float b_value) -> `Floats(float_of_int a_value, b_value)
| _ -> raise Type_mismatch
end
| Atom(Float a_value) ->
begin
match b with
Atom(Int b_value) -> `Floats(a_value, float_of_int b_value)
| Atom(Float b_value) -> `Floats(a_value, b_value)
| _ -> raise Type_mismatch
end
| _ -> raise Type_mismatch
let lisp_list_of_caml_list l =
List.fold_right (fun a cons ->
Cons(a, List cons)
) l Nil
let caml_list_of_lisp_list cons =
let list = ref [] in
iter_cons (fun v -> list := v::!list) cons;
List.rev !list