Implement Ocaml-style return

This commit is contained in:
백현웅 2022-02-08 01:22:49 +09:00
parent 7cddc45e8b
commit 1f91d214ee
3 changed files with 27 additions and 15 deletions

22
eval.ml
View file

@ -213,7 +213,7 @@ let rec binop op l r =
exception Unbound of string
let rec eval env ast : value =
let rec eval env ast : string * value =
let rec aux = function
| Nint n -> Int n
| Nfloat n -> Float n
@ -232,9 +232,6 @@ let rec eval env ast : value =
| Binop (l, op, r) ->
let l = aux l and r = aux r in
binop op l r
| Let (var, e) ->
let v = aux e in
Env.set env var v; v
| Apply (v, args) ->
begin match aux v with
| Function (vars, e) ->
@ -243,7 +240,7 @@ let rec eval env ast : value =
let nenv = Env.make env in
List.combine vars args
|> List.iter (fun (v, a) -> Env.set nenv v a);
eval nenv e
snd @@ eval nenv e
| External f ->
let args = List.map aux args in
External.apply f args
@ -263,8 +260,15 @@ let rec eval env ast : value =
Hashtbl.replace Parser.oper_assoc op @@ Parser.assoc_of_string a;
Nop
| Get_binop_aso op ->
match Hashtbl.find_opt Parser.oper_assoc op with
| None -> String "left"
| Some a -> String (Parser.assoc_to_string a)
(match Hashtbl.find_opt Parser.oper_assoc op with
| None -> String "left"
| Some a -> String (Parser.assoc_to_string a))
| _ -> failwith "Eval.eval"
in
aux ast
match ast with
| Let (var, e) ->
let v = aux e in
Env.set env var v;
var, v
| ast -> "-", aux ast

View file

@ -36,7 +36,7 @@ let rep env : unit =
printf "> ";
let line = read_line () in
if line = "quit" then raise Exit;
let v =
let var, v =
line
|> Lex.tokenize
|> Parser.parse
@ -46,7 +46,8 @@ let rep env : unit =
| Nop -> ()
| _ ->
Env.set env "ans" v;
printf "%s\n" @@ Value.to_string v
printf "%s: %s = %s\n"
var (Type.to_string @@ Value.typeof v) (Value.to_string v)
exception Reset_line (* used to indicate ^C is pressed *)

View file

@ -139,17 +139,24 @@ let more f seq =
let xs, seq = aux [] seq in
List.rev xs, seq
(* decl := let_value
* | expr
*)
let rec decl seq =
seq |> oneof [
let_value;
expr min_int;
]
(* expr := level
* | assoc
* | let
* | apply
* | value binop_right
*)
let rec expr pre seq =
and expr pre seq =
seq |> oneof [
level;
assoc;
let_value;
lambda;
extern_value;
apply;
@ -267,6 +274,6 @@ and binop pre left seq =
(* parse tokens *)
let parse ts =
let ast, rest = expr min_int ts in
let ast, rest = decl ts in
if rest () <> Seq.Nil then failwith "Parser.parse";
ast