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
|
| Let of string * t
|
||||||
| Unary of Operator.t * t
|
| Unary of Operator.t * t
|
||||||
| Binop of t * Operator.t * t
|
| Binop of t * Operator.t * t
|
||||||
|
| Apply of t * t list
|
||||||
| Set_binop_pre of Operator.t * t
|
| Set_binop_pre of Operator.t * t
|
||||||
| Get_binop_pre of Operator.t
|
| Get_binop_pre of Operator.t
|
||||||
| Set_binop_aso of Operator.t * string
|
| Set_binop_aso of Operator.t * string
|
||||||
|
@ -132,17 +133,16 @@ let print ast =
|
||||||
| Value n -> pv n
|
| Value n -> pv n
|
||||||
| Var v -> pr "%s" v
|
| Var v -> pr "%s" v
|
||||||
| Let (v, e) ->
|
| Let (v, e) ->
|
||||||
pr "(let %s " v;
|
pr "(let %s " v; aux e; pr ")"
|
||||||
aux e;
|
| Unary (op, t) ->
|
||||||
pr ")"
|
|
||||||
| Unary (op, t) -> begin
|
|
||||||
let op = Operator.to_string op in
|
let op = Operator.to_string op in
|
||||||
pr "(%s " op; aux t; pr ")";
|
pr "(%s " op; aux t; pr ")"
|
||||||
end
|
| Binop (left, op, right) ->
|
||||||
| Binop (left, op, right) -> begin
|
|
||||||
let op = Operator.to_string op in
|
let op = Operator.to_string op in
|
||||||
pr "(%s " op; aux left; pr " "; aux right; pr ")";
|
pr "(%s " op; aux left; pr " "; aux right; pr ")"
|
||||||
end
|
| Apply (f, args) ->
|
||||||
|
pr "("; List.iter aux @@ f::args; pr ")"
|
||||||
|
|
||||||
| Set_binop_pre (op, pre) ->
|
| Set_binop_pre (op, pre) ->
|
||||||
pr "(set_pre %s " (Operator.to_string op);
|
pr "(set_pre %s " (Operator.to_string op);
|
||||||
aux pre;
|
aux pre;
|
||||||
|
|
27
eval.ml
27
eval.ml
|
@ -3,6 +3,7 @@ open Ast.Value
|
||||||
|
|
||||||
exception No_operation
|
exception No_operation
|
||||||
exception No_such_variable of string
|
exception No_such_variable of string
|
||||||
|
exception No_such_function of string
|
||||||
|
|
||||||
let resolve_type op tp =
|
let resolve_type op tp =
|
||||||
let optypes = Operator.get_types op in
|
let optypes = Operator.get_types op in
|
||||||
|
@ -37,6 +38,25 @@ let rec binop op l r =
|
||||||
end
|
end
|
||||||
| Some f -> f l r
|
| 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 eval vars ast =
|
||||||
let rec aux = function
|
let rec aux = function
|
||||||
| Value v -> v
|
| Value v -> v
|
||||||
|
@ -55,6 +75,13 @@ let eval vars ast =
|
||||||
let v = aux e in
|
let v = aux e in
|
||||||
Hashtbl.replace vars var v;
|
Hashtbl.replace vars var v;
|
||||||
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) ->
|
| Set_binop_pre (op, l) ->
|
||||||
let l =
|
let l =
|
||||||
match aux l with
|
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
|
| Parser.Unexpected_token t -> sprintf "unexpected token \"%s\"" t
|
||||||
| Ast.Invalid_type t -> sprintf "invalid type %s" (Ast.Type.to_string 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_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
|
| Failure f -> sprintf "error on %s" f
|
||||||
| Division_by_zero -> "cannot divide by zero"
|
| Division_by_zero -> "cannot divide by zero"
|
||||||
| _ -> raise e
|
| _ -> raise e
|
||||||
|
|
26
parser.ml
26
parser.ml
|
@ -117,13 +117,28 @@ let oneof fs seq =
|
||||||
in
|
in
|
||||||
aux fs
|
aux fs
|
||||||
|
|
||||||
|
let either f g = fun seq ->
|
||||||
|
try f seq with _ -> g seq
|
||||||
|
|
||||||
let (@>) f g = fun seq ->
|
let (@>) f g = fun seq ->
|
||||||
let a, seq = f seq in
|
let a, seq = f seq in
|
||||||
g a seq
|
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
|
(* expr := level
|
||||||
* | assoc
|
* | assoc
|
||||||
* | let
|
* | let
|
||||||
|
* | apply
|
||||||
* | value binop_right
|
* | value binop_right
|
||||||
*)
|
*)
|
||||||
let rec expr pre seq =
|
let rec expr pre seq =
|
||||||
|
@ -131,9 +146,8 @@ let rec expr pre seq =
|
||||||
level;
|
level;
|
||||||
assoc;
|
assoc;
|
||||||
let_value;
|
let_value;
|
||||||
(* TODO: merge these two *)
|
apply;
|
||||||
unary @> binop pre;
|
(either unary value) @> binop pre;
|
||||||
value @> binop pre;
|
|
||||||
]
|
]
|
||||||
|
|
||||||
(* level := "level" {"get" | "set"} [op] *)
|
(* level := "level" {"get" | "set"} [op] *)
|
||||||
|
@ -170,6 +184,12 @@ and let_value seq =
|
||||||
let e, seq = expr min_int seq in
|
let e, seq = expr min_int seq in
|
||||||
Let (id, e), seq
|
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 *)
|
(* unary := - value *)
|
||||||
and unary seq =
|
and unary seq =
|
||||||
let op, seq =
|
let op, seq =
|
||||||
|
|
Loading…
Add table
Reference in a new issue