Skip to content

Commit

Permalink
compiler: add support for record updates.
Browse files Browse the repository at this point in the history
This closes #23, taking use one step closer to v0.1
  • Loading branch information
leostera committed Oct 29, 2020
1 parent 7595b97 commit e1886c9
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 15 deletions.
37 changes: 24 additions & 13 deletions src/compiler/ocaml_to_erlang/fun.ml
Original file line number Diff line number Diff line change
Expand Up @@ -251,21 +251,32 @@ and mk_expression exp ~var_names ~modules ~functions ~module_name =
args
in
Expr.apply name args
(* NOTE: use `extended_expression` to provide map overrides *)
| Texp_record { fields; _ } ->
Expr.map
( fields |> Array.to_list
|> List.map (fun (field, value) ->
let value =
match value with
| Kept _ -> Error.unsupported_feature `Record_update
| Overridden (_, exp) ->
| Texp_record { fields; extended_expression; _ } -> (
let fields =
fields |> Array.to_list
|> List.filter_map (fun (field, value) ->
match value with
| Kept _ -> None
| Overridden (_, exp) ->
let value =
mk_expression exp ~var_names ~modules ~functions
~module_name
in
Expr.map_field
(Expr.const (Const.atom (Atom.mk field.lbl_name)))
value) )
in
let field =
Expr.map_field
(Expr.const (Const.atom (Atom.mk field.lbl_name)))
value
in
Some field)
in

match extended_expression with
| None -> Expr.map fields
| Some prior_map ->
Expr.map_update
(mk_expression prior_map ~var_names ~modules ~functions
~module_name)
fields )
| Texp_field (expr, _, { lbl_name; _ }) ->
let name =
let m = Atom.mk "maps" |> Name.atom in
Expand Down
4 changes: 2 additions & 2 deletions src/erlang/erl_printer.ml
Original file line number Diff line number Diff line change
Expand Up @@ -454,15 +454,15 @@ and pp_expression prefix ppf expr ~module_ =
match fields with
| [] -> Format.fprintf ppf "#{}"
| { mf_name; mf_value; _ } :: fs -> (
Format.fprintf ppf "#{ %a => " (pp_expression "" ~module_) mf_name;
Format.fprintf ppf "#{ %a := " (pp_expression "" ~module_) mf_name;
pp_expression "" ppf mf_value ~module_;
match fs with
| [] -> Format.fprintf ppf " }"
| fs ->
Format.fprintf ppf "\n";
fs
|> List.iter (fun { mf_name; mf_value; _ } ->
Format.fprintf ppf "%s, %a => " padding
Format.fprintf ppf "%s, %a := " padding
(pp_expression "" ~module_)
mf_name;
pp_expression "" ppf mf_value ~module_;
Expand Down
5 changes: 5 additions & 0 deletions tests/compiler/expressions.t/record_update.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
type t = { x: int; y: int; z: int }

let f () =
let a = { x=0; y=0; z=0 } in
{ a with x=2; y=2 }
26 changes: 26 additions & 0 deletions tests/compiler/expressions.t/run.t
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
match.ml
names.ml
names_primes.ml
record_update.ml
records.ml
$ caramelc compile apply.ml
File "apply.ml", line 6, characters 4-8:
Expand Down Expand Up @@ -587,3 +588,28 @@
$ cat let_rec.erl
cat: let_rec.erl: No such file or directory
[1]
$ caramelc compile record_update.ml
Compiling record_update.erl OK
$ cat record_update.erl
% Source code generated with Caramel.
-module(record_update).
-export_type([t/0]).

-export([f/0]).

-type t() :: #{ x => integer()
, y => integer()
, z => integer()
}.

-spec f() -> t().
f() ->
A = #{ x => 0
, y => 0
, z => 0
},
A#{ x := 2
, y := 2
}.


0 comments on commit e1886c9

Please sign in to comment.