Leandro  

I'll try to answer the following questions:

1. What is Caramel and why should I care?

2. What can we build with it?

3. How do I get involved?

is...

  1. an OCaml to Erlang Compiler
     
  2. a type-checker for Erlang

as an OCaml to Erlang compiler

Lets you write OCaml code



 

and generates type-safe Erlang code




 

 

(* file: hello.ml *)
let hello name = Io.format "Hello, ~p!" [name]
% Source code generated by Caramel.
-module(hello).
-export([hello/1]).
hello(Name) -> io:format(<<"Hello, ~p!">>, [Name|[]]).

that you can just run.

as an OCaml to Erlang compiler

It has some limitations:

let add () =
    let i = ref 0 in
    i := !i + 1;
    !i
class stack = object
  val mutable v = [0; 2]
  method pop = (* ... *)
  method push hd = (* ... *)
end

No Mutable State

No Classes

But we are used to this on the BEAM 😉

as an OCaml to Erlang compiler

And it lets you use the OCaml type-system to rule out things that should not happen.

let add x y = x + y

add "goodbye" 2020
    ^^^^^^^^^

This expression has type string but an expression was expected of type
       
       int

#1 - All functions always receive good arguments

as an OCaml to Erlang compiler

let user = User.make name in

User.promote user
             ^^^^
Error: This expression has type regular user
       but an expression was expected of type promotable user
       Type regular is not compatible with type promotable

#2 - Types can help us prevent bugs

as an OCaml to Erlang compiler

(** A user in our system. *)
type 'kind user = {
  (** the name of the user *)
  name: string
} 

let user = User.make "Joe"

user
- : regular user = {name = "Joe"}

#3 - Types can help explain our programs

% Source code generated with Caramel.
-module(user).

% A user in our system.
-type user(_Kind) :: #{
  % the name of the user
  name => binary()
}.

as an OCaml to Erlang compiler

type 'kind user = {
  name: string;
  (** new field added! *)
  age: int
} 

let make name = { name }
                ^^^^^^^^
Error: Some record fields are undefined: age

#3 - Types can help us refactor our programs

as an OCaml to Erlang compiler

Extends the OCaml compiler and provides a new compilation target:
 

.ml / .mli
sources

.erl
sources

world class type system with >25 years of industrial use
and research

as an OCaml to Erlang compiler

It inherits a lot from OCaml:

Built for speed and scale: companies like Jane Street compile millions of lines of OCaml code every day.

Sound and Correct: if the compiler says you're good to go, you're guaranteed no runtime errors.

Pragmatic: the type-system has evolved to be intuitive and usable in the industry.

OCaml to Erlang Compilation

as a type-checker for Erlang

You give it Erlang code, and it finds bugs:




 

 

-module(typed_send).

-export([start/0]).

loop(S) ->                                                                 
  receive                                                                        
    {replace, X} -> loop(X);                                               
    print -> print_int(S), loop(S)                                     
  end.                                                                           
                                                                                 
spawn_int(S) -> erlang:spawn(fun () -> loop(S) end).                             
                                                                                 
start() -> spawn_int(0) ! {replace, <<"wrong value">>}.  
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                          
Error: This expression has type [> `replace of string ]
       but an expression was expected of type [< `print | `replace of int ]
       Types for tag `replace are incompatible

It reuses the OCaml type-checker, by translating the Erlang sources into OCaml.

.erl
sources

OK

Type errors!

as a type-checker for Erlang

.ml

as a type-checker for Erlang

It has some limitations:

run(Mod, Fun) ->
  Mod:Fun([1,2,3]).
receive 
  X when is_integer(X) -> ok;
  _ -> err
end

No Dynamic Dispatch

No Untagged Case/Receive

We sometimes do this on the BEAM 🙈 

Typechecking Erlang as OCaml

What can we build with it?

Typed interfaces to existing code:

* OTP, Phoenix, Cowboy, Ecto

Business logic that needs to be airtight

Use it as building block for code generation:

* Generate JSON validation code

How do I get involved?

Caramel as an Ecosystem Bridging Project

+

=

🦄🚀

as an Ecosystem Bridging Project

Let all existing OCaml code run on the BEAM

Make it easy to reuse existing infrastructure

Bring more static safety to the BEAM

* direct compilation
* NIF generation

* typed interface generation
* type check and automated fixes to existing Erlang/Elixir code

* parsers for Erlang and Core Erlang

* tools that work at the Core Erlang level

* general libraries to build static analysis tools

as an Ecosystem Bridging Project

So far what we have built is:

Backend to the OCaml compiler

Infrastructure for building, testing, and publishing

Proof of concept for typed interface to Erlang stdlib

Library for working with Erlang sources from OCaml, which includes a Parser, an AST, and Printer for Standard Erlang

tree-sitter grammar for Standard Erlang (WIP)

Translations from the Erlang AST to the OCaml Parsetree that enables the Erlang type-checking

hex and rebar3 plugins

bindings to tree-sitter library to use new grammars for Erlang/Elixir

as an Ecosystem Bridging Project

But there's plenty to be done!

Verify compilation is sound by fuzzing the compiler

Better integration with build systems to leverage incremental type-checking and compilation

Wider surface area for typed interface to Stdlib and OTP

Improve OCaml libraries to manipulate CST and ASTs for Core Erlang and potentially Elixir as well

Finish tree-sitter grammar for Standard Erlang

Generate typed interfaces for any Elixir / Erlang library

NIF generation for OCaml code that can't be trivially ran on the BEAM

tree-sitter grammar for Elixir / Core Erlang

Build static analysis and refactoring tools that rely on types

Support ReasonML and ReScript syntax

as an Ecosystem Bridging Project

8 individual sponsors

1 company

7 fabulous contributors

(one without a picture!)

Thank you!

Introducing Caramel

By Leandro Ostera

Introducing Caramel

In this presentation I describe the current architecture of Caramel, the motivation for building it, and what is my vision for it as a language and tool.

  • 642