Skip to content

Commit 4316b26

Browse files
committed
Merge branch 'master' of github.com:FStarLang/karamel into _taramana_mutrec
2 parents 8ab12b7 + b6df0cc commit 4316b26

File tree

9 files changed

+396
-158
lines changed

9 files changed

+396
-158
lines changed

include/krml/internal/target.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,9 @@ typedef double float64_t;
4646
# define KRML_HOST_PRINTF printf
4747
#endif
4848

49-
#if ( \
50-
(defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
49+
#if ( \
50+
((defined(__cplusplus) && __cplusplus > 199711L) || \
51+
(defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) && \
5152
(!(defined KRML_HOST_EPRINTF)))
5253
# define KRML_HOST_EPRINTF(...) fprintf(stderr, __VA_ARGS__)
5354
#elif !(defined KRML_HOST_EPRINTF) && defined(_MSC_VER)

include/krml/lowstar_endianness.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
/******************************************************************************/
1313

1414
/* ... for Linux */
15-
#if defined(__linux__) || defined(__CYGWIN__) || defined (__USE_SYSTEM_ENDIAN_H__) || defined(__GLIBC__)
15+
#if defined(__linux__) || defined(__CYGWIN__) || defined (__USE_SYSTEM_ENDIAN_H__) || defined(__GLIBC__) || defined(ESP_PLATFORM)
1616
# include <endian.h>
1717

1818
/* ... for OSX */

lib/AstToMiniRust.ml

Lines changed: 89 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -273,25 +273,47 @@ module Splits = struct
273273
(* Unlocks better comparisons in many cases *)
274274
let norm e =
275275
let exception NotConstant in
276-
let rec norm (e: MiniRust.expr) =
276+
let rec is_zero e =
277+
try norm e = 0
278+
with NotConstant -> false
279+
280+
and norm (e: MiniRust.expr) =
277281
(* This function assumes no overflow on index comparisons... FIXME *)
278282
match e with
279283
| As (e, _) ->
280284
norm e
285+
286+
| MethodCall (e1, [ "wrapping_add" ], [ e2 ])
287+
| Call (Operator (Add | AddW), _, [ e1; e2 ]) when is_zero e1 ->
288+
norm e2
289+
290+
| MethodCall (e1, [ "wrapping_add" ], [ e2 ])
291+
| Call (Operator (Add | AddW), _, [ e1; e2 ]) when is_zero e2 ->
292+
norm e1
293+
281294
| MethodCall (e1, [ "wrapping_add" ], [ e2 ])
282295
| Call (Operator (Add | AddW), _, [ e1; e2 ]) ->
283296
norm e1 + norm e2
297+
298+
| MethodCall (e1, [ "wrapping_mul" ], [ e2 ])
299+
| Call (Operator (Mult | MultW), _, [ e1; e2 ]) when is_zero e1 || is_zero e2 ->
300+
0
301+
284302
| MethodCall (e1, [ "wrapping_mul" ], [ e2 ])
285303
| Call (Operator (Mult | MultW), _, [ e1; e2 ]) ->
286304
norm e1 * norm e2
305+
287306
| MethodCall (e1, [ "wrapping_sub" ], [ e2 ])
288307
| Call (Operator (Sub | SubW), _, [ e1; e2 ]) ->
289308
norm e1 - norm e2
309+
290310
| MethodCall (e1, [ "wrapping_div" ], [ e2 ])
291311
| Call (Operator (Div | DivW), _, [ e1; e2 ]) ->
292312
norm e1 / norm e2
313+
293314
| Constant (_, c) ->
294315
int_of_string c
316+
295317
| _ ->
296318
raise NotConstant
297319
in
@@ -650,9 +672,9 @@ let field_type env (e: Ast.expr) f =
650672
[fn_t_ret] corresponds to the return type of the function we are currently
651673
translating, and is used for EReturn nodes.
652674
*)
653-
let rec translate_expr (env: env) (fn_t_ret: MiniRust.typ) (e: Ast.expr) : env * MiniRust.expr =
675+
let rec translate_expr (env: env) ?context (fn_t_ret: MiniRust.typ) (e: Ast.expr) : env * MiniRust.expr =
654676
(* KPrint.bprintf "translate_expr: %a : %a\n" PrintAst.Ops.pexpr e PrintAst.Ops.ptyp e.typ; *)
655-
translate_expr_with_type env fn_t_ret e (translate_type env e.typ)
677+
translate_expr_with_type env ?context fn_t_ret e (translate_type env e.typ)
656678

657679
and translate_expr_list (env: env) (fn_t_ret: MiniRust.typ) (es: Ast.expr list) : env * MiniRust.expr list =
658680
let env, acc =
@@ -697,7 +719,7 @@ and translate_array (env: env) (fn_t_ret: MiniRust.typ) is_toplevel (init: Ast.e
697719

698720
(* However, generally, we will have a type provided by the context that may
699721
necessitate the insertion of conversions *)
700-
and translate_expr_with_type (env: env) (fn_t_ret: MiniRust.typ) (e: Ast.expr) (t_ret: MiniRust.typ): env * MiniRust.expr =
722+
and translate_expr_with_type (env: env) ?(context=`Other) (fn_t_ret: MiniRust.typ) (e: Ast.expr) (t_ret: MiniRust.typ): env * MiniRust.expr =
701723
(* KPrint.bprintf "translate_expr_with_type: %a @@ %a\n" PrintMiniRust.ptyp t_ret PrintAst.Ops.pexpr e; *)
702724

703725
let erase_borrow_kind_info = (object(self)
@@ -732,10 +754,16 @@ and translate_expr_with_type (env: env) (fn_t_ret: MiniRust.typ) (e: Ast.expr) (
732754
Constant (SizeT, x)
733755
| _, Constant UInt32, Constant SizeT ->
734756
As (x, Constant SizeT)
757+
735758
| _, Function (_, _, ts, t), Function (_, _, ts', t') when ts = ts' && t = t' ->
736759
(* The type annotations coming from Ast do not feature polymorphic binders in types, but we
737760
do retain them in our Function type -- so we need to relax the comparison here *)
738-
x
761+
begin match e.node with
762+
| EQualified _ when context <> `CallHead ->
763+
As (x, t_ret)
764+
| _ ->
765+
x
766+
end
739767

740768
(* More conversions due to box-ing types. *)
741769
| _, Ref (_, _, Slice _), App (Name (["Box"], _), [Slice _]) ->
@@ -850,9 +878,12 @@ and translate_expr_with_type (env: env) (fn_t_ret: MiniRust.typ) (e: Ast.expr) (
850878
| EAny -> failwith "Unexpected EAny"
851879
| EAbort (_, s) ->
852880
env, Panic (Stdlib.Option.value ~default:"" s)
853-
| EIgnore _ ->
854-
failwith "unexpected: EIgnore"
855-
| EApp ({ node = EOp (o, _); _ }, es) when H.is_wrapping_operator o ->
881+
| EIgnore e ->
882+
let t = translate_type env e.typ in
883+
let env, e = translate_expr env fn_t_ret e in
884+
let binding: MiniRust.binding = { name = "_"; typ = t; mut = false; ref = false } in
885+
env, Let (binding, Some e, Unit)
886+
| EApp ({ node = EOp (o, w); _ }, es) when H.is_wrapping_operator o && not (Constant.is_float w) ->
856887
let w = Helpers.assert_tint (List.hd es).typ in
857888
let env, es = translate_expr_list env fn_t_ret es in
858889
env, possibly_convert (MethodCall (List.hd es, [ H.wrapping_operator o ], List.tl es)) (Constant w)
@@ -915,7 +946,7 @@ and translate_expr_with_type (env: env) (fn_t_ret: MiniRust.typ) (e: Ast.expr) (
915946
| [ { typ = TUnit; node; _ } ] -> assert (node = EUnit); []
916947
| _ -> es
917948
in
918-
let env, e = translate_expr env fn_t_ret e in
949+
let env, e = translate_expr env ~context:`CallHead fn_t_ret e in
919950
let ts = List.map (translate_type env) ts in
920951
let env, es = translate_expr_list env fn_t_ret es in
921952
env, Call (e, ts, es)
@@ -934,7 +965,7 @@ and translate_expr_with_type (env: env) (fn_t_ret: MiniRust.typ) (e: Ast.expr) (
934965
| _ -> es, snd (Helpers.flatten_arrow e0.typ)
935966
in
936967
(* KPrint.bprintf "Translating arguments to call %a\n" PrintAst.Ops.pexpr e0; *)
937-
let env, e0 = translate_expr env fn_t_ret e0 in
968+
let env, e0 = translate_expr env ~context:`CallHead fn_t_ret e0 in
938969
let env, es = translate_expr_list_with_types env fn_t_ret es (List.map (translate_type env) ts) in
939970
env, possibly_convert (Call (e0, [], es)) (translate_type env e.typ)
940971

@@ -1072,6 +1103,7 @@ and translate_expr_with_type (env: env) (fn_t_ret: MiniRust.typ) (e: Ast.expr) (
10721103
sub-environments since their variables go out of scope? *)
10731104
env, IfThenElse (e1, e2, e3)
10741105
| ESequence _ ->
1106+
(* `sequence_to_let` eliminates all sequences *)
10751107
failwith "unexpected: ESequence"
10761108
| EAssign (e1, e2) ->
10771109
let lvalue_type = match e1.node with
@@ -1346,7 +1378,12 @@ and translate_pat env (p: Ast.pattern): MiniRust.pat =
13461378
) field_names pats)
13471379
| PUnit -> failwith "TODO: PUnit"
13481380
| PBool _ -> failwith "TODO: PBool"
1349-
| PEnum _ -> failwith "TODO: PEnum"
1381+
| PEnum cons ->
1382+
(* Same as constructors, above, since enums and variants are the same in Rust (`enum`
1383+
keyword). *)
1384+
let lid = Helpers.assert_tlid p.typ in
1385+
let name = lookup_type env lid in
1386+
StructP (`Variant (name, snd cons), [])
13501387
| PTuple ps ->
13511388
TupleP (List.map (translate_pat env) ps)
13521389
| PDeref _ -> failwith "TODO: PDeref"
@@ -1370,7 +1407,20 @@ let is_handled_primitively = function
13701407

13711408
(* In Rust, like in C, all the declarations from the current module are in
13721409
* scope immediately. This requires us to duplicate a little bit of work. *)
1373-
let bind_decl env (d: Ast.decl): env =
1410+
let bind_type_decl env (d: Ast.decl): env =
1411+
match d with
1412+
| DType (lid, _flags, _, _, _decl) ->
1413+
if LidMap.mem lid env.types then
1414+
(* Name already assigned thanks to a forward declaration *)
1415+
env
1416+
else
1417+
let env, name = translate_lid env lid in
1418+
let env = push_type env lid name in
1419+
env
1420+
| _ ->
1421+
env
1422+
1423+
let bind_non_type_decl env (d: Ast.decl): env =
13741424
match d with
13751425
| DFunction (_, _, _, _, _, lid, _, _) when is_handled_primitively lid ->
13761426
env
@@ -1429,17 +1479,9 @@ let bind_decl env (d: Ast.decl): env =
14291479
let name = translate_unknown_lid lid in
14301480
push_decl env lid (name, make_poly (translate_type_with_config env {default_config with keep_mut = true} t) type_parameters)
14311481

1432-
| DType (lid, _flags, _, _, decl) ->
1433-
let env, name =
1434-
if LidMap.mem lid env.types then
1435-
(* Name already assigned thanks to a forward declaration *)
1436-
env, lookup_type env lid
1437-
else
1438-
let env, name = translate_lid env lid in
1439-
let env = push_type env lid name in
1440-
env, name
1441-
in
1442-
match decl with
1482+
| DType (lid, _, _, _, decl) ->
1483+
let name = lookup_type env lid in
1484+
begin match decl with
14431485
| Flat fields ->
14441486
(* These sets are mutually exclusive, so we don't box *and* introduce a
14451487
lifetime at the same time *)
@@ -1454,6 +1496,8 @@ let bind_decl env (d: Ast.decl): env =
14541496
in
14551497
let fields = List.map (fun (f, (t, _m)) ->
14561498
let f = Option.get f in
1499+
(* let open PrintAst.Ops in *)
1500+
(* KPrint.bprintf "%a: field %s has type %a\n" plid lid f ptyp t; *)
14571501
{ MiniRust.name = f; visibility = Some Pub; typ = translate_type_with_config env { box; lifetime; keep_mut = false } t }
14581502
) fields in
14591503
{ env with
@@ -1479,6 +1523,7 @@ let bind_decl env (d: Ast.decl): env =
14791523
) env branches
14801524
| _ ->
14811525
env
1526+
end
14821527

14831528
let translate_meta attributes flags =
14841529
let comments = List.filter_map (function Common.Comment c -> Some c | _ -> None) flags in
@@ -1595,7 +1640,11 @@ let translate_decl env { derives; attributes; static; no_mangle; _ } (d: Ast.dec
15951640
| Enum idents ->
15961641
(* TODO: enum cases with set values *)
15971642
(* No need to do name binding here since there are entirely resolved via the type name. *)
1598-
let items = List.map (fun (i, v) -> assert (v = None); snd i, None) idents in
1643+
let items = List.map (fun (i, (v: Z.t option)) ->
1644+
snd i, match v with
1645+
| None -> MiniRust.Unit None
1646+
| Some c -> Unit (Some c)
1647+
) idents in
15991648
Some (Enumeration { name; meta; items; derives; generic_params = [] })
16001649
| Abbrev t ->
16011650
let has_inner_pointer = has_pointer env t in
@@ -1619,7 +1668,7 @@ let translate_decl env { derives; attributes; static; no_mangle; _ } (d: Ast.dec
16191668
let items = List.map (fun (cons, _) ->
16201669
let fields = DataTypeMap.find (`Variant (lid, cons)) env.struct_fields in
16211670
let fields = List.map (fun (x: MiniRust.struct_field) -> { x with visibility = None }) fields in
1622-
cons, Some fields
1671+
cons, if fields = [] then MiniRust.Unit None else MiniRust.Struct fields
16231672
) branches in
16241673
Some (Enumeration { name; meta; items; derives; generic_params })
16251674
| Union _ ->
@@ -1807,10 +1856,24 @@ let translate_files_with_metadata files metadata =
18071856
| _ -> true
18081857
) decls in
18091858

1859+
(* Step 0.5: bind all *type* declarations so that types are in scope for adding functions in the
1860+
environment (with their types) *)
1861+
let env = List.fold_left (fun env d ->
1862+
try
1863+
bind_type_decl env d
1864+
with e ->
1865+
(* We do not increase failures as this will be counted below. *)
1866+
KPrint.bprintf "%sERROR translating type of %a: %s%s\n%s\n" Ansi.red
1867+
PrintAst.Ops.plid (Ast.lid_of_decl d)
1868+
(Printexc.to_string e) Ansi.reset
1869+
(Printexc.get_backtrace ());
1870+
env
1871+
) env decls in
1872+
18101873
(* Step 1: bind all declarations and add them to the environment with their types *)
18111874
let env = List.fold_left (fun env d ->
18121875
try
1813-
bind_decl env d
1876+
bind_non_type_decl env d
18141877
with e ->
18151878
(* We do not increase failures as this will be counted below. *)
18161879
KPrint.bprintf "%sERROR translating type of %a: %s%s\n%s\n" Ansi.red

lib/Constant.ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ let unsigned_of_signed = function
7272
let is_signed = function
7373
| Int8 | Int16 | Int32 | Int64 | CInt | PtrdiffT -> true
7474
| UInt8 | UInt16 | UInt32 | UInt64 | SizeT -> false
75-
| Bool | Float32 | Float64 -> raise (Invalid_argument "is_signed")
75+
| Bool -> raise (Invalid_argument "is_signed: bool")
76+
| Float32 | Float64 -> raise (Invalid_argument "is_signed: float")
7677

7778
let is_unsigned w = not (is_signed w)
7879

lib/MiniRust.ml

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ end
88
type borrow_kind_ = Mut | Shared
99
[@@deriving show]
1010

11-
type borrow_kind = borrow_kind_ [@ opaque ]
12-
and constant = Constant.t [@ opaque ]
13-
and width = Constant.width [@ opaque ]
14-
and op = Constant.op [@ opaque ]
11+
type borrow_kind = borrow_kind_ [@ visitors.opaque ]
12+
and constant = Constant.t [@ visitors.opaque ]
13+
and width = Constant.width [@ visitors.opaque ]
14+
and op = Constant.op [@ visitors.opaque ]
1515
and name = Name.t [@ visitors.opaque ]
1616

1717
(* Some design choices.
@@ -21,7 +21,7 @@ and name = Name.t [@ visitors.opaque ]
2121
between statements and expressions -- Rust is not as strict as C in that
2222
regard. We'll do "the right thing" once we go to a concrete Rust syntax
2323
tree prior to pretty-printing. *)
24-
and db_index = int [@ opaque ]
24+
and db_index = int [@ visitors.opaque ]
2525
[@@deriving show,
2626
visitors { variety = "map"; name = "map_misc"; polymorphic = true },
2727
visitors { variety = "reduce"; name = "reduce_misc"; polymorphic = true }]
@@ -131,7 +131,8 @@ and pat =
131131
(* In the Rust grammar, both variants and structs are covered by the struct
132132
case. We disambiguate between the two *)
133133
and struct_name =
134-
[ `Struct of name | `Variant of name * string ] [@ opaque]
134+
[ `Struct of name | `Variant of name * string ] [@ visitors.opaque]
135+
[@@deriving show]
135136

136137
and open_var = {
137138
name: string;
@@ -182,7 +183,7 @@ type decl =
182183
}
183184
| Enumeration of {
184185
name: name;
185-
items: item list;
186+
items: enum_variant list;
186187
derives: trait list;
187188
meta: meta;
188189
generic_params: generic_param list;
@@ -218,9 +219,13 @@ type decl =
218219
mut: bool;
219220
}
220221

221-
and item =
222-
(* Not supporting tuples yet *)
223-
string * struct_field list option
222+
and enum_variant =
223+
string * enum_variant_payload
224+
225+
and enum_variant_payload =
226+
| Struct of struct_field list
227+
| Unit of Z.t option (* discriminant, if specified *)
228+
(* TODO: tuple *)
224229

225230
and struct_field = {
226231
name: string;

0 commit comments

Comments
 (0)