(* interpréteur de mini-Pascal *) open Ast exception Error of string let unbound_var s = raise (Error ("unbound variable " ^ s)) let unbound_procedure f = raise (Error ("unbound procedure " ^ f)) let bad_arity x = raise (Error ("bad arity for " ^ x)) (* primitives *) open Graphics let is_open = ref false let drawline x1 y1 x2 y2 = if not !is_open then begin is_open := true; open_graph " 800x600" end; moveto x1 y1; lineto x2 y2 let writeln v = Format.printf "%d@." v (* table des variables globales *) let globals = Hashtbl.create 17 (* structure de données pour les variables locales *) module Smap = Map.Make(String) (* expressions arithmétiques *) let binop = function Add -> (+) Sub -> (-) Mul -> ( * ) (* :-) *) Div -> (/) let rec expr env = function Econst n -> n Evar x when Smap.mem x env -> Smap.find x env Evar x when Hashtbl.mem globals x -> Hashtbl.find globals x Evar x -> unbound_var x Ebinop (op, e1, e2) -> binop op (expr env e1) (expr env e2) (* expressions booléennes (conditions) *) let cmp c = match c with Eq -> (=) Neq -> (<>) Lt -> (<) Le -> (<=) Gt -> (>) Ge -> (>=) let rec condition env = function Bcmp (c, e1, e2) -> cmp c (expr env e1) (expr env e2) Band (c1, c2) -> condition env c1 && condition env c2 Bor (c1, c2) -> condition env c1 || condition env c2 Bnot c -> not (condition env c) (* table des procédures *) let procs = Hashtbl.create 17 (* instructions *) let rec stmt env = function Sassign (x, e) when Smap.mem x env -> (* variable locale *) Smap.add x (expr env e) env Sassign (x, e) when Hashtbl.mem globals x -> (* variable globale *) Hashtbl.replace globals x (expr env e); env Sassign (x, _) -> unbound_var x Sif (c, s1, s2) -> if condition env c then stmt env s1 else stmt env s2 Swhile (c, s1) as s -> if condition env c then begin stmt (stmt env s1) s end else env Sblock sl -> List.fold_left stmt env sl Scall ("writeln", [e]) -> writeln (expr env e); env Scall ("writeln", _) -> bad_arity "writeln" Scall ("drawline", [e1;e2;e3;e4]) -> drawline (expr env e1) (expr env e2) (expr env e3) (expr env e4); env Scall ("drawline", _) -> bad_arity "drawline" Scall (x, el) -> let p = try Hashtbl.find procs x with Not_found -> unbound_procedure x in let env' = try List.fold_left2 (fun env' x e -> Smap.add x (expr env e) env') Smap.empty p.formals el with Invalid_argument _ -> bad_arity x in let env' = List.fold_left (fun env x -> Smap.add x 0 env) env' p.locals in ignore (stmt env' p.body); env let prog p = List.iter (fun x -> Hashtbl.add globals x 0) p.globals; List.iter (fun p -> Hashtbl.add procs p.name p) p.procs; ignore (stmt Smap.empty p.main); if !is_open then begin ignore (read_key ()); close_graph () end
This document was generated using caml2html