summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/bytecode_util.ml7
-rw-r--r--src/c_backend.ml16
-rw-r--r--test/c/option_nest.expect1
-rw-r--r--test/c/option_nest.sail18
4 files changed, 33 insertions, 9 deletions
diff --git a/src/bytecode_util.ml b/src/bytecode_util.ml
index fa41e1e1..4320e945 100644
--- a/src/bytecode_util.ml
+++ b/src/bytecode_util.ml
@@ -626,6 +626,11 @@ let cdef_map_instr f = function
| CDEF_spec (id, ctyps, ctyp) -> CDEF_spec (id, ctyps, ctyp)
| CDEF_type tdef -> CDEF_type tdef
+let ctype_def_map_ctyp f = function
+ | CTD_enum (id, ids) -> CTD_enum (id, ids)
+ | CTD_struct (id, ctors) -> CTD_struct (id, List.map (fun (field, ctyp) -> (field, f ctyp)) ctors)
+ | CTD_variant (id, ctors) -> CTD_variant (id, List.map (fun (field, ctyp) -> (field, f ctyp)) ctors)
+
(** Map over each ctyp in a cdef using map_instr_ctyp *)
let cdef_map_ctyp f = function
| CDEF_reg_dec (id, ctyp, instrs) -> CDEF_reg_dec (id, f ctyp, List.map (map_instr_ctyp f) instrs)
@@ -634,7 +639,7 @@ let cdef_map_ctyp f = function
| CDEF_startup (id, instrs) -> CDEF_startup (id, List.map (map_instr_ctyp f) instrs)
| CDEF_finish (id, instrs) -> CDEF_finish (id, List.map (map_instr_ctyp f) instrs)
| CDEF_spec (id, ctyps, ctyp) -> CDEF_spec (id, List.map f ctyps, f ctyp)
- | CDEF_type tdef -> CDEF_type tdef (* FIXME *)
+ | CDEF_type tdef -> CDEF_type (ctype_def_map_ctyp f tdef)
(* Map over all sequences of instructions contained within an instruction *)
let rec map_instrs f (I_aux (instr, aux)) =
diff --git a/src/c_backend.ml b/src/c_backend.ml
index d79a2957..62310f60 100644
--- a/src/c_backend.ml
+++ b/src/c_backend.ml
@@ -1781,7 +1781,7 @@ let flatten_instrs =
| cdef -> cdef
-let rec specialize_variants ctx =
+let rec specialize_variants ctx prior =
let unifications = ref (Bindings.empty) in
@@ -1859,8 +1859,8 @@ let rec specialize_variants ctx =
} in
let cdefs = List.map (cdef_map_ctyp (map_ctyp (fix_variant_ctyp var_id new_ctors))) cdefs in
- let cdefs, ctx = specialize_variants ctx cdefs in
- CDEF_type (CTD_variant (var_id, new_ctors)) :: cdefs, ctx
+ let prior = List.map (cdef_map_ctyp (map_ctyp (fix_variant_ctyp var_id new_ctors))) prior in
+ specialize_variants ctx (CDEF_type (CTD_variant (var_id, new_ctors)) :: prior) cdefs
| cdef :: cdefs ->
let remove_poly (I_aux (instr, aux)) =
@@ -1870,10 +1870,9 @@ let rec specialize_variants ctx =
| instr -> I_aux (instr, aux)
in
let cdef = cdef_map_instr remove_poly cdef in
- let cdefs, ctx = specialize_variants ctx cdefs in
- cdef :: cdefs, ctx
+ specialize_variants ctx (cdef :: prior) cdefs
- | [] -> [], ctx
+ | [] -> List.rev prior, ctx
(** Once we specialize variants, there may be additional type
dependencies which could be in the wrong order. As such we need to
@@ -2834,9 +2833,10 @@ let codegen_ctg ctx = function
any auxillary type definitions that are required. *)
let codegen_def ctx def =
let ctyps = cdef_ctyps ctx def in
- (* We should have erased only polymorphism introduced by variants at this point! *)
+ (* We should have erased any polymorphism introduced by variants at this point! *)
if List.exists is_polymorphic ctyps then
let polymorphic_ctyps = List.filter is_polymorphic ctyps in
+ prerr_endline (Pretty_print_sail.to_string (pp_cdef def));
c_error (Printf.sprintf "Found polymorphic types:\n%s\nwhile generating definition."
(Util.string_of_list "\n" string_of_ctyp polymorphic_ctyps))
else
@@ -2966,7 +2966,7 @@ let compile_ast ctx (Defs defs) =
let ctx = { ctx with tc_env = snd (Type_error.check ctx.tc_env (Defs [assert_vs; exit_vs])) } in
let chunks, ctx = List.fold_left (fun (chunks, ctx) def -> let defs, ctx = compile_def ctx def in defs :: chunks, ctx) ([], ctx) defs in
let cdefs = List.concat (List.rev chunks) in
- let cdefs, ctx = specialize_variants ctx cdefs in
+ let cdefs, ctx = specialize_variants ctx [] cdefs in
let cdefs = sort_ctype_defs cdefs in
let cdefs = optimize ctx cdefs in
(*
diff --git a/test/c/option_nest.expect b/test/c/option_nest.expect
new file mode 100644
index 00000000..9daeafb9
--- /dev/null
+++ b/test/c/option_nest.expect
@@ -0,0 +1 @@
+test
diff --git a/test/c/option_nest.sail b/test/c/option_nest.sail
new file mode 100644
index 00000000..995bf074
--- /dev/null
+++ b/test/c/option_nest.sail
@@ -0,0 +1,18 @@
+
+union test ('a : Type) = {
+ Just : 'a,
+ Nothing : unit
+}
+
+union option ('a : Type) = {
+ None : unit,
+ Some : 'a
+}
+
+val "print_endline" : string -> unit
+
+function main() : unit -> unit = {
+ let _ : test(option(int)) = Just(None());
+ let Just(Some(x)) = Just(Some("test"));
+ print_endline(x)
+} \ No newline at end of file