Skip to content

Commit

Permalink
WIP: handling match nodes properly
Browse files Browse the repository at this point in the history
  • Loading branch information
msprotz committed Sep 16, 2024
1 parent 7e04b98 commit 1f6f6d7
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 3 deletions.
28 changes: 27 additions & 1 deletion lib/DataTypes.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1314,11 +1314,37 @@ let optimize files =
let files = remove_unit_fields#visit_files () files in
files

(* For Rust, we leave `match` nodes in the AST -- Rust *does* have
pattern-matching, after all. However, F* code contains a lot of one-branch
matches, of the form `match e with _ -> ...` or `match e with { f = x; } ->
...`. Therefore, for code quality, we replace the latter with `...` and the
former with `let x = e.f in ...`. *)
let remove_one_branch_matches = object (self)

inherit [_] map as _super

method! visit_EMatch (_, _t as env) c scrut branches =
let scrut = self#visit_expr env scrut in
match branches with
| [ [], _, e ] ->
(* A match made of a single branch; e is always evaluated. *)
(self#visit_expr env e).node
| [ [ b ], { node = PBound _; _ }, e ] ->
(* match scrut with \ b. x -> e ~~> let x = scrut in e *)
ELet (b, scrut, self#visit_expr env e)
| [ [ b ], { node = PRecord ps; _ }, e ] ->
(* match scrut with \ b. { f = x } -> e ~~> let x = scrut.f in e *)
let f = Option.get (List.find_map (fun (f, x) -> match x.node with PBound _ -> Some f | _ -> None) ps) in
ELet (b, with_type b.typ (EField (scrut, f)), self#visit_expr env e)
| _ ->
EMatch (c, scrut, self#visit_branches env branches)
end

(* General compilation scheme *)
let everything files =
let map = build_scheme_map files in
let files = (compile_simple_matches map)#visit_files () files in
let files = if Options.rust () then files else (compile_all_matches map)#visit_files () files in
let files = if Options.rust () then remove_one_branch_matches#visit_files () files else (compile_all_matches map)#visit_files () files in
let files = remove_non_scalar_casts#visit_files () files in
let files = remove_empty_structs files in
map, files
Expand Down
5 changes: 3 additions & 2 deletions lib/OptimizeMiniRust.ml
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ let rec infer (env: env) (expected: typ) (known: known) (e: expr): known * expr
known, Assign (Index (e1, e2), e3, t)

(* x.f[e2] = e3 *)
| Assign (Index (Field (_, f, st) as e1, e2), e3, t) ->
| Assign (Index (Field (_, f, st (* optional type *)) as e1, e2), e3, t) ->
let known = add_mut_field st f known in
let known, e2 = infer env usize known e2 in
let known, e3 = infer env t known e3 in
Expand Down Expand Up @@ -361,7 +361,8 @@ let rec infer (env: env) (expected: typ) (known: known) (e: expr): known * expr
we would need to add the expected type of the scrutinee to the Match node,
similar to what is done for Assign and Field, in order to recurse on
the scrutinee *)
(* FIXME per comment above *)
(* FIXME per comment above + need to open binders in match branches + need
to mark some of those binders as mutable *)
let known, arms = List.fold_left_map (fun known (bs, pat, e) ->
let known, e = infer env expected known e in
known, (bs, pat, e)
Expand Down

0 comments on commit 1f6f6d7

Please sign in to comment.