Add closure
This commit is contained in:
parent
cd3487dd81
commit
d5ac54365d
3 changed files with 34 additions and 10 deletions
6
ast.ml
6
ast.ml
|
@ -9,6 +9,7 @@ type t =
|
||||||
| Nexternal of string
|
| Nexternal of string
|
||||||
| Var of string
|
| Var of string
|
||||||
| Let of string * t
|
| Let of string * t
|
||||||
|
| Letin of string * t * t
|
||||||
| Unary of operator * t
|
| Unary of operator * t
|
||||||
| Binop of t * operator * t
|
| Binop of t * operator * t
|
||||||
| If of t * t * t (* cond then else *)
|
| If of t * t * t (* cond then else *)
|
||||||
|
@ -61,9 +62,12 @@ let print ast =
|
||||||
List.iter (pr " %s") @@ List.tl args;
|
List.iter (pr " %s") @@ List.tl args;
|
||||||
pr ") "; aux e; pr ")"
|
pr ") "; aux e; pr ")"
|
||||||
| Nexternal e -> pr "(extern %s)" e
|
| Nexternal e -> pr "(extern %s)" e
|
||||||
|
|
||||||
| Var v -> pr "%s" v
|
| Var v -> pr "%s" v
|
||||||
| Let (v, e) ->
|
| Let (v, e) ->
|
||||||
pr "(let %s " v; aux e; pr ")"
|
pr "(define %s " v; aux e; pr ")"
|
||||||
|
| Letin (v, e, f) ->
|
||||||
|
pr "(let ((%s " v; aux e; pr "))"; aux f; pr ")"
|
||||||
| Unary (op, t) ->
|
| Unary (op, t) ->
|
||||||
let op = op_to_string op in
|
let op = op_to_string op in
|
||||||
pr "(%s " op; aux t; pr ")"
|
pr "(%s " op; aux t; pr ")"
|
||||||
|
|
16
eval.ml
16
eval.ml
|
@ -7,7 +7,7 @@ type value =
|
||||||
| Bool of bool
|
| Bool of bool
|
||||||
| String of string
|
| String of string
|
||||||
| Symbol of string
|
| Symbol of string
|
||||||
| Function of string list * expr
|
| Function of string list * expr * env
|
||||||
| External of string
|
| External of string
|
||||||
| Nop (* return of system operations (will be deprecated) *)
|
| Nop (* return of system operations (will be deprecated) *)
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ module Value = struct
|
||||||
| Bool b -> string_of_bool b
|
| Bool b -> string_of_bool b
|
||||||
| String s -> "\"" ^ s ^ "\""
|
| String s -> "\"" ^ s ^ "\""
|
||||||
| Symbol s -> "symbol " ^ s
|
| Symbol s -> "symbol " ^ s
|
||||||
| Function (vars, _) ->
|
| Function (vars, _, _) ->
|
||||||
Printf.sprintf "function with %d arguments" @@ List.length vars
|
Printf.sprintf "function with %d arguments" @@ List.length vars
|
||||||
| External f -> "external " ^ f
|
| External f -> "external " ^ f
|
||||||
| Nop -> "nop"
|
| Nop -> "nop"
|
||||||
|
@ -268,12 +268,20 @@ let rec eval env ast : string * value =
|
||||||
| Nbool b -> Bool b
|
| Nbool b -> Bool b
|
||||||
| Nstring s -> String s
|
| Nstring s -> String s
|
||||||
| Nsymbol s -> Symbol s
|
| Nsymbol s -> Symbol s
|
||||||
| Nfunction (args, e) -> Function (args, e)
|
| Nfunction (args, e) ->
|
||||||
|
let nenv = Env.make env in
|
||||||
|
Function (args, e, nenv)
|
||||||
| Nexternal f -> External f
|
| Nexternal f -> External f
|
||||||
|
|
||||||
| Var v -> begin match Env.get_opt env v with
|
| Var v -> begin match Env.get_opt env v with
|
||||||
| None -> raise @@ Unbound v
|
| None -> raise @@ Unbound v
|
||||||
| Some v -> v
|
| Some v -> v
|
||||||
end
|
end
|
||||||
|
| Letin (v, e, f) ->
|
||||||
|
let nenv = Env.make env in
|
||||||
|
Env.set nenv v (aux e);
|
||||||
|
snd @@ eval nenv f
|
||||||
|
|
||||||
| Unary (op, t) ->
|
| Unary (op, t) ->
|
||||||
let t = aux t in
|
let t = aux t in
|
||||||
let op = Operator.get_unary op in
|
let op = Operator.get_unary op in
|
||||||
|
@ -289,7 +297,7 @@ let rec eval env ast : string * value =
|
||||||
end
|
end
|
||||||
| Apply (v, args) ->
|
| Apply (v, args) ->
|
||||||
begin match aux v with
|
begin match aux v with
|
||||||
| Function (vars, e) ->
|
| Function (vars, e, env) ->
|
||||||
assert_same_length vars args;
|
assert_same_length vars args;
|
||||||
let args = List.map aux args in
|
let args = List.map aux args in
|
||||||
let nenv = Env.make env in
|
let nenv = Env.make env in
|
||||||
|
|
22
parser.ml
22
parser.ml
|
@ -81,7 +81,7 @@ let token_is_operator tok =
|
||||||
Hashtbl.mem operators tok
|
Hashtbl.mem operators tok
|
||||||
|
|
||||||
let is_keyword = function
|
let is_keyword = function
|
||||||
| "if" | "then" | "else" | "let" -> true
|
| "if" | "then" | "else" | "let" | "in" -> true
|
||||||
| _ -> false
|
| _ -> false
|
||||||
|
|
||||||
(* common parsers *)
|
(* common parsers *)
|
||||||
|
@ -155,17 +155,17 @@ let more f seq =
|
||||||
let xs, seq = aux [] seq in
|
let xs, seq = aux [] seq in
|
||||||
List.rev xs, seq
|
List.rev xs, seq
|
||||||
|
|
||||||
(* decl := let_value
|
(* decl := let_global
|
||||||
* | expr
|
* | expr
|
||||||
*)
|
*)
|
||||||
let rec decl seq =
|
let rec decl seq =
|
||||||
seq |> oneof [
|
seq |> oneof [
|
||||||
let_value;
|
|
||||||
expr min_int;
|
expr min_int;
|
||||||
|
let_global;
|
||||||
]
|
]
|
||||||
|
|
||||||
(* let_value := "let" ident "=" expr *)
|
(* let_global := "let" ident "=" expr *)
|
||||||
and let_value seq =
|
and let_global seq =
|
||||||
let _, seq = ident "let" seq in
|
let _, seq = ident "let" seq in
|
||||||
let id, seq = any_ident seq in
|
let id, seq = any_ident seq in
|
||||||
let _, seq = token Token.Equal seq in
|
let _, seq = token Token.Equal seq in
|
||||||
|
@ -173,6 +173,7 @@ and let_value seq =
|
||||||
Let (id, e), seq
|
Let (id, e), seq
|
||||||
|
|
||||||
(* expr := level
|
(* expr := level
|
||||||
|
* | let_value
|
||||||
* | assoc
|
* | assoc
|
||||||
* | apply
|
* | apply
|
||||||
* | value binop_right
|
* | value binop_right
|
||||||
|
@ -180,6 +181,7 @@ and let_value seq =
|
||||||
and expr pre seq =
|
and expr pre seq =
|
||||||
seq |> oneof [
|
seq |> oneof [
|
||||||
ifexpr;
|
ifexpr;
|
||||||
|
let_value;
|
||||||
oneof [apply; unary; value] @> binop pre;
|
oneof [apply; unary; value] @> binop pre;
|
||||||
level;
|
level;
|
||||||
assoc;
|
assoc;
|
||||||
|
@ -187,6 +189,16 @@ and expr pre seq =
|
||||||
extern_value;
|
extern_value;
|
||||||
]
|
]
|
||||||
|
|
||||||
|
(* let_value := "let" id "=" expr "in" expr *)
|
||||||
|
and let_value seq =
|
||||||
|
let _, seq = ident "let" seq in
|
||||||
|
let id, seq = any_ident seq in
|
||||||
|
let _, seq = token Equal seq in
|
||||||
|
let e, seq = expr min_int seq in
|
||||||
|
let _, seq = ident "in" seq in
|
||||||
|
let f, seq = expr min_int seq in
|
||||||
|
Letin (id, e, f), seq
|
||||||
|
|
||||||
(* level := "level" {"get" | "set"} [op] *)
|
(* level := "level" {"get" | "set"} [op] *)
|
||||||
and level seq =
|
and level seq =
|
||||||
let _, seq = ident "level" seq in
|
let _, seq = ident "level" seq in
|
||||||
|
|
Loading…
Add table
Reference in a new issue