Add basic function evaluation
This commit is contained in:
parent
b699ed6b2f
commit
c33fd366ee
4 changed files with 60 additions and 12 deletions
18
ast.ml
18
ast.ml
|
@ -111,6 +111,7 @@ type t =
|
|||
| Let of string * t
|
||||
| Unary of Operator.t * t
|
||||
| Binop of t * Operator.t * t
|
||||
| Apply of t * t list
|
||||
| Set_binop_pre of Operator.t * t
|
||||
| Get_binop_pre of Operator.t
|
||||
| Set_binop_aso of Operator.t * string
|
||||
|
@ -132,17 +133,16 @@ let print ast =
|
|||
| Value n -> pv n
|
||||
| Var v -> pr "%s" v
|
||||
| Let (v, e) ->
|
||||
pr "(let %s " v;
|
||||
aux e;
|
||||
pr ")"
|
||||
| Unary (op, t) -> begin
|
||||
pr "(let %s " v; aux e; pr ")"
|
||||
| Unary (op, t) ->
|
||||
let op = Operator.to_string op in
|
||||
pr "(%s " op; aux t; pr ")";
|
||||
end
|
||||
| Binop (left, op, right) -> begin
|
||||
pr "(%s " op; aux t; pr ")"
|
||||
| Binop (left, op, right) ->
|
||||
let op = Operator.to_string op in
|
||||
pr "(%s " op; aux left; pr " "; aux right; pr ")";
|
||||
end
|
||||
pr "(%s " op; aux left; pr " "; aux right; pr ")"
|
||||
| Apply (f, args) ->
|
||||
pr "("; List.iter aux @@ f::args; pr ")"
|
||||
|
||||
| Set_binop_pre (op, pre) ->
|
||||
pr "(set_pre %s " (Operator.to_string op);
|
||||
aux pre;
|
||||
|
|
27
eval.ml
27
eval.ml
|
@ -3,6 +3,7 @@ open Ast.Value
|
|||
|
||||
exception No_operation
|
||||
exception No_such_variable of string
|
||||
exception No_such_function of string
|
||||
|
||||
let resolve_type op tp =
|
||||
let optypes = Operator.get_types op in
|
||||
|
@ -37,6 +38,25 @@ let rec binop op l r =
|
|||
end
|
||||
| Some f -> f l r
|
||||
|
||||
let deg r =
|
||||
r *. 180. /. Float.pi
|
||||
|
||||
let rad d =
|
||||
d /. 180. *. Float.pi
|
||||
|
||||
let floatfun f = function
|
||||
| Float n -> Float (f n)
|
||||
| v -> raise @@ Invalid_type (typeof v)
|
||||
|
||||
let apply f args =
|
||||
match f, args with
|
||||
| "sin", [n] -> floatfun Float.sin n
|
||||
| "cos", [n] -> floatfun Float.cos n
|
||||
| "tan", [n] -> floatfun Float.tan n
|
||||
| "deg", [n] -> floatfun deg n
|
||||
| "rad", [n] -> floatfun rad n
|
||||
| _ -> raise @@ No_such_function f
|
||||
|
||||
let eval vars ast =
|
||||
let rec aux = function
|
||||
| Value v -> v
|
||||
|
@ -55,6 +75,13 @@ let eval vars ast =
|
|||
let v = aux e in
|
||||
Hashtbl.replace vars var v;
|
||||
v
|
||||
| Apply (v, args) ->
|
||||
let args = List.map aux args in
|
||||
begin match v with
|
||||
| Var id -> apply id args
|
||||
| _ -> assert false
|
||||
end
|
||||
|
||||
| Set_binop_pre (op, l) ->
|
||||
let l =
|
||||
match aux l with
|
||||
|
|
1
main.ml
1
main.ml
|
@ -10,6 +10,7 @@ let error_to_string e =
|
|||
| Parser.Unexpected_token t -> sprintf "unexpected token \"%s\"" t
|
||||
| Ast.Invalid_type t -> sprintf "invalid type %s" (Ast.Type.to_string t)
|
||||
| Eval.No_such_variable v -> sprintf "no such variable %s" v
|
||||
| Eval.No_such_function f -> sprintf "no such function \"%s\"" f
|
||||
| Failure f -> sprintf "error on %s" f
|
||||
| Division_by_zero -> "cannot divide by zero"
|
||||
| _ -> raise e
|
||||
|
|
26
parser.ml
26
parser.ml
|
@ -117,13 +117,28 @@ let oneof fs seq =
|
|||
in
|
||||
aux fs
|
||||
|
||||
let either f g = fun seq ->
|
||||
try f seq with _ -> g seq
|
||||
|
||||
let (@>) f g = fun seq ->
|
||||
let a, seq = f seq in
|
||||
g a seq
|
||||
|
||||
let more f seq =
|
||||
let rec aux xs seq =
|
||||
try
|
||||
let x, seq = f seq in
|
||||
aux (x::xs) seq
|
||||
with
|
||||
| _ -> xs, seq
|
||||
in
|
||||
let xs, seq = aux [] seq in
|
||||
List.rev xs, seq
|
||||
|
||||
(* expr := level
|
||||
* | assoc
|
||||
* | let
|
||||
* | apply
|
||||
* | value binop_right
|
||||
*)
|
||||
let rec expr pre seq =
|
||||
|
@ -131,9 +146,8 @@ let rec expr pre seq =
|
|||
level;
|
||||
assoc;
|
||||
let_value;
|
||||
(* TODO: merge these two *)
|
||||
unary @> binop pre;
|
||||
value @> binop pre;
|
||||
apply;
|
||||
(either unary value) @> binop pre;
|
||||
]
|
||||
|
||||
(* level := "level" {"get" | "set"} [op] *)
|
||||
|
@ -170,6 +184,12 @@ and let_value seq =
|
|||
let e, seq = expr min_int seq in
|
||||
Let (id, e), seq
|
||||
|
||||
(* apply := ident [value]* *)
|
||||
and apply seq =
|
||||
let id, seq = any_ident seq in
|
||||
let args, seq = more value seq in
|
||||
Apply (Var id, args), seq
|
||||
|
||||
(* unary := - value *)
|
||||
and unary seq =
|
||||
let op, seq =
|
||||
|
|
Loading…
Add table
Reference in a new issue