Advertisement
Hinski2

Untitled

May 26th, 2024
14
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.05 KB | None | 0 0
  1. open Ast
  2.  
  3. module M = Map.Make(String)
  4.  
  5. exception Type_error
  6. exception Unbound_var of ident
  7.  
  8. exception MyExn
  9.  
  10. type env = value M.t
  11.  
  12. and value =
  13. | VUnit
  14. | VInt of int
  15. | VBool of bool
  16. | VClosure of pattern * expr * env
  17. | VPair of value * value
  18. | VCtor of cname * value
  19.  
  20. let eval_op (op : bop) (v1 : value) (v2 : value) : value =
  21. match op, v1, v2 with
  22. | Add, VInt i1, VInt i2 -> VInt (i1 + i2)
  23. | Sub, VInt i1, VInt i2 -> VInt (i1 - i2)
  24. | Mult, VInt i1, VInt i2 -> VInt (i1 * i2)
  25. | Div, VInt i1, VInt i2 -> VInt (i1 / i2)
  26. | Eq, VInt i1, VInt i2 -> VBool (i1 = i2)
  27. | Lt, VInt i1, VInt i2 -> VBool (i1 < i2)
  28. | Gt, VInt i1, VInt i2 -> VBool (i1 > i2)
  29. | Leq, VInt i1, VInt i2 -> VBool (i1 <= i2)
  30. | Geq, VInt i1, VInt i2 -> VBool (i1 >= i2)
  31. | Neq, VInt i1, VInt i2 -> VBool (i1 <> i2)
  32. | _ -> raise Type_error
  33.  
  34. let rec match_pattern env v p =
  35. match v, p with
  36. | _, PWildcard -> Some env
  37. | VUnit, PUnit -> Some env
  38. | _, PUnit -> None
  39. | VInt n, PInt m when n = m -> Some env
  40. | _, PInt _ -> None
  41. | VBool x, PBool y when x = y -> Some env
  42. | _, PBool _ -> None
  43. | _, PVar x -> Some (M.add x v env)
  44. | VCtor(c1, v), PCtor(c2, p) when c1 = c2 ->
  45. match_pattern env v p
  46. | _, PCtor _ -> None
  47. | VPair(v1, v2), PPair(p1, p2) ->
  48. (match match_pattern env v1 p1 with
  49. | None -> None
  50. | Some env -> match_pattern env v2 p2)
  51. | _, PPair _ -> None
  52. | _, PAs(p, x) ->
  53. (match match_pattern env v p with (*dodanie as*)
  54. | Some env -> Some (M.add x v env)
  55. | None -> None)
  56.  
  57. let check_pattern p =
  58. let rec aux p ids =
  59. match p with
  60. | PWildcard | PUnit | PInt _ | PBool _ -> ids
  61. | PVar id -> if List.mem id ids
  62. then failwith ("duplicate id " ^ id)
  63. else id::ids
  64. | PPair(p1, p2) ->
  65. let new_ids = aux p1 ids in
  66. aux p2 new_ids
  67. | PCtor(_, pat) -> aux pat ids
  68. | PAs(_, id) -> (*dodanie sprawdznie as*)
  69. if List.mem id ids
  70. then failwith ("duplicate id " ^ id)
  71. else id::ids
  72. in ignore(aux p [])
  73.  
  74. let add_pattern env v p =
  75. check_pattern p;
  76. match match_pattern env v p with
  77. | Some env -> env
  78. | None -> failwith "match failure"
  79.  
  80. let rec eval_env (env : env) (e : expr) : value =
  81. match e with
  82. | Unit -> VUnit
  83. | Int n -> VInt n
  84. | Bool b -> VBool b
  85. | Ctor(c, e) -> VCtor(c, eval_env env e)
  86. | If (p, t, e) ->
  87. (match eval_env env p with
  88. | VBool true -> eval_env env t
  89. | VBool false -> eval_env env e
  90. | _ -> raise Type_error)
  91. | Binop (And, e1, e2) ->
  92. (match eval_env env e1 with
  93. | VBool true -> eval_env env e2
  94. | VBool false -> VBool false
  95. | _ -> raise Type_error)
  96. | Binop (Or, e1, e2) ->
  97. (match eval_env env e1 with
  98. | VBool false -> eval_env env e2
  99. | VBool true -> VBool true
  100. | _ -> raise Type_error)
  101. | Binop (op, e1, e2) -> eval_op op (eval_env env e1) (eval_env env e2)
  102. | Let (pat, e1, e2) ->
  103. let r = eval_env env e1 in
  104. let new_env = add_pattern env r pat in
  105. eval_env new_env e2
  106. | Var x ->
  107. (match M.find_opt x env with
  108. | Some v -> v
  109. | None -> raise (Unbound_var x))
  110. | Fun (pat, e) -> VClosure (pat, e, env)
  111. | App (e1, e2) ->
  112. (match eval_env env e1, eval_env env e2 with
  113. | VClosure (pat, body, clo_env), v -> eval_env (add_pattern clo_env v pat) body
  114. | _, _ -> raise Type_error)
  115. | Pair(e1, e2) ->
  116. VPair(eval_env env e1, eval_env env e2)
  117. | Fst e ->
  118. (match eval_env env e with
  119. | VPair(v1, _) -> v1
  120. | _ -> raise Type_error)
  121. | Snd e ->
  122. (match eval_env env e with
  123. | VPair(_, v2) -> v2
  124. | _ -> raise Type_error)
  125. | Raise -> raise MyExn
  126. | Try(e1, e2) ->
  127. (try eval_env env e1 with
  128. | MyExn -> eval_env env e2)
  129. | Match(e, cs) ->
  130. match_clauses env (eval_env env e) cs
  131.  
  132. and match_clauses env v cs =
  133. match cs with
  134. | [] -> failwith "match failure"
  135. | (p, e) :: cs ->
  136. check_pattern p;
  137. match match_pattern env v p with
  138. | Some env -> eval_env env e
  139. | None -> match_clauses env v cs
  140.  
  141. let eval_prog = eval_env M.empty
  142.  
  143. let rec string_of_value v =
  144. match v with
  145. | VUnit -> "()"
  146. | VInt n -> string_of_int n
  147. | VBool true -> "true"
  148. | VBool false -> "false"
  149. | VClosure _ -> "<fun>"
  150. | VPair(v1, v2) -> print_VPair (v1, v2) true
  151. | VCtor(c, v) -> print_VCtor (c, v)
  152.  
  153. and print_VPair (v1, v2) add =
  154. if add then "(" ^ print_VPair (v1, v2) false ^ ")"
  155. else
  156. match v1 with
  157. | VPair(a, b) -> print_VPair (a, b) false ^ ", " ^ string_of_value v2
  158. | _ -> string_of_value v1 ^ ", " ^ string_of_value v2
  159.  
  160. and print_VCtor (c, v) =
  161. match v with
  162. | VInt n -> c ^ " " ^ string_of_int n (*4 pierwsze dla lepszej czytelności*)
  163. | VBool true -> c ^ " true"
  164. | VBool false -> c ^ " false"
  165. | VClosure _ -> c ^ " <fun>"
  166. | VCtor(_, _) -> c ^ "(" ^ string_of_value v ^ ")"
  167. | _ -> c ^ string_of_value v
  168.  
  169. let print_value v =
  170. print_endline (string_of_value v)
  171.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement