2022-01-18 16:52:33 +09:00
|
|
|
module Type = struct
|
|
|
|
type t =
|
|
|
|
| Int
|
|
|
|
| Float
|
2022-01-20 23:36:53 +09:00
|
|
|
| String
|
2022-01-18 16:52:33 +09:00
|
|
|
|
|
|
|
let to_string = function
|
|
|
|
| Int -> "int"
|
|
|
|
| Float -> "float"
|
2022-01-20 23:36:53 +09:00
|
|
|
| String -> "string"
|
2022-01-18 16:52:33 +09:00
|
|
|
|
|
|
|
let merge a b =
|
|
|
|
match a, b with
|
|
|
|
| Int, Float -> Float
|
|
|
|
| Float, Int -> Float
|
|
|
|
| a, b when a = b -> a
|
|
|
|
| _ -> failwith "Type.merge"
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
exception Invalid_type of Type.t
|
|
|
|
|
|
|
|
module Value = struct
|
|
|
|
type t =
|
|
|
|
| Int of int
|
|
|
|
| Float of float
|
2022-01-20 23:36:53 +09:00
|
|
|
| String of string
|
2022-01-18 16:52:33 +09:00
|
|
|
| Nop (* return of system operations *)
|
|
|
|
|
|
|
|
let to_string = function
|
2022-01-20 23:36:53 +09:00
|
|
|
| Int n -> string_of_int n
|
|
|
|
| Float n -> string_of_float n
|
2022-01-21 02:17:34 +09:00
|
|
|
| String s -> "\"" ^ s ^ "\""
|
2022-01-18 16:52:33 +09:00
|
|
|
| Nop -> "nop"
|
|
|
|
|
|
|
|
let typeof = function
|
|
|
|
| Int _ -> Type.Int
|
|
|
|
| Float _ -> Type.Float
|
2022-01-20 23:36:53 +09:00
|
|
|
| String _ -> Type.String
|
2022-01-18 16:52:33 +09:00
|
|
|
| Nop -> failwith "Value.typeof"
|
|
|
|
|
|
|
|
let promote = function
|
|
|
|
| Int n -> Float (float n)
|
|
|
|
| Float n -> Float n
|
|
|
|
| _ -> failwith "Value.promote"
|
|
|
|
end
|
|
|
|
|
|
|
|
(* binary operator *)
|
2022-01-19 02:10:34 +09:00
|
|
|
(* binary operator has type 'a -> 'a -> 'b. *)
|
2022-01-18 16:52:33 +09:00
|
|
|
module Binop = struct
|
|
|
|
type t =
|
|
|
|
| Add | Sub | Mul | Div (* arithmetics *)
|
|
|
|
| Mod (* modular operation *)
|
|
|
|
| Exp (* exponentation *)
|
|
|
|
|
|
|
|
let to_string = function
|
|
|
|
| Add -> "+"
|
|
|
|
| Sub -> "-"
|
|
|
|
| Mul -> "*"
|
|
|
|
| Div -> "/"
|
|
|
|
| Mod -> "%"
|
|
|
|
| Exp -> "^"
|
|
|
|
|
|
|
|
let vi f a b =
|
|
|
|
let open Value in
|
|
|
|
match a, b with
|
|
|
|
| Int a, Int b -> Int (f a b)
|
|
|
|
| _ -> raise @@ Invalid_type Int
|
|
|
|
|
|
|
|
let vf f a b =
|
|
|
|
let open Value in
|
|
|
|
match a, b with
|
|
|
|
| Float a, Float b -> Float (f a b)
|
|
|
|
| _ -> raise @@ Invalid_type Float
|
|
|
|
|
|
|
|
let operators =
|
|
|
|
let open Type in
|
|
|
|
[
|
|
|
|
Add, [Int, vi Int.add; Float, vf Float.add];
|
|
|
|
Sub, [Int, vi Int.sub; Float, vf Float.sub];
|
|
|
|
Mul, [Int, vi Int.mul; Float, vf Float.mul];
|
|
|
|
Div, [Int, vi Int.div; Float, vf Float.div];
|
|
|
|
Mod, [Int, vi Int.rem; Float, vf Float.rem];
|
|
|
|
Exp, [Float, vf Float.pow];
|
|
|
|
]
|
|
|
|
|> List.to_seq
|
|
|
|
|> Hashtbl.of_seq
|
|
|
|
|
|
|
|
let get op typ =
|
|
|
|
Hashtbl.find operators op
|
|
|
|
|> List.assoc_opt typ
|
|
|
|
end
|
2022-01-10 01:31:47 +09:00
|
|
|
|
2022-01-10 23:11:13 +09:00
|
|
|
type t =
|
2022-01-18 16:52:33 +09:00
|
|
|
| Value of Value.t
|
2022-01-19 14:17:04 +09:00
|
|
|
| Var of string
|
2022-01-21 00:17:01 +09:00
|
|
|
| Let of string * t
|
2022-01-18 16:52:33 +09:00
|
|
|
| Binop of t * Binop.t * t
|
|
|
|
| Set_binop_pre of Binop.t * t
|
|
|
|
| Get_binop_pre of Binop.t
|
2022-01-20 23:36:53 +09:00
|
|
|
| Set_binop_aso of Binop.t * string
|
|
|
|
| Get_binop_aso of Binop.t
|
2022-01-10 01:31:47 +09:00
|
|
|
|
|
|
|
let value v = Value v
|
|
|
|
|
|
|
|
let binop left op right =
|
|
|
|
Binop (left, op, right)
|
|
|
|
|
|
|
|
(* print ast LISP style. *)
|
|
|
|
let print ast =
|
|
|
|
let pr = Printf.printf in
|
2022-01-18 16:52:33 +09:00
|
|
|
let pv v = pr "%s" @@ Value.to_string v in
|
2022-01-10 23:11:13 +09:00
|
|
|
let rec aux = function
|
2022-01-10 01:31:47 +09:00
|
|
|
| Value n -> pv n
|
2022-01-19 14:17:04 +09:00
|
|
|
| Var v -> pr "%s" v
|
2022-01-21 00:17:01 +09:00
|
|
|
| Let (v, e) ->
|
|
|
|
pr "(let %s " v;
|
|
|
|
aux e;
|
|
|
|
pr ")"
|
2022-01-10 01:31:47 +09:00
|
|
|
| Binop (left, op, right) -> begin
|
2022-01-18 16:52:33 +09:00
|
|
|
let op = Binop.to_string op in
|
|
|
|
pr "(%s " op; aux left; pr " "; aux right; pr ")";
|
2022-01-10 01:31:47 +09:00
|
|
|
end
|
|
|
|
| Set_binop_pre (op, pre) ->
|
2022-01-18 16:52:33 +09:00
|
|
|
pr "(set_pre %s " (Binop.to_string op);
|
2022-01-10 01:31:47 +09:00
|
|
|
aux pre;
|
|
|
|
pr ")"
|
2022-01-11 01:05:29 +09:00
|
|
|
| Get_binop_pre op ->
|
2022-01-18 16:52:33 +09:00
|
|
|
pr "(get_pre %s)" (Binop.to_string op)
|
2022-01-20 23:36:53 +09:00
|
|
|
| Set_binop_aso (op, aso) ->
|
|
|
|
pr "(set_assoc %s %s)" (Binop.to_string op) aso
|
|
|
|
| Get_binop_aso op ->
|
|
|
|
pr "(get_pre %s)" (Binop.to_string op)
|
2022-01-10 01:31:47 +09:00
|
|
|
in
|
|
|
|
aux ast; pr "\n"
|