You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have not found an easy way to lay out what a release for Caramel should look like, so I'm sketching out this issue with a a big checklist of stuff that I think could be somewhat usable for pure-OCaml modules.
To do this we need:
the core type language, excluding support for the fancier features of the type system (like GADTs, or universal quantification in records), so variants, records, tuples, and type parameters.
immutable, functional ocaml, excluding all the imperative and object-oriented features, and some features like recursive let bindings which have no direct translation to Erlang
enough pattern matching so we can work with all the values allowed by the core type languages
support for modules, but not as first class values, and without functors or inclusions
This could already be enough to write some OCaml on the BEAM successfully. We'll see once we get there.
Checklist
To make it easier to keep track of what's what and where we currently are, here's a list of the features that are currently working and missing. Where necessary I'll try to make separate issues and link them here.
Idioms
Empty tuple () is a common value in OCaml, this is translated to the atom ok in Erlang. This is not entirely idiomatic, since some functions are generated that take for last argument the atom ok, but it is much nicer for the returned values.
OCaml let rec's inside of a module-level function definition should be reported as errors. It is common in OCaml to define a recursive helper function to traverse a value using a default accumulator that is hidden from the user, but we can ask the programmer to move this outside for now. See Forbid let rec inside of a let binding #13
OCaml allows ' (prime) to be used as part of variable names, so it's not uncommon to see x and x' and x''. The equivalent Erlang would be X, X1, and X2, primarily because the single quote is not a valid character to have in a name. See Ensure OCaml variable names are translated to valid Erlang #15
OCaml allows shadowing of names, which is not supported in Erlang. so that let x = 1 in let x = x + 1 in x yields 2. The equivalent Erlang would crash. See Forbid name shadowing through let binding #16
Module System
The goal here is to support the basic OCaml module system, with its nesting and aliasing to provide a flexible and safe way of structuring large amounts of code. Module interfaces should be allowed to dictate what is exported and what isn't.
Modules definitions -- we treat files as modules, and we can create nested modules. Nested modules will be flattened out into separate Erlang modules namespacing the module names. Modules without exports should generate no Erlang sources.
Module interfaces -- interface files will be respected and anything that is not exported there will not be exported in the generated Erlang source. This applies to both types and functions.
Module Declarations -- only functions will be allowed at the module level. Defining values should be an compilation error.
Type Language
These are the features of the type-language that I'm aiming to support and compile to Dialyzer specs.
Type variables
Phantom types -- should be turned into an unused type-variable that will be properly named with an underscore.
Variants -- compiled into constructor_atom or {constructor_atom, arg0, arg1,...}
Polymorphic Variants
Explicit constructors -- compiled into constructor_atom or {constructor_atom, arg0, arg1,...}
Inherited constructors
Tuples
Aliases
Records
Function types
Interface files constrain exports of types
Expressions
The following expressions will be supported on the OCaml side
In order to continue building the standard library of FFIs to Erlang, I
had to add support to replace the name of a function for the appropriate
external name.
For example, the function `maps:new()` in Erlang would mean that we need
a function `Maps.new ()` in OCaml. This unfortunately won't work since
`new` is a reserved word.
However, by allowing the programmer to choose the final name to be used
by the FFI during the translation process, we can make the OCaml
function have a different name.
```ocaml
(* file: maps.ml *)
external make : unit -> map = "new"
```
Using `Maps.make ()` will compile to `maps:new()` in Erlang.
Works on #6
I'm thinking that the next milestone will include no more work on this particular compilation chain, but rather on the inverse process: parsing and type-checking Erlang.
Thanks @nyaray for the push there to scope things more clearly.
Summary
I have not found an easy way to lay out what a release for Caramel should look like, so I'm sketching out this issue with a a big checklist of stuff that I think could be somewhat usable for pure-OCaml modules.
To do this we need:
the core type language, excluding support for the fancier features of the type system (like GADTs, or universal quantification in records), so variants, records, tuples, and type parameters.
immutable, functional ocaml, excluding all the imperative and object-oriented features, and some features like recursive let bindings which have no direct translation to Erlang
enough pattern matching so we can work with all the values allowed by the core type languages
support for modules, but not as first class values, and without functors or inclusions
This could already be enough to write some OCaml on the BEAM successfully. We'll see once we get there.
Checklist
To make it easier to keep track of what's what and where we currently are, here's a list of the features that are currently working and missing. Where necessary I'll try to make separate issues and link them here.
Idioms
Empty tuple
()
is a common value in OCaml, this is translated to the atomok
in Erlang. This is not entirely idiomatic, since some functions are generated that take for last argument the atomok
, but it is much nicer for the returned values.OCaml let rec's inside of a module-level function definition should be reported as errors. It is common in OCaml to define a recursive helper function to traverse a value using a default accumulator that is hidden from the user, but we can ask the programmer to move this outside for now. See Forbid let rec inside of a let binding #13
OCaml allows
'
(prime) to be used as part of variable names, so it's not uncommon to seex
andx'
andx''
. The equivalent Erlang would beX
,X1
, andX2
, primarily because the single quote is not a valid character to have in a name. See Ensure OCaml variable names are translated to valid Erlang #15OCaml allows shadowing of names, which is not supported in Erlang. so that
let x = 1 in let x = x + 1 in x
yields 2. The equivalent Erlang would crash. See Forbid name shadowing through let binding #16Module System
The goal here is to support the basic OCaml module system, with its nesting and aliasing to provide a flexible and safe way of structuring large amounts of code. Module interfaces should be allowed to dictate what is exported and what isn't.
Modules definitions -- we treat files as modules, and we can create nested modules. Nested modules will be flattened out into separate Erlang modules namespacing the module names. Modules without exports should generate no Erlang sources.
Module interfaces -- interface files will be respected and anything that is not exported there will not be exported in the generated Erlang source. This applies to both types and functions.
Module Declarations -- only functions will be allowed at the module level. Defining values should be an compilation error.
Type Language
These are the features of the type-language that I'm aiming to support and compile to Dialyzer specs.
constructor_atom
or{constructor_atom, arg0, arg1,...}
constructor_atom
or{constructor_atom, arg0, arg1,...}
Expressions
The following expressions will be supported on the OCaml side
F
as a parameter, and passing a reference to a function. Waiting on Function references have the wrong arity #10match x with | 1 | 2 -> true
) -- Cascading match cases result in empty patterns #9Patterns
These are the patterns that we can use on the left side of match branches and function headers.
Foreign Interfaces
external
The text was updated successfully, but these errors were encountered: