(* Source iInter.ml *)


open IAst (* À changer en open Pcf.I.Ast à l'extérieur de la bibliothèque *)

type value =
  | Num_v of int | Clo of string *  t * env (* comme pour Pcf pur, entiers et fermetures *)
  | Void_v (* Constante 'Unit' *)
  | Ref_v of value ref
(* Référence Pcf, tout simplement encodée par une référence de Caml *)

and env = (string * valuelist


(*************************)
(* Afficheur des valeurs *)
(*************************)


let rec print_value chan v = match v with
  | Num_v i -> Printf.fprintf chan "%i" i
  | Ref_v r -> Printf.fprintf chan "{%a}" print_value !r
  | Void_v -> Printf.fprintf chan "()"
  | Clo (_,_,_) -> Printf.fprintf chan "<fun>"

exception Error of string

(*******************************)
(* Interpréteur proprement dit *)
(*******************************)

let fun_of_op op = match op with
  | Add -> (+)
  | Mul -> ( * )
  | Sub -> fun x y -> if y>x then 0 else x-y
  | Div -> (/)

let rec inter env t = match t with
Unit -> Void_v
Num i -> Num_v i
Ref v -> Ref_v (ref (inter env v))
Var x ->
    begin try
      List.assoc x env
    with Not_found ->
      raise (Error (Printf.sprintf "undefined variable %S" x))
    end
Op (op,t1,t2) ->
    let n1 = inter_int env t1 in
    let n2 = inter_int env t2 in
    Num_v (fun_of_op op n1 n2)
Ifz (t1,t2,t3) ->
    let v1 = inter_int env t1 in
    inter env (if v1 = 0 then t2 else t3)
Let (x,t1,t2) ->
    let v1 = inter env t1 in
    inter ((x,v1)::envt2
App (t1,t2) ->
    let x,t_clo,e_clo = inter_clo env t1 in
    let v2 = inter env t2 in
    inter ((x,v2)::e_clot_clo
Fun (x,t) -> Clo (x,t,env)
Fix (f,Fun (x,t)) ->
    let rec clo = Clo (x,t,(f,clo)::envin
    clo
Fix _ -> raise (Error "Fix allowed on Fun only")
Set (t,v) ->
    let r = inter_ref env t in
    let v = inter env v in
    r := v ;
(* La valeur est 'void' *)
    Void_v
Get t -> !(inter_ref env t)
Seq (a,b) ->
    let va = inter env a in
    let vb = inter env b in
    if va <> Void_v then begin
      (* Diagnostic sur la sortie d'erreur *)
      Printf.eprintf "Warning: sequence ignores its first value!\n" ;
      flush stderr
    end ;
    vb

and
 inter_int env t = match inter env t with
Num_v i -> i
Clo _ -> raise (Error "Num_v expected, got Clo")
Ref_v _ -> raise (Error "Num_v expected, got Ref_v")
Void_v -> raise (Error "Num_v expected, got Void_v")

and inter_clo env t = match inter env t with
Clo (x,t,e) -> (x,t,e)
Num_v _ -> raise (Error "Clo expected, got Num_v")
Ref_v _ -> raise (Error "Clo expected, got Ref_v")
Void_v -> raise (Error "Clo expected, got Void_v")

and inter_ref env t = match inter env t with
Ref_v r -> r
Clo _ -> raise (Error "Ref expected, got Clo")
Num_v _ -> raise (Error "Ref expected, got Num_v")
Void_v -> raise (Error "Ref expected, got Void_v")

This document was translated from LATEX by HEVEA.