implemented break

This commit is contained in:
Moritz Gmeiner 2024-08-27 02:46:17 +02:00
commit e288a626fd
6 changed files with 84 additions and 72 deletions

View file

@ -13,18 +13,18 @@ let rec interpret_expr (env : environment) (expr_node : expr_node) :
(lox_value, runtime_error) result =
let { pos; expr } = expr_node in
match expr with
| Literal literal -> Ok (value_of_literal literal)
| Literal literal -> value_of_literal literal |> Result.ok
| Variable name -> (
let value_opt = Env.get env name in
match value_opt with
| Some x -> Ok x
| None ->
let msg = Printf.sprintf "name \"%s\" is not defined" name in
Error (RuntimeError.make pos msg))
RuntimeError.make pos msg |> Result.error)
| Assignment { name; expr } ->
if not (Env.is_defined env name) then
let msg = Printf.sprintf "tried to assign to undefined variable %s" name in
Error (RuntimeError.make pos msg)
RuntimeError.make pos msg |> Result.error
else
let* value = interpret_expr env expr in
Env.update env name value;
@ -32,44 +32,44 @@ let rec interpret_expr (env : environment) (expr_node : expr_node) :
| Unary { op; expr } -> (
let* expr = interpret_expr env expr in
match (op, expr) with
| Neg, Number x -> Ok (Number (-.x))
| Not, Bool b -> Ok (Bool (not b))
| Neg, Number x -> Number (-.x) |> Result.ok
| Not, Bool b -> Bool (not b) |> Result.ok
| _, _ ->
let msg =
Printf.sprintf "Invalid operant of type %s to operator %s"
(type_string_of_lox_value expr) (show_unary_op op)
in
Error (RuntimeError.make pos msg))
RuntimeError.make pos msg |> Result.error)
| Binary { op; left; right } -> (
let* left = interpret_expr env left in
let* right = interpret_expr env right in
match (left, op, right) with
| String a, Plus, String b -> Ok (String (a ^ b))
| Number x, Plus, Number y -> Ok (Number (x +. y))
| Number x, Minus, Number y -> Ok (Number (x -. y))
| Number x, Mul, Number y -> Ok (Number (x *. y))
| String a, Plus, String b -> String (a ^ b) |> Result.ok
| Number x, Plus, Number y -> Number (x +. y) |> Result.ok
| Number x, Minus, Number y -> Number (x -. y) |> Result.ok
| Number x, Mul, Number y -> Number (x *. y) |> Result.ok
| Number x, Div, Number y ->
if y <> 0. then Ok (Number (x /. y))
if y <> 0. then Number (x /. y) |> Result.ok
else
let msg = "Division by 0" in
Error { pos; msg }
| Bool b, And, Bool c -> Ok (Bool (b && c))
| Bool b, Or, Bool c -> Ok (Bool (b || c))
RuntimeError.make pos msg |> Result.error
| Bool b, And, Bool c -> Bool (b && c) |> Result.ok
| Bool b, Or, Bool c -> Bool (b || c) |> Result.ok
| _, Equal, _ -> Ok (Bool (left = right))
| Number x, Greater, Number y -> Ok (Bool (x > y))
| Number x, GreaterEqual, Number y -> Ok (Bool (x >= y))
| Number x, Less, Number y -> Ok (Bool (x < y))
| Number x, LessEqual, Number y -> Ok (Bool (x <= y))
| String a, Greater, String b -> Ok (Bool (a > b))
| String a, GreaterEqual, String b -> Ok (Bool (a >= b))
| String a, Less, String b -> Ok (Bool (a < b))
| String a, LessEqual, String b -> Ok (Bool (a <= b))
| Number x, Greater, Number y -> Bool (x > y) |> Result.ok
| Number x, GreaterEqual, Number y -> Bool (x >= y) |> Result.ok
| Number x, Less, Number y -> Bool (x < y) |> Result.ok
| Number x, LessEqual, Number y -> Bool (x <= y) |> Result.ok
| String a, Greater, String b -> Bool (a > b) |> Result.ok
| String a, GreaterEqual, String b -> Bool (a >= b) |> Result.ok
| String a, Less, String b -> Bool (a < b) |> Result.ok
| String a, LessEqual, String b -> Bool (a <= b) |> Result.ok
| _, _, _ ->
let msg =
Printf.sprintf "Invalid operands of type %s and %s to operator %s"
(type_string_of_lox_value left) (type_string_of_lox_value right) (show_binary_op op)
in
Error { pos; msg })
RuntimeError.make pos msg |> Result.error)
| Logical { op; left; right } -> (
let* left = interpret_expr env left in
match (op, lox_value_to_bool left) with
@ -83,6 +83,10 @@ let rec interpret_stmt (env : environment) (stmt_node : stmt_node) : (unit, runt
| Expr expr ->
let* _ = interpret_expr env expr in
Ok ()
| Break ->
(* print_endline "break!";
Ok () (* TODO *) *)
RuntimeError.break () |> Result.error
| Print expr ->
let* value = interpret_expr env expr in
print_endline (Value.string_of_lox_value value);
@ -93,7 +97,7 @@ let rec interpret_stmt (env : environment) (stmt_node : stmt_node) : (unit, runt
if success then Ok ()
else
let msg = Printf.sprintf "Tried to define %s, but was already defined" name in
Error (RuntimeError.make pos msg)
RuntimeError.make pos msg |> Result.error
| Block stmts ->
let env = Env.enter env in
let rec _interpret stmts =
@ -113,6 +117,9 @@ let rec interpret_stmt (env : environment) (stmt_node : stmt_node) : (unit, runt
let* cond = interpret_expr env cond in
let cond = lox_value_to_bool cond in
if cond then
let* _ = interpret_stmt env body in
interpret_stmt env stmt_node
let result = interpret_stmt env body in
match result with
| Error { is_break = true; _ } -> Ok ()
| Error e -> Error e
| _ -> interpret_stmt env stmt_node
else Ok ()