primitives_visitor.py 14 KB

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