Skip to content

Commit

Permalink
Support for enums & structs. We assume no complicated lifetime needs.
Browse files Browse the repository at this point in the history
  • Loading branch information
msprotz committed Jan 23, 2024
1 parent dc526fc commit 140a50e
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 14 deletions.
43 changes: 32 additions & 11 deletions lib/AstToMiniRust.ml
Original file line number Diff line number Diff line change
Expand Up @@ -376,14 +376,14 @@ let borrow_kind_of_bool b: MiniRust.borrow_kind =
else
Mut

let rec translate_type (env: env) (t: Ast.typ): MiniRust.typ =
let rec translate_type_with_lt (env: env) (lt: MiniRust.lifetime option) (t: Ast.typ): MiniRust.typ =
match t with
| TInt w -> Constant w
| TBool -> Constant Bool
| TUnit -> Unit
| TAny -> failwith "unexpected: [type] no casts in Low* -> Rust"
| TBuf (t, b) -> Ref (borrow_kind_of_bool b, Slice (translate_type env t))
| TArray (t, c) -> Array (translate_type env t, int_of_string (snd c))
| TBuf (t, b) -> Ref (lt, borrow_kind_of_bool b, Slice (translate_type_with_lt env lt t))
| TArray (t, c) -> Array (translate_type_with_lt env lt t, int_of_string (snd c))
| TQualified lid ->
begin try
Name (lookup_type env lid)
Expand All @@ -393,14 +393,16 @@ let rec translate_type (env: env) (t: Ast.typ): MiniRust.typ =
| TArrow _ ->
let t, ts = Helpers.flatten_arrow t in
let ts = match ts with [ TUnit ] -> [] | _ -> ts in
Function (0, List.map (translate_type env) ts, translate_type env t)
Function (0, List.map (translate_type_with_lt env lt) ts, translate_type_with_lt env lt t)
| TApp _ -> failwith "TODO: TApp"
| TBound i -> Bound i
| TTuple _ -> failwith "TODO: TTuple"
| TAnonymous _ -> failwith "unexpected: we don't compile data types going to Rust"
| TCgArray _ -> failwith "Impossible: TCgArray"
| TCgApp _ -> failwith "Impossible: TCgApp"

let translate_type env = translate_type_with_lt env None


(* Expressions *)

Expand Down Expand Up @@ -486,7 +488,7 @@ and translate_expr_with_type (env: env) (e: Ast.expr) (t_ret: MiniRust.typ): env
(* KPrint.bprintf "translate_expr_with_type: %a @@ %a\n" PrintMiniRust.ptyp t_ret PrintAst.Ops.pexpr e; *)
let possibly_convert (x: MiniRust.expr) t: MiniRust.expr =
begin match x, t, t_ret with
| _, (MiniRust.Vec _ | Array _), Ref (k, Slice _) ->
| _, (MiniRust.Vec _ | Array _), Ref (_, k, Slice _) ->
Borrow (k, x)
| Constant (w, x), Constant UInt32, Constant SizeT ->
assert (w = Constant.UInt32);
Expand Down Expand Up @@ -831,10 +833,10 @@ let translate_decl env (d: Ast.decl) =
false
in
match d with
| Ast.DFunction (_, _, _, _, _, lid, _, _) when is_handled_primitively lid ->
| DFunction (_, _, _, _, _, lid, _, _) when is_handled_primitively lid ->
env, None

| Ast.DFunction (_cc, flags, n_cgs, type_parameters, t, lid, args, body) ->
| DFunction (_cc, flags, n_cgs, type_parameters, t, lid, args, body) ->
assert (type_parameters = 0 && n_cgs = 0);
if Options.debug "rs" then
KPrint.bprintf "Ast.DFunction (%a)\n" PrintAst.Ops.plid lid;
Expand All @@ -858,7 +860,7 @@ let translate_decl env (d: Ast.decl) =
let inline = List.mem Common.Inline flags in
env, Some (MiniRust.Function { type_parameters; parameters; return_type; body; name; public; inline })

| Ast.DGlobal (flags, lid, _, t, e) ->
| DGlobal (flags, lid, _, t, e) ->
let body, typ = match e.node with
| EBufCreate _ | EBufCreateL _ ->
let _, body, typ = translate_array env true e in body, typ
Expand All @@ -872,13 +874,32 @@ let translate_decl env (d: Ast.decl) =
let env = push_global env lid (name, typ) in
env, Some (MiniRust.Constant { name; typ; body; public })

| Ast.DExternal (_, _, _, type_parameters, lid, t, _param_names) ->
| DExternal (_, _, _, type_parameters, lid, t, _param_names) ->
let name = translate_unknown_lid lid in
let env = push_global env lid (name, make_poly (translate_type env t) type_parameters) in
env, None

| Ast.DType (name, _, _, _, _) ->
Warn.failwith "TODO: Ast.DType (%a)\n" PrintAst.Ops.plid name
| DType (lid, flags, _, _, decl) ->
(* creative naming for the lifetime *)
let name = translate_lid env lid in
let public = not (List.mem Common.Private flags) in
match decl with
| Flat fields ->
let lifetime = MiniRust.Label "a" in
let generic_params = [ MiniRust.Lifetime lifetime ] in
let fields = List.map (fun (f, (t, _m)) ->
let f = Option.get f in
f, translate_type_with_lt env (Some lifetime) t
) fields in
env, Some (Struct { name; public; fields; generic_params })
| Enum idents ->
let items = List.map (fun i -> translate_lid env i, None) idents in
env, Some (Enumeration { name; public; items })
| Abbrev _
| Variant _
| Union _
| Forward _ ->
Warn.failwith "TODO: Ast.DType (%a)\n" PrintAst.Ops.plid lid

let identify_path_components_rev filename =
let components = ref [] in
Expand Down
29 changes: 28 additions & 1 deletion lib/MiniRust.ml
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,13 @@ and db_index = int [@ opaque ]
[@@deriving show,
visitors { variety = "map"; name = "map_misc"; polymorphic = true }]

type lifetime =
| Label of string
[@@deriving show]

type typ_ =
| Constant of Constant.width (* excludes cint, ptrdifft *)
| Ref of borrow_kind * typ_
| Ref of lifetime option * borrow_kind * typ_
| Vec of typ_
| Array of typ_ * int
| Slice of typ_ (* always appears underneath Ref *)
Expand Down Expand Up @@ -103,6 +107,27 @@ type decl =
body: expr;
public: bool;
}
| Enumeration of {
name: name;
items: item list;
public: bool;
}
| Struct of {
name: name;
fields: struct_field list;
public: bool;
generic_params: generic_param list;
}

and item =
(* Not supporting tuples yet *)
name * struct_field list option

and generic_param =
| Lifetime of lifetime

and struct_field =
string * typ

(* Some visitors for name management *)

Expand Down Expand Up @@ -153,6 +178,8 @@ let lift (k: int) (expr: expr): expr =

let name_of_decl (d: decl) =
match d with
| Enumeration { name; _ }
| Struct { name; _ }
| Function { name; _ }
| Constant { name; _ } ->
name
39 changes: 37 additions & 2 deletions lib/PrintMiniRust.ml
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,20 @@ let print_constant (w, s) =
else
string s

let print_lifetime = function
| Label l ->
squote ^^ string l

let print_lifetime_option = function
| Some l ->
print_lifetime l ^^ space
| None ->
empty

let rec print_typ env (t: typ): document =
match t with
| Constant w -> string (string_of_width w)
| Ref (k, t) -> group (ampersand ^^ print_borrow_kind k ^^ print_typ env t)
| Ref (lt, k, t) -> group (ampersand ^^ print_lifetime_option lt ^^ print_borrow_kind k ^^ print_typ env t)
| Vec t -> group (string "Vec" ^^ angles (print_typ env t))
| Array (t, n) -> group (brackets (print_typ env t ^^ semi ^/^ int n))
| Slice t -> group (brackets (print_typ env t))
Expand Down Expand Up @@ -398,7 +408,7 @@ let arrow = string "->"
let print_pub p =
if p then string "pub" ^^ break1 else empty

let print_decl env (d: decl) =
let rec print_decl env (d: decl) =
let env, target_name = register_global env (name_of_decl d) in
env, match d with
| Function { type_parameters; parameters; return_type; body; public; inline; _ } ->
Expand All @@ -415,6 +425,31 @@ let print_decl env (d: decl) =
group @@
group (print_pub public ^^ string "const" ^/^ print_name env target_name ^^ colon ^/^ print_typ env typ ^/^ equals) ^^
nest 4 (break1 ^^ print_expr env max_int body) ^^ semi
| Enumeration { items; public; _ } ->
group @@
group (print_pub public ^^ string "enum" ^/^ print_name env target_name) ^/^
braces_with_nesting (
separate_map (comma ^^ hardline) (fun (item_name, item_struct) ->
group @@
print_name env item_name ^^ match item_struct with
| None -> empty
| Some item_struct -> break1 ^^ print_struct env item_struct
) items)
| Struct { fields; public; generic_params; _ } ->
group @@
group (print_pub public ^^ string "struct" ^/^ print_name env target_name ^^ print_generic_params generic_params) ^/^
braces_with_nesting (print_struct env fields)

and print_generic_params params =
if params = [] then
empty
else
break1 ^^ angles (separate_map (comma ^^ break1) (function
| Lifetime l -> print_lifetime l
) params)

and print_struct env fields =
separate_map (comma ^^ break1) (fun (i, t) -> string i ^^ colon ^/^ group (print_typ env t)) fields

let failures = ref 0

Expand Down

0 comments on commit 140a50e

Please sign in to comment.