Advertisement
Guest User

Untitled

a guest
Aug 5th, 2018
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
OCaml 12.35 KB | None | 0 0
  1. (* Interprete di un semplice linguaggio funzionale.*)
  2.  
  3. type variable = string ;;
  4.  
  5. type constant = Int of int | Bool of bool ;;
  6.  
  7. type operator = Plus | Minus | Times | Div | LessThan | LessThanEq ;;
  8.  
  9. (* Le espressioni. *)
  10.  
  11. type exp =
  12.   | Constant_e of constant
  13.   | Op_e of exp * operator * exp
  14.   | Var_e of variable
  15.   | If_e of exp * exp * exp
  16.   | Fun_e of variable * exp
  17.   | FunCall_e of exp * exp
  18.   | Let_e of variable * exp * exp
  19.   | Letrec_e of variable * exp * exp
  20.   (* Estensione delle espressioni *)
  21.   | ETree of tree (* gli alberi sono anche espressioni *)
  22.   | ApplyOver of exp * exp (* applicazione di funzione ai nodi *)
  23.   | Update of (variable list) * exp * exp (* aggiornamento di un nodo *)
  24.   | Select of (variable list) * exp * exp (* selezione condizionale di un nodo *)
  25.     and tree = Empty (* albero vuoto *)
  26.     | Node of variable * exp * tree * tree (* albero binario *)
  27. ;;
  28.  
  29. (* funzioni del run-time *)
  30.  
  31. (* Controllo per valori *)
  32.  
  33. let rec is_value (e:exp) : bool =
  34.   match e with
  35.     | Constant_e _ -> true
  36.     | Fun_e (_,_) -> true
  37.     | (
  38.         Op_e (_,_,_)
  39.        | Var_e _
  40.        | If_e (_,_,_)
  41.        | FunCall_e (_,_)
  42.        | Let_e (_,_,_)
  43.        | Letrec_e (_,_,_)
  44.        | ETree _
  45.        | ApplyOver (_,_)
  46.        | Update (_,_,_)
  47.        | Select (_,_,_)
  48.     ) -> false
  49. ;;
  50.  
  51. (* casi possibili di run-time exception *)
  52.  
  53. exception UnboundVariable of variable ;;
  54. exception BadApplication of exp ;;
  55. exception BadIf of exp ;;
  56. exception BadOp of exp * operator * exp ;;
  57.  
  58. (* decodifica delle operazioni di base *)
  59.  
  60. let apply_op v1 op v2 =
  61.   match v1, op, v2 with
  62.     | Constant_e (Int i), Plus, Constant_e (Int j) ->
  63.         Constant_e (Int (i+j))
  64.     | Constant_e (Int i), Minus, Constant_e (Int j) ->
  65.         Constant_e (Int (i-j))
  66.     | Constant_e (Int i), Times, Constant_e (Int j) ->
  67.         Constant_e (Int (i*j))
  68.     | Constant_e (Int i), Div, Constant_e (Int j) ->
  69.         Constant_e (Int (i/j))
  70.     | Constant_e (Int i), LessThan, Constant_e (Int j) ->
  71.         Constant_e (Bool (i<j))
  72.     | Constant_e (Int i), LessThanEq, Constant_e (Int j) ->
  73.         Constant_e (Bool (i<=j))
  74.     | _, _, _ -> raise (BadOp (v1,op,v2))
  75. ;;
  76.  
  77. (* Funzione di sostituzione *)
  78. (* Notare uso di una funzione ricorsiva ausiliaria *)
  79.  
  80. (* let x = v in e *)
  81. let substitute (v:exp) (x:variable) (e:exp) : exp =
  82.   let rec subst (e:exp) : exp =
  83.     match e with
  84.     | Var_e y -> if x = y then v else e
  85.     | Constant_e _ -> e
  86.     | Op_e (e1,op,e2) -> Op_e(subst e1,op,subst e2)
  87.     | If_e (e1,e2,e3) -> If_e(subst e1,subst e2,subst e3)
  88.     | FunCall_e (e1,e2) -> FunCall_e(subst e1,subst e2)
  89.     | Fun_e (y,e1) -> if x = y then e else Fun_e (y, subst e1)
  90.     | Let_e (y,e1,e2) ->
  91.         Let_e (y, subst e1, if x = y then e2 else subst e2)
  92.     | Letrec_e (y,e1,e2) ->
  93.         if x = y then Letrec_e (y,e1,e2) else Letrec_e (y,subst e1,subst e2)
  94.     (* ESTENSIONE *)
  95.     | ETree t -> (
  96.         match t with
  97.         | Empty -> ETree(Empty)
  98.         | Node(y, e, lt, rt) ->
  99.             (match subst (ETree lt) with
  100.                 | ETree lts ->
  101.                     (match subst (ETree rt) with
  102.                         | ETree rts -> ETree(Node(y, subst e, lts, rts))
  103.                         | v2 -> raise(BadApplication v2)
  104.                     )
  105.                 | v1 -> raise(BadApplication v1)
  106.             )
  107.         )
  108.     | ApplyOver (exf, ext) -> ApplyOver(subst exf, subst ext)
  109.     | Update (idl, exf, ext) -> Update (idl, subst exf, subst ext)
  110.     | Select (idl, exf, ext) -> Select (idl, subst exf, subst ext)
  111.   in
  112.     subst e
  113. ;;
  114.  
  115.  
  116. (* Ciclo dell'interprete *)
  117. (* Notare uso di una chiamata ricorsiva tramite parametri higher-order *)
  118. (* Notare uso della sostituzione per fare unwind della ricorsione *)
  119.  
  120. let eval_body (eval_loop:exp->exp) (e:exp) : exp =
  121.   match e with
  122.     | Constant_e c -> Constant_e c
  123.     | Fun_e (x,e) -> Fun_e (x,e)
  124.     | Op_e (e1,op,e2) ->
  125.         let v1 = eval_loop e1 in
  126.         let v2 = eval_loop e2 in
  127.           apply_op v1 op v2
  128.     | If_e (e1,e2,e3) ->
  129.           (match eval_loop e1 with
  130.              | Constant_e (Bool true) -> eval_loop e2
  131.              | Constant_e (Bool false) -> eval_loop e3
  132.              | v1 -> raise (BadIf v1))
  133.     | Let_e (x,e1,e2) -> eval_loop (substitute (eval_loop e1) x e2)
  134.     | FunCall_e (e1,e2) ->
  135.         (match eval_loop e1 with
  136.            | Fun_e (x,e) -> eval_loop (substitute (eval_loop e2) x e)
  137.            | v1 -> raise (BadApplication v1))
  138.     | Var_e x -> raise (UnboundVariable x)
  139.     | Letrec_e (x,e1,e2) ->
  140.         let e1_unwind = substitute (Letrec_e (x,e1,Var_e x)) x e1 in
  141.           eval_loop (Let_e (x,e1_unwind,e2))
  142.     (* ESTENSIONE *)
  143.     | ETree t -> (
  144.         match t with
  145.         | Empty -> ETree (Empty)
  146.         | Node(y, et, lt, rt) ->
  147.             (match eval_loop ( ETree(lt) ) with
  148.                 | ETree lte ->
  149.                     (match eval_loop ( ETree(rt) ) with
  150.                         | ETree rte -> ETree(Node(y, eval_loop et, lte, rte))
  151.                         | v2 -> raise(BadApplication v2)
  152.                     )
  153.                 | v1 -> raise(BadApplication v1)
  154.             )
  155.         )
  156.     | ApplyOver(exf, ext) ->
  157.         (match eval_loop exf with
  158.             | Fun_e (p, ef) -> (
  159.                 match eval_loop ext with
  160.                 | ETree(Empty) -> ETree(Empty)
  161.                 | ETree Node(idl, en, lt, rt) ->
  162.                     (match eval_loop (ApplyOver(Fun_e(p, ef), ( ETree(lt) ))) with
  163.                     | ETree lte -> (
  164.                         match eval_loop (ApplyOver(Fun_e(p, ef), ( ETree(rt) ))) with
  165.                             | ETree rte ->
  166.                                 ETree(Node(
  167.                                     idl,
  168.                                     eval_loop (FunCall_e(Fun_e(p, ef), eval_loop en)),
  169.                                     lte,
  170.                                     rte
  171.                                  ))
  172.                             | v4 -> raise(BadApplication v4)
  173.                         )
  174.                     | v3 -> raise(BadApplication v3)
  175.                     )
  176.                 | v2 -> raise(BadApplication v2)
  177.               )
  178.             | v1 -> raise(BadApplication v1)
  179.         )
  180.     | Update(idl, exf, ext) ->
  181.       (match eval_loop exf with
  182.         | Fun_e (p, ef) ->
  183.           (match eval_loop ext with
  184.             | ETree(Empty) -> ETree(Empty)
  185.             | ETree Node(idln, en, lt, rt) ->
  186.               (match idl with
  187.                 | [] -> ETree(Node(idln, en, lt, rt))
  188.                 | h::[] -> (if h = idln then ETree(Node(
  189.                                     idln,
  190.                                     eval_loop (FunCall_e(Fun_e(p, ef), (eval_loop en))),
  191.                                     lt,
  192.                                     rt
  193.                                   ))
  194.                   else ETree(Node(idln, en, lt, rt)))
  195.                 | h::t -> (if h = idln then
  196.                         (match eval_loop (Update(t, Fun_e (p, ef), ETree(lt))) with
  197.                             | ETree lte ->
  198.                                 (match eval_loop (Update(t, Fun_e (p, ef), ETree(rt))) with
  199.                                     | ETree rte ->
  200.                                        ETree(Node(
  201.                                           idln,
  202.                                           en,
  203.                                           lte,
  204.                                           rte
  205.                                        ))
  206.                                     | v4 -> raise(BadApplication v4)
  207.                                 )
  208.                             | v3 -> raise(BadApplication v3)
  209.                         )
  210.                   else ETree(Node(idln, en, lt, rt)))
  211.             )
  212.             | v2 -> raise(BadApplication v2)
  213.           )
  214.         | v1 -> raise(BadApplication v1)
  215.       )
  216.     | Select(idl, exf, ext) -> (
  217.         match eval_loop exf with
  218.             | Fun_e (p, ef) -> (
  219.                 match eval_loop ext with
  220.                     | ETree(Empty) -> ETree(Empty)
  221.                     | ETree Node(idt, en, lt, rt) ->
  222.                         (
  223.                             match idl with
  224.                             | [] -> ETree(Empty)
  225.                             | h::[] -> if h = idt then
  226.                                     let ret = eval_loop (FunCall_e(Fun_e (p, ef), eval_loop en)) in
  227.                                         (
  228.                                             match ret with
  229.                                             | Constant_e(Bool(t)) ->
  230.                                                 (
  231.                                                     if t = true then ETree(Node(idt, en, lt, rt))
  232.                                                     else ETree(Empty)
  233.                                                 )
  234.                                             | v3 -> raise(BadApplication v3)
  235.                                         )
  236.                                 else ETree(Empty)
  237.                             | h::t -> if h = idt then
  238.                                     let ret = eval_loop (FunCall_e(Fun_e (p, ef), eval_loop en)) in
  239.                                         (
  240.                                             match ret with
  241.                                             | Constant_e(Bool(tr)) ->
  242.                                                 (
  243.                                                     if tr = true then
  244.                                                         (match eval_loop (Select(t, exf, ETree(lt))) with
  245.                                                             | ETree(Empty) ->
  246.                                                                 (match eval_loop (Select(t, exf, ETree(rt))) with
  247.                                                                     | ETree(Empty) -> ETree(Empty)
  248.                                                                     | st -> st
  249.                                                                 )
  250.                                                             | st -> st
  251.                                                         )
  252.                                                     else ETree(Empty)
  253.                                                 )
  254.                                             | v3 -> raise(BadApplication v3)
  255.                                         )
  256.                                 else ETree(Empty)
  257.                         )
  258.                     | v2 -> raise(BadApplication v2)
  259.                 )
  260.             | v1 -> raise(BadApplication v1)
  261.         )
  262. ;;
  263.  
  264. let rec eval e = eval_body eval e
  265. ;;
  266.  
  267. (* TEST *)
  268.  
  269. (* Definizione albero di prova *)
  270. let albero = ETree(
  271.     Node("a", Constant_e(Int(2)),
  272.       Node("b", Op_e(Constant_e(Int(3)), Plus, Constant_e(Int(1))),
  273.         Empty,
  274.         Node("d", Constant_e(Int(6)),
  275.           Node("f", Op_e(Constant_e(Int(4)), Times, Constant_e(Int(2))), Empty, Empty),
  276.           Empty
  277.         )
  278.       ),
  279.       Node("c", Constant_e(Int(3)),
  280.         Empty,
  281.         Node("e", Constant_e(Int(7)), Empty, Empty)
  282.       )
  283.     )
  284.   );;
  285. (*
  286. Albero:      ("a",2)
  287.              /     \
  288.       ("b",3+1)   ("c",3)
  289.          \         \
  290.       ("d", 6)     ("e", 7)
  291.         /
  292.       ("f", 4*2)
  293. *)
  294.  
  295. (* Funzione che triplica un numero *)
  296. let triplica_body = Fun_e("x",
  297.     Op_e (Var_e "x", Times, Constant_e (Int 3)));;
  298.  
  299. (* Funzione per controllare disparità di un numero *)
  300. (* Facciamo:    x <= 2*|x/2| <-- vero se e solo se è pari  *)
  301. let ispari_body = Fun_e("x", Op_e (Var_e "x", LessThanEq, Op_e(Constant_e(Int 2), Times, Op_e(Var_e "x", Div, Constant_e(Int 2)) )));;
  302.  
  303. (* Valutazione di un albero: valuta le espressioni dei singoli nodi *)
  304. eval albero;;
  305.  
  306. (* Test ApplyOver *)
  307. eval (ApplyOver(triplica_body, albero));; (* Ritorna l'albero con tutte le espressioni triplicate *)
  308. eval (ApplyOver(ispari_body, albero));; (* Ritorna l'albero con tutte le espressioni triplicate *)
  309.  
  310. (* Test Update *)
  311. eval (Update(["a";"b";"d"], triplica_body, albero));; (* Triplica solo il nodo con espressione 6, avente cammino "a" "b" "d" *)
  312. eval (Update(["a";"b";"c"], triplica_body, albero));; (* Non esiste nessun cammino con etichettatura "a" "b" "c", l'albero rimane invariato *)
  313.  
  314. (* Test Select *)
  315. eval (Select(["a";"b";"d"], ispari_body, albero));; (* Seleziono il sotto albero avente radice il nodo con etichetta "d" *)
  316. eval (Select(["a";"b";"z"], ispari_body, albero));; (* Non trova nessun cammino con etichettaura "a" "b" "z"*)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement