Skip to content

Commit

Permalink
feat(compiler): disambiguate OCaml record names derived from Catala s…
Browse files Browse the repository at this point in the history
…truct
  • Loading branch information
EmileRolley committed Jul 12, 2022
1 parent 43eb4de commit 90e6b18
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 10 deletions.
33 changes: 23 additions & 10 deletions compiler/lcalc/to_ocaml.ml
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,15 @@ let avoid_keywords (s : string) : string =

let format_struct_name (fmt : Format.formatter) (v : Dcalc.Ast.StructName.t) :
unit =
Format.fprintf fmt "%s"
(avoid_keywords
(to_lowercase
(to_ascii (Format.asprintf "%a" Dcalc.Ast.StructName.format_t v))))
Format.asprintf "%a" Dcalc.Ast.StructName.format_t v
|> to_ascii
|> to_lowercase
|> avoid_keywords
|> String.split_on_char '_'
|> List.map String.capitalize_ascii
|> String.concat ""
|> Format.fprintf fmt "%s"
[@@ocamlformat "disable"]

let format_struct_field_name
(fmt : Format.formatter)
Expand Down Expand Up @@ -201,12 +206,13 @@ let rec format_typ (fmt : Format.formatter) (typ : Dcalc.Ast.typ Pos.marked) :
match Pos.unmark typ with
| TLit l -> Format.fprintf fmt "%a" Dcalc.Print.format_tlit l
| TTuple (ts, None) ->
(* TODO: what should be done here? *)
Format.fprintf fmt "@[<hov 2>(%a)@]"
(Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt "@ *@ ")
format_typ_with_parens)
ts
| TTuple (_, Some s) -> Format.fprintf fmt "%a" format_struct_name s
| TTuple (_, Some s) -> Format.fprintf fmt "%a.t" format_struct_name s
| TEnum ([t], e) when D.EnumName.compare e Ast.option_enum = 0 ->
Format.fprintf fmt "@[<hov 2>(%a)@] %a" format_typ_with_parens t
format_enum_name e
Expand Down Expand Up @@ -455,9 +461,16 @@ let format_ctx
(ctx : D.decl_ctx) : unit =
let format_struct_decl fmt (struct_name, struct_fields) =
if List.length struct_fields = 0 then
Format.fprintf fmt "type %a = unit@\n@\n" format_struct_name struct_name
Format.fprintf fmt
"module %a = struct@\n@[<hov 2>@ type t = unit\nend@] @\n"
format_struct_name struct_name
else
Format.fprintf fmt "type %a = {@\n@[<hov 2> %a@]@\n}@\n@\n"
Format.fprintf fmt
"module %a = struct@\n\
@[<hov 2>@ type t = {@\n\
@[<hov 2> %a@]@\n\
}\n\
end@]@\n"
format_struct_name struct_name
(Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt "@\n")
Expand Down Expand Up @@ -502,9 +515,9 @@ let format_ctx
(fun struct_or_enum ->
match struct_or_enum with
| Scopelang.Dependency.TVertex.Struct s ->
Format.fprintf fmt "%a@\n@\n" format_struct_decl (s, find_struct s ctx)
Format.fprintf fmt "%a@\n" format_struct_decl (s, find_struct s ctx)
| Scopelang.Dependency.TVertex.Enum e ->
Format.fprintf fmt "%a@\n@\n" format_enum_decl (e, find_enum e ctx))
Format.fprintf fmt "%a@\n" format_enum_decl (e, find_enum e ctx))
(type_ordering @ scope_structs)

let rec format_scope_body_expr
Expand Down Expand Up @@ -534,7 +547,7 @@ let rec format_scopes
Bindlib.unbind scope_def.scope_body.scope_body_expr
in
let scope_var, scope_next = Bindlib.unbind scope_def.scope_next in
Format.fprintf fmt "@\n@\n@[<hov 2>let %a (%a: %a) : %a =@\n%a@]%a"
Format.fprintf fmt "@\n@\n@[<hov 2>let %a (%a: %a.t) : %a.t =@\n%a@]%a"
format_var scope_var format_var scope_input_var format_struct_name
scope_def.scope_body.scope_body_input_struct format_struct_name
scope_def.scope_body.scope_body_output_struct
Expand Down
20 changes: 20 additions & 0 deletions tests/test_scope/good/191_fix_record_name_confusion.catala_en
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
## Article

```catala
declaration scope ScopeA:
context output a content boolean

declaration scope ScopeB:
context a content boolean
scopeA scope ScopeA

scope ScopeA:
definition a equals true

scope ScopeB:
definition a equals scopeA.a
```

```catala-test {id="OCaml"}
catala OCaml
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
(** This file has been generated by the Catala compiler, do not edit! *)

open Runtime

[@@@ocaml.warning "-4-26-27-32-41-42"]

module ScopeAOut = struct
type t = {
a_out: bool;
}
end

module ScopeAIn = struct
type t = {
a_in: unit -> bool;
}
end

module ScopeBOut = struct
type t = unit
end

module ScopeBIn = struct
type t = {
a_in: unit -> bool;
}
end



let scope_a (scope_a_in: ScopeAIn.t) : ScopeAOut.t =
let a_: unit -> bool = scope_a_in.a_in in
let a_: bool = (try
(handle_default ([|(fun (_: _) -> a_ ())|])
(fun (_: _) -> true)
(fun (_: _) ->
handle_default
([|(fun (_: _) ->
handle_default ([||]) (fun (_: _) -> true)
(fun (_: _) -> true))|])
(fun (_: _) -> false)
(fun (_: _) -> raise EmptyError))) with
EmptyError -> (raise (NoValueProvided
{filename = "tests/test_scope/good/191_fix_record_name_confusion.catala_en";
start_line=5; start_column=18;
end_line=5; end_column=19; law_headings=["Article"]}))) in
{a_out = a_}

let scope_b (scope_b_in: ScopeBIn.t) : ScopeBOut.t =
let a_: unit -> bool = scope_b_in.a_in in
let scope_a_dot_a_: unit -> bool = fun (_: unit) -> (raise EmptyError) in
let result_: ScopeAOut.t = ((scope_a) {a_in = scope_a_dot_a_}) in
let scope_a_dot_a_: bool = result_.a_out in
let a_: bool = (try
(handle_default ([|(fun (_: _) -> a_ ())|])
(fun (_: _) -> true)
(fun (_: _) ->
handle_default
([|(fun (_: _) ->
handle_default ([||]) (fun (_: _) -> true)
(fun (_: _) -> scope_a_dot_a_))|])
(fun (_: _) -> false)
(fun (_: _) -> raise EmptyError))) with
EmptyError -> (raise (NoValueProvided
{filename = "tests/test_scope/good/191_fix_record_name_confusion.catala_en";
start_line=8; start_column=11;
end_line=8; end_column=12; law_headings=["Article"]}))) in
()

0 comments on commit 90e6b18

Please sign in to comment.