adapap

i give up

May 9th, 2020
786
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.17 KB | None | 0 0
  1. open Ast
  2. open Ds
  3.  
  4. (* params * body * super * fields *)
  5. type method_decl = string list*Ast.expr*string*string list
  6.  
  7. type method_env = (string*method_decl) list
  8.  
  9. type class_decl = string*string list*method_env
  10.  
  11. type class_env = ((string*class_decl) list)
  12.  
  13. (* Global holding the store *)
  14. let g_store = Store.empty_store 20 (NumVal 0)
  15.  
  16. (* Global holding class declarations *)
  17. let g_class_env : class_env ref = ref []
  18.  
  19.  
  20. (* Helper functions for SOOL *)
  21.  
  22. (*
  23. * Return all visible fields from class c_name
  24. * Note: Should produce an error if the super class does not exist, this is pending
  25. *)
  26. let rec get_fields cs c_name class_decls =
  27. match class_decls with
  28. | [] -> []
  29. | Class (name,super,fields,_methods)::_ when name=c_name ->
  30. fields :: get_fields cs super cs
  31. | Class (_,_,_,_)::cs' -> get_fields cs c_name cs'
  32.  
  33. (*
  34. * Return all visible methods from class c_name
  35. * Note: Should produce an error if the super class does not exist, this is pending
  36. *)
  37. let rec get_methods cs c_name fss = function
  38. | [] -> []
  39. | Class (name,super,_fields,methods)::_ when name=c_name ->
  40. (List.map (fun (Method(n,pars,body))
  41. -> (n,(pars,body,super,List.flatten fss)))
  42. methods) @ get_methods cs super (List.tl fss) cs
  43. | Class (_,_,_,_)::cs' -> get_methods cs c_name fss cs'
  44.  
  45. (*
  46. * Initialize contents of g_class_env variable
  47. *)
  48. let initialize_class_env cs =
  49. let rec initialize_class_env' cs = function
  50. | [] -> ()
  51. | Class (name,super,fields,methods)::cs' ->
  52. let fss = fields :: get_fields cs super cs
  53. in let ms = (List.map (fun (Method(n,pars,body))
  54. -> (n,(pars,body,super,List.flatten fss)))
  55. methods) @ get_methods cs super (List.tl fss) cs
  56. in
  57. g_class_env := (name,(super,List.flatten fss,ms))::!g_class_env;
  58. initialize_class_env' cs cs'
  59. in g_class_env := [];
  60. initialize_class_env' cs cs
  61.  
  62. let lookup_class : string -> class_env -> class_decl ea_result = fun c_name c_env ->
  63. return (List.assoc c_name c_env)
  64.  
  65. let rec new_env : string list -> env ea_result = fun fs ->
  66. match fs with
  67. | [] -> empty_env()
  68. | h::t ->
  69. new_env t >>+
  70. extend_env h(RefVal(Store.new_ref g_store (NumVal 0)))
  71.  
  72. let slice fs env =
  73. let rec slice' fs acc env =
  74. match fs, env with
  75. | [],_ -> acc
  76. | id::ids, ExtendEnv(id',ev,tail) when id=id' ->
  77. slice' ids (ExtendEnv(id',ev,acc)) tail
  78. | _,_ -> failwith "slice: ids different or lists have different lengths"
  79. in
  80. return (slice' fs EmptyEnv env)
  81.  
  82. let lookup_method : string -> string -> class_env ->
  83. method_decl option = fun c_name m_name c_env ->
  84. match (List.assoc c_name c_env) with
  85. | (_, _, methods) -> List.assoc_opt m_name methods
  86.  
  87. (* Helper function for records *)
  88. let rec addIds fs evs =
  89. match fs,evs with
  90. | [],[] -> []
  91. | (id,_)::t1, v::t2 -> (id,v):: addIds t1 t2
  92. | _,_ -> failwith "error: lists have different sizes"
  93.  
  94. let rec apply_method : string -> exp_val -> exp_val list ->
  95. method_decl -> exp_val ea_result = fun m_name self args (pars,body,super,fs) ->
  96. let l = Store.new_ref g_store self
  97. and l_args = List.map (fun ev -> RefVal (Store.new_ref g_store ev)) args
  98. in let l' = Store.new_ref g_store (StringVal super)
  99. in
  100. if List.length args<> List.length pars
  101. then error (m_name ^ ": args and params have different lengths")
  102. else
  103. obj_of_objectVal self >>= fun (_c_name,env) ->
  104. slice fs env >>+
  105. extend_env_list ("_super"::"_self"::pars) ((RefVal l')
  106. ::(RefVal l)::l_args) >>+
  107. eval_expr body
  108. and
  109. apply_proc ev1 ev2 =
  110. match ev1 with
  111. | ProcVal(par,body,en) ->
  112. return en >>+
  113. extend_env par (RefVal (Store.new_ref g_store ev2)) >>+
  114. eval_expr body
  115. | _ -> error "apply_proc: Not a procVal"
  116. and
  117. eval_expr : expr -> exp_val ea_result = fun e ->
  118. match e with
  119. | Int(n) -> return @@ NumVal n
  120. | Var(id) ->
  121. apply_env id >>=
  122. int_of_refVal >>= fun l ->
  123. (match Store.deref g_store l with
  124. | None -> error "Index out of bounds"
  125. | Some ev -> return ev)
  126. | Add(e1,e2) ->
  127. eval_expr e1 >>=
  128. int_of_numVal >>= fun n1 ->
  129. eval_expr e2 >>=
  130. int_of_numVal >>= fun n2 ->
  131. return @@ NumVal (n1+n2)
  132. | Sub(e1,e2) ->
  133. eval_expr e1 >>=
  134. int_of_numVal >>= fun n1 ->
  135. eval_expr e2 >>=
  136. int_of_numVal >>= fun n2 ->
  137. return @@ NumVal (n1-n2)
  138. | Mul(e1,e2) ->
  139. eval_expr e1 >>=
  140. int_of_numVal >>= fun n1 ->
  141. eval_expr e2 >>=
  142. int_of_numVal >>= fun n2 ->
  143. return @@ NumVal (n1*n2)
  144. | Div(e1,e2) ->
  145. eval_expr e1 >>=
  146. int_of_numVal >>= fun n1 ->
  147. eval_expr e2 >>=
  148. int_of_numVal >>= fun n2 ->
  149. if n2==0
  150. then error "Division by zero"
  151. else return @@ NumVal (n1/n2)
  152. | Let(v,def,body) ->
  153. eval_expr def >>= fun ev ->
  154. let l = Store.new_ref g_store ev
  155. in extend_env v (RefVal l) >>+
  156. eval_expr body
  157. | ITE(e1,e2,e3) ->
  158. eval_expr e1 >>=
  159. bool_of_boolVal >>= fun b ->
  160. if b
  161. then eval_expr e2
  162. else eval_expr e3
  163. | IsZero(e) ->
  164. eval_expr e >>=
  165. int_of_numVal >>= fun n ->
  166. return @@ BoolVal (n = 0)
  167. | Pair(e1,e2) ->
  168. eval_expr e1 >>= fun ev1 ->
  169. eval_expr e2 >>= fun ev2 ->
  170. return @@ PairVal(ev1,ev2)
  171. | Fst(e) ->
  172. eval_expr e >>=
  173. pair_of_pairVal >>= fun p ->
  174. return @@ fst p
  175. | Snd(e) ->
  176. eval_expr e >>=
  177. pair_of_pairVal >>= fun p ->
  178. return @@ snd p
  179. | Proc(id,e) ->
  180. lookup_env >>= fun en ->
  181. return (ProcVal(id,e,en))
  182. | App(e1,e2) ->
  183. eval_expr e1 >>= fun v1 ->
  184. eval_expr e2 >>= fun v2 ->
  185. apply_proc v1 v2
  186. | Letrec(id,par,e,target) ->
  187. let l = Store.new_ref g_store UnitVal in
  188. extend_env id (RefVal l) >>+
  189. (lookup_env >>= fun env ->
  190. (let[@warning "-8"] Some _ = Store.set_ref g_store l (ProcVal(par,e,env))
  191. in eval_expr target)
  192. )
  193. (* Mutable references operations *)
  194. | Set(id,e) ->
  195. eval_expr e >>= fun ev ->
  196. apply_env id >>=
  197. int_of_refVal >>= fun l ->
  198. (match Store.set_ref g_store l ev with
  199. | None -> error "Index out of bounds"
  200. | Some _ -> return UnitVal)
  201. | BeginEnd([]) ->
  202. return UnitVal
  203. | BeginEnd(es) ->
  204. sequence (List.map eval_expr es) >>= fun vs ->
  205. return (List.hd (List.rev vs))
  206. (* Record operations *)
  207. | Record(fs) ->
  208. sequence (List.map (fun (_, e) -> eval_expr e) fs) >>= fun evs ->
  209. return (RecordVal (addIds fs evs))
  210. | Proj(e,id) ->
  211. eval_expr e >>=
  212. fields_of_recordVal >>= fun fs ->
  213. (match List.assoc_opt id fs with
  214. | None -> error "not found"
  215. | Some ev -> return ev)
  216.  
  217. (* SOOL operations *)
  218. | NewObject(c_name,es) ->
  219. let g_env = !g_class_env in
  220. sequence (List.map eval_expr es) >>= fun args ->
  221. lookup_class c_name g_env >>= fun (_, fields, methods) ->
  222. new_env fields >>= fun c_env ->
  223. let x = (match List.assoc_opt "initialize" methods with
  224. | None -> error "no init"
  225. | Some m -> apply_method "initialize" (ObjectVal(c_name, c_env)) args m) in
  226. return (ObjectVal(c_name, c_env))
  227. | Send(e,m_name,es) ->
  228. eval_expr e >>= fun v ->
  229. obj_of_objectVal v >>= fun (c_name, c_env) ->
  230. let self = ObjectVal(c_name, c_env) in
  231. sequence (List.map eval_expr es) >>= fun args ->
  232. (match lookup_method c_name m_name !g_class_env with
  233. | None -> error "Method not found"
  234. | Some m -> apply_method m_name self args m)
  235. | Self ->
  236. eval_expr (Var "_self")
  237. | Super(m_name,es) ->
  238. sequence (List.map eval_expr es) >>= fun args ->
  239. eval_expr (Var "_super") >>=
  240. string_of_stringVal >>= fun c_name ->
  241. eval_expr ( Var "_self") >>= fun self ->
  242. (match lookup_method c_name m_name !g_class_env with
  243. | None -> error "Method not found"
  244. | Some m -> apply_method m_name self args m)
  245.  
  246. (* List operations* *)
  247. | List(es) ->
  248. sequence (List.map eval_expr es) >>= fun args ->
  249. return (ListVal args)
  250. | Cons(e1,e2) ->
  251. eval_expr e1 >>= fun ev ->
  252. eval_expr e2 >>=
  253. list_of_listVal >>= fun l ->
  254. return (ListVal (ev::l))
  255. | Hd(e) ->
  256. eval_expr e >>=
  257. list_of_listVal >>= fun l ->
  258. return (List.hd l)
  259. | Tl(e) ->
  260. eval_expr e >>=
  261. list_of_listVal >>= fun l ->
  262. return (ListVal (List.tl l))
  263. | EmptyPred(e) ->
  264. eval_expr e >>=
  265. list_of_listVal >>= fun l ->
  266. return (BoolVal (l=[]))
  267. (* Debug *)
  268. | Debug(_e) ->
  269. string_of_env >>= fun str_env ->
  270. let str_store = Store.string_of_store string_of_expval g_store
  271. in (print_endline (str_env^"\n"^str_store);
  272. error "Reached breakpoint")
  273. | _ -> error ("eval_expr: Not implemented: "^string_of_expr e)
  274. and
  275. eval_prog : prog -> exp_val ea_result = fun (AProg(cs, e)) ->
  276. initialize_class_env cs; (* Step 1 *)
  277. eval_expr e (* Step 2 *)
  278.  
  279.  
  280. (* Parse a string into an ast *)
  281.  
  282. let parse s =
  283. let lexbuf = Lexing.from_string s in
  284. let ast = Parser.prog Lexer.read lexbuf in
  285. ast
  286.  
  287. let lexer s =
  288. let lexbuf = Lexing.from_string s
  289. in Lexer.read lexbuf
  290.  
  291.  
  292. (* Interpret an expression *)
  293. let interp (s:string) : exp_val result =
  294. let c = s |> parse |> eval_prog
  295. in run c
  296.  
  297. let read_file (filename:string) : string =
  298. let lines = ref [] in
  299. let chan = open_in filename in
  300. try
  301. while true do
  302. lines := input_line chan :: !lines
  303. done;
  304. "" (* never reaches this line *)
  305. with End_of_file ->
  306. close_in chan;
  307. String.concat "" (List.rev !lines)
  308.  
  309. (* Interpret an expression read from a file with optional extension .rec *)
  310. let interpf (s:string) : exp_val result =
  311. let s = String.trim s (* remove leading and trailing spaces *)
  312. in let file_name = (* allow rec to be optional *)
  313. match String.index_opt s '.' with None -> s^".sool" | _ -> s
  314. in
  315. interp @@ read_file file_name
  316.  
  317. let interpp () : exp_val result =
  318. interpf "ex1"
  319.  
  320.  
  321. let parsef (s:string) : Ast.prog =
  322. let s = String.trim s (* remove leading and trailing spaces *)
  323. in let file_name = (* allow rec to be optional *)
  324. match String.index_opt s '.' with None -> s^".sool" | _ -> s
  325. in
  326. parse @@ read_file file_name
Advertisement
Add Comment
Please, Sign In to add comment