LexiFi / gen_js_api

Easy OCaml bindings for Javascript libraries
MIT License
177 stars 31 forks source link

Support recursive modules #153

Closed cannorin closed 3 years ago

cannorin commented 3 years ago

Closes #67.

We would want to bind to JS classes and TS interfaces as OCaml modules. However, classes and interfaces often have recursive references to each other, making it difficult to bind in OCaml.

class Foo {
  constructor(name) { this.name = name; }
  describe() { return "Foo:".concat(this.name); }
  toBar() { return new Bar(this.name); }
}

class Bar {
  constructor(name) { this.name = name; }
  describe() { return "Bar:".concat(this.name); }
  toBar() { return new Foo(this.name); }
}

This PR adds support for recursive modules as input. With this PR, we can easily bind to the above example as follows:

module [@js.scope "Foo"] rec Foo : sig
  type t = private Ojs.t
  val t_of_js: Ojs.t -> t
  val t_to_js: t -> Ojs.t
  val create: string -> t [@@js.create]
  val describe: t -> string [@@js.call "describe"]
  val to_bar: t -> Bar.t [@@js.call "toBar"]
end

and [@js.scope "Bar"] Bar : sig
  type t = private Ojs.t
  val t_of_js: Ojs.t -> t
  val t_to_js: t -> Ojs.t
  val create: string -> t [@@js.create]
  val describe: t -> string [@@js.call "describe"]
  val to_foo: t -> Foo.t [@@js.call "toFoo"]
end
cannorin commented 3 years ago

I will do that myself once I have a time but feel free to fix the missing newline at the end of file, I thought it would be added automatically by my editor but it didn't work.

mlasson commented 3 years ago

That's neat. Let's merge it !