Advertisement
Guest User

Untitled

a guest
Mar 30th, 2017
63
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.90 KB | None | 0 0
  1. provide {parse-n-calc: parse-n-calc} end
  2.  
  3. import sets as S
  4. import shared-gdrive("calc-fields-typed-definitions.arr", "0B5p0KwAwF4VoRXV0ZkdZY3M0dGM") as C
  5. include string-dict
  6.  
  7. fun parse-n-calc(prog :: String) -> Set<String>:
  8. doc: "Parse a program with a hole, and return the fields avaiable there"
  9. calc-locals(C.parse(prog), [string-dict:])
  10. end
  11.  
  12.  
  13. fun calc-locals(expr :: C.Expr, bound :: C.TEnv) -> Set<String>:
  14. doc: "Find all of the fields available at a hole."
  15. cases (C.Expr) expr :
  16. | e-num(v) => [set:]
  17. | e-bool(b) => [set:]
  18. | e-op(op, left, right) => calc-locals(left, bound).union(calc-locals(right, bound))
  19. | e-if(cond, consq, altern) =>
  20. calc-locals(cond, bound).union(calc-locals(consq, bound)).union(calc-locals(altern, bound))
  21. | e-id(name) => [set:]
  22. | e-lam(param, body) => calc-locals(body, bound.set(param, body))
  23. | e-app(func, arg) => calc-locals(func, bound).union(calc-locals(arg, bound))
  24. | e-let(id, value, body) =>
  25. new-pvar = bound.set(id, value)
  26. calc-locals(value, new-pvar).union(calc-locals(body, new-pvar))
  27. | e-rec(fields) => rec-helper(fields.keys().to-list(), fields, bound)
  28.  
  29. | e-lookup(recr, field-name-or-hole) =>
  30. cases (C.Expr) expr :
  31. | l-hole =>
  32. type-check(field-name-or-hole, bound)
  33.  
  34. | l-name => calc-locals(recr, bound)
  35. end
  36.  
  37.  
  38.  
  39. | e-extend(reco, field-name, new-val) => calc-locals(reco, bound).union(calc-locals(new-val, bound))
  40. # | e-num(n) =>
  41.  
  42.  
  43. #| e-bool(b)
  44. | e-op(op, l, r)
  45. | e-if(cond, consq, altern)
  46. | e-id(name)
  47. | e-app(func, arg)
  48. | e-let(na, ex, bdy)
  49. | e-rec(fields)
  50. | e-lookup(recr, field-na)
  51. | e-extend(reco, field-name, new-val)
  52. | e-lam(id, ar, body) |#
  53. end
  54. end
  55.  
  56. fun rec-helper(f :: List<String>, fields, bound) -> Set<String>:
  57. #rec-accum(f, [set:], bound)
  58. cases (List) f:
  59. | empty => [set: ]
  60. | link(first, rest) => calc-locals(fields.get-value(first), bound).union(rec-helper(rest, fields, bound))
  61.  
  62.  
  63. end
  64.  
  65. end
  66.  
  67. #|
  68. fun rec-accum(l, sofar, bound):
  69. cases (List) l:
  70. | empty => sofar
  71. | link(f, r) => calc-locals(l.get-value(f), bound).union(rec-accum, r
  72. end
  73. end
  74. |#
  75.  
  76.  
  77. check:
  78. parse-n-calc("(lookup (record (x 1)) @)") is [set: "x"]
  79. parse-n-calc("(let (x (record (a 1) (b 2))) (let (y (extend x c 3)) (lookup y @)))") is [set: "a", "b", "c"]
  80. end
  81.  
  82. ## Type Checker Below ##
  83.  
  84.  
  85. fun type-check(e :: C.Expr, env :: C.TEnv) -> C.Type:
  86. doc: "Find the type of the given expression."
  87. cases (C.Expr) e:
  88. | e-op(op :: C.Operator, left :: C.Expr, right :: C.Expr) => op-helper(op, type-check(left, env), type-check(right, env))
  89. | e-un-op(op :: C.UnaryOperator, expr :: C.Expr) => un-op-helper(op, type-check(expr, env))
  90. | e-if(cond :: C.Expr, consq :: C.Expr, altern :: C.Expr) => if-helper(type-check(cond, env), type-check(consq, env), type-check(altern, env))
  91.  
  92. | e-let(name :: String, expr :: C.Expr, body :: C.Expr) => let-helper(name, type-check(expr, env), body, env)
  93.  
  94. | e-lam(param :: String, arg-type :: C.Type, body :: C.Expr) => lam-helper(param, arg-type, type-check(body, env.set(param, arg-type)))
  95. | e-app(func :: C.Expr, arg :: C.Expr) => app-helper(type-check(func, env), type-check(arg, env))
  96. | e-id(name :: String) => id-helper(name, env)
  97. | e-num(value :: Number) => C.t-num
  98. | e-bool(value :: Boolean) => C.t-bool
  99. | e-empty(elem-type :: C.Type) => C.t-list(elem-type)
  100.  
  101.  
  102. end
  103. end
  104.  
  105. fun op-helper(op :: C.Operator, left :: C.Type, right :: C.Type) -> C.Type:
  106.  
  107. cases (C.Operator) op:
  108. | op-plus => if C.is-t-num(left):
  109. if C.is-t-num(right):
  110. C.t-num
  111. else: raise(C.tc-err-bad-arg-to-op(op, right))
  112. end
  113. else: raise(C.tc-err-bad-arg-to-op(op, left))
  114. end
  115. | op-num-eq => if C.is-t-num(left):
  116. if C.is-t-num(right):
  117. C.t-bool
  118. else: raise(C.tc-err-bad-arg-to-op(op, right))
  119. end
  120. else: raise(C.tc-err-bad-arg-to-op(op, left))
  121. end
  122. | op-link => if not(C.is-t-list(right)):
  123. raise(C.tc-err-bad-arg-to-op(op, right))
  124. else if not(C.t-list(left) == right): #right matches type of list.
  125. raise(C.tc-err-bad-arg-to-op(op, left))
  126. else:
  127. C.t-list(left)
  128.  
  129.  
  130. end
  131.  
  132.  
  133. end
  134. end
  135.  
  136. fun if-helper(cond :: C.Type, consq :: C.Type, altern :: C.Type) -> C.Type:
  137. if cond == C.t-bool:
  138. if not(consq == altern):
  139. raise(C.tc-err-if-branches(consq, altern))
  140. else: consq
  141. end
  142. else:
  143. raise(C.tc-err-if-got-non-boolean(cond))
  144. end
  145.  
  146.  
  147. end
  148.  
  149. fun un-op-helper(op :: C.UnaryOperator, exprt :: C.Type) -> C.Type:
  150. cases (C.UnaryOperator) op:
  151. | op-first =>
  152. if not(C.is-t-list(exprt)):
  153. raise(C.tc-err-bad-arg-to-op(op, exprt))
  154. else:
  155. exprt
  156. end
  157. | op-rest =>
  158. if not(C.is-t-list(exprt)):
  159. raise(C.tc-err-bad-arg-to-op(op, exprt))
  160. else:
  161. exprt
  162. end
  163. | op-is-empty =>
  164. if not(C.is-t-list(exprt)):
  165. raise(C.tc-err-bad-arg-to-op(op, exprt))
  166.  
  167. else:
  168. C.t-bool
  169. end
  170.  
  171. end
  172. end
  173.  
  174. fun app-helper(func :: C.Type, arg :: C.Type) -> C.Type:
  175. if not(func.arg-type == arg):
  176. raise(C.tc-err-bad-arg-to-fun(func, arg))
  177. else:
  178. func.return-type
  179. end
  180.  
  181.  
  182. end
  183.  
  184. fun let-helper(name :: String, et :: C.Type, body :: C.Expr, env :: C.TEnv) -> C.Type:
  185. type-check(body, env.set(name,et))
  186. end
  187.  
  188. fun id-helper(name :: String, env :: C.TEnv) -> C.Type:
  189.  
  190. if env.has-key(name):
  191. env.get-value(name)
  192. else:
  193. raise(C.tc-err-unbound-id(name))
  194. end
  195. end
  196.  
  197.  
  198. fun lam-helper(name :: String, arg-type :: C.Type, bodyt :: C.Type) -> C.Type:
  199. if not(arg-type == bodyt):
  200. raise(C.tc-err-bad-arg-to-fun(bodyt, arg-type))
  201.  
  202. else:
  203. C.t-fun(arg-type, bodyt)
  204.  
  205. end
  206.  
  207. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement