open Pp exception PasEncore type valeur = | Vint of int | Undefined type erreur = | Inconnue of string | DivZero | Type of type_expr * valeur | PasDef exception Erreur of erreur let erreur e = raise (Erreur e) ;; (* Les environnements *) type env_t = { fonctions : (string * definition) list ; globals : (string * valeur ref) list ; locals : (string * valeur ref) list } let trouve_var {globals = glob ; locals = loc } x = try List.assoc x loc with | Not_found -> try List.assoc x glob with | Not_found -> erreur (Inconnue ("variable: "^x)) let binop op i1 i2 = match op with | Plus -> Vint (i1 + i2) | Minus -> Vint (i1 - i2) | Times -> Vint (i1 * i2) | Div -> if i2 = 0 then erreur DivZero else Vint (i1/i2) | _ -> raise PasEncore let rec expr env = function | Int i -> Vint i | Bin (op,e1, e2) -> (* Attention à l'ordre *) let i1 = expr_int env e1 in let i2 = expr_int env e2 in binop op i1 i2 | Get x -> !(trouve_var env x) | _ -> raise PasEncore and expr_int env e = match expr env e with | Vint i -> i | Undefined -> erreur PasDef | v -> erreur (Type (Integer,v)) and instr env = function | Set (x, e) -> let xcell = trouve_var env x in let v = expr env e in xcell := v | Sequence is -> instrs env is | Writeln_int e -> let i = expr_int env e in print_int i ; print_newline () | _ -> raise PasEncore and instrs env is = List.iter (instr env) is let eval {global_vars = globs ; definitions = defs ; main = i} = let start_env = {globals = List.map (fun (x,_) -> x, ref Undefined) globs ; fonctions = defs ; locals = []} in instrs start_env i