-
Notifications
You must be signed in to change notification settings - Fork 0
/
ocamlilib.ml
219 lines (197 loc) · 9.44 KB
/
ocamlilib.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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
open Tinyocaml
open Ocamliutil
open Parsetree
let debug = ref false
let otherlibs = ref ""
let showstdlibinit = ref false
(* Beginning of what was ocamilib.ml *)
let load_stdlib = ref true
let stdlib_dir =
let tname = Filename.temp_file "ocaml" "ocamli" in
ignore (Sys.command ("ocamlc -config >" ^ tname));
let tmp = open_in tname in
let line = ref "" in
try
while true do
let s = input_line tmp in
if
String.length s >= 18 &&
String.sub s 0 18 = "standard_library: "
then
line := s
done;
assert false
with
End_of_file ->
close_in tmp;
Sys.remove tname;
if !line <> "" then
(Filename.dir_sep ^
(String.sub !line 19 (String.length !line - 19)))
else
raise (Failure "could not find standard library")
(* Read the definitions from a loaded module, so they can be put into the
environment. *)
let rec add_prefix_to_pattern f = function
PatVar v -> PatVar (f v)
| PatTuple ps -> PatTuple (List.map (add_prefix_to_pattern f) ps)
| PatArray ps -> PatArray (Array.map (add_prefix_to_pattern f) ps)
| x -> x (* FIXME: Fill in the rest *)
let add_prefix_to_binding name (pattern, e) =
if name = "" then (pattern, e) else (* pervasives *)
(add_prefix_to_pattern (fun x -> name ^ "." ^ x) pattern, e)
(* Prefix the type name and type constructors *)
let add_prefix_to_constructor name c =
match c with
{pcd_name = ({txt} as n)} -> {c with pcd_name = {n with txt = name ^ "." ^ txt}}
let add_prefix_to_ptype_kind name = function
| Ptype_abstract -> Ptype_abstract
| Ptype_variant constructors ->
Ptype_variant (List.map (add_prefix_to_constructor name) constructors)
| Ptype_record record -> Ptype_record record (* FIXME *)
| Ptype_open -> Ptype_open
let add_prefix_to_typedecl name typedecl =
{typedecl with
ptype_name = {typedecl.ptype_name with txt = name ^ "." ^ typedecl.ptype_name.txt};
ptype_kind = add_prefix_to_ptype_kind name typedecl.ptype_kind}
let add_prefix_to_bindings name envitem =
match envitem with
EnvBinding (recflag, bindings) ->
EnvBinding(recflag, ref (List.map (add_prefix_to_binding name) !bindings))
| EnvFunctor (n, i, a, b, c) ->
if name = ""
then EnvFunctor (n, i, a, b, c) (* pervasives *)
else EnvFunctor (name ^ "." ^ n, i, a, b, c)
| EnvType (recflag, typedecls) ->
if name = ""
then EnvType (recflag, typedecls) (*pervasives *)
else EnvType (recflag, List.map (add_prefix_to_typedecl name) typedecls)
let rec definitions_of_module (env : Tinyocaml.env) = function
Struct (_, items) ->
List.flatten
(List.map
(fun x ->
match x with
LetDef (recflag, bindings) -> [EnvBinding (recflag, ref bindings)]
| TypeDef t -> [EnvType t]
| ModuleBinding (name, (Struct (_, items) as themod)) ->
load_module_from_struct name env themod
| ModuleBinding (name, Functor (fname, ftype, fcontents)) ->
[EnvFunctor (name, fname, ftype, fcontents, [])] (* FIXME env?*)
| _ -> [])
items)
| s ->
failwith (Printf.sprintf "definitions_of_module: found a %s" (Tinyocaml.to_string s))
and load_module_from_struct name (env : Tinyocaml.env) themod : Tinyocaml.env =
let themod = Eval.eval_until_value !showstdlibinit false env themod in (* <-- module initialisation *)
List.rev (List.map (add_prefix_to_bindings name) (definitions_of_module env themod))
and load_module (name : string) (env : Tinyocaml.env) (file : string) : Tinyocaml.env =
if !debug then Printf.printf "Loading module %s...%!" name;
let themod = snd (Tinyocamlrw.of_real_ocaml env (ast ~filename:(filename_of_modname name) (load_file file))) in
if !debug then Printf.printf "read...%!";
let r = load_module_from_struct name env themod in
if !debug then Printf.printf "done\n%!";
r
and load_module_from_text (name : string) (env : Tinyocaml.env) (text : string) : Tinyocaml.env =
if !debug then Printf.printf "Loading module from text %s...%!" name;
let themod = snd (Tinyocamlrw.of_real_ocaml env (ast ~filename:(filename_of_modname name) text)) in
if !debug then Printf.printf "read...%!";
let r = load_module_from_struct name env themod in
if !debug then Printf.printf "done\n%!";
r
let otherlib_modules () =
[("Unix", !otherlibs ^ Filename.dir_sep ^ "unix", "unix.ml");
(*("Num", !otherlibs, "num.ml");*) (* Not_found *)
(*("Str", !otherlibs, "str.ml");*) (* modinit fails *)
(*("Threads", !otherlibs, "thread.ml");*) (* not clear what files to use *)
(*("Graphics", !otherlibs, "graphics.ml");*) (* slow... *)
("Bigarray", !otherlibs ^ Filename.dir_sep ^ "bigarray", "bigarray.ml")]
(*let stdlib_modules () =
[("Example", "./stdlib", "example.ml")]*)
(* We use an old stdlib for now -- new stdlib/pervasives stuff to be dealt with *)
let stdlib_dir = "/Users/john/repos/ocamli/stdlib"
let stdlib_modules () =
[("StdLabels", stdlib_dir, "stdLabels.ml");
("MoreLabels", stdlib_dir, "moreLabels.ml");
("StringLabels", stdlib_dir, "stringLabels.ml");
("BytesLabels", stdlib_dir, "bytesLabels.ml");
("ListLabels", stdlib_dir, "listLabels.ml");
("ArrayLabels", stdlib_dir, "arrayLabels.ml");
("Complex", stdlib_dir, "complex.ml");
("Filename", stdlib_dir, "filename.ml");
("Emphemeron", stdlib_dir, "ephemeron.ml");
("Genlex", stdlib_dir, "genlex.ml");
("CamlinternalMod", stdlib_dir, "camlinternalMod.ml");
("Oo", stdlib_dir, "oo.ml");
("CamlinternalOO", stdlib_dir, "camlinternalOO.ml");
("Callback", stdlib_dir, "callback.ml");
(*("Scanf", "./stdlib", "scanf.ml"); (* let-refactoring will fix. See programs/scanf_fail.ml *)*)
("Uchar", stdlib_dir, "uchar.ml");
(*("Format", "./stdlib", "format.ml");*)
("Weak", stdlib_dir, "weak.ml");
("Hashtbl", stdlib_dir, "hashtbl.ml");
("Random", stdlib_dir, "random.ml");
("Digest", stdlib_dir, "digest.ml");
("Gc", stdlib_dir, "gc.ml");
("Printexc", stdlib_dir, "printexc.ml");
("Arg", stdlib_dir, "arg.ml");
("Printf", stdlib_dir, "printf.ml");
("CamlinternalFormat", stdlib_dir, "camlinternalFormat.ml");
("Buffer", stdlib_dir, "buffer.ml");
("Stream", stdlib_dir, "stream.ml");
("Lazy", stdlib_dir, "lazy.ml");
("CamlinternalLazy", stdlib_dir, "camlinternalLazy.ml");
("Queue", stdlib_dir, "queue.ml");
("Stack", stdlib_dir, "stack.ml");
("Map", stdlib_dir, "map.ml");
("Set", stdlib_dir, "set.ml");
("Parsing", stdlib_dir, "parsing.ml");
("Lexing", stdlib_dir, "lexing.ml");
("Nativeint", stdlib_dir, "nativeint.ml");
("Int64", stdlib_dir, "int64.ml");
("Int32", stdlib_dir, "int32.ml");
("Array", stdlib_dir, "array.ml");
("Obj", stdlib_dir, "obj.ml");
("Marshal", stdlib_dir, "marshal.ml");
("Sort", stdlib_dir, "sort.ml");
("String", stdlib_dir, "string.ml");
("Bytes", stdlib_dir, "bytes.ml");
("Char", stdlib_dir, "char.ml");
("List", stdlib_dir, "list.ml");
("Sys", stdlib_dir, "sys.ml");
("", "/Users/john/repos/ocamli/stdlib", "pervasives.ml"); (* The special empty strng *)
("Pervasives", "/Users/john/repos/ocamli/stdlib", "pervasives.ml");
("CamlinternalFormatBasics", stdlib_dir, "camlinternalFormatBasics.ml")]
let loadlib () =
List.fold_right
(fun (n, lib, filename) libs ->
load_module n libs (Filename.concat lib filename) @ libs)
((if !otherlibs <> "" then otherlib_modules () else []) @ stdlib_modules ())
[]
let load_library () =
let t = !Ocamliutil.typecheck in
Ocamliutil.typecheck := false;
if !load_stdlib then Eval.lib := loadlib ();
Ocamliutil.typecheck := t
(* Load some modules, given a module name and a string for each *)
let load_library_modules modules =
List.fold_left
(fun libs (n, text) ->
load_module_from_text n libs text @ libs)
!Eval.lib (* <- initial libs from standard library which has already been loaded *)
modules
let print_binding (pat, e) =
Printf.printf "%s = %s\n" (to_string_pat pat) (Pptinyocaml.to_string e)
let showlib () =
if !debug then
List.iter
(fun envitem ->
match envitem with
EnvBinding (recflag, bindings) ->
print_string (if recflag then "let rec:\n" else "let:\n");
List.iter print_binding !bindings
| EnvFunctor (n, i, a, b, c) ->
print_string "EnvFunctor: "; print_string n; print_string "\n"
| EnvType t ->
print_string "EnvType")
!Eval.lib