diff --git a/Changes.md b/Changes.md index 446f7f532..20b3bb975 100644 --- a/Changes.md +++ b/Changes.md @@ -13,6 +13,8 @@ Unreleased ([#1164](https://github.com/melange-re/melange/pull/1164)) - Fix code generation of custom `true` / `false` constructors ([#1175](https://github.com/melange-re/melange/pull/1175)) +- Fix code generation of OCaml objects that refers to an init variable in scope + ([#1183](https://github.com/melange-re/melange/pull/1183)) 4.0.1 2024-06-07 --------------- diff --git a/flake.lock b/flake.lock index ce632f4e8..df8f1f610 100644 --- a/flake.lock +++ b/flake.lock @@ -28,11 +28,11 @@ ] }, "locked": { - "lastModified": 1727645950, - "narHash": "sha256-xJmVyAQ4FQyPojnUiuGpwfCTpVnTEO4jhxGIMDys4Ps=", + "lastModified": 1728189430, + "narHash": "sha256-uf5rHgvoWekml5HSquY2YtqQCC56oo7ML/HIuBrDHak=", "owner": "melange-re", "repo": "melange-compiler-libs", - "rev": "bd6a2fb5ec54936ba7aa789965f2af1d0f1e1bf4", + "rev": "5548a064ea3cfe7593676a22013fd81df7ee970f", "type": "github" }, "original": { @@ -64,11 +64,11 @@ "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1727987141, - "narHash": "sha256-wJLCtS1HhFhTBqN0+F2Wrcq/ilsbDvjzFTqejVN7xfg=", + "lastModified": 1728141961, + "narHash": "sha256-jKk4zhu8b5AvZnolb0IMlAk6jUd9kYGhUbIvBr+9OZI=", "owner": "nix-ocaml", "repo": "nix-overlays", - "rev": "614db0fa6bc7ee19b844f39ac944cebd45b38f4f", + "rev": "8a5d125c9e3c01cd26b489cba8c3424cfaf26704", "type": "github" }, "original": { @@ -79,17 +79,17 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1727968508, - "narHash": "sha256-2rDTgqMf84us7lARphOGRxnr5Q4nJ0RAQsCKYWeRsmI=", + "lastModified": 1728055773, + "narHash": "sha256-Fih2RMPboL+nuY7IEp3ujaCjLXLgFfoDQf+CT/GJdok=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "e873268a358f13746037e5ae3e88aa7aa626b9cf", + "rev": "d5f1752ca905354f763f2fab62e6139310b5ce91", "type": "github" }, "original": { "owner": "NixOS", "repo": "nixpkgs", - "rev": "e873268a358f13746037e5ae3e88aa7aa626b9cf", + "rev": "d5f1752ca905354f763f2fab62e6139310b5ce91", "type": "github" } }, diff --git a/test/blackbox-tests/objects-close-over-variable.t b/test/blackbox-tests/objects-close-over-variable.t new file mode 100644 index 000000000..86cec7dd2 --- /dev/null +++ b/test/blackbox-tests/objects-close-over-variable.t @@ -0,0 +1,104 @@ +Test classes that close over an init variable from the outside scope + + $ . ./setup.sh + $ cat > dune-project < (lang dune 3.9) + > (using melange 0.1) + > EOF + + $ cat > dune < (melange.emit + > (target out) + > (preprocess + > (pps melange.ppx))) + > EOF + + $ cat > x.ml < let fresh () = + > let r = 2 in + > let dummy = object + > val mutable x = r + > method get_x = x + > method set_x y = x <- y + > end in + > dummy + > let () = + > let f = (fresh()) in + > let x = f#get_x in + > Js.log2 "x expect 2" x; + > f#set_x 42 ; + > let y = f#get_x in + > Js.log2 "x expect 42" y; + > EOF + + $ dune build @melange + + $ node _build/default/out/x.js + x expect 2 2 + x expect 42 42 + + $ cat _build/default/out/x.js + // Generated by Melange + 'use strict'; + + const Caml_oo_curry = require("melange.js/caml_oo_curry.js"); + const CamlinternalOO = require("melange/camlinternalOO.js"); + const Curry = require("melange.js/curry.js"); + + const shared = [ + "set_x", + "get_x" + ]; + + const object_tables = { + TAG: /* Cons */0, + key: undefined, + data: undefined, + next: undefined + }; + + function fresh(param) { + if (!object_tables.key) { + const $$class = CamlinternalOO.create_table(shared); + const ids = CamlinternalOO.new_methods_variables($$class, shared, ["x"]); + const set_x = ids[0]; + const get_x = ids[1]; + const x = ids[2]; + CamlinternalOO.set_methods($$class, [ + get_x, + (function (self$1) { + return self$1[x]; + }), + set_x, + (function (self$1, y) { + self$1[x] = y; + }) + ]); + const env_init = function (env) { + const self = CamlinternalOO.create_object_opt(undefined, $$class); + self[x] = env[1]; + return self; + }; + CamlinternalOO.init_class($$class); + object_tables.key = env_init; + } + return Curry._1(object_tables.key, [ + undefined, + 2 + ]); + } + + const f = fresh(undefined); + + const x = Caml_oo_curry.js1(291546447, 1, f); + + console.log("x expect 2", x); + + Caml_oo_curry.js2(-97543333, 2, f, 42); + + const y = Caml_oo_curry.js1(291546447, 3, f); + + console.log("x expect 42", y); + + exports.fresh = fresh; + /* f Not a pure module */ diff --git a/vendor/melange-compiler-libs b/vendor/melange-compiler-libs index bd6a2fb5e..5548a064e 160000 --- a/vendor/melange-compiler-libs +++ b/vendor/melange-compiler-libs @@ -1 +1 @@ -Subproject commit bd6a2fb5ec54936ba7aa789965f2af1d0f1e1bf4 +Subproject commit 5548a064ea3cfe7593676a22013fd81df7ee970f