primitives_visitor.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. import string
  2. from visitor import Visitor
  3. class PrimitivesVisitor(Visitor):
  4. def __init__(self):
  5. self.output = []
  6. self.free_id = 0
  7. self.function_values = dict()
  8. def node(self):
  9. self.output.append(("N", self.free_id))
  10. self.free_id += 1
  11. return self.free_id - 1
  12. def dict(self, src, val, trgt):
  13. if src is None or trgt is None:
  14. raise Exception("Got None")
  15. if isinstance(val, str):
  16. val = "\"%s\"" % val
  17. self.output.append(("D", (src, val, trgt)))
  18. def value(self, value):
  19. self.output.append(("V", (self.free_id, value)))
  20. self.free_id += 1
  21. return self.free_id - 1
  22. def edge(self, source, target):
  23. self.output.append(("E", (self.free_id, source, target)))
  24. self.free_id += 1
  25. return self.free_id - 1
  26. def dump(self):
  27. output = []
  28. for t, data in self.output:
  29. if t == "N":
  30. output.append("N auto_%s\n" % data)
  31. elif t == "V":
  32. name, value = data
  33. name = name if self.first != name else "initial_IP"
  34. output.append("V auto_%s(%s)\n" % (name, value))
  35. elif t == "D":
  36. source, value, target = data
  37. source = source if self.first != source else "auto_initial_IP"
  38. target = target if self.first != target else "auto_initial_IP"
  39. source = "auto_%s" % source if isinstance(source, int) else source
  40. target = "auto_%s" % target if isinstance(target, int) else target
  41. output.append("D %s,%s,%s\n" % (source, value, target))
  42. elif t == "E":
  43. name, source, target = data
  44. source = source if self.first != source else "auto_initial_IP"
  45. target = target if self.first != target else "auto_initial_IP"
  46. name = "auto_%s" % name if isinstance(name, int) else name
  47. source = "auto_%s" % source if isinstance(source, int) else source
  48. target = "auto_%s" % target if isinstance(target, int) else target
  49. output.append("E %s(%s,%s)\n" % (name, source, target))
  50. return "".join(output)
  51. def set_primitive(self, tree, primitive):
  52. tree.primitive = primitive
  53. def get_primitive(self, tree):
  54. return getattr(tree, 'primitive', None)
  55. def forward_primitive_of_child(self, tree, i):
  56. self.visit_children(tree)
  57. self.set_primitive(tree, self.get_primitive(tree.get_tail()[i]))
  58. # a visit_* method for each non-terminal in the grammar
  59. def visit_start(self, tree):
  60. primitives = []
  61. for child in tree.get_children("funcdecl"):
  62. p = self.pre_visit_funcdecl(child)
  63. if p:
  64. # funcdecl returns a (global, assign) pair
  65. primitives.extend(p)
  66. for child in tree.get_tail():
  67. self.visit(child)
  68. p = self.get_primitive(child)
  69. if p is not None:
  70. if type(p) in (list, tuple):
  71. # funcdecl returns a (global, assign) pair
  72. primitives.extend(p)
  73. else:
  74. primitives.append(p)
  75. if child.head == "return":
  76. break
  77. self.first = primitives[0]
  78. for i in range(len(primitives)-1):
  79. self.dict(primitives[i], "next", primitives[i+1])
  80. self.last_instruction = primitives[-1]
  81. def visit_vardecl(self, tree):
  82. symbol = self.get_symbol(tree)
  83. if symbol.is_global:
  84. d = self.value("global")
  85. n = self.value('"%s"' % symbol.name)
  86. else:
  87. d = self.value("declare")
  88. n = self.node()
  89. symbol.node = n
  90. self.dict(d, "var", n)
  91. self.set_primitive(tree, d)
  92. def visit_assignment(self, tree):
  93. self.visit_children(tree)
  94. a = self.value("assign")
  95. var = self.get_primitive(tree.get_tail()[0])
  96. value = self.get_primitive(tree.get_tail()[-1])
  97. self.dict(a, "var", var)
  98. self.dict(a, "value", value)
  99. self.set_primitive(tree, a)
  100. def visit_expression(self, tree):
  101. self.forward_primitive_of_child(tree, 0)
  102. def visit_binary_operation(self, tree):
  103. self.forward_primitive_of_child(tree, 0)
  104. def visit_disjunction(self, tree):
  105. self.forward_primitive_of_child(tree, 0)
  106. def visit_conjunction(self, tree):
  107. self.forward_primitive_of_child(tree, 0)
  108. def visit_comparison(self, tree):
  109. self.forward_primitive_of_child(tree, 0)
  110. def visit_relation(self, tree):
  111. self.forward_primitive_of_child(tree, 0)
  112. def visit_sum(self, tree):
  113. self.forward_primitive_of_child(tree, 0)
  114. def visit_term(self, tree):
  115. self.forward_primitive_of_child(tree, 0)
  116. def visit_factor(self, tree):
  117. self.forward_primitive_of_child(tree, 0)
  118. def visit_primary(self, tree):
  119. self.forward_primitive_of_child(tree, 0)
  120. def visit_parenthesized(self, tree):
  121. self.forward_primitive_of_child(tree, 1)
  122. def visit_atomvalue(self, tree):
  123. self.forward_primitive_of_child(tree, 0)
  124. def visit_type_specifier(self, tree):
  125. self.visit_literal(tree)
  126. def visit_actionname(self, tree):
  127. self.visit_literal(tree.get_tail()[1])
  128. self.set_primitive(tree, self.get_primitive(tree.get_tail()[1]))
  129. def visit_string(self, tree):
  130. self.visit_literal(tree)
  131. # there is no such rule in the grammar, we just avoid code duplicates
  132. def visit_literal(self, tree):
  133. # TODO dictionary and list
  134. # if self.no_constant:
  135. # n = self.new_value(tree.get_text())
  136. # self.set_id(tree, n)
  137. # else:
  138. c = self.value("constant")
  139. n = self.value(tree.get_text())
  140. self.dict(c, "node", n)
  141. self.set_primitive(tree, c)
  142. def visit_integer(self, tree):
  143. self.visit_literal(tree)
  144. def visit_float(self, tree):
  145. self.visit_literal(tree)
  146. def visit_rvalue(self, tree):
  147. if tree.get_tail()[0].head == "expression":
  148. self.visit_expression(tree.get_tail()[0])
  149. r = self.get_primitive(tree)
  150. self.set_primitive(tree, r)
  151. else:
  152. self.visit_lvalue(tree)
  153. r = self.get_primitive(tree)
  154. if r is None:
  155. return
  156. a = self.value("access")
  157. self.dict(a, "var", r)
  158. self.set_primitive(tree, a)
  159. def visit_lvalue(self, tree):
  160. symbol = self.get_symbol(tree)
  161. if symbol.name in ["input", "output"]:
  162. return
  163. r = self.value("resolve")
  164. # print symbol.name, symbol.is_func(), symbol.node
  165. self.dict(r, "var", symbol.node)
  166. self.set_primitive(tree, r)
  167. def visit_func_call(self, tree):
  168. self.visit_children(tree)
  169. symbol = self.get_symbol(tree.get_tail()[0])
  170. expressions = tree.get_children("expression")
  171. arg_nodes_reversed = []
  172. for i in reversed(range(len(expressions))):
  173. arg_name = '"{}"'.format(string.ascii_lowercase[i])
  174. arg_node = self.node()
  175. name_node = self.value(arg_name)
  176. self.dict(arg_node, "name", name_node)
  177. # print expressions[i].get_text()
  178. value_node = self.get_primitive(expressions[i])
  179. self.dict(arg_node, "value", value_node)
  180. if arg_nodes_reversed:
  181. next_node = arg_nodes_reversed[-1]
  182. self.dict(arg_node, "next_param", next_node)
  183. arg_nodes_reversed.append(arg_node)
  184. c = self.value("call")
  185. a = self.get_primitive(tree.get_tail()[0])
  186. self.dict(c, "func", a)
  187. if arg_nodes_reversed:
  188. self.dict(c, "params", arg_nodes_reversed[-1])
  189. self.dict(c, "last_param", arg_nodes_reversed[0])
  190. self.set_primitive(tree, c)
  191. def visit_input(self, tree):
  192. self.visit_children(tree)
  193. v = self.value("input")
  194. self.set_primitive(tree, v)
  195. def visit_output(self, tree):
  196. self.visit_children(tree)
  197. v = self.value("output")
  198. value = self.get_primitive(tree.get_child("expression"))
  199. self.dict(v, "value", value)
  200. self.set_primitive(tree, v)
  201. def visit_dictionary(self, tree):
  202. pass # TODO dictionary and list
  203. def visit_list(self, tree):
  204. pass # TODO dictionary and list
  205. def visit_dict_item(self, tree):
  206. pass
  207. def visit_ifelse(self, tree):
  208. self.visit_children(tree)
  209. expressions = [self.get_primitive(e) for e in
  210. tree.get_children("expression")]
  211. blocks = [self.get_primitive(b) for b in tree.get_children("block")]
  212. first = None
  213. prev = None
  214. for e, b in zip(expressions, blocks):
  215. v = self.value("if")
  216. if first is None:
  217. first = v
  218. self.dict(v, "cond", e)
  219. self.dict(v, "then", b)
  220. if prev:
  221. self.dict(prev, "else", v)
  222. prev = v
  223. if len(expressions) != len(blocks):
  224. self.dict(prev, "else", blocks[-1])
  225. self.set_primitive(tree, first)
  226. def visit_while(self, tree):
  227. self.visit_children(tree)
  228. w = self.value("while")
  229. c = self.get_primitive(tree.get_child("expression"))
  230. b = self.get_primitive(tree.get_child("block"))
  231. self.dict(w, "cond", c)
  232. self.dict(w, "body", b)
  233. self.set_primitive(tree, w)
  234. def visit_block(self, tree):
  235. self.visit_children(tree)
  236. primitives = []
  237. for child in tree.get_tail():
  238. p = self.get_primitive(child)
  239. if p:
  240. primitives.append(p)
  241. if child.head == "return":
  242. break
  243. for i in range(len(primitives)-1):
  244. self.dict(primitives[i], "next", primitives[i+1])
  245. self.set_primitive(tree, primitives[0])
  246. def visit_func_body(self, tree):
  247. self.forward_primitive_of_child(tree, 0)
  248. def pre_visit_funcdecl(self, tree):
  249. symbol = self.get_symbol(tree)
  250. if symbol.name in ["input", "output"]:
  251. return
  252. # TODO: fix funcdecl special case: "X function f(...) = ..."
  253. # Note: replicates "Element x; x = ?primiteves/a" behavior
  254. # Dangerous: SemanticsVisitor handles it as a function
  255. if not tree.get_child("func_body"):
  256. return
  257. new_value = self.node()
  258. self.function_values[symbol.name] = new_value
  259. root = self.value('"%s"' % symbol.name)
  260. symbol.node = root
  261. declare = self.value("global")
  262. self.dict(declare, "var", root)
  263. resolve = self.value("resolve")
  264. self.dict(resolve, "var", root)
  265. assign = self.value("assign")
  266. self.dict(assign, "var", resolve)
  267. const = self.value("constant")
  268. self.dict(const, "node", new_value)
  269. self.dict(assign, "value", const)
  270. return declare, assign
  271. def visit_funcdecl(self, tree):
  272. symbol = self.get_symbol(tree)
  273. if symbol.name in ["input", "output"]:
  274. return
  275. func_body = tree.get_child("func_body")
  276. if func_body:
  277. self.visit_children(tree)
  278. vf = self.function_values[symbol.name]
  279. parameters = tree.get_children("parameter")
  280. if parameters:
  281. ps = self.node()
  282. self.dict(vf, "params", ps)
  283. for i in range(len(parameters)):
  284. n = self.get_primitive(parameters[i])
  285. self.dict(ps, string.ascii_lowercase[i], n)
  286. b = self.get_primitive(func_body)
  287. self.dict(vf, "body", b)
  288. else:
  289. # TODO: fix funcdecl special case: "X function f(...) = ..."
  290. # Note: replicates "Element x; x = ?primiteves/a" behavior
  291. # Dangerous: SemanticsVisitor handles it as a function
  292. root = self.value('"%s"' % symbol.name)
  293. symbol.node = root
  294. if tree.get_child("ASSIGN"):
  295. new_value = "?" + tree.get_child("ANYTHING").get_text()
  296. elif tree.get_child("ASSIGN") and not tree.get_child("ANYTHING"):
  297. new_value = self.node()
  298. else:
  299. return
  300. declare = self.value("global")
  301. self.dict(declare, "var", root)
  302. resolve = self.value("resolve")
  303. self.dict(resolve, "var", root)
  304. assign = self.value("assign")
  305. self.dict(assign, "var", resolve)
  306. const = self.value("constant")
  307. self.dict(const, "node", new_value)
  308. self.dict(assign, "value", const)
  309. self.set_primitive(tree, (declare, assign))
  310. def visit_definition(self, tree):
  311. symbol = self.get_symbol(tree)
  312. root = self.value('"%s"' % symbol.name)
  313. declare = self.value("global")
  314. self.dict(declare, "var", root)
  315. symbol.node = root
  316. resolve = self.value("resolve")
  317. self.dict(resolve, "var", root)
  318. assign = self.value("assign")
  319. self.dict(assign, "var", resolve)
  320. const = self.value("constant")
  321. self.visit_atomvalue(tree.get_tail()[-1])
  322. value = self.get_primitive(tree.get_tail()[-1])
  323. #TODO hack...
  324. if value is None:
  325. value = self.node()
  326. self.dict(const, "node", value)
  327. self.dict(assign, "value", const)
  328. self.set_primitive(tree, (declare, assign))
  329. def visit_parameter(self, tree):
  330. n = self.node()
  331. symbol = self.get_symbol(tree)
  332. symbol.node = n
  333. self.set_primitive(tree, n)
  334. def visit_return(self, tree):
  335. self.visit_children(tree)
  336. r = self.value("return")
  337. if len(tree.get_tail()) > 1:
  338. v = self.get_primitive(tree.get_tail()[1])
  339. self.dict(r, "value", v)
  340. self.set_primitive(tree, r)
  341. def visit_bool(self, tree):
  342. self.visit_literal(tree)