Skip to content

Commit 76d362c

Browse files
committed
various small updates
* new js_of_ocaml toplevel execution model * minor changes to iocaml exception reporting (still a buffer fill up problem though) * makefile stuff for 64-32 bit compilation + core_kernel tests new notebooks require bigarray updates.
1 parent 6c3f43e commit 76d362c

File tree

7 files changed

+27
-21
lines changed

7 files changed

+27
-21
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@
22
*~
33
.ipynb_checkpoints
44
notebooks/.ipynb_checkpoints
5+
static/services/kernels/js/kernel.*.js
6+
static/services/kernels/js/kernel.js

Makefile

+11-3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
# 1. PACKAGES - a set of ocamlfind packages
2929
# 2. SYNTAX - a set of ocamlfind syntax extensions
3030
# 3. MODULES - module names to keep
31+
# 4. PRIMJS - extra javascript primtives
3132
#
3233
# Note; the syntax extensions in step 2 are linked in not run
3334
# Note; to specify more than one package separate with spaces
@@ -41,17 +42,21 @@
4142
#######################################################################
4243
# configuration
4344

45+
#JSC=/home/andyman/.opam/4.01.0-test/bin/js_of_ocaml
46+
JSC=js_of_ocaml
47+
4448
# js_of_ocaml
4549
ifeq ($(OPT),1)
4650
JS_OF_OCAML_OPTS=-opt 2 noinline -linkall
4751
else
48-
JS_OF_OCAML_OPTS=-noinline -linkall
52+
JS_OF_OCAML_OPTS=-noinline -linkall -pretty -debuginfo -tc none
4953
endif
5054

5155
JS_FILES= \
5256
$(shell ocamlfind query js_of_ocaml)/runtime.js \
5357
$(shell ocamlfind query js_of_ocaml)/weak.js \
54-
toplevel_runtime.js
58+
$(shell ocamlfind query js_of_ocaml)/toplevel.js \
59+
$(PRIMJS)
5560

5661
# Compiler libs
5762
COMPILER_LIBS=ocamlcommon.cma ocamlbytecomp.cma ocamltoplevel.cma
@@ -129,6 +134,9 @@ full:
129134
min:
130135
make all OPT=1 EXT=".min"
131136

137+
core:
138+
make all EXT=".core" PACKAGES="core_kernel" PRIMJS="core_runtime.js" MODULES="Core_kernel"
139+
132140
#######################################################################
133141
# build
134142

@@ -169,7 +177,7 @@ iocaml.byte: iocaml_full.byte
169177
$(KEEP_MODULES) $(MODULES)
170178

171179
iocaml.js: iocaml.byte $(JS_FILES)
172-
js_of_ocaml -toplevel -noruntime $(JS_OF_OCAML_OPTS) \
180+
$(JSC) -toplevel -noruntime $(JS_OF_OCAML_OPTS) \
173181
$(USER_PACKAGES_INC) \
174182
$(SYNTAX_INC) $(CAMLP4_LIBS_INC) \
175183
-I . $(COMPILER_LIBS_INC) $(JS_FILES) \

core_runtime.js

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
//Provides: unix_gethostname
2+
//Requires: caml_new_string
3+
function unix_gethostname() {
4+
return caml_new_string('localhost');
5+
}

exec.ml

+2-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ let run_cell_lb execution_count lb =
5656
| Ok(false) -> Error(Buffer.contents buffer) :: out_messages
5757
| Error(Sys.Break) -> Error("Interrupted.") :: out_messages
5858
| Error(exn) ->
59-
Error(try get_error_info exn with _ -> "Execution error.") :: out_messages
59+
Error(try get_error_info exn
60+
with _ -> ("IOcaml execution error: " ^ Printexc.to_string exn)) :: out_messages
6061
end
6162
in
6263
List.rev (run [] phrases)

iocaml.ml

+5-17
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,6 @@ module Compile = struct
4343
split beg (cur + 1) in
4444
Array.of_list(split 0 0)
4545

46-
class type global_data = object
47-
method compile : (string -> string) Js.writeonly_prop
48-
method auto_register_file_ : (string -> int) Js.writeonly_prop
49-
end
50-
51-
external global_data : unit -> global_data Js.t = "caml_get_global_data"
52-
let g = global_data ()
53-
5446
let () = Topdirs.dir_directory "/cmis"
5547

5648
let initial_primitive_count =
@@ -93,7 +85,7 @@ module Compile = struct
9385
let res = String.concat "" !stubs ^ res in
9486
res
9587
in
96-
g##compile <- compile (*XXX HACK!*)
88+
Js.Unsafe.global##toplevelCompile <- compile (*XXX HACK!*)
9789
end
9890

9991
module Base64 = struct
@@ -218,6 +210,7 @@ let execute execution_count str =
218210
v
219211

220212
let load_from_server path =
213+
try
221214
let xml = XmlHttpRequest.create () in
222215
let () = xml##_open(Js.string "GET", Js.string ("file/" ^ path), Js._false) in
223216
let () = xml##send(Js.null) in
@@ -231,13 +224,8 @@ let load_from_server path =
231224
Some(str)
232225
else
233226
None
234-
235-
let auto_register_file name =
236-
match load_from_server name with
237-
| None -> 0
238-
| Some(content) ->
239-
let () = Sys_js.register_file ~name ~content in
240-
1
227+
with _ ->
228+
None
241229

242230
let send_stdout_message s w =
243231
if Js.Opt.test ipython##notebook && Js.Opt.test ipython##notebook##kernel then
@@ -257,7 +245,7 @@ let send_clear ?(wait=true) ?(stdout=true) ?(stderr=true) ?(other=true) () =
257245

258246
let main () =
259247
(* automatically query server for files *)
260-
Compile.g##auto_register_file_ <- auto_register_file;
248+
Sys_js.register_autoload "" load_from_server;
261249
(*let ipython : _iPython Js.t = Js.Unsafe.variable "IPython" in*)
262250
Firebug.console##log (Js.string "iocamljs");
263251
(* re-direct output to the notebook *)

notebooks/iocamljs-bigarray.ipynb

+1
Large diffs are not rendered by default.

notebooks/iocamljs-core_kernel.ipynb

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"metadata":{"name":"","language":"ocaml"},"worksheets":[{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Loading core_kernel with js_of_ocaml\n\nThe following session is run using the iocamljs `min` kernel compiled using a 32 bit OCaml toolchain on a 64 bit host given [here](https://github.com/andrewray/opam/tree/master/compilers/4.01.0/4.01.0%2B32bit). The final `js_of_ocaml` compilation step is done with a 64 bit version of the `js_of_ocaml` compiler due to a [problem](https://github.com/ocsigen/js_of_ocaml/issues/133) with the 32 bit version.\n\nI have also been able to run the following to the same extent with a full 64 bit build, however, that requires various patches to bin_prot (32 bit bit patterns like `0x8000_0000` get marshalled in the `.cmo/a` files as 64 bit constants, which cannot be unmarshalled by js_of_ocaml - replacing them with code like `1 lsl 31` fixes it but it's a kludge)."},{"metadata":{},"input":"#use \"topfind\"","cell_type":"code","prompt_number":1,"outputs":[{"text":"- : unit = ()\n","output_type":"stream","stream":"stdout"},{"text":"Findlib has been successfully loaded. Additional directives:\n #require \"package\";; to load a package\n #list;; to list the available packages\n #camlp4o;; to load camlp4 (standard syntax)\n #camlp4r;; to load camlp4 (revised syntax)\n #predicates \"p,q,...\";; to set these predicates\n Topfind.reset();; to force that packages will be reloaded\n #thread;; to enable threads\n","output_type":"stream","stream":"stdout"},{"text":"\n","output_type":"stream","stream":"stdout"},{"text":"- : unit = ()\n","output_type":"stream","stream":"stdout"}],"language":"python","collapsed":false},{"metadata":{},"input":"#require \"unix,bigarray,dynlink,type_conv\"","cell_type":"code","prompt_number":2,"outputs":[{"text":"/home/andyman/.opam/4.01.0+32bit/lib/ocaml/unix.cma: loaded\n","output_type":"stream","stream":"stderr"},{"text":"/home/andyman/.opam/4.01.0+32bit/lib/ocaml/bigarray.cma: loaded\n","output_type":"stream","stream":"stderr"},{"text":"/home/andyman/.opam/4.01.0+32bit/lib/ocaml/dynlink.cma: loaded\n","output_type":"stream","stream":"stderr"},{"text":"/home/andyman/.opam/4.01.0+32bit/lib/ocaml/camlp4: added to search path\n","output_type":"stream","stream":"stderr"},{"text":"/home/andyman/.opam/4.01.0+32bit/lib/type_conv: added to search path\n","output_type":"stream","stream":"stderr"}],"language":"python","collapsed":false},{"metadata":{},"input":"#require \"bin_prot\"","cell_type":"code","prompt_number":3,"outputs":[{"text":"/home/andyman/.opam/4.01.0+32bit/lib/bin_prot: added to search path\n","output_type":"stream","stream":"stderr"},{"text":"/home/andyman/.opam/4.01.0+32bit/lib/bin_prot/bin_prot.cma: loaded\n","output_type":"stream","stream":"stderr"}],"language":"python","collapsed":false},{"metadata":{},"input":"#require \"variantslib,sexplib\"","cell_type":"code","prompt_number":4,"outputs":[{"text":"/home/andyman/.opam/4.01.0+32bit/lib/variantslib: added to search path\n","output_type":"stream","stream":"stderr"},{"text":"/home/andyman/.opam/4.01.0+32bit/lib/variantslib/variantslib.cma: loaded\n","output_type":"stream","stream":"stderr"},{"text":"/home/andyman/.opam/4.01.0+32bit/lib/sexplib: added to search path\n","output_type":"stream","stream":"stderr"},{"text":"/home/andyman/.opam/4.01.0+32bit/lib/sexplib/sexplib.cma: loaded\n","output_type":"stream","stream":"stderr"}],"language":"python","collapsed":false},{"metadata":{},"input":"#require \"fieldslib,pa_bench,oUnit,pa_ounit\"","cell_type":"code","prompt_number":5,"outputs":[{"text":"/home/andyman/.opam/4.01.0+32bit/lib/fieldslib: added to search path\n","output_type":"stream","stream":"stderr"},{"text":"/home/andyman/.opam/4.01.0+32bit/lib/fieldslib/fieldslib.cma: loaded\n","output_type":"stream","stream":"stderr"},{"text":"/home/andyman/.opam/4.01.0+32bit/lib/pa_bench: added to search path\n","output_type":"stream","stream":"stderr"},{"text":"/home/andyman/.opam/4.01.0+32bit/lib/pa_bench/pa_bench_lib.cma: loaded\n","output_type":"stream","stream":"stderr"},{"text":"/home/andyman/.opam/4.01.0+32bit/lib/oUnit: added to search path\n","output_type":"stream","stream":"stderr"},{"text":"/home/andyman/.opam/4.01.0+32bit/lib/oUnit/oUnitAdvanced.cma: loaded\n","output_type":"stream","stream":"stderr"},{"text":"/home/andyman/.opam/4.01.0+32bit/lib/oUnit/oUnit.cma: loaded\n","output_type":"stream","stream":"stderr"},{"text":"/home/andyman/.opam/4.01.0+32bit/lib/pa_ounit: added to search path\n","output_type":"stream","stream":"stderr"},{"text":"/home/andyman/.opam/4.01.0+32bit/lib/pa_ounit/pa_ounit_lib.cma: loaded\n","output_type":"stream","stream":"stderr"}],"language":"python","collapsed":false},{"metadata":{},"input":"#require \"typerep_lib\"","cell_type":"code","prompt_number":2,"outputs":[{"text":"/home/andyman/.opam/4.01.0+32bit/lib/typerep_lib: added to search path\n","output_type":"stream","stream":"stderr"},{"text":"/home/andyman/.opam/4.01.0+32bit/lib/typerep_lib/typerep_lib.cma: loaded\n","output_type":"stream","stream":"stderr"},{"text":"Exception: Failure \"TypeError: Cannot read property '1' of undefined\".\n","output_type":"stream","stream":"stdout"}],"language":"python","collapsed":false},{"metadata":{},"input":"#require \"core_kernel\"","cell_type":"code","prompt_number":7,"outputs":[{"text":"/home/andyman/.opam/4.01.0+32bit/lib/enumerate: added to search path\n","output_type":"stream","stream":"stderr"},{"text":"/home/andyman/.opam/4.01.0+32bit/lib/core_kernel: added to search path\n","output_type":"stream","stream":"stderr"},{"text":"/home/andyman/.opam/4.01.0+32bit/lib/core_kernel/raise_without_backtrace.cma: loaded\n","output_type":"stream","stream":"stderr"},{"text":"/home/andyman/.opam/4.01.0+32bit/lib/core_kernel/core_kernel.cma: loaded\n","output_type":"stream","stream":"stderr"},{"html":"<pre style=\"color:red;max-height:100px;overflow:hidden\" \nonclick=\"\nif (this.style.maxHeight === 'none') \n this.style.maxHeight = '100px';\nelse\n this.style.maxHeight = 'none'; \n\">File &quot;[7]&quot;, line 1:\nError: Reference to undefined global `Typerep_lib'\n</pre>","output_type":"pyout","prompt_number":7,"metadata":{}}],"language":"python","collapsed":false},{"metadata":{},"cell_type":"markdown","source":"So `typerep_lib` fails to load with a javascript exception which in turn stops core_kernel from loading."},{"metadata":{},"cell_type":"markdown","source":"# Buiding typerep_lib\n\nfrom `_build/_log`\n\n```\nocamlfind ocamlc -pack -g \n lib/named_intf.cmo \n lib/type_equal.cmo \n lib/typename.cmo \n lib/variant_and_record_intf.cmo \n lib/std_internal.cmo \n lib/make_typename.cmo \n lib/typerepable.cmo \n lib/type_abstract.cmo \n lib/type_generic_intf.cmo \n lib/type_generic.cmo \n lib/typerep_obj.cmo \n lib/std.cmo \n -o lib/typerep_lib.cmo\n```\n\nTry loading each of the `.cmo` files one at a time to find the bad module."},{"metadata":{},"input":"#directory \"/home/andyman/dev/github/forks/typerep/_build/lib\"","cell_type":"code","prompt_number":1,"outputs":[],"language":"python","collapsed":false},{"metadata":{},"input":"#load \"named_intf.cmo\"","cell_type":"code","prompt_number":2,"outputs":[],"language":"python","collapsed":false},{"metadata":{},"input":"#load \"type_equal.cmo\"","cell_type":"code","prompt_number":5,"outputs":[],"language":"python","collapsed":false},{"metadata":{},"input":"Type_equal.conv","cell_type":"code","prompt_number":6,"outputs":[{"html":"<pre style=\"color:slategray;max-height:100px;overflow:hidden\" \nonclick=\"\nif (this.style.maxHeight === 'none') \n this.style.maxHeight = '100px';\nelse\n this.style.maxHeight = 'none'; \n\">- : ('a, 'b) Type_equal.t -&gt; 'a -&gt; 'b = &lt;fun&gt;\n</pre>","output_type":"pyout","prompt_number":6,"metadata":{}}],"language":"python","collapsed":false},{"metadata":{},"input":"#load \"typename.cmo\"","cell_type":"code","prompt_number":7,"outputs":[],"language":"python","collapsed":false},{"metadata":{},"input":"#load \"variant_and_record_intf.cmo\"","cell_type":"code","prompt_number":8,"outputs":[],"language":"python","collapsed":false},{"metadata":{},"input":"#load \"std_internal.cmo\"","cell_type":"code","prompt_number":9,"outputs":[{"text":"Exception: Failure \"TypeError: Cannot read property '1' of undefined\".\n","output_type":"stream","stream":"stdout"}],"language":"python","collapsed":false},{"metadata":{},"cell_type":"markdown","source":"So our problems start in `std_internal.cmo`."},{"metadata":{},"input":"#load \"make_typename.cmo\"","cell_type":"code","outputs":[],"language":"python","collapsed":false},{"metadata":{},"input":"#load \"typerepable.cmo\"","cell_type":"code","outputs":[],"language":"python","collapsed":false},{"metadata":{},"input":"#load \"type_abstract.cmo\"","cell_type":"code","outputs":[],"language":"python","collapsed":false},{"metadata":{},"input":"#load \"type_generic_intf.cmo\"","cell_type":"code","outputs":[],"language":"python","collapsed":false},{"metadata":{},"input":"#load \"type_generic.cmo\"","cell_type":"code","outputs":[],"language":"python","collapsed":false},{"metadata":{},"input":"#load \"typerep_obj.cmo\"","cell_type":"code","outputs":[],"language":"python","collapsed":false},{"metadata":{},"input":"#load \"std.cmo\"","cell_type":"code","outputs":[],"language":"python","collapsed":false},{"metadata":{},"cell_type":"markdown","source":"My suspicion is it is the recursive module defined in `std_internal`. Lets have a play."},{"metadata":{},"input":"module Typename = struct\n type 'a t\nend\nmodule Type_equal = struct\n type ('a,'b) t\nend\n\nmodule rec Typerep : sig\n\n type _ t =\n | Int : int t\n | Int32 : int32 t\n | Int64 : int64 t\n | Nativeint : nativeint t\n | Char : char t\n | Float : float t\n | String : string t\n | Bool : bool t\n | Unit : unit t\n | Option : 'a t -> 'a option t\n | List : 'a t -> 'a list t\n | Array : 'a t -> 'a array t\n | Lazy : 'a t -> 'a Lazy.t t\n | Ref : 'a t -> 'a ref t\n (*| Function : ('dom t * 'rng t) -> ('dom -> 'rng) t\n | Tuple : 'a Typerep.Tuple.t -> 'a t\n | Record : 'a Typerep.Record.t -> 'a t\n | Variant : 'a Typerep.Variant.t -> 'a t\n | Named : ('a Typerep.Named.t * 'a t Lazy.t option) -> 'a t*)\n module Named : sig\n module type T0 = sig\n type named\n type t\n val typename_of_named : named Typename.t\n val typename_of_t : t Typename.t\n val witness : (t, named) Type_equal.t\n end\n type 'a t = T0 of (module T0 with type t = 'a)\n val arity : _ t -> int\n end\nend = struct\n\n type _ t =\n | Int : int t\n | Int32 : int32 t\n | Int64 : int64 t\n | Nativeint : nativeint t\n | Char : char t\n | Float : float t\n | String : string t\n | Bool : bool t\n | Unit : unit t\n | Option : 'a t -> 'a option t\n | List : 'a t -> 'a list t\n | Array : 'a t -> 'a array t\n | Lazy : 'a t -> 'a Lazy.t t\n | Ref : 'a t -> 'a ref t\n (*| Function : ('dom t * 'rng t) -> ('dom -> 'rng) t\n | Tuple : 'a Typerep.Tuple.t -> 'a t\n | Record : 'a Typerep.Record.t -> 'a t\n | Variant : 'a Typerep.Variant.t -> 'a t\n | Named : ('a Typerep.Named.t * 'a t Lazy.t option) -> 'a t*)\n\n module Named = struct\n module type T0 = sig\n type named\n type t\n val typename_of_named : named Typename.t\n val typename_of_t : t Typename.t\n val witness : (t, named) Type_equal.t\n end\n type 'a t = T0 of (module T0 with type t = 'a)\n let arity = function T0 _ -> 0 \n end\n \nend","cell_type":"code","prompt_number":25,"outputs":[{"html":"<pre style=\"color:slategray;max-height:100px;overflow:hidden\" \nonclick=\"\nif (this.style.maxHeight === 'none') \n this.style.maxHeight = '100px';\nelse\n this.style.maxHeight = 'none'; \n\">module Typename : sig type 'a t end\n</pre>","output_type":"pyout","prompt_number":25,"metadata":{}},{"html":"<pre style=\"color:slategray;max-height:100px;overflow:hidden\" \nonclick=\"\nif (this.style.maxHeight === 'none') \n this.style.maxHeight = '100px';\nelse\n this.style.maxHeight = 'none'; \n\">module Type_equal : sig type ('a, 'b) t end\n</pre>","output_type":"pyout","prompt_number":25,"metadata":{}},{"html":"<pre style=\"color:red;max-height:100px;overflow:hidden\" \nonclick=\"\nif (this.style.maxHeight === 'none') \n this.style.maxHeight = '100px';\nelse\n this.style.maxHeight = 'none'; \n\">Exception: Failure &quot;TypeError: Cannot read property '1' of undefined&quot;.\n</pre>","output_type":"pyout","prompt_number":25,"metadata":{}}],"language":"python","collapsed":false},{"metadata":{},"cell_type":"markdown","source":"The error comes with the addition of the `arity` function.\n\nLets try to simplify a bit."},{"metadata":{},"input":"module rec Typerep : sig\n module Named : sig\n module type T0 = sig\n type named\n type t\n end\n type 'a t = T0 of (module T0 with type t = 'a)\n val arity : _ t -> int\n end\nend = struct\n module Named = struct\n module type T0 = sig\n type named\n type t\n end\n type 'a t = T0 of (module T0 with type t = 'a)\n let arity = function T0 _ -> 0 \n end\n \nend","cell_type":"code","prompt_number":2,"outputs":[{"output_type":"pyout","prompt_number":2,"html":"<pre style=\"color:red;max-height:100px;overflow:hidden\" \nonclick=\"\nif (this.style.maxHeight === 'none') \n this.style.maxHeight = '100px';\nelse\n this.style.maxHeight = 'none'; \n\">Exception: Failure &quot;TypeError: Cannot read property '1' of undefined&quot;.\n</pre>","metadata":{}}],"language":"python","collapsed":false},{"metadata":{},"cell_type":"markdown","source":"Remove the `rec`"},{"metadata":{},"input":"module Typerep : sig\n module Named : sig\n module type T0 = sig\n type named\n type t\n end\n type 'a t = T0 of (module T0 with type t = 'a)\n val arity : _ t -> int\n end\nend = struct\n module Named = struct\n module type T0 = sig\n type named\n type t\n end\n type 'a t = T0 of (module T0 with type t = 'a)\n let arity = function T0 _ -> 0 \n end\n \nend","cell_type":"code","prompt_number":4,"outputs":[{"output_type":"pyout","prompt_number":4,"html":"<pre style=\"color:slategray;max-height:100px;overflow:hidden\" \nonclick=\"\nif (this.style.maxHeight === 'none') \n this.style.maxHeight = '100px';\nelse\n this.style.maxHeight = 'none'; \n\">module Typerep :\n sig\n module Named :\n sig\n module type T0 = sig type named type t end\n type 'a t = T0 of (module T0 with type t = 'a)\n val arity : 'a t -&gt; int\n end\n end\n</pre>","metadata":{}}],"language":"python","collapsed":false},{"metadata":{},"input":"","cell_type":"code","outputs":[],"language":"python","collapsed":false}],"metadata":{}}],"nbformat":3,"nbformat_minor":0}

0 commit comments

Comments
 (0)