type literal = String of string | Number of float | Bool of bool | Nil [@@deriving show { with_path = false }] (* let show_literal literal = match literal with | String s -> s | Number x -> string_of_float x | Bool b -> string_of_bool b | Nil -> "nil" *) type binary_op = | Plus | Minus | Mul | Div | Equal | Less | Greater | LessEqual | GreaterEqual | And | Or [@@deriving show { with_path = false }] type unary_op = Neg | Not [@@deriving show { with_path = false }] type expr = | Literal of literal | BinaryExpr of { op : binary_op; left : expr_node; right : expr_node } | UnaryExpr of { op : unary_op; expr : expr_node } and expr_node = { expr : expr; pos : Error.code_pos } let rec show_expr ?(indent = 0) expr = let show_indented = show_expr ~indent:(indent + 2) in let ident_s = String.make indent ' ' in match expr with | Literal literal -> ident_s ^ show_literal literal | BinaryExpr { op; left; right } -> ident_s ^ show_binary_op op ^ "\n" ^ show_indented left.expr ^ "\n" ^ show_indented right.expr | UnaryExpr { op; expr } -> ident_s ^ show_unary_op op ^ "\n" ^ show_indented expr.expr let show_expr_node expr_node = show_expr expr_node.expr let make_expr_node (pos : Error.code_pos) (expr : expr) = { expr; pos } let make_string (pos : Error.code_pos) (s : string) = make_expr_node pos (Literal (String s)) let make_number (pos : Error.code_pos) (x : float) = make_expr_node pos (Literal (Number x)) let make_bool (pos : Error.code_pos) (b : bool) = make_expr_node pos (Literal (Bool b)) let make_nil (pos : Error.code_pos) = make_expr_node pos (Literal Nil) let make_binary (pos : Error.code_pos) (op : binary_op) (left : expr_node) (right : expr_node) = make_expr_node pos (BinaryExpr { op; left; right }) let make_unary (pos : Error.code_pos) (op : unary_op) (expr : expr_node) = make_expr_node pos (UnaryExpr { op; expr })