diff options
author | Nathan Ringo <nathan@remexre.com> | 2024-01-24 19:13:45 -0600 |
---|---|---|
committer | Nathan Ringo <nathan@remexre.com> | 2024-01-24 19:13:45 -0600 |
commit | a4c90a9c3ed05ead786e5e3fc06ad7e6bbd77b57 (patch) | |
tree | 8e724c3b56e95208f59564c73911c183f221b1f4 /discocaml/eval.ml | |
parent | 00d3ea6b17b73594c95318adf266802b02f65abb (diff) |
However... this is now no longer doing capture-avoiding substitution for
letrecs... and making the variable the redex kinda makes it harder to do
the substitution...
Maybe it's time to switch to using pointers in variables.
Diffstat (limited to 'discocaml/eval.ml')
-rw-r--r-- | discocaml/eval.ml | 49 |
1 files changed, 35 insertions, 14 deletions
diff --git a/discocaml/eval.ml b/discocaml/eval.ml index 9f94e41..6bb21ad 100644 --- a/discocaml/eval.ml +++ b/discocaml/eval.ml @@ -109,13 +109,16 @@ let%expect_test "get_fresh_in" = exception FoundRedex of expr index -let check_redex (ast : expr ast) (i : expr index) : unit = +let check_redex (ast : expr ast) (binders : binder_info option array) + (i : expr index) : unit = match get_subexpr ast i with | App (f, _) -> ( match get_subexpr ast f with Lam _ -> raise (FoundRedex i) | _ -> ()) | If (cond, _, _) -> ( match get_subexpr ast cond with Bool _ -> raise (FoundRedex i) | _ -> ()) - | Let (_, _, _, _) -> raise (FoundRedex i) + | Let (false, _, _, _) -> raise (FoundRedex i) + | Let (true, name, _, body) -> + if not (has_free_var ast body name) then raise (FoundRedex i) | Prim (Add, (l, r)) | Prim (Sub, (l, r)) | Prim (Mul, (l, r)) -> ( match (get_subexpr ast l, get_subexpr ast r) with | Int _, Int _ -> raise (FoundRedex i) @@ -125,10 +128,17 @@ let check_redex (ast : expr ast) (i : expr index) : unit = | Bool _, Bool _ -> raise (FoundRedex i) | Int _, Int _ -> raise (FoundRedex i) | _ -> ()) - | Var _ -> () + | Var _ -> ( + match binders.(i.index) with + | Some (`Bound j) -> ( + match get_subexpr ast j with + | Let (true, _, _, _) -> raise (FoundRedex i) + | _ -> ()) + | _ -> ()) | Bool _ | Cons _ | Int _ | Lam _ | Nil -> () -let find_redex_cbv_in (ast : expr ast) : expr index -> unit = +let find_redex_cbv_in (ast : expr ast) (binders : binder_info option array) : + expr index -> unit = let rec loop (i : expr index) : unit = (match get_subexpr ast i with | App (f, x) -> @@ -147,13 +157,14 @@ let find_redex_cbv_in (ast : expr ast) : expr index -> unit = loop r | Var _ -> () | Bool _ | Cons _ | Int _ | Lam _ | Nil -> ()); - check_redex ast i + check_redex ast binders i in loop -let find_redex_cbn_in (ast : expr ast) : expr index -> unit = +let find_redex_cbn_in (ast : expr ast) (binders : binder_info option array) : + expr index -> unit = let rec loop (i : expr index) : unit = - check_redex ast i; + check_redex ast binders i; match get_subexpr ast i with | App (f, x) -> loop f; @@ -171,15 +182,17 @@ let find_redex_cbn_in (ast : expr ast) : expr index -> unit = in loop -let find_redex_cbv (ast : expr ast) : expr index option = +let find_redex_cbv (ast : expr ast) (binders : binder_info option array) : + expr index option = try - find_redex_cbv_in ast ast.root; + find_redex_cbv_in ast binders ast.root; None with FoundRedex i -> Some i -let find_redex_cbn (ast : expr ast) : expr index option = +let find_redex_cbn (ast : expr ast) (binders : binder_info option array) : + expr index option = try - find_redex_cbn_in ast ast.root; + find_redex_cbn_in ast binders ast.root; None with FoundRedex i -> Some i @@ -229,7 +242,8 @@ let rec subst (ast : expr ast) (from : string) (to_ : expr index) : in loop -let reduce (ast : expr ast) (i : expr index) : expr ast = +let reduce (ast : expr ast) (binders : binder_info option array) + (i : expr index) : expr ast = let fail () = raise (NotARedex { ast with root = i }) in let ast = copy ast in let must_int j = match get_subexpr ast j with Int n -> n | _ -> fail () in @@ -246,8 +260,8 @@ let reduce (ast : expr ast) (i : expr index) : expr ast = | _ -> fail ()) | Let (_, name, _, body) when not (has_free_var ast body name) -> get_subexpr ast body - | Let (recursive, name, bound, body) -> - Let (recursive, name, bound, subst ast name bound body) + | Let (false, name, bound, body) -> + get_subexpr ast (subst ast name bound body) | Prim (Add, (l, r)) -> Int (must_int l + must_int r) | Prim (Sub, (l, r)) -> Int (must_int l - must_int r) | Prim (Mul, (l, r)) -> Int (must_int l * must_int r) @@ -266,5 +280,12 @@ let reduce (ast : expr ast) (i : expr index) : expr ast = | `GTE -> l >= r | `EQ -> l = r | `NE -> l <> r) + | Var _ -> ( + match binders.(i.index) with + | Some (`Bound j) -> ( + match get_subexpr ast j with + | Let (true, _, bound, _) -> get_subexpr ast bound + | _ -> fail ()) + | _ -> fail ()) | _ -> fail ()); ast |