Merge Binop and Unary to Operator

This commit is contained in:
백현웅 2022-01-28 00:56:24 +09:00
parent bb2ee45c33
commit 282fbfa738
3 changed files with 31 additions and 39 deletions

60
ast.ml
View file

@ -41,31 +41,13 @@ module Value = struct
| _ -> failwith "Value.promote" | _ -> failwith "Value.promote"
end end
module Unary = struct (* operators *)
type t = module Operator = struct
| Negate
let to_string = function
| Negate -> "-"
let negate = function
| Value.Int n -> Value.Int ~-n
| Float n -> Value.Float ~-.n
| _ -> failwith "Unary.negate"
let get op _typ =
match op with
| Negate -> negate
end
(* binary operator *)
(* binary operator has type 'a -> 'a -> 'b. *)
module Binop = struct
type t = type t =
| Add | Sub | Mul | Div (* arithmetics *) | Add | Sub | Mul | Div (* arithmetics *)
| Mod (* modular operation *) | Mod (* modular operation *)
| Exp (* exponentation *) | Exp (* exponentation *)
| Negate
exception Unavailable of t exception Unavailable of t
@ -76,6 +58,12 @@ module Binop = struct
| Div -> "/" | Div -> "/"
| Mod -> "%" | Mod -> "%"
| Exp -> "^" | Exp -> "^"
| Negate -> "-"
let negate = function
| Value.Int n -> Value.Int ~-n
| Float n -> Value.Float ~-.n
| _ -> failwith "Operator.negate"
let vi f a b = let vi f a b =
let open Value in let open Value in
@ -108,7 +96,11 @@ module Binop = struct
| None -> raise @@ Unavailable op | None -> raise @@ Unavailable op
| Some p -> List.map fst p | Some p -> List.map fst p
let get op typ = let get_unary = function
| Negate -> negate
| op -> raise @@ Unavailable op
let get_binary op typ =
Hashtbl.find operators op Hashtbl.find operators op
|> List.assoc_opt typ |> List.assoc_opt typ
end end
@ -117,12 +109,12 @@ type t =
| Value of Value.t | Value of Value.t
| Var of string | Var of string
| Let of string * t | Let of string * t
| Unary of Unary.t * t | Unary of Operator.t * t
| Binop of t * Binop.t * t | Binop of t * Operator.t * t
| Set_binop_pre of Binop.t * t | Set_binop_pre of Operator.t * t
| Get_binop_pre of Binop.t | Get_binop_pre of Operator.t
| Set_binop_aso of Binop.t * string | Set_binop_aso of Operator.t * string
| Get_binop_aso of Binop.t | Get_binop_aso of Operator.t
let value v = Value v let value v = Value v
@ -144,22 +136,22 @@ let print ast =
aux e; aux e;
pr ")" pr ")"
| Unary (op, t) -> begin | Unary (op, t) -> begin
let op = Unary.to_string op in let op = Operator.to_string op in
pr "(%s " op; aux t; pr ")"; pr "(%s " op; aux t; pr ")";
end end
| Binop (left, op, right) -> begin | Binop (left, op, right) -> begin
let op = Binop.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 end
| Set_binop_pre (op, pre) -> | Set_binop_pre (op, pre) ->
pr "(set_pre %s " (Binop.to_string op); pr "(set_pre %s " (Operator.to_string op);
aux pre; aux pre;
pr ")" pr ")"
| Get_binop_pre op -> | Get_binop_pre op ->
pr "(get_pre %s)" (Binop.to_string op) pr "(get_pre %s)" (Operator.to_string op)
| Set_binop_aso (op, aso) -> | Set_binop_aso (op, aso) ->
pr "(set_assoc %s %s)" (Binop.to_string op) aso pr "(set_assoc %s %s)" (Operator.to_string op) aso
| Get_binop_aso op -> | Get_binop_aso op ->
pr "(get_pre %s)" (Binop.to_string op) pr "(get_pre %s)" (Operator.to_string op)
in in
aux ast; pr "\n" aux ast; pr "\n"

View file

@ -5,7 +5,7 @@ exception No_operation
exception No_such_variable of string exception No_such_variable of string
let resolve_type op tp = let resolve_type op tp =
let optypes = Binop.get_types op in let optypes = Operator.get_types op in
let q = Queue.create () in let q = Queue.create () in
let rec aux (t1, t2) = let rec aux (t1, t2) =
if List.mem (t1, t2) optypes then if List.mem (t1, t2) optypes then
@ -30,7 +30,7 @@ let rec binop op l r =
in in
let l = promote_until t1 l let l = promote_until t1 l
and r = promote_until t2 r in and r = promote_until t2 r in
match Binop.get op (t1, t2) with match Operator.get_binary op (t1, t2) with
| None -> begin | None -> begin
try binop op (promote l) (promote r) try binop op (promote l) (promote r)
with _ -> raise No_operation with _ -> raise No_operation
@ -46,7 +46,7 @@ let eval vars ast =
end end
| Unary (op, t) -> | Unary (op, t) ->
let t = aux t in let t = aux t in
let op = Unary.get op (Value.typeof t) in let op = Operator.get_unary op in
op t op t
| Binop (l, op, r) -> | Binop (l, op, r) ->
let l = aux l and r = aux r in let l = aux l and r = aux r in

View file

@ -1,5 +1,5 @@
open Ast open Ast
open Ast.Binop open Ast.Operator
module S = Set.Make(String) module S = Set.Make(String)
@ -177,7 +177,7 @@ and unary seq =
| Seq.Nil -> raise End_of_tokens | Seq.Nil -> raise End_of_tokens
| Seq.Cons (x, seq) -> | Seq.Cons (x, seq) ->
if x = Minus if x = Minus
then Unary.Negate, seq then Negate, seq
else expected "minus" else expected "minus"
in in
let v, seq = value seq in let v, seq = value seq in