type typ = | TInt | TBool | TVoid | TStruct of string | TArray of 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 typ * string * 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 : (typ * string) 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 typ * string * expr option type program = top list val string_of_typ : typ -> string val string_of_program : program -> string val parse_string : string -> (program, string) result val type_check : program -> (unit, string) result val parse_and_type_check : string -> (program, string) result