(* définition des différents types : tout est à reprendre et étendre *) type expr = Const of int | BConst of bool | Add of expr*expr | Mul of expr*expr | Min of expr*expr | Eq of expr*expr | Gt of expr*expr | Lt of expr*expr | Gte of expr*expr | Lte of expr*expr | Band of expr*expr | Bor of expr*expr | ITE of expr*expr*expr | PrInt of expr | Var of string | LetIn of string*expr*expr | Fun of string*expr | App of expr*expr type valeur = VInt of int | VBool of bool | VFunc of string*expr type env = (string*valeur) list let empty_env = [] exception InvalidTypeException exception UnknownVariableException let rec readVar env v0 e = match env with | [] -> raise e | (v,x)::t -> if (v0 = v) then x else readVar t v0 e let rec intIntOp op e1 e2 env = match (eval e1 env, eval e2 env) with | VInt k1,VInt k2 -> VInt(op k1 k2) | _ -> raise InvalidTypeException and intBoolOp op e1 e2 env = match (eval e1 env, eval e2 env) with | VInt k1,VInt k2 -> VBool(op k1 k2) | _ -> raise InvalidTypeException (* sémantique opérationnelle à grands pas *) and eval e env = match e with | Const(k) -> VInt k | BConst(b) -> VBool b | Fun(v,e) -> VFunc(v,e) | Add(e1,e2) -> intIntOp ( + ) e1 e2 env | Mul(e1,e2) -> intIntOp ( * ) e1 e2 env | Min(e1,e2) -> intIntOp ( - ) e1 e2 env | Gt(e1,e2) -> intBoolOp ( > ) e1 e2 env | Lt(e1,e2) -> intBoolOp ( < ) e1 e2 env | Gte(e1,e2) -> intBoolOp ( >= ) e1 e2 env | Lte(e1,e2) -> intBoolOp ( <= ) e1 e2 env | Eq(e1,e2) -> (match (eval e1 env, eval e2 env) with | VInt k1,VInt k2 -> VBool (k1=k2) | VBool k1,VBool k2 -> VBool (k1=k2) | _ -> raise InvalidTypeException) | Band(e1,e2) -> (match (eval e1 env, eval e2 env) with | VBool b1,VBool b2 -> VBool (b1 && b2) | _ -> raise InvalidTypeException) | Bor(e1,e2) -> (match (eval e1 env, eval e2 env) with | VBool b1,VBool b2 -> VBool (b1 || b2) | _ -> raise InvalidTypeException) | ITE(ec,e1,e2) -> (match (eval ec env) with | VBool bc -> eval (if bc then e1 else e2) env | _ -> raise InvalidTypeException) | PrInt e1 -> (match (eval e1 env) with | VInt k -> VInt k | _ -> raise InvalidTypeException) | Var(v) -> readVar env v UnknownVariableException | LetIn(v,e0,e1) -> eval e1 ((v,eval e0 env)::env) | App(e0,e1) -> (match (eval e0 env) with | VFunc(v,e) -> eval (LetIn(v,e1,e)) env (* On utilise l'équivalence (fun x->e) y <=> let x=y in e *) | _ -> raise InvalidTypeException)