type typ = | TInt | TBool | TVoid | TStruct of string | TArray of typ | TComptime of typ | TCombo of typ * typ type binop = | Add | Sub | Mul | Div | Mod | And | Or | Eq | Ne | Lt | Le | Gt | Ge type unop = Neg | Not type expr = | IntLit of int | BoolLit of bool | Var of string | Binop of binop * expr * expr | Unop of unop * expr | Assign of expr * expr | Call of expr * expr list | ArrayGet of expr * expr | StructGet of expr * string type stmt = | VarDecl of bool * string * typ option * expr option | Expr of expr | If of expr * stmt list * stmt list | ForEach of typ * string * expr * stmt list | Return of expr option | Block of stmt list type func = { name : string; params : (string * typ) list; ret : typ; body : stmt list; } type struct_def = { sname : string; fields : (typ * string) list; } type top = | TopStruct of struct_def | TopFunc of func | TopGlobalVar of bool * string * typ option * expr option type program = top list val string_of_typ : typ -> string val string_of_binop : binop -> string val string_of_unop : unop -> string val string_of_expr : expr -> string val string_of_program : program -> string val equal_typ : typ -> typ -> bool