Move Value module into Env
This commit is contained in:
parent
995d95df41
commit
05797676ce
4 changed files with 110 additions and 110 deletions
102
ast.ml
102
ast.ml
|
@ -30,6 +30,7 @@ type t =
|
|||
| Unary of operator * t
|
||||
| Binop of t * operator * t
|
||||
| Apply of t * t list (* function application *)
|
||||
(* these will be seperated into (toplevel) directives. *)
|
||||
| Set_binop_pre of operator * t
|
||||
| Get_binop_pre of operator
|
||||
| Set_binop_aso of operator * string
|
||||
|
@ -41,49 +42,7 @@ and operator =
|
|||
| Exp (* exponentation *)
|
||||
| Negate
|
||||
|
||||
exception Invalid_type of Type.t
|
||||
|
||||
module Value = struct
|
||||
type expr = t
|
||||
|
||||
type t =
|
||||
| Int of int
|
||||
| Float of float
|
||||
| String of string
|
||||
| Function of string list * expr
|
||||
| External of string
|
||||
| Nop (* return of system operations (will be deprecated) *)
|
||||
|
||||
let to_string = function
|
||||
| Int n -> string_of_int n
|
||||
| Float n -> string_of_float n
|
||||
| String s -> "\"" ^ s ^ "\""
|
||||
| Function (vars, _) ->
|
||||
Printf.sprintf "function with %d arguments" @@ List.length vars
|
||||
| External f -> "external " ^ f
|
||||
| Nop -> "nop"
|
||||
|
||||
let typeof = function
|
||||
| Int _ -> Type.Int
|
||||
| Float _ -> Type.Float
|
||||
| String _ -> Type.String
|
||||
| Function _ -> Type.Function
|
||||
| External _ -> Type.External
|
||||
| Nop -> failwith "Value.typeof"
|
||||
|
||||
let promote = function
|
||||
| Int n -> Float (float n)
|
||||
| Float n -> Float n
|
||||
| _ -> failwith "Value.promote"
|
||||
end
|
||||
|
||||
(* operators *)
|
||||
module Operator = struct
|
||||
type t = operator
|
||||
|
||||
exception Unavailable of t
|
||||
|
||||
let to_string = function
|
||||
let op_to_string = function
|
||||
| Add -> "+"
|
||||
| Sub -> "-"
|
||||
| Mul -> "*"
|
||||
|
@ -92,51 +51,6 @@ module Operator = struct
|
|||
| Exp -> "^"
|
||||
| Negate -> "-"
|
||||
|
||||
open Value
|
||||
|
||||
let negate = function
|
||||
| Int n -> Int ~-n
|
||||
| Float n -> Float ~-.n
|
||||
| _ -> failwith "Operator.negate"
|
||||
|
||||
let vi f a b =
|
||||
match a, b with
|
||||
| Int a, Int b -> Int (f a b)
|
||||
| _ -> raise @@ Invalid_type Int
|
||||
|
||||
let vf f a b =
|
||||
match a, b with
|
||||
| Float a, Float b -> Float (f a b)
|
||||
| _ -> raise @@ Invalid_type Float
|
||||
|
||||
let operators =
|
||||
let open Type in
|
||||
let ip = Int, Int and fp = Float, Float in
|
||||
[
|
||||
Add, [ip, vi Int.add; fp, vf Float.add];
|
||||
Sub, [ip, vi Int.sub; fp, vf Float.sub];
|
||||
Mul, [ip, vi Int.mul; fp, vf Float.mul];
|
||||
Div, [ip, vi Int.div; fp, vf Float.div];
|
||||
Mod, [ip, vi Int.rem; fp, vf Float.rem];
|
||||
Exp, [fp, vf Float.pow];
|
||||
]
|
||||
|> List.to_seq
|
||||
|> Hashtbl.of_seq
|
||||
|
||||
let get_types op =
|
||||
match Hashtbl.find_opt operators op with
|
||||
| None -> raise @@ Unavailable op
|
||||
| Some p -> List.map fst p
|
||||
|
||||
let get_unary = function
|
||||
| Negate -> negate
|
||||
| op -> raise @@ Unavailable op
|
||||
|
||||
let get_binary op typ =
|
||||
Hashtbl.find operators op
|
||||
|> List.assoc_opt typ
|
||||
end
|
||||
|
||||
let unary op t =
|
||||
Unary (op, t)
|
||||
|
||||
|
@ -159,23 +73,23 @@ let print ast =
|
|||
| Let (v, e) ->
|
||||
pr "(let %s " v; aux e; pr ")"
|
||||
| Unary (op, t) ->
|
||||
let op = Operator.to_string op in
|
||||
let op = op_to_string op in
|
||||
pr "(%s " op; aux t; pr ")"
|
||||
| Binop (left, op, right) ->
|
||||
let op = Operator.to_string op in
|
||||
let op = op_to_string op in
|
||||
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);
|
||||
pr "(set_pre %s " (op_to_string op);
|
||||
aux pre;
|
||||
pr ")"
|
||||
| Get_binop_pre op ->
|
||||
pr "(get_pre %s)" (Operator.to_string op)
|
||||
pr "(get_pre %s)" (op_to_string op)
|
||||
| Set_binop_aso (op, aso) ->
|
||||
pr "(set_assoc %s %s)" (Operator.to_string op) aso
|
||||
pr "(set_assoc %s %s)" (op_to_string op) aso
|
||||
| Get_binop_aso op ->
|
||||
pr "(get_pre %s)" (Operator.to_string op)
|
||||
pr "(get_pre %s)" (op_to_string op)
|
||||
in
|
||||
aux ast; pr "\n"
|
||||
|
|
40
env.ml
40
env.ml
|
@ -1,10 +1,44 @@
|
|||
module Value = Ast.Value
|
||||
|
||||
type t = {
|
||||
vars : (string, Value.t) Hashtbl.t;
|
||||
vars : (string, value) Hashtbl.t;
|
||||
parent : t option;
|
||||
}
|
||||
|
||||
and value =
|
||||
| Int of int
|
||||
| Float of float
|
||||
| String of string
|
||||
| Function of string list * expr
|
||||
| External of string
|
||||
| Nop (* return of system operations (will be deprecated) *)
|
||||
|
||||
and expr = Ast.t
|
||||
|
||||
module Value = struct
|
||||
module Type = Ast.Type
|
||||
type t = value
|
||||
|
||||
let to_string = function
|
||||
| Int n -> string_of_int n
|
||||
| Float n -> string_of_float n
|
||||
| String s -> "\"" ^ s ^ "\""
|
||||
| Function (vars, _) ->
|
||||
Printf.sprintf "function with %d arguments" @@ List.length vars
|
||||
| External f -> "external " ^ f
|
||||
| Nop -> "nop"
|
||||
|
||||
let typeof = function
|
||||
| Int _ -> Type.Int
|
||||
| Float _ -> Type.Float
|
||||
| String _ -> Type.String
|
||||
| Function _ -> Type.Function
|
||||
| External _ -> Type.External
|
||||
| Nop -> failwith "Value.typeof"
|
||||
|
||||
let promote = function
|
||||
| Int n -> Float (float n)
|
||||
| _ -> failwith "Value.promote"
|
||||
end
|
||||
|
||||
let init_global () = {
|
||||
vars = Hashtbl.create 100;
|
||||
parent = None;
|
||||
|
|
56
eval.ml
56
eval.ml
|
@ -1,12 +1,65 @@
|
|||
open Ast
|
||||
open Ast.Value
|
||||
open Env
|
||||
open Env.Value
|
||||
|
||||
exception No_operation
|
||||
exception No_such_variable of string
|
||||
exception No_such_function of string
|
||||
exception Invalid_type of Type.t
|
||||
|
||||
exception Too_many_arguments
|
||||
|
||||
(* operators *)
|
||||
module Operator = struct
|
||||
type t = Ast.operator
|
||||
|
||||
exception Unavailable of t
|
||||
|
||||
let to_string = Ast.op_to_string
|
||||
|
||||
let negate = function
|
||||
| Int n -> Int ~-n
|
||||
| Float n -> Float ~-.n
|
||||
| _ -> failwith "Operator.negate"
|
||||
|
||||
let vi f a b =
|
||||
match a, b with
|
||||
| Int a, Int b -> Int (f a b)
|
||||
| _ -> raise @@ Invalid_type Int
|
||||
|
||||
let vf f a b =
|
||||
match a, b with
|
||||
| Float a, Float b -> Float (f a b)
|
||||
| _ -> raise @@ Invalid_type Float
|
||||
|
||||
let operators =
|
||||
let open Type in
|
||||
let ip = Int, Int and fp = Float, Float in
|
||||
[
|
||||
Add, [ip, vi Int.add; fp, vf Float.add];
|
||||
Sub, [ip, vi Int.sub; fp, vf Float.sub];
|
||||
Mul, [ip, vi Int.mul; fp, vf Float.mul];
|
||||
Div, [ip, vi Int.div; fp, vf Float.div];
|
||||
Mod, [ip, vi Int.rem; fp, vf Float.rem];
|
||||
Exp, [fp, vf Float.pow];
|
||||
]
|
||||
|> List.to_seq
|
||||
|> Hashtbl.of_seq
|
||||
|
||||
let get_types op =
|
||||
match Hashtbl.find_opt operators op with
|
||||
| None -> raise @@ Unavailable op
|
||||
| Some p -> List.map fst p
|
||||
|
||||
let get_unary = function
|
||||
| Negate -> negate
|
||||
| op -> raise @@ Unavailable op
|
||||
|
||||
let get_binary op typ =
|
||||
Hashtbl.find operators op
|
||||
|> List.assoc_opt typ
|
||||
end
|
||||
|
||||
let assert_same_length vars args =
|
||||
let vl = List.length vars
|
||||
and al = List.length args in
|
||||
|
@ -14,7 +67,6 @@ let assert_same_length vars args =
|
|||
failwith "assert_same_length"
|
||||
else if vl < al then
|
||||
raise Too_many_arguments
|
||||
else ()
|
||||
|
||||
let resolve_type op tp =
|
||||
let optypes = Operator.get_types op in
|
||||
|
|
8
main.ml
8
main.ml
|
@ -8,7 +8,7 @@ let error_to_string e =
|
|||
| Lex.Expected c -> sprintf "expected %c" c
|
||||
| Parser.Expected t -> sprintf "expected %s" t
|
||||
| Parser.Unexpected_token t -> sprintf "unexpected token \"%s\"" t
|
||||
| Ast.Invalid_type t -> sprintf "invalid type %s" (Ast.Type.to_string t)
|
||||
| Eval.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
|
||||
| Eval.Too_many_arguments -> "applied too many arguments"
|
||||
|
@ -24,7 +24,7 @@ let stdlib = [
|
|||
"deg"; "rad";
|
||||
]
|
||||
|> List.to_seq
|
||||
|> Seq.map (fun v -> v, Ast.Value.External v)
|
||||
|> Seq.map (fun v -> v, Env.External v)
|
||||
|
||||
let g =
|
||||
let g = Env.init_global () in
|
||||
|
@ -46,12 +46,12 @@ let rep env : unit =
|
|||
| Nop -> ()
|
||||
| _ ->
|
||||
Env.set env "ans" v;
|
||||
printf "%s\n" @@ Ast.Value.to_string v
|
||||
printf "%s\n" @@ Env.Value.to_string v
|
||||
|
||||
exception Reset_line (* used to indicate ^C is pressed *)
|
||||
|
||||
let init_repl () =
|
||||
Env.set g "ans" (Ast.Value.Int 0);
|
||||
Env.set g "ans" (Env.Int 0);
|
||||
(* treat Ctrl-C as to reset line *)
|
||||
let reset_line _ = raise Reset_line in
|
||||
Sys.(set_signal sigint (Signal_handle reset_line))
|
||||
|
|
Loading…
Add table
Reference in a new issue