mirror of
https://github.com/MorizzG/MLox.git
synced 2025-12-06 04:22:41 +00:00
added closures
This commit is contained in:
parent
34c279ec2e
commit
b425a59db5
5 changed files with 59 additions and 28 deletions
|
|
@ -6,8 +6,7 @@ module Hashtbl = struct
|
||||||
let contains tbl key = find_opt tbl key |> Option.is_some
|
let contains tbl key = find_opt tbl key |> Option.is_some
|
||||||
end
|
end
|
||||||
|
|
||||||
type env_table = (string, lox_value) Hashtbl.t
|
type environment = Value.environment
|
||||||
type environment = { globals : env_table ref; locals : env_table list }
|
|
||||||
|
|
||||||
module Env = struct
|
module Env = struct
|
||||||
type t = environment
|
type t = environment
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,7 @@ let rec interpret_expr (env : environment) (expr_node : expr_node) : lox_value i
|
||||||
RuntimeError.make pos msg |> error
|
RuntimeError.make pos msg |> error
|
||||||
else
|
else
|
||||||
match fn args with Ok value -> Ok value | Error s -> RuntimeError.make pos s |> error)
|
match fn args with Ok value -> Ok value | Error s -> RuntimeError.make pos s |> error)
|
||||||
| Function { name; arity; arg_names; body } -> (
|
| Function { name; env; arity; arg_names; body } -> (
|
||||||
let args_len = List.length args in
|
let args_len = List.length args in
|
||||||
if args_len <> arity then
|
if args_len <> arity then
|
||||||
let msg =
|
let msg =
|
||||||
|
|
@ -149,7 +149,8 @@ let rec interpret_expr (env : environment) (expr_node : expr_node) : lox_value i
|
||||||
in
|
in
|
||||||
RuntimeError.make pos msg |> error
|
RuntimeError.make pos msg |> error
|
||||||
else
|
else
|
||||||
let env = Env.push_frame env in
|
(* let env = Env.push_frame env in *)
|
||||||
|
let env = Env.enter env in
|
||||||
let () =
|
let () =
|
||||||
List.iter2 (fun name value -> assert (Env.define env name value)) arg_names args
|
List.iter2 (fun name value -> assert (Env.define env name value)) arg_names args
|
||||||
in
|
in
|
||||||
|
|
@ -190,7 +191,7 @@ and interpret_stmt (env : environment) (stmt_node : stmt_node) : unit interprete
|
||||||
in
|
in
|
||||||
RuntimeError.make pos msg |> error
|
RuntimeError.make pos msg |> error
|
||||||
| FunDecl { name; arg_names; body } ->
|
| FunDecl { name; arg_names; body } ->
|
||||||
let fn = make_lox_function name arg_names body in
|
let fn = make_lox_function name env arg_names body in
|
||||||
let success = Env.define env name fn in
|
let success = Env.define env name fn in
|
||||||
if success then Ok ()
|
if success then Ok ()
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -419,7 +419,6 @@ and fun_declaration (state : state) : stmt_result =
|
||||||
let* () = consume state RightParen in
|
let* () = consume state RightParen in
|
||||||
let* body = with_is_in_fun block state in
|
let* body = with_is_in_fun block state in
|
||||||
make_fun_decl pos name arg_names body |> Result.ok
|
make_fun_decl pos name arg_names body |> Result.ok
|
||||||
(* make_nil pos |> make_expr_stmt pos |> Result.ok *)
|
|
||||||
|
|
||||||
and declaration (state : state) : stmt_result =
|
and declaration (state : state) : stmt_result =
|
||||||
match peek_tt state with
|
match peek_tt state with
|
||||||
|
|
|
||||||
13
lib/value.ml
13
lib/value.ml
|
|
@ -1,12 +1,12 @@
|
||||||
type lox_function = {
|
type lox_function = {
|
||||||
name : string;
|
name : string;
|
||||||
|
env : environment;
|
||||||
arity : int;
|
arity : int;
|
||||||
(* env : Environment.environment; [@printer fun fmt _ -> fprintf fmt "<env>"] *)
|
|
||||||
arg_names : string list;
|
arg_names : string list;
|
||||||
body : Stmt.stmt_node; [@printer fun fmt _ -> fprintf fmt "<body>"]
|
body : Stmt.stmt_node; [@printer fun fmt _ -> fprintf fmt "<body>"]
|
||||||
}
|
}
|
||||||
|
|
||||||
type native_function = {
|
and native_function = {
|
||||||
name : string;
|
name : string;
|
||||||
arity : int;
|
arity : int;
|
||||||
fn : lox_value list -> (lox_value, string) result;
|
fn : lox_value list -> (lox_value, string) result;
|
||||||
|
|
@ -20,6 +20,9 @@ and lox_value =
|
||||||
| Bool of bool
|
| Bool of bool
|
||||||
| Nil
|
| Nil
|
||||||
|
|
||||||
|
and env_table = (string, lox_value) Hashtbl.t
|
||||||
|
and environment = { globals : env_table ref; locals : env_table list }
|
||||||
|
|
||||||
let string_of_lox_value lox_value =
|
let string_of_lox_value lox_value =
|
||||||
match lox_value with
|
match lox_value with
|
||||||
| Function { name; arity; _ } -> Printf.sprintf "<fn %s/%d>" name arity
|
| Function { name; arity; _ } -> Printf.sprintf "<fn %s/%d>" name arity
|
||||||
|
|
@ -40,7 +43,7 @@ let type_string_of_lox_value lox_value =
|
||||||
|
|
||||||
let lox_value_to_bool lox_value = match lox_value with Bool b -> b | Nil -> false | _ -> true
|
let lox_value_to_bool lox_value = match lox_value with Bool b -> b | Nil -> false | _ -> true
|
||||||
|
|
||||||
let make_lox_function (name : string) (arg_names : string list) (body : Stmt.stmt_node) : lox_value
|
let make_lox_function (name : string) (env : environment) (arg_names : string list)
|
||||||
=
|
(body : Stmt.stmt_node) : lox_value =
|
||||||
let arity = List.length arg_names in
|
let arity = List.length arg_names in
|
||||||
Function { name; arity; arg_names; body }
|
Function { name; env; arity; arg_names; body }
|
||||||
|
|
|
||||||
63
lox.t/run.t
63
lox.t/run.t
|
|
@ -205,19 +205,28 @@ $ mlox class/reference_self.lox
|
||||||
|
|
||||||
|
|
||||||
file closure/assign_to_closure.lox
|
file closure/assign_to_closure.lox
|
||||||
$ mlox closure/assign_to_closure.lox
|
$ mlox closure/assign_to_closure.lox
|
||||||
|
local
|
||||||
|
after f
|
||||||
|
after f
|
||||||
|
after g
|
||||||
|
|
||||||
|
|
||||||
file closure/assign_to_shadowed_later.lox
|
file closure/assign_to_shadowed_later.lox
|
||||||
$ mlox closure/assign_to_shadowed_later.lox
|
$ mlox closure/assign_to_shadowed_later.lox
|
||||||
|
inner
|
||||||
|
assigned
|
||||||
|
|
||||||
|
|
||||||
file closure/close_over_function_parameter.lox
|
file closure/close_over_function_parameter.lox
|
||||||
$ mlox closure/close_over_function_parameter.lox
|
$ mlox closure/close_over_function_parameter.lox
|
||||||
|
param
|
||||||
|
|
||||||
|
|
||||||
file closure/close_over_later_variable.lox
|
file closure/close_over_later_variable.lox
|
||||||
$ mlox closure/close_over_later_variable.lox
|
$ mlox closure/close_over_later_variable.lox
|
||||||
|
b
|
||||||
|
a
|
||||||
|
|
||||||
|
|
||||||
file closure/close_over_method_parameter.lox
|
file closure/close_over_method_parameter.lox
|
||||||
|
|
@ -225,35 +234,48 @@ $ mlox closure/close_over_method_parameter.lox
|
||||||
|
|
||||||
|
|
||||||
file closure/closed_closure_in_function.lox
|
file closure/closed_closure_in_function.lox
|
||||||
$ mlox closure/closed_closure_in_function.lox
|
$ mlox closure/closed_closure_in_function.lox
|
||||||
|
local
|
||||||
|
|
||||||
|
|
||||||
file closure/nested_closure.lox
|
file closure/nested_closure.lox
|
||||||
$ mlox closure/nested_closure.lox
|
$ mlox closure/nested_closure.lox
|
||||||
|
a
|
||||||
|
b
|
||||||
|
c
|
||||||
|
|
||||||
|
|
||||||
file closure/open_closure_in_function.lox
|
file closure/open_closure_in_function.lox
|
||||||
$ mlox closure/open_closure_in_function.lox
|
$ mlox closure/open_closure_in_function.lox
|
||||||
|
local
|
||||||
|
|
||||||
|
|
||||||
file closure/reference_closure_multiple_times.lox
|
file closure/reference_closure_multiple_times.lox
|
||||||
$ mlox closure/reference_closure_multiple_times.lox
|
$ mlox closure/reference_closure_multiple_times.lox
|
||||||
|
a
|
||||||
|
a
|
||||||
|
|
||||||
|
|
||||||
file closure/reuse_closure_slot.lox
|
file closure/reuse_closure_slot.lox
|
||||||
$ mlox closure/reuse_closure_slot.lox
|
$ mlox closure/reuse_closure_slot.lox
|
||||||
|
a
|
||||||
|
|
||||||
|
|
||||||
file closure/shadow_closure_with_local.lox
|
file closure/shadow_closure_with_local.lox
|
||||||
$ mlox closure/shadow_closure_with_local.lox
|
$ mlox closure/shadow_closure_with_local.lox
|
||||||
|
closure
|
||||||
|
shadow
|
||||||
|
closure
|
||||||
|
|
||||||
|
|
||||||
file closure/unused_closure.lox
|
file closure/unused_closure.lox
|
||||||
$ mlox closure/unused_closure.lox
|
$ mlox closure/unused_closure.lox
|
||||||
|
ok
|
||||||
|
|
||||||
|
|
||||||
file closure/unused_later_closure.lox
|
file closure/unused_later_closure.lox
|
||||||
$ mlox closure/unused_later_closure.lox
|
$ mlox closure/unused_later_closure.lox
|
||||||
|
a
|
||||||
|
|
||||||
|
|
||||||
file comments/line_at_eof.lox
|
file comments/line_at_eof.lox
|
||||||
|
|
@ -532,9 +554,9 @@ file function/extra_arguments.lox
|
||||||
|
|
||||||
|
|
||||||
file function/local_mutual_recursion.lox
|
file function/local_mutual_recursion.lox
|
||||||
$ mlox function/local_mutual_recursion.lox
|
$ mlox function/local_mutual_recursion.lox
|
||||||
RuntimeError at line 4, column 11: name "isOdd" is not defined
|
RuntimeError at line 4, column 11: name "isOdd" is not defined
|
||||||
[1]
|
[1]
|
||||||
|
|
||||||
file function/local_recursion.lox
|
file function/local_recursion.lox
|
||||||
$ mlox function/local_recursion.lox
|
$ mlox function/local_recursion.lox
|
||||||
|
|
@ -1079,7 +1101,8 @@ file print/missing_argument.lox
|
||||||
|
|
||||||
|
|
||||||
file regression/40.lox
|
file regression/40.lox
|
||||||
$ mlox regression/40.lox
|
$ mlox regression/40.lox
|
||||||
|
false
|
||||||
|
|
||||||
|
|
||||||
file regression/394.lox
|
file regression/394.lox
|
||||||
|
|
@ -1268,6 +1291,8 @@ file variable/duplicate_parameter.lox
|
||||||
|
|
||||||
file variable/early_bound.lox
|
file variable/early_bound.lox
|
||||||
$ mlox variable/early_bound.lox
|
$ mlox variable/early_bound.lox
|
||||||
|
outer
|
||||||
|
outer
|
||||||
|
|
||||||
|
|
||||||
file variable/in_middle_of_block.lox
|
file variable/in_middle_of_block.lox
|
||||||
|
|
@ -1379,7 +1404,10 @@ $ mlox while/class_in_body.lox
|
||||||
|
|
||||||
|
|
||||||
file while/closure_in_body.lox
|
file while/closure_in_body.lox
|
||||||
$ mlox while/closure_in_body.lox
|
$ mlox while/closure_in_body.lox
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
|
||||||
|
|
||||||
file while/fun_in_body.lox
|
file while/fun_in_body.lox
|
||||||
|
|
@ -1390,7 +1418,8 @@ file while/fun_in_body.lox
|
||||||
|
|
||||||
|
|
||||||
file while/return_closure.lox
|
file while/return_closure.lox
|
||||||
$ mlox while/return_closure.lox
|
$ mlox while/return_closure.lox
|
||||||
|
i
|
||||||
|
|
||||||
|
|
||||||
file while/return_inside.lox
|
file while/return_inside.lox
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue