primitives_visitor.py 14 KB

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