123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447 |
- import string
- from visitor import Visitor
- class PrimitivesVisitor(Visitor):
- def __init__(self, args):
- Visitor.__init__(self, args)
- self.output = []
- self.free_id = 0
- self.function_values = dict()
- self.debug_symbols = "--debug" in args
- def debug(self, node, tree, msg=""):
- if self.debug_symbols:
- self.dict(node, "__debug", self.value('"[%s] %s"' % (tree.get_reference_line(), msg)))
- def node(self):
- self.output.append(("N", self.free_id))
- self.free_id += 1
- return self.free_id - 1
- def dict(self, src, val, trgt):
- if src is None or trgt is None:
- raise Exception("Got None")
- if isinstance(val, str):
- val = "\"%s\"" % val
- self.output.append(("D", (src, val, trgt)))
- def value(self, value):
- self.output.append(("V", (self.free_id, value)))
- self.free_id += 1
- return self.free_id - 1
- def edge(self, source, target):
- self.output.append(("E", (self.free_id, source, target)))
- self.free_id += 1
- return self.free_id - 1
- def dump(self):
- output = []
- for t, data in self.output:
- if t == "N":
- output.append("N auto_%s\n" % data)
- elif t == "V":
- name, value = data
- name = name if self.first != name else "initial_IP"
- output.append("V auto_%s(%s)\n" % (name, value))
- elif t == "D":
- source, value, target = data
- source = source if self.first != source else "auto_initial_IP"
- target = target if self.first != target else "auto_initial_IP"
- source = "auto_%s" % source if isinstance(source, int) else source
- target = "auto_%s" % target if isinstance(target, int) else target
- output.append("D %s,%s,%s\n" % (source, value, target))
- elif t == "E":
- name, source, target = data
- source = source if self.first != source else "auto_initial_IP"
- target = target if self.first != target else "auto_initial_IP"
- name = "auto_%s" % name if isinstance(name, int) else name
- source = "auto_%s" % source if isinstance(source, int) else source
- target = "auto_%s" % target if isinstance(target, int) else target
- output.append("E %s(%s,%s)\n" % (name, source, target))
- return "".join(output)
- def set_primitive(self, tree, primitive):
- tree.primitive = primitive
- def get_primitive(self, tree):
- return getattr(tree, 'primitive', None)
- def forward_primitive_of_child(self, tree, i):
- self.visit_children(tree)
- self.set_primitive(tree, self.get_primitive(tree.get_tail()[i]))
- # a visit_* method for each non-terminal in the grammar
- def visit_start(self, tree):
- primitives = []
- for child in tree.get_children("funcdecl"):
- p = self.pre_visit_funcdecl(child)
- if p:
- # funcdecl returns a (global, assign) pair
- primitives.extend(p)
- for child in tree.get_tail():
- self.visit(child)
- p = self.get_primitive(child)
- if p is not None:
- if type(p) in (list, tuple):
- # funcdecl returns a (global, assign) pair
- primitives.extend(p)
- else:
- primitives.append(p)
- if child.head == "return":
- break
- self.first = primitives[0]
- for i in range(len(primitives)-1):
- self.dict(primitives[i], "next", primitives[i+1])
- self.last_instruction = primitives[-1]
- def visit_vardecl(self, tree):
- symbol = self.get_symbol(tree)
- if symbol.is_global:
- d = self.value("global")
- n = self.value('"%s"' % symbol.name)
- else:
- d = self.value("declare")
- n = self.node()
- symbol.node = n
- self.dict(d, "var", n)
- self.debug(d, tree)
- self.set_primitive(tree, d)
- def visit_assignment(self, tree):
- self.visit_children(tree)
- a = self.value("assign")
- var = self.get_primitive(tree.get_tail()[0])
- value = self.get_primitive(tree.get_tail()[-1])
- self.dict(a, "var", var)
- self.dict(a, "value", value)
- self.debug(a, tree)
- self.set_primitive(tree, a)
- def visit_expression(self, tree):
- self.forward_primitive_of_child(tree, 0)
- def visit_binary_operation(self, tree):
- self.forward_primitive_of_child(tree, 0)
- def visit_disjunction(self, tree):
- self.forward_primitive_of_child(tree, 0)
- def visit_conjunction(self, tree):
- self.forward_primitive_of_child(tree, 0)
- def visit_comparison(self, tree):
- self.forward_primitive_of_child(tree, 0)
- def visit_relation(self, tree):
- self.forward_primitive_of_child(tree, 0)
- def visit_sum(self, tree):
- self.forward_primitive_of_child(tree, 0)
- def visit_term(self, tree):
- self.forward_primitive_of_child(tree, 0)
- def visit_factor(self, tree):
- self.forward_primitive_of_child(tree, 0)
- def visit_primary(self, tree):
- self.forward_primitive_of_child(tree, 0)
- def visit_parenthesized(self, tree):
- self.forward_primitive_of_child(tree, 1)
- def visit_atomvalue(self, tree):
- self.forward_primitive_of_child(tree, 0)
- def visit_type_specifier(self, tree):
- self.visit_literal(tree)
- def visit_actionname(self, tree):
- self.visit_literal(tree.get_tail()[1])
- self.set_primitive(tree, self.get_primitive(tree.get_tail()[1]))
- def visit_string(self, tree):
- self.visit_literal(tree)
- # there is no such rule in the grammar, we just avoid code duplicates
- def visit_literal(self, tree):
- # TODO dictionary and list
- # if self.no_constant:
- # n = self.new_value(tree.get_text())
- # self.set_id(tree, n)
- # else:
- c = self.value("constant")
- n = self.value(tree.get_text())
- self.dict(c, "node", n)
- self.debug(c, tree)
- self.set_primitive(tree, c)
- def visit_integer(self, tree):
- self.visit_literal(tree)
- def visit_float(self, tree):
- self.visit_literal(tree)
- def visit_rvalue(self, tree):
- self.visit_lvalue(tree)
- r = self.get_primitive(tree)
- if r is None:
- return
- a = self.value("access")
- self.dict(a, "var", r)
- self.debug(a, tree)
- self.set_primitive(tree, a)
- def visit_lvalue(self, tree):
- symbol = self.get_symbol(tree)
- if symbol.name in ["input", "output"]:
- return
- r = self.value("resolve")
- # print symbol.name, symbol.is_func(), symbol.node
- self.dict(r, "var", symbol.node)
- self.debug(r, tree)
- self.set_primitive(tree, r)
- def visit_func_call(self, tree):
- self.visit_children(tree)
- symbol = self.get_symbol(tree.get_tail()[0])
- expressions = tree.get_children("expression")
- arg_nodes_reversed = []
- for i in reversed(range(len(expressions))):
- arg_name = '"{}"'.format(string.ascii_lowercase[i])
- arg_node = self.node()
- name_node = self.value(arg_name)
- self.dict(arg_node, "name", name_node)
- # print expressions[i].get_text()
- value_node = self.get_primitive(expressions[i])
- self.dict(arg_node, "value", value_node)
- if arg_nodes_reversed:
- next_node = arg_nodes_reversed[-1]
- self.dict(arg_node, "next_param", next_node)
- arg_nodes_reversed.append(arg_node)
- c = self.value("call")
- a = self.get_primitive(tree.get_tail()[0])
- self.dict(c, "func", a)
- self.debug(c, tree)
- if arg_nodes_reversed:
- self.dict(c, "params", arg_nodes_reversed[-1])
- self.dict(c, "last_param", arg_nodes_reversed[0])
- self.set_primitive(tree, c)
- def visit_input(self, tree):
- self.visit_children(tree)
- v = self.value("input")
- self.debug(v, tree)
- self.set_primitive(tree, v)
- def visit_output(self, tree):
- self.visit_children(tree)
- v = self.value("output")
- self.debug(v, tree)
- value = self.get_primitive(tree.get_child("expression"))
- self.dict(v, "value", value)
- self.set_primitive(tree, v)
- def visit_ifelse(self, tree):
- self.visit_children(tree)
- expressions = [self.get_primitive(e) for e in
- tree.get_children("expression")]
- blocks = [self.get_primitive(b) for b in tree.get_children("block")]
- first = None
- prev = None
- for e, b in zip(expressions, blocks):
- v = self.value("if")
- self.debug(v, tree)
- if first is None:
- first = v
- self.dict(v, "cond", e)
- self.dict(v, "then", b)
- if prev:
- self.dict(prev, "else", v)
- prev = v
- if len(expressions) != len(blocks):
- self.dict(prev, "else", blocks[-1])
- self.set_primitive(tree, first)
- def visit_while(self, tree):
- self.visit_children(tree)
- w = self.value("while")
- self.debug(w, tree)
- c = self.get_primitive(tree.get_child("expression"))
- b = self.get_primitive(tree.get_child("block"))
- self.dict(w, "cond", c)
- self.dict(w, "body", b)
- self.set_primitive(tree, w)
- def visit_block(self, tree):
- self.visit_children(tree)
- primitives = []
- for child in tree.get_tail():
- p = self.get_primitive(child)
- if p:
- primitives.append(p)
- if child.head == "return":
- break
- for i in range(len(primitives)-1):
- self.dict(primitives[i], "next", primitives[i+1])
- self.set_primitive(tree, primitives[0])
- def visit_func_body(self, tree):
- self.forward_primitive_of_child(tree, 0)
- def pre_visit_funcdecl(self, tree):
- symbol = self.get_symbol(tree)
- if symbol.name in ["input", "output"]:
- return
- # TODO: fix funcdecl special case: "X function f(...) = ..."
- # Note: replicates "Element x; x = ?primiteves/a" behavior
- # Dangerous: SemanticsVisitor handles it as a function
- if not tree.get_child("func_body"):
- return
- new_value = self.node()
- self.function_values[symbol.name] = new_value
- root = self.value('"%s"' % symbol.name)
- symbol.node = root
- declare = self.value("global")
- self.dict(declare, "var", root)
- resolve = self.value("resolve")
- self.dict(resolve, "var", root)
- assign = self.value("assign")
- self.dict(assign, "var", resolve)
- const = self.value("constant")
- self.dict(const, "node", new_value)
- self.dict(assign, "value", const)
- return declare, assign
- def visit_funcdecl(self, tree):
- symbol = self.get_symbol(tree)
- if symbol.name in ["input", "output"]:
- return
- func_body = tree.get_child("func_body")
- if func_body:
- self.visit_children(tree)
- vf = self.function_values[symbol.name]
- parameters = tree.get_children("parameter")
- if parameters:
- ps = self.node()
- self.dict(vf, "params", ps)
- for i in range(len(parameters)):
- n = self.get_primitive(parameters[i])
- self.dict(ps, string.ascii_lowercase[i], n)
- # Add the name in case we want to pre-compile in the MvK
- self.dict(n, "name", self.value('"%s"' % string.ascii_lowercase[i]))
- b = self.get_primitive(func_body)
- self.dict(vf, "body", b)
- else:
- # TODO: fix funcdecl special case: "X function f(...) = ..."
- # Note: replicates "Element x; x = ?primiteves/a" behavior
- # Dangerous: SemanticsVisitor handles it as a function
- root = self.value('"%s"' % symbol.name)
- symbol.node = root
- if tree.get_child("ASSIGN"):
- new_value = "?" + tree.get_child("ANYTHING").get_text()
- elif tree.get_child("ASSIGN") and not tree.get_child("ANYTHING"):
- new_value = self.node()
- else:
- return
- declare = self.value("global")
- self.dict(declare, "var", root)
- self.debug(declare, tree)
- resolve = self.value("resolve")
- self.dict(resolve, "var", root)
- assign = self.value("assign")
- self.dict(assign, "var", resolve)
- const = self.value("constant")
- self.dict(const, "node", new_value)
- self.dict(assign, "value", const)
- self.set_primitive(tree, (declare, assign))
- def visit_definition(self, tree):
- symbol = self.get_symbol(tree)
- root = self.value('"%s"' % symbol.name)
- declare = self.value("global")
- self.dict(declare, "var", root)
- self.debug(declare, tree)
- symbol.node = root
- resolve = self.value("resolve")
- self.dict(resolve, "var", root)
- assign = self.value("assign")
- self.dict(assign, "var", resolve)
- const = self.value("constant")
- self.visit_atomvalue(tree.get_tail()[-1])
- value = self.get_primitive(tree.get_tail()[-1])
- #TODO hack...
- if value is None:
- value = self.node()
- self.dict(const, "node", value)
- self.dict(assign, "value", const)
- self.set_primitive(tree, (declare, assign))
- def visit_parameter(self, tree):
- n = self.node()
- symbol = self.get_symbol(tree)
- symbol.node = n
- self.set_primitive(tree, n)
- def visit_return(self, tree):
- self.visit_children(tree)
- r = self.value("return")
- self.debug(r, tree)
- if len(tree.get_tail()) > 1:
- v = self.get_primitive(tree.get_tail()[1])
- self.dict(r, "value", v)
- self.set_primitive(tree, r)
- def visit_bool(self, tree):
- self.visit_literal(tree)
|