Browse Source

Completely rewrite the internal data structure of the HUTN compiler

Yentl Van Tendeloo 7 years ago
parent
commit
d73ace55d0

+ 1 - 0
interface/HUTN/hutn_compiler/bootstrap_visitor.py

@@ -1,4 +1,5 @@
 import string
 import string
+from hutn_compiler.hutnparser import Tree
 from hutn_compiler.primitives_visitor import PrimitivesVisitor, Action
 from hutn_compiler.primitives_visitor import PrimitivesVisitor, Action
 
 
 class BootstrapVisitor(PrimitivesVisitor):
 class BootstrapVisitor(PrimitivesVisitor):

+ 14 - 15
interface/HUTN/hutn_compiler/compiler.py

@@ -1,4 +1,3 @@
-
 try:
 try:
     import cPickle as pickle
     import cPickle as pickle
 except ImportError:
 except ImportError:
@@ -127,41 +126,41 @@ def do_compile(inputfile, grammarfile, visitors=[], include_paths = [], mode="")
         msg = "%s:%s:%s: %s\nContext:\n%s" % (inputfile, result["line"], result["column"], result["text"], lines)
         msg = "%s:%s:%s: %s\nContext:\n%s" % (inputfile, result["line"], result["column"], result["text"], lines)
         raise Exception(msg)
         raise Exception(msg)
     else:
     else:
-        for child in result["tree"].tail:
-            child.inputfile = inputfile
+        for child in result["tree"]['tail']:
+            child['inputfile'] = inputfile
         included = set()
         included = set()
         while True:
         while True:
-            for i, v in enumerate(result["tree"].tail):
-                if v.head == "include":
+            for i, v in enumerate(result["tree"]['tail']):
+                if v['head'] == "include":
                     # Expand this node
                     # Expand this node
-                    for j in v.tail:
-                        if j.head == "STRVALUE":
-                            f = str(j.tail[0])[1:-1]
+                    for j in v['tail']:
+                        if j['head'] == "STRVALUE":
+                            f = str(j['tail'][0])[1:-1]
                             if f in included:
                             if f in included:
                                 subtree = []
                                 subtree = []
                             else:
                             else:
-                                name = str(j.tail[0])[1:-1]
-                                subtree = do_parse(find_file(name, include_paths), grammarfile)["tree"].tail
+                                name = str(j['tail'][0])[1:-1]
+                                subtree = do_parse(find_file(name, include_paths), grammarfile)["tree"]['tail']
                                 if subtree is None:
                                 if subtree is None:
                                     raise Exception("Parsing error for included file %s" % find_file(name, include_paths))
                                     raise Exception("Parsing error for included file %s" % find_file(name, include_paths))
 
 
                                 for t in subtree:
                                 for t in subtree:
-                                    t.inputfile = name
+                                    t['inputfile'] = name
                                 included.add(f)
                                 included.add(f)
                             # Found the string value, so break from the inner for ("searching for element")
                             # Found the string value, so break from the inner for ("searching for element")
                             break
                             break
 
 
                     # Merge all nodes in
                     # Merge all nodes in
-                    before = result["tree"].tail[:i]
-                    after = result["tree"].tail[i+1:]
-                    result["tree"].tail = before + subtree + after
+                    before = result["tree"]['tail'][:i]
+                    after = result["tree"]['tail'][i+1:]
+                    result["tree"]['tail'] = before + subtree + after
                     # Found an include node, but to prevent corruption of the tree, we need to start over again, so break from the outer for loop
                     # Found an include node, but to prevent corruption of the tree, we need to start over again, so break from the outer for loop
                     break
                     break
             else:
             else:
                 # The outer for finally finished, so there were no includes remaining, thus terminate the infinite while loop
                 # The outer for finally finished, so there were no includes remaining, thus terminate the infinite while loop
                 break
                 break
 
 
-    result["tree"].fix_tracability(inputfile)
+    Tree.fix_tracability(result['tree'], inputfile)
 
 
     for visitor in visitors:
     for visitor in visitors:
         visitor.visit(result["tree"])
         visitor.visit(result["tree"])

+ 41 - 50
interface/HUTN/hutn_compiler/constructors_visitor.py

@@ -1,10 +1,5 @@
-
-try:
-    import cPickle as pickle
-except ImportError:
-    import pickle as pickle
-
 from hutn_compiler.visitor import Visitor
 from hutn_compiler.visitor import Visitor
+from hutn_compiler.hutnparser import Tree
 
 
 class ConstructorsVisitor(Visitor):
 class ConstructorsVisitor(Visitor):
     def __init__(self, args):
     def __init__(self, args):
@@ -21,30 +16,28 @@ class ConstructorsVisitor(Visitor):
     # a visit_* method for each non-terminal in the grammar
     # a visit_* method for each non-terminal in the grammar
     def visit_start(self, tree):
     def visit_start(self, tree):
         # declare all functions
         # declare all functions
-        for child in tree.get_children("funcdecl"):
+        for child in Tree.get_children(tree, "funcdecl"):
             if self.pre_visit_funcdecl(child):
             if self.pre_visit_funcdecl(child):
                 self.add_constructors(True)
                 self.add_constructors(True)
 
 
-        tail = tree.get_tail_without(["newline"])
-        # tail = tree.get_children("funcdecl") +\
-        #     tree.get_tail_without(["newline", "funcdecl"])
+        tail = Tree.get_tail_without(tree, ["newline"])
         last = tail[-1]
         last = tail[-1]
         for child in tail[:-1]:
         for child in tail[:-1]:
-            if child.head in ["return", "break", "continue"]:
+            if child['head'] in ["return", "break", "continue"]:
                 last = child
                 last = child
                 break
                 break
             else:
             else:
                 # funcdecl may add no constructors
                 # funcdecl may add no constructors
                 new_constructors_were_added = self.visit(child)
                 new_constructors_were_added = self.visit(child)
-                if child.head == "func_call":  # pop 'false'
+                if child['head'] == "func_call":  # pop 'false'
                     self.constructors.pop()
                     self.constructors.pop()
                 if new_constructors_were_added:
                 if new_constructors_were_added:
                     self.add_constructors(True)
                     self.add_constructors(True)
         new_constructors_were_added = self.visit(last)
         new_constructors_were_added = self.visit(last)
-        if last.head == "func_call":  # pop 'false'
+        if last['head'] == "func_call":  # pop 'false'
             self.constructors.pop()
             self.constructors.pop()
         if new_constructors_were_added:
         if new_constructors_were_added:
-            if last.head not in ["return", "break", "continue"]:
+            if last['head'] not in ["return", "break", "continue"]:
                 self.add_constructors(False)
                 self.add_constructors(False)
         elif self.constructors:
         elif self.constructors:
             self.constructors.pop()  # pop 'true'
             self.constructors.pop()  # pop 'true'
@@ -61,8 +54,8 @@ class ConstructorsVisitor(Visitor):
 
 
     def visit_assignment(self, tree):
     def visit_assignment(self, tree):
         self.add_constructors("assign")
         self.add_constructors("assign")
-        self.visit(tree.get_tail()[0])
-        self.visit(tree.get_tail()[2])
+        self.visit(Tree.get_tail(tree)[0])
+        self.visit(Tree.get_tail(tree)[2])
         return True
         return True
 
 
     def visit_expression(self, tree):
     def visit_expression(self, tree):
@@ -102,25 +95,23 @@ class ConstructorsVisitor(Visitor):
         self.visit_children(tree)
         self.visit_children(tree)
 
 
     def visit_type_specifier(self, tree):
     def visit_type_specifier(self, tree):
-        self.add_constructors("const",
-            {"value": tree.get_text()})
+        self.add_constructors("const", {"value": Tree.get_text(tree)})
 
 
     def visit_actionname(self, tree):
     def visit_actionname(self, tree):
-        self.add_constructors("const",
-            {"value": tree.get_tail()[0].get_text()[1:]})
+        self.add_constructors("const", {"value": Tree.get_text(Tree.get_tail(tree)[0])[1:]})
 
 
     def visit_string(self, tree):
     def visit_string(self, tree):
-        v = tree.get_text()[1:-1]
+        v = Tree.get_text(tree)[1:-1]
         v = v.replace("\\n", "\n")
         v = v.replace("\\n", "\n")
         v = v.replace("\\t", "\t")
         v = v.replace("\\t", "\t")
         v = v.replace("\\\"", "\"")
         v = v.replace("\\\"", "\"")
         self.add_constructors("const", v)
         self.add_constructors("const", v)
 
 
     def visit_integer(self, tree):
     def visit_integer(self, tree):
-        self.add_constructors("const", int(tree.get_text()))
+        self.add_constructors("const", int(Tree.get_text(tree)))
 
 
     def visit_float(self, tree):
     def visit_float(self, tree):
-        self.add_constructors("const", float(tree.get_text()))
+        self.add_constructors("const", float(Tree.get_text(tree)))
 
 
     def visit_rvalue(self, tree):
     def visit_rvalue(self, tree):
         self.add_constructors("access")
         self.add_constructors("access")
@@ -134,13 +125,13 @@ class ConstructorsVisitor(Visitor):
         self.add_constructors("resolve", symbol.node)
         self.add_constructors("resolve", symbol.node)
 
 
     def visit_func_call(self, tree):
     def visit_func_call(self, tree):
-        symbol = self.get_symbol(tree.get_tail()[0])
+        symbol = self.get_symbol(Tree.get_tail(tree)[0])
         self.add_constructors("call")
         self.add_constructors("call")
         if hasattr(symbol, "pathmv"):
         if hasattr(symbol, "pathmv"):
             self.add_constructors("deref", symbol.pathmv)
             self.add_constructors("deref", symbol.pathmv)
         else:
         else:
-            self.visit(tree.get_tail()[0])
-        expressions = tree.get_children("expression")
+            self.visit(Tree.get_tail(tree)[0])
+        expressions = Tree.get_children(tree, "expression")
         self.add_constructors(len(expressions))
         self.add_constructors(len(expressions))
         for expression in expressions:
         for expression in expressions:
             self.visit(expression)
             self.visit(expression)
@@ -153,7 +144,7 @@ class ConstructorsVisitor(Visitor):
 
 
     def visit_output(self, tree):
     def visit_output(self, tree):
         self.add_constructors("output")
         self.add_constructors("output")
-        self.visit(tree.get_child("expression"))
+        self.visit(Tree.get_child(tree, "expression"))
         return True
         return True
 
 
     def visit_dictionary(self, tree):
     def visit_dictionary(self, tree):
@@ -167,8 +158,8 @@ class ConstructorsVisitor(Visitor):
 
 
     def visit_ifelse(self, tree):
     def visit_ifelse(self, tree):
         self.add_constructors("if")
         self.add_constructors("if")
-        expressions = tree.get_children("expression")
-        blocks = tree.get_children("block")
+        expressions = Tree.get_children(tree, "expression")
+        blocks = Tree.get_children(tree, "block")
         self.visit(expressions[0])  # condition
         self.visit(expressions[0])  # condition
         self.visit(blocks[0])  # then-clause
         self.visit(blocks[0])  # then-clause
 
 
@@ -190,59 +181,59 @@ class ConstructorsVisitor(Visitor):
 
 
     def visit_while(self, tree):
     def visit_while(self, tree):
         self.add_constructors("while")
         self.add_constructors("while")
-        self.visit(tree.get_child("expression"))
-        self.visit(tree.get_child("block"))
+        self.visit(Tree.get_child(tree, "expression"))
+        self.visit(Tree.get_child(tree, "block"))
         return True
         return True
 
 
     def visit_block(self, tree):
     def visit_block(self, tree):
-        tail = tree.get_tail_without(["newline", "indent"])
+        tail = Tree.get_tail_without(tree, ["newline", "indent"])
         last = tail[-1]
         last = tail[-1]
         for child in tail[:-1]:
         for child in tail[:-1]:
-            if child.head in ["return", "break", "continue"]:
+            if child['head'] in ["return", "break", "continue"]:
                 last = child
                 last = child
                 break
                 break
             else:
             else:
                 self.visit(child)
                 self.visit(child)
-                if child.head == "func_call":  # pop 'false'
+                if child['head'] == "func_call":  # pop 'false'
                     self.constructors.pop()
                     self.constructors.pop()
                 self.add_constructors(True)
                 self.add_constructors(True)
         self.visit(last)
         self.visit(last)
-        if last.head == "func_call":  # pop 'false'
+        if last['head'] == "func_call":  # pop 'false'
             self.constructors.pop()
             self.constructors.pop()
-        if last.head not in ["return", "break", "continue"]:
+        if last['head'] not in ["return", "break", "continue"]:
             self.add_constructors(False)
             self.add_constructors(False)
 
 
     def visit_func_body(self, tree):
     def visit_func_body(self, tree):
         self.visit_children(tree)
         self.visit_children(tree)
 
 
     def pre_visit_funcdecl(self, tree):
     def pre_visit_funcdecl(self, tree):
-        func_body = tree.get_child("func_body")
+        func_body = Tree.get_child(tree, "func_body")
         symbol = self.get_symbol(tree)
         symbol = self.get_symbol(tree)
         symbol.node = symbol.name
         symbol.node = symbol.name
         return False
         return False
 
 
     def visit_funcdecl(self, tree):
     def visit_funcdecl(self, tree):
-        func_body = tree.get_child("func_body")
+        func_body = Tree.get_child(tree, "func_body")
         symbol = self.get_symbol(tree)
         symbol = self.get_symbol(tree)
         if func_body:
         if func_body:
             if symbol.name in ["input", "output"]:
             if symbol.name in ["input", "output"]:
                 return False
                 return False
-            if tree.get_children("MUTABLE"):
+            if Tree.get_children(tree, "MUTABLE"):
                 self.add_constructors("mutable_funcdef")
                 self.add_constructors("mutable_funcdef")
             else:
             else:
                 self.add_constructors("funcdef")
                 self.add_constructors("funcdef")
             self.add_constructors(symbol.node,
             self.add_constructors(symbol.node,
                                   len(symbol.params))
                                   len(symbol.params))
-            for p in tree.get_children("parameter"):
+            for p in Tree.get_children(tree, "parameter"):
                 self.visit(p)
                 self.visit(p)
             self.visit(func_body)
             self.visit(func_body)
             return True
             return True
-        elif tree.get_child("ASSIGN"):
+        elif Tree.get_child(tree, "ASSIGN"):
             # TODO: fix funcdecl special case: "X function f(...) = ..."
             # TODO: fix funcdecl special case: "X function f(...) = ..."
             # Note: replicates "Element x; x = ?primiteves/a" behavior
             # Note: replicates "Element x; x = ?primiteves/a" behavior
             # Dangerous: SemanticsVisitor handles it as a function
             # Dangerous: SemanticsVisitor handles it as a function
             # pathmv is needed in visit_func_call(self, tree)
             # pathmv is needed in visit_func_call(self, tree)
-            symbol.pathmv = tree.get_child("ANYTHING").get_text()
+            symbol.pathmv = Tree.get_text(Tree.get_child(tree, "ANYTHING"))
 
 
             self.add_constructors("global", symbol.node, "deref", symbol.pathmv)
             self.add_constructors("global", symbol.node, "deref", symbol.pathmv)
 
 
@@ -268,15 +259,15 @@ class ConstructorsVisitor(Visitor):
         
         
     def visit_return(self, tree):
     def visit_return(self, tree):
         self.add_constructors("return")
         self.add_constructors("return")
-        if len(tree.get_tail()) > 2:
+        if len(Tree.get_tail(tree)) > 2:
             self.add_constructors(True)
             self.add_constructors(True)
-            self.visit(tree.get_tail()[1])
+            self.visit(Tree.get_tail(tree)[1])
         else:
         else:
             self.add_constructors(False)
             self.add_constructors(False)
         return True
         return True
 
 
     def visit_bool(self, tree):
     def visit_bool(self, tree):
-        if tree.get_text() == "True":
+        if Tree.get_text(tree) == "True":
             self.add_constructors("const", True)
             self.add_constructors("const", True)
         else:
         else:
             self.add_constructors("const", False)
             self.add_constructors("const", False)
@@ -286,17 +277,17 @@ class ConstructorsVisitor(Visitor):
         symbol = self.get_symbol(tree)
         symbol = self.get_symbol(tree)
         self.declare(symbol)
         self.declare(symbol)
 
 
-        if tree.get_children("ASSIGN"):
+        if Tree.get_children(tree, "ASSIGN"):
             # Determine whether it is just a constant, or a deref
             # Determine whether it is just a constant, or a deref
-            atom = tree.get_child("atomvalue")
-            if atom.get_child("deref"):
+            atom = Tree.get_child(tree, "atomvalue")
+            if Tree.get_child(atom, "deref"):
                 # Deref
                 # Deref
-                dest = atom.get_child("deref").get_child("ANYTHING")
+                dest = Tree.get_child(Tree.get_child(atom, "deref"), "ANYTHING")
                 if dest is None:
                 if dest is None:
                     # Just an empty questionmark!
                     # Just an empty questionmark!
                     self.add_constructors("empty")
                     self.add_constructors("empty")
                 else:
                 else:
-                    self.add_constructors("deref", dest.get_text())
+                    self.add_constructors("deref", Tree.get_text(dest))
             else:
             else:
                 # Constant
                 # Constant
                 self.visit(atom)
                 self.visit(atom)

+ 10 - 10
interface/HUTN/hutn_compiler/declare_functions_visitor.py

@@ -1,7 +1,7 @@
 import hutn_compiler.symbol_table as st
 import hutn_compiler.symbol_table as st
 import hutn_compiler.types_mv as types_mv
 import hutn_compiler.types_mv as types_mv
 from hutn_compiler.visitor import Visitor
 from hutn_compiler.visitor import Visitor
-
+from hutn_compiler.hutnparser import Tree
 
 
 # Declare the function but do not visit its body
 # Declare the function but do not visit its body
 class DeclareFunctionsVisitor(Visitor):
 class DeclareFunctionsVisitor(Visitor):
@@ -12,18 +12,18 @@ class DeclareFunctionsVisitor(Visitor):
 
 
     def compute_parameter_types(self, tree):
     def compute_parameter_types(self, tree):
         parameter_types = []
         parameter_types = []
-        for parameter in tree.get_children('parameter'):
-            type_specifier = parameter.get_children("type_specifier")[0].get_text()
+        for parameter in Tree.get_children(tree, 'parameter'):
+            type_specifier = Tree.get_text(Tree.get_children(parameter, "type_specifier")[0])
             parameter_types.append(types_mv.string_to_type(type_specifier))
             parameter_types.append(types_mv.string_to_type(type_specifier))
         return parameter_types
         return parameter_types
 
 
     def compute_func_type(self, tree):
     def compute_func_type(self, tree):
-        self.visit(tree.get_tail()[0])
-        func_type = self.get_type(tree.get_tail()[0])
+        self.visit(Tree.get_tail(tree)[0])
+        func_type = self.get_type(Tree.get_tail(tree)[0])
         return func_type
         return func_type
 
 
     def visit_funcdecl(self, tree):
     def visit_funcdecl(self, tree):
-        func_name = tree.get_children("func_name")[0].get_text()
+        func_name = Tree.get_text(Tree.get_children(tree, "func_name")[0])
         func_type = self.compute_func_type(tree)
         func_type = self.compute_func_type(tree)
         parameter_types = self.compute_parameter_types(tree)
         parameter_types = self.compute_parameter_types(tree)
         self.set_type(tree, func_type)
         self.set_type(tree, func_type)
@@ -33,12 +33,12 @@ class DeclareFunctionsVisitor(Visitor):
             s = st.Symbol(func_name, func_type, is_global=True, params=parameter_types)
             s = st.Symbol(func_name, func_type, is_global=True, params=parameter_types)
             self.symbol_table.add(s)
             self.symbol_table.add(s)
         except Exception:
         except Exception:
-            if "COLON" in tree.get_tail() or "ASSIGN" in tree.get_tail():
+            if "COLON" in Tree.get_tail(tree) or "ASSIGN" in Tree.get_tail(tree):
                 raise RuntimeError(
                 raise RuntimeError(
                     "{}:{}:{}: error: redeclaration of '{}'".format(
                     "{}:{}:{}: error: redeclaration of '{}'".format(
-                        self.inputfiles[0], tree.startpos['line'],
-                        tree.startpos['column'], func_name))
+                        self.inputfiles[0], tree['startpos']['line'],
+                        tree['startpos']['column'], func_name))
         self.set_symbol(tree, s)
         self.set_symbol(tree, s)
 
 
     def visit_func_type(self, tree):
     def visit_func_type(self, tree):
-        self.set_type(tree, types_mv.string_to_type(tree.get_text()))
+        self.set_type(tree, types_mv.string_to_type(Tree.get_text(tree)))

+ 33 - 33
interface/HUTN/hutn_compiler/grammar_compiler_visitor.py

@@ -69,21 +69,21 @@ class Visitor(object):
     """
     """
     def isTree(self, item):
     def isTree(self, item):
         ret = False
         ret = False
-        if isinstance(item, Tree):
-            if len(item.tail) > 1:
+        if isinstance(item, dict):
+            if len(item['tail']) > 1:
                 ret = True
                 ret = True
-            elif len(item.tail) == 1 and isinstance(item.tail[0], Tree):
+            elif len(item['tail']) == 1 and isinstance(item['tail'][0], dict):
                 ret = True
                 ret = True
         return ret
         return ret
 
 
     def isToken(self,item):
     def isToken(self,item):
         ret = False
         ret = False
-        if isinstance(item, Tree):
+        if isinstance(item, dict):
             try:
             try:
-                if len(item.tail) == 1 and isinstance(item.tail[0], basestring):
+                if len(item['tail']) == 1 and isinstance(item['tail'][0], basestring):
                     ret = True
                     ret = True
             except NameError:
             except NameError:
-                if len(item.tail) == 1 and isinstance(item.tail[0], str):
+                if len(item['tail']) == 1 and isinstance(item['tail'][0], str):
                     ret = True
                     ret = True
         return ret
         return ret
 
 
@@ -92,8 +92,8 @@ class Visitor(object):
         # place_name : LOWER_LETTER
         # place_name : LOWER_LETTER
         #and item is place_name than the value is at the bottom of place_name -> LOWER_LETTER -> value
         #and item is place_name than the value is at the bottom of place_name -> LOWER_LETTER -> value
         #USE ONLY WHEN SURE YOU ARE EXPECTING A TOKEN VALUE
         #USE ONLY WHEN SURE YOU ARE EXPECTING A TOKEN VALUE
-        while item and isinstance(item, Tree):
-            item = item.tail[0]
+        while item and isinstance(item, dict):
+            item = item['tail'][0]
         return str(item)
         return str(item)
 
 
 
 
@@ -106,9 +106,9 @@ class GrammarCompilerVisitor(Visitor):
 
 
     def visit(self, tree):
     def visit(self, tree):
         if self.isTree(tree):
         if self.isTree(tree):
-            if tree.head == START_RULE:
-                for item in tree.tail:
-                    if self.isTree(item) and item.head == GRAMMAR_RULE:
+            if tree['head'] == START_RULE:
+                for item in tree['tail']:
+                    if self.isTree(item) and item['head'] == GRAMMAR_RULE:
                         self.visitGrammar(item)
                         self.visitGrammar(item)
                     #elif self.isTree(item, Tree) and item.head == MAPPER_RULE:
                     #elif self.isTree(item, Tree) and item.head == MAPPER_RULE:
                     #    self.visitMapper(item)
                     #    self.visitMapper(item)
@@ -122,9 +122,9 @@ class GrammarCompilerVisitor(Visitor):
 
 
     def visitGrammar(self,tree):
     def visitGrammar(self,tree):
         if self.isTree(tree):
         if self.isTree(tree):
-            for child in tree.tail:
+            for child in tree['tail']:
                 if self.isTree(child):
                 if self.isTree(child):
-                    rule = child.head
+                    rule = child['head']
                     if rule == PROD_RULE: #a grammar consists of prod rules and a prod rule can be a rule or token
                     if rule == PROD_RULE: #a grammar consists of prod rules and a prod rule can be a rule or token
                         self.visitGrammar(child)
                         self.visitGrammar(child)
                     elif rule == RULE_DEF: #top level rule definition
                     elif rule == RULE_DEF: #top level rule definition
@@ -140,9 +140,9 @@ class GrammarCompilerVisitor(Visitor):
             body = ''
             body = ''
             msg = ''
             msg = ''
             rm = False
             rm = False
-            for child in tree.tail:
+            for child in tree['tail']:
                 if self.isTree(child):
                 if self.isTree(child):
-                    rule = child.head
+                    rule = child['head']
                     if rule == RULE_NAME:
                     if rule == RULE_NAME:
                        name = self.getTokenValue(child)
                        name = self.getTokenValue(child)
                        # print name
                        # print name
@@ -152,7 +152,7 @@ class GrammarCompilerVisitor(Visitor):
                         #TODO this will not work for the moment due to having an extra parent
                         #TODO this will not work for the moment due to having an extra parent
                         #the child  0 is @Msg or Message
                         #the child  0 is @Msg or Message
                         #child 1 is a token of type REGEXP and his tail contains the value
                         #child 1 is a token of type REGEXP and his tail contains the value
-                        msg = self.getTokenValue(child.tail[1])
+                        msg = self.getTokenValue(child['tail'][1])
                     elif rule == REMOVE:
                     elif rule == REMOVE:
                         rm = True
                         rm = True
                     else:
                     else:
@@ -184,8 +184,8 @@ class GrammarCompilerVisitor(Visitor):
         allowUnpack = True #allow unpacking in upperlevel of recursion
         allowUnpack = True #allow unpacking in upperlevel of recursion
         operator = '.' #we always assume it is a sequence we can change it later if we are wrong
         operator = '.' #we always assume it is a sequence we can change it later if we are wrong
         rhs = []
         rhs = []
-        for item in tree.tail:
-            head = item.head
+        for item in tree['tail']:
+            head = item['head']
             if self.isTree(item):
             if self.isTree(item):
                 if head == TOKEN_NAME: # a reference to a token
                 if head == TOKEN_NAME: # a reference to a token
                     tok =  '$' + self.getTokenValue(item)
                     tok =  '$' + self.getTokenValue(item)
@@ -207,10 +207,10 @@ class GrammarCompilerVisitor(Visitor):
                     allowUnpack = False
                     allowUnpack = False
                     operator = '#'
                     operator = '#'
                     extra = '('
                     extra = '('
-                    for child in item.tail:
-                        if child.head == MINUS:
+                    for child in item['tail']:
+                        if child['head'] == MINUS:
                             extra += '-'
                             extra += '-'
-                        if child.head == INT:
+                        if child['head'] == INT:
                             extra += self.getTokenValue(child) + ')'
                             extra += self.getTokenValue(child) + ')'
                             operator += extra
                             operator += extra
 
 
@@ -228,10 +228,10 @@ class GrammarCompilerVisitor(Visitor):
                     else:
                     else:
                         rhs.append(r)
                         rhs.append(r)
                 else:
                 else:
-                    print('Encountered unexpected rule type in tree RHS with head: ' + str(item.head))
+                    print('Encountered unexpected rule type in tree RHS with head: ' + str(item['head']))
             elif self.isToken(item):
             elif self.isToken(item):
                 #print "TOKEN INNER in rule:",  tree.head, "with name", item.head, " value", self.getTokenValue(item)
                 #print "TOKEN INNER in rule:",  tree.head, "with name", item.head, " value", self.getTokenValue(item)
-                head = item.head
+                head = item['head']
                 if head == OPER:
                 if head == OPER:
                     operator = self.getTokenValue(item)
                     operator = self.getTokenValue(item)
                     allowUnpack = False
                     allowUnpack = False
@@ -280,17 +280,17 @@ class GrammarCompilerVisitor(Visitor):
 
 
     def visitTokens(self,tree):
     def visitTokens(self,tree):
         if self.isTree(tree):
         if self.isTree(tree):
-            for child in tree.tail:
+            for child in tree['tail']:
                 if self.isTree(child):
                 if self.isTree(child):
-                    rule = child.head
+                    rule = child['head']
                     if rule == TOKEN_DEF:
                     if rule == TOKEN_DEF:
                         self.fillTokenInfo(child)
                         self.fillTokenInfo(child)
                     elif rule == TOKEN_SUB_COLLECTION:
                     elif rule == TOKEN_SUB_COLLECTION:
                         #a collection is 0 type 1: 2 name 3 {  4 and further token_defs last }
                         #a collection is 0 type 1: 2 name 3 {  4 and further token_defs last }
-                        colType  = self.getTokenValue(child.tail[0])
-                        colName = self.getTokenValue(child.tail[2])
-                        for item in child.tail[4:]:
-                            if self.isTree(item) and item.head == TOKEN_DEF:
+                        colType  = self.getTokenValue(child['tail'][0])
+                        colName = self.getTokenValue(child['tail'][2])
+                        for item in child['tail'][4:]:
+                            if self.isTree(item) and item['head'] == TOKEN_DEF:
                                 self.fillTokenInfo(item,colType, colName)
                                 self.fillTokenInfo(item,colType, colName)
                     else: #token_collection_content is the  parent of both token def and token sub collection
                     else: #token_collection_content is the  parent of both token def and token sub collection
                         self.visitTokens(child)
                         self.visitTokens(child)
@@ -300,9 +300,9 @@ class GrammarCompilerVisitor(Visitor):
         val = ''
         val = ''
         msg = ''
         msg = ''
         rm = False
         rm = False
-        for item in tree.tail:
+        for item in tree['tail']:
             if self.isTree(item):
             if self.isTree(item):
-                head = item.head
+                head = item['head']
                 if head == TOKEN_NAME:
                 if head == TOKEN_NAME:
                     #roken name contains a child of type token uppercase and this child contains the actual value
                     #roken name contains a child of type token uppercase and this child contains the actual value
                     name =  self.getTokenValue(item)
                     name =  self.getTokenValue(item)
@@ -311,11 +311,11 @@ class GrammarCompilerVisitor(Visitor):
                 elif head == MESSAGE:
                 elif head == MESSAGE:
                     #the child  0 is @Msg or Message
                     #the child  0 is @Msg or Message
                     #child 1 is a token of type REGEXP and his tail contains the value
                     #child 1 is a token of type REGEXP and his tail contains the value
-                    msg = self.getTokenValue(item.tail[1])
+                    msg = self.getTokenValue(item['tail'][1])
                 elif head == MODIFIER:
                 elif head == MODIFIER:
                     #the tail is the token, the head gives us the name we don't need the actual value
                     #the tail is the token, the head gives us the name we don't need the actual value
                     #especially since the actual value might change
                     #especially since the actual value might change
-                    if item.tail[0].head == IMPL_MOD:
+                    if item['tail'][0]['head'] == IMPL_MOD:
                         self.implicit.append( '$' + name)
                         self.implicit.append( '$' + name)
                     #else:
                     #else:
                         #pass
                         #pass

+ 90 - 99
interface/HUTN/hutn_compiler/hutnparser.py

@@ -39,34 +39,29 @@ def get_buffer(base, start):
         return buffer(base, start)
         return buffer(base, start)
 
 
 class Tree(object):
 class Tree(object):
-    def __init__(self, head, tail, startpos, endpos, inputfile = None):
-        self.head = head
-        self.tail = tail
-        self.startpos = startpos
-        self.endpos = endpos
-        self._tail = None
-        self.inputfile = inputfile
-        # IMPORTANT: self.replaced: replace_child defines self.replaced
-
-    def is_rule(self):
-        return self.head.islower()
-
-    def is_token(self):
-        return not self.is_rule()
-
-    def get_tail(self):
-        if self.is_rule():
-            if not self._tail:
-                self._tail = [t for t in self.get_raw_tail()
-                              if not t.head.startswith("implicit_autogenerated_")]
-            return self._tail
+    @staticmethod
+    def is_rule(tree):
+        return tree['head'].islower()
+
+    @staticmethod
+    def is_token(tree):
+        return not Tree.is_rule(tree)
+
+    @staticmethod
+    def get_tail(tree):
+        if Tree.is_rule(tree):
+            if not tree.get("_tail", None):
+                tree['_tail'] = [t for t in Tree.get_raw_tail(tree) if not t['head'].startswith("implicit_autogenerated_")]
+            return tree['_tail']
         else:
         else:
-            return self.get_raw_tail()
+            return tree['tail']
 
 
-    def get_raw_tail(self):
-        return self.tail
+    @staticmethod
+    def get_raw_tail(tree):
+        return tree['tail']
 
 
-    def get_text(self, with_implicit=False):
+    @staticmethod
+    def get_text(tree, with_implicit=False):
         parts = []
         parts = []
 
 
         if with_implicit:
         if with_implicit:
@@ -76,62 +71,60 @@ class Tree(object):
 
 
         def post_order(tree):
         def post_order(tree):
             for child in tail(tree):
             for child in tail(tree):
-                if hasattr(child, "replaced"):
-                    child = child.replaced
-                if isinstance(child, Tree):
+                if "replaced" in child:
+                    child = child['replaced']
+                if isinstance(child, dict):
                     post_order(child)
                     post_order(child)
                 else:
                 else:
                     parts.append(child)
                     parts.append(child)
 
 
-        post_order(self)
+        post_order(tree)
 
 
         return ''.join(parts)
         return ''.join(parts)
 
 
-    def get_child(self, name):
-        for child in self.get_tail():
-            if child.head == name:
+    @staticmethod
+    def get_child(tree, name):
+        for child in Tree.get_tail(tree):
+            if child['head'] == name:
                 return child
                 return child
         return None
         return None
 
 
-    def get_children(self, name):
+    @staticmethod
+    def get_children(tree, name):
         children = []
         children = []
-        for child in self.get_tail():
-            if child.head == name:
+        for child in Tree.get_tail(tree):
+            if child['head'] == name:
                 children.append(child)
                 children.append(child)
         return children
         return children
 
 
-    def replace_child(self, old_child, new_child):
-        new_child.replaced = old_child
+    @staticmethod
+    def replace_child(tree, old_child, new_child):
+        new_child['replaced'] = old_child
 
 
-        i = self.get_raw_tail().index(old_child)
-        self.get_raw_tail()[i] = new_child
+        i = Tree.get_raw_tail(tree).index(old_child)
+        Tree.get_raw_tail(tree)[i] = new_child
 
 
-        i = self.get_tail().index(old_child)
-        self.get_tail()[i] = new_child
+        i = Tree.get_tail(tree).index(old_child)
+        Tree.get_tail(tree)[i] = new_child
 
 
-    def get_tail_without(self, names):
-        if self.is_rule():
-            return [t for t in self.get_tail() if not t.head in names]
+    @staticmethod
+    def get_tail_without(tree, names):
+        if Tree.is_rule(tree):
+            return [t for t in Tree.get_tail(tree) if not t['head'] in names]
         else:
         else:
-            return self.get_raw_tail()
+            return Tree.get_raw_tail(tree)
 
 
-    def __str__(self):
-        return "(%s, %s) [%s]" % (
-            self.head, str((self.startpos, self.endpos)),
-            ", ".join([str(i) for i in self.get_raw_tail()]))
+    @staticmethod
+    def get_reference_line(tree):
+        return "%s:%s:%s-%s" % (tree['inputfile'], tree['startpos']["line"], tree['startpos']["column"], tree['endpos']["column"])
 
 
-    def get_reference_line(self):
-        return "%s:%s:%s-%s" % (self.inputfile, self.startpos["line"], self.startpos["column"], self.endpos["column"])
-
-    def fix_tracability(self, inputfile):
-        if self.inputfile is None:
-            self.inputfile = inputfile
-        for f in self.tail:
-            if isinstance(f, Tree):
-                f.fix_tracability(self.inputfile)
-
-    def pretty_print(self, i=0):
-        return "\t" * i + str(self.head) + "\n" + "\n".join([("\t" * (i+1) + st) if isinstance(st, str) else st.pretty_print(i+1) for st in self.get_tail()])
+    @staticmethod
+    def fix_tracability(tree, inputfile):
+        if 'inputfile' not in tree:
+            tree['inputfile'] = inputfile
+        for t in tree['tail']:
+            if isinstance(t, dict):
+                Tree.fix_tracability(t, tree['inputfile'])
 
 
 class Parser(object):
 class Parser(object):
     class Constants(object):
     class Constants(object):
@@ -329,8 +322,8 @@ class Parser(object):
         elif len(results) == 1:
         elif len(results) == 1:
             result = results[0]
             result = results[0]
             result.update({'status': Parser.Constants.Success})
             result.update({'status': Parser.Constants.Success})
-            if result['tree'].head != 'start':
-                result['tree'] = Tree('start', [result['tree']], result['tree'].startpos, result['tree'].endpos)
+            if result['tree']['head'] != 'start':
+                result['tree'] = {"head": "start", "tail": [result['tree']], "startpos": result['tree']['startpos'], "endpos": result['tree']['endpos']}
             result['tree'] = IgnorePostProcessor(self.rules, self.tokens).visit(result['tree'])
             result['tree'] = IgnorePostProcessor(self.rules, self.tokens).visit(result['tree'])
             if self.linePosition: #Added by Daniel
             if self.linePosition: #Added by Daniel
                 result['tree'] = Parser.PositionPostProcessor(self.convertToLineColumn).visit(result['tree'])
                 result['tree'] = Parser.PositionPostProcessor(self.convertToLineColumn).visit(result['tree'])
@@ -592,10 +585,9 @@ class Parser(object):
             results = self.eval_body(rulename, rule['body'], j)
             results = self.eval_body(rulename, rule['body'], j)
             for r in results:
             for r in results:
                 if (r['tree']):
                 if (r['tree']):
-                    head = r['tree'].head
+                    head = r['tree']['head']
                     if(head == '*' or head == '+' or head == '?' or head == '|' or head == '.'):
                     if(head == '*' or head == '+' or head == '?' or head == '|' or head == '.'):
-                        newr = {'tree': Tree(rulename, [r['tree']], r['startpos'], r['endpos']), 'startpos': r['startpos'],
-                         'endpos': r['endpos']}
+                        newr = {"tree": {"head": rulename, "tail": [r['tree']], "startpos": r['startpos'], 'endpos': r['endpos']}, "startpos": r['startpos'], "endpos": r["endpos"]}
                         r = newr
                         r = newr
                 newresults.append(r)
                 newresults.append(r)
         elif (self.isType(rule, Parser.Constants.Token)):
         elif (self.isType(rule, Parser.Constants.Token)):
@@ -663,7 +655,7 @@ class Parser(object):
             # this is a failure! nice to register!
             # this is a failure! nice to register!
             self.failure.update({rulename: {'startpos': j, 'text': self.tokens[rulename]['errortext']}})
             self.failure.update({rulename: {'startpos': j, 'text': self.tokens[rulename]['errortext']}})
             return []
             return []
-        return [{'tree': Tree(rulename, [mobj.group()], j, j + mobj.end()), 'startpos': j, 'endpos': j + mobj.end()}]
+        return [{'tree': {"head": rulename, "tail": [mobj.group()], "startpos": j, "endpos": j + mobj.end()}, 'startpos': j, 'endpos': j + mobj.end()}]
 
 
     def anonTerm(self, term, j):
     def anonTerm(self, term, j):
         """
         """
@@ -677,12 +669,12 @@ class Parser(object):
             self.failure.update({ name : {'startpos': j, 'text': name}})
             self.failure.update({ name : {'startpos': j, 'text': name}})
             return []
             return []
 
 
-        mobj = re.match(term, self.input[j:])
+        mobj = re.match(term, get_buffer(self.input, j))
         if (not mobj):
         if (not mobj):
             # this is a failure! nice to register!
             # this is a failure! nice to register!
             self.failure.update({ name : {'startpos': j, 'text': name }})
             self.failure.update({ name : {'startpos': j, 'text': name }})
             return []
             return []
-        return [{'tree': Tree(name , [mobj.group()], j, j + mobj.end()), 'startpos': j, 'endpos': j + mobj.end()}]
+        return [{'tree': {"head": name, "tail": [mobj.group()], "startpos": j, "endpos": j + mobj.end()}, 'startpos': j, 'endpos': j + mobj.end()}]
 
 
     def many(self, rulename, ls, j):
     def many(self, rulename, ls, j):
 
 
@@ -701,10 +693,10 @@ class Parser(object):
         overall_results = []
         overall_results = []
         for r in results:
         for r in results:
             if (r['tree']):
             if (r['tree']):
-                if (len(r['tree'].tail) > 1):
-                    left = r['tree'].tail[0]
-                    right = r['tree'].tail[1].tail
-                    r['tree'].tail = [left] + right
+                if (len(r['tree']['tail']) > 1):
+                    left = r['tree']['tail'][0]
+                    right = r['tree']['tail'][1]['tail']
+                    r['tree']['tail'] = [left] + right
                 overall_results.append(r)
                 overall_results.append(r)
 
 
 
 
@@ -727,10 +719,10 @@ class Parser(object):
         overall_results = []
         overall_results = []
         for r in results:
         for r in results:
             if (r['tree']):
             if (r['tree']):
-                if (len(r['tree'].tail) > 1):
-                    left = r['tree'].tail[0]
-                    right = r['tree'].tail[1].tail
-                    r['tree'].tail = [left] + right
+                if (len(r['tree']['tail']) > 1):
+                    left = r['tree']['tail'][0]
+                    right = r['tree']['tail'][1]['tail']
+                    r['tree']['tail'] = [left] + right
                 overall_results.append(r)
                 overall_results.append(r)
 
 
         return overall_results
         return overall_results
@@ -864,11 +856,10 @@ class Parser(object):
         for elem_n in newres:
         for elem_n in newres:
             tail = []
             tail = []
             if ('tree' in elem_p and elem_p['tree']):
             if ('tree' in elem_p and elem_p['tree']):
-                tail += elem_p['tree'].tail
+                tail += elem_p['tree']['tail']
             if ('tree' in elem_n and elem_n['tree']):
             if ('tree' in elem_n and elem_n['tree']):
                 tail.append(elem_n['tree'])
                 tail.append(elem_n['tree'])
-            value = {'tree': Tree(rulename, tail, elem_p['startpos'], elem_n['endpos']), 'startpos': elem_p['startpos'],
-                     'endpos': elem_n['endpos']}
+            value = {'tree': {"head": rulename, "tail": tail, "startpos": elem_p['startpos'], "endpos": elem_n["endpos"]}, 'startpos': elem_p['startpos'], 'endpos': elem_n['endpos']}
             results += [value]
             results += [value]
         return results
         return results
 
 
@@ -910,12 +901,12 @@ class Parser(object):
             self.calcPosMethod = method
             self.calcPosMethod = method
 
 
         def inner_visit(self,tree):
         def inner_visit(self,tree):
-            startDic = self.calcPosMethod(tree.startpos)
-            endDic = self.calcPosMethod(tree.endpos)
-            tree.startpos = Position(startDic["line"], startDic["column"])
-            tree.endpos =  Position(endDic["line"], endDic["column"])
-            for item in tree.tail:
-                if (isinstance(item, Tree)):
+            startDic = self.calcPosMethod(tree['startpos'])
+            endDic = self.calcPosMethod(tree['endpos'])
+            tree['startpos'] = Position(startDic["line"], startDic["column"])
+            tree['endpos'] =  Position(endDic["line"], endDic["column"])
+            for item in tree['tail']:
+                if (isinstance(item, dict)):
                     self.inner_visit(item)
                     self.inner_visit(item)
 
 
         def visit(self, tree):
         def visit(self, tree):
@@ -930,8 +921,8 @@ class Parser(object):
             self.output = output
             self.output = output
 
 
         def inner_visit(self, tree):
         def inner_visit(self, tree):
-            for item in tree.tail:
-                if (isinstance(item, Tree)):
+            for item in tree['tail']:
+                if (isinstance(item, dict)):
                     self.inner_visit(item)
                     self.inner_visit(item)
                 else:
                 else:
                     self.outputStream += item
                     self.outputStream += item
@@ -956,9 +947,9 @@ class Parser(object):
         def inner_visit(self, tree):
         def inner_visit(self, tree):
             self.tabcount += 1
             self.tabcount += 1
             self.outputStream += self.tab()
             self.outputStream += self.tab()
-            self.outputStream += 'node ' + tree.head + ':\n'
-            for item in tree.tail:
-                if (isinstance(item, Tree)):
+            self.outputStream += 'node ' + tree['head'] + ':\n'
+            for item in tree['tail']:
+                if (isinstance(item, dict)):
                     self.inner_visit(item)
                     self.inner_visit(item)
                 else:
                 else:
                     self.tabcount += 1
                     self.tabcount += 1
@@ -979,20 +970,20 @@ class IgnorePostProcessor(object):
 
 
     def inner_visit(self, tree):
     def inner_visit(self, tree):
         results = []
         results = []
-        if (isinstance(tree, Tree)):
-            if (self.isHidden(tree.head)):
-                for item in tree.tail:
+        if (isinstance(tree, dict)):
+            if (self.isHidden(tree['head'])):
+                for item in tree['tail']:
                     ivlist = []
                     ivlist = []
                     ivresult = self.inner_visit(item)
                     ivresult = self.inner_visit(item)
                     for elem in ivresult:
                     for elem in ivresult:
-                        if (isinstance(elem, Tree)):
+                        if (isinstance(elem, dict)):
                             ivlist += [elem]
                             ivlist += [elem]
                     results += ivlist
                     results += ivlist
             else:
             else:
                 tlist = []
                 tlist = []
-                for item in tree.tail:
+                for item in tree['tail']:
                     tlist += self.inner_visit(item)
                     tlist += self.inner_visit(item)
-                tree.tail = tlist
+                tree['tail'] = tlist
                 results += [tree]
                 results += [tree]
             return results
             return results
 
 
@@ -1001,9 +992,9 @@ class IgnorePostProcessor(object):
     def visit(self, tree):
     def visit(self, tree):
         # start cannot be hidden
         # start cannot be hidden
         tlist = []
         tlist = []
-        for item in tree.tail:
+        for item in tree['tail']:
             tlist += self.inner_visit(item)
             tlist += self.inner_visit(item)
-        tree.tail = tlist
+        tree['tail'] = tlist
         return tree
         return tree
 
 
     def isHidden(self, head):
     def isHidden(self, head):

+ 50 - 49
interface/HUTN/hutn_compiler/model_bootstrap_visitor.py

@@ -1,4 +1,5 @@
 from hutn_compiler.visitor import Visitor
 from hutn_compiler.visitor import Visitor
+from hutn_compiler.hutnparser import Tree
 from hutn_compiler.compiler import main as do_compile
 from hutn_compiler.compiler import main as do_compile
 import os
 import os
 import uuid
 import uuid
@@ -27,43 +28,43 @@ class ModelBootstrapVisitor(Visitor):
             raise AttributeError()
             raise AttributeError()
 
 
     def visit_start(self, tree):
     def visit_start(self, tree):
-        for t in tree.get_tail():
+        for t in Tree.get_tail(tree):
             self.visit(t)
             self.visit(t)
         self.code += '\tdict_overwrite(%s, "types", get_type_mapping(%s))\n' % (self.current_model, self.current_model)
         self.code += '\tdict_overwrite(%s, "types", get_type_mapping(%s))\n' % (self.current_model, self.current_model)
 
 
     def visit_include_files(self, tree):
     def visit_include_files(self, tree):
-        self.includes.append('include %s' % tree.get_children("STRVALUE")[0].get_text())
+        self.includes.append('include %s' % Tree.get_text(Tree.get_children(tree, "STRVALUE")[0]))
 
 
     def visit_import(self, tree):
     def visit_import(self, tree):
-        url = tree.get_children("MV_URL")[0]
-        target = tree.get_children("MODEL_ID")[0]
+        url = Tree.get_children(tree, "MV_URL")[0]
+        target = Tree.get_children(tree, "MODEL_ID")[0]
         #self.constructors.extend(["import_node", url.get_text(), target.get_text()])
         #self.constructors.extend(["import_node", url.get_text(), target.get_text()])
-        self.code += '\tElement %s\n' % target.get_text()
-        self.code += '\t%s = import_node("%s")\n' % (target.get_text(), url.get_text())
+        self.code += '\tElement %s\n' % Tree.get_text(target)
+        self.code += '\t%s = import_node("%s")\n' % (Tree.get_text(target), Tree.get_text(url))
 
 
     def visit_export(self, tree):
     def visit_export(self, tree):
-        url = tree.get_children("MV_URL")[0]
-        target = tree.get_children("MODEL_ID")[0]
+        url = Tree.get_children(tree, "MV_URL")[0]
+        target = Tree.get_children(tree, "MODEL_ID")[0]
         #self.constructors.extend(["export_node", target.get_text(), url.get_text()])
         #self.constructors.extend(["export_node", target.get_text(), url.get_text()])
-        self.code += '\texport_node("%s", %s)\n' % (url.get_text(), target.get_text())
+        self.code += '\texport_node("%s", %s)\n' % (Tree.get_text(url), Tree.get_text(target))
 
 
     def visit_model(self, tree):
     def visit_model(self, tree):
-        children = tree.get_children("MODEL_ID")
-        model_type = children[0].get_text()
-        model_name = children[-1].get_text()
+        children = Tree.get_children(tree, "MODEL_ID")
+        model_type = Tree.get_text(children[0])
+        model_name = Tree.get_text(children[-1])
         #self.constructors.extend(["instantiate_model", model_type, model_name])
         #self.constructors.extend(["instantiate_model", model_type, model_name])
         self.code += "\tElement %s\n" % model_name
         self.code += "\tElement %s\n" % model_name
         self.code += '\t%s = instantiate_model(%s)\n' % (model_name, model_type)
         self.code += '\t%s = instantiate_model(%s)\n' % (model_name, model_type)
         self.current_model = model_name
         self.current_model = model_name
         self.names = set()
         self.names = set()
-        for element in tree.get_children("model_element"):
+        for element in Tree.get_children(tree, "model_element"):
             self.visit(element)
             self.visit(element)
 
 
     def visit_model_element(self, tree):
     def visit_model_element(self, tree):
-        children = tree.get_children("MODEL_ID")
-        element_type = children[0].get_text()
+        children = Tree.get_children(tree, "MODEL_ID")
+        element_type = Tree.get_text(children[0])
         if len(children) == 2 or len(children) == 4:
         if len(children) == 2 or len(children) == 4:
-            element_name = children[1].get_text()
+            element_name = Tree.get_text(children[1])
         else:
         else:
             element_name = "__%s" % self.free_id
             element_name = "__%s" % self.free_id
             self.free_id += 1
             self.free_id += 1
@@ -73,8 +74,8 @@ class ModelBootstrapVisitor(Visitor):
 
 
         if len(children) > 2:
         if len(children) > 2:
             # So we have a source and target; but aren't sure which is which, because the name is optional!
             # So we have a source and target; but aren't sure which is which, because the name is optional!
-            source_name = children[-2].get_text()
-            target_name = children[-1].get_text()
+            source_name = Tree.get_text(children[-2])
+            target_name = Tree.get_text(children[-1])
             if source_name not in self.names:
             if source_name not in self.names:
                 raise Exception("Source of link %s unknown: %s" % (element_name, source_name))
                 raise Exception("Source of link %s unknown: %s" % (element_name, source_name))
             if target_name not in self.names:
             if target_name not in self.names:
@@ -89,10 +90,10 @@ class ModelBootstrapVisitor(Visitor):
         self.names.add(element_name)
         self.names.add(element_name)
         self.current_element.append(element_name)
         self.current_element.append(element_name)
 
 
-        if tree.get_children("inheritance"):
-            self.visit(tree.get_children("inheritance")[0])
+        if Tree.get_children(tree, "inheritance"):
+            self.visit(Tree.get_children(tree, "inheritance")[0])
             
             
-        for attr in tree.get_children("model_attribute"):
+        for attr in Tree.get_children(tree, "model_attribute"):
             self.visit(attr)
             self.visit(attr)
 
 
         self.current_element.pop()
         self.current_element.pop()
@@ -100,8 +101,8 @@ class ModelBootstrapVisitor(Visitor):
         return element_name
         return element_name
 
 
     def visit_inheritance(self, tree):
     def visit_inheritance(self, tree):
-        for token in tree.get_children("MODEL_ID"):
-            superclass = token.get_text()
+        for token in Tree.get_children(tree, "MODEL_ID"):
+            superclass = Tree.get_text(token)
             if superclass not in self.names:
             if superclass not in self.names:
                 raise Exception("Superclass %s is undefined" % superclass)
                 raise Exception("Superclass %s is undefined" % superclass)
 
 
@@ -110,15 +111,15 @@ class ModelBootstrapVisitor(Visitor):
             self.names.add("%s_inherits_from_%s" % (self.current_element[-1], superclass))
             self.names.add("%s_inherits_from_%s" % (self.current_element[-1], superclass))
 
 
     def visit_model_attribute(self, tree):
     def visit_model_attribute(self, tree):
-        children = tree.get_children("MODEL_ID")
-        is_definition = bool(tree.get_children("COLON"))
-        is_assign = bool(tree.get_children("model_attr_instance"))
-        is_nested = bool(tree.get_children("model_element"))
+        children = Tree.get_children(tree, "MODEL_ID")
+        is_definition = bool(Tree.get_children(tree, "COLON"))
+        is_assign = bool(Tree.get_children(tree, "model_attr_instance"))
+        is_nested = bool(Tree.get_children(tree, "model_element"))
 
 
         if is_definition:
         if is_definition:
-            attr_name = children[0].get_text()
-            attr_optional = len(tree.get_children("OPTIONAL")) > 0
-            attr_type = children[1].get_text()
+            attr_name = Tree.get_text(children[0])
+            attr_optional = len(Tree.get_children(tree, "OPTIONAL")) > 0
+            attr_type = Tree.get_text(children[1])
             #self.constructors.extend(["model_define_attribute", self.current_model, self.current_element[-1], attr_name, attr_optional, attr_type])
             #self.constructors.extend(["model_define_attribute", self.current_model, self.current_element[-1], attr_name, attr_optional, attr_type])
             self.code += '\tmodel_define_attribute(%s, "%s", "%s", %s, "%s")\n' % (self.current_model, self.current_element[-1], attr_name, attr_optional, attr_type)
             self.code += '\tmodel_define_attribute(%s, "%s", "%s", %s, "%s")\n' % (self.current_model, self.current_element[-1], attr_name, attr_optional, attr_type)
             full_attribute_name = self.current_element[-1] + "_" + attr_name
             full_attribute_name = self.current_element[-1] + "_" + attr_name
@@ -127,18 +128,18 @@ class ModelBootstrapVisitor(Visitor):
                 # There are also some attributes to set!
                 # There are also some attributes to set!
                 self.current_element.append(full_attribute_name)
                 self.current_element.append(full_attribute_name)
 
 
-                for f in tree.get_children("model_attr_instance"):
+                for f in Tree.get_children(tree, "model_attr_instance"):
                     self.visit(f)
                     self.visit(f)
 
 
                 self.current_element.pop()
                 self.current_element.pop()
         elif is_assign:
         elif is_assign:
-            self.visit(tree.get_children("model_attr_instance")[0])
+            self.visit(Tree.get_children(tree, "model_attr_instance")[0])
         elif is_nested:
         elif is_nested:
-            if tree.get_children("MODEL_ID"):
-                contains_link = tree.get_children("MODEL_ID")[0].get_text()
+            if Tree.get_children(tree, "MODEL_ID"):
+                contains_link = Tree.get_text(Tree.get_children(tree, "MODEL_ID")[0])
             else:
             else:
                 contains_link = ""
                 contains_link = ""
-            entry = self.visit(tree.get_children("model_element")[0])
+            entry = self.visit(Tree.get_children(tree, "model_element")[0])
             #self.constructors.extend(["instantiate_link", self.current_model, contains_link, "__%s" % self.free_id, self.current_element[-1], entry])
             #self.constructors.extend(["instantiate_link", self.current_model, contains_link, "__%s" % self.free_id, self.current_element[-1], entry])
             self.code += '\tinstantiate_link(%s, "%s", "__%s", "%s", "%s")\n' % (self.current_model, contains_link, self.free_id, self.current_element[-1], entry)
             self.code += '\tinstantiate_link(%s, "%s", "__%s", "%s", "%s")\n' % (self.current_model, contains_link, self.free_id, self.current_element[-1], entry)
             self.names.add("__%s" % self.free_id)
             self.names.add("__%s" % self.free_id)
@@ -161,31 +162,31 @@ class ModelBootstrapVisitor(Visitor):
             compiled = do_compile(".code.alc", directory + "/../grammars/actionlanguage.g", "CS")
             compiled = do_compile(".code.alc", directory + "/../grammars/actionlanguage.g", "CS")
             return compiled
             return compiled
 
 
-        children = tree.get_children("MODEL_ID")
-        attr_name = children[0].get_text()
-        if tree.get_children("value"):
+        children = Tree.get_children(tree, "MODEL_ID")
+        attr_name = Tree.get_text(children[0])
+        if Tree.get_children(tree, "value"):
             # Value attribute
             # Value attribute
-            attr_value = tree.get_children("value")[0].get_tail()[0]
-            if attr_value.head == "STRVALUE":
-                attr_value = '"%s"' %  attr_value.get_text()[1:-1]
-            elif attr_value.head == "TRUE":
+            attr_value = Tree.get_tail(Tree.get_children(tree, "value")[0])[0]
+            if attr_value['head'] == "STRVALUE":
+                attr_value = '"%s"' %  Tree.get_text(attr_value)[1:-1]
+            elif attr_value['head'] == "TRUE":
                 attr_value = True
                 attr_value = True
-            elif attr_value.head == "FALSE":
+            elif attr_value['head'] == "FALSE":
                 attr_value = False
                 attr_value = False
-            elif attr_value.head == "DEC_NUMBER":
-                attr_value = int(attr_value.get_text())
+            elif attr_value['head'] == "DEC_NUMBER":
+                attr_value = int(Tree.get_text(attr_value))
             elif attr_value.head == "FLOAT_NUMBER":
             elif attr_value.head == "FLOAT_NUMBER":
-                attr_value = float(attr_value.get_text())
+                attr_value = float(Tree.get_text(attr_value))
             else:
             else:
-                raise Exception(attr_value.head)
+                raise Exception(attr_value['head'])
             #self.constructors.extend(["instantiate_attribute", self.current_model, self.current_element[-1], attr_name, attr_value])
             #self.constructors.extend(["instantiate_attribute", self.current_model, self.current_element[-1], attr_name, attr_value])
             self.code += '\tinstantiate_attribute(%s, "%s", "%s", %s)\n' % (self.current_model, self.current_element[-1], attr_name, attr_value)
             self.code += '\tinstantiate_attribute(%s, "%s", "%s", %s)\n' % (self.current_model, self.current_element[-1], attr_name, attr_value)
-        elif tree.get_children("DOLLAR"):
+        elif Tree.get_children(tree, "DOLLAR"):
             # Coded attribute
             # Coded attribute
             raise Exception("Code is no longer allowed in bootstrap files, as the HUTN parser is not initialized yet")
             raise Exception("Code is no longer allowed in bootstrap files, as the HUTN parser is not initialized yet")
             #self.constructors.extend(["instantiate_attribute_code", self.current_model, self.current_element[-1], attr_name])
             #self.constructors.extend(["instantiate_attribute_code", self.current_model, self.current_element[-1], attr_name])
             #self.constructors.extend(constructors_compile(tree.get_children("ANYTHING_EXCEPT_DOLLAR")[0].get_text()))
             #self.constructors.extend(constructors_compile(tree.get_children("ANYTHING_EXCEPT_DOLLAR")[0].get_text()))
-            code = tree.get_children("ANYTHING_EXCEPT_DOLLAR")[0].get_text()
+            code = Tree.get_text(Tree.get_children(tree, "ANYTHING_EXCEPT_DOLLAR")[0])
 
 
             code_fragments = code.split("\n")
             code_fragments = code.split("\n")
             code_fragments = [i for i in code_fragments if i.strip() != ""]
             code_fragments = [i for i in code_fragments if i.strip() != ""]

+ 41 - 40
interface/HUTN/hutn_compiler/model_visitor.py

@@ -1,5 +1,6 @@
 from hutn_compiler.visitor import Visitor
 from hutn_compiler.visitor import Visitor
 from hutn_compiler.compiler import main as do_compile
 from hutn_compiler.compiler import main as do_compile
+from hutn_compiler.hutnparser import Tree
 import os
 import os
 
 
 def empty(s):
 def empty(s):
@@ -24,17 +25,17 @@ class ModelVisitor(Visitor):
             raise AttributeError()
             raise AttributeError()
 
 
     def visit_start(self, tree):
     def visit_start(self, tree):
-        for t in tree.get_tail():
+        for t in Tree.get_tail(tree):
             self.visit(t)
             self.visit(t)
 
 
     def visit_include_files(self, tree):
     def visit_include_files(self, tree):
-        self.includes.append('include %s' % tree.get_children("STRVALUE")[0].get_text())
+        self.includes.append('include %s' % Tree.get_text(Tree.get_children(tree, "STRVALUE")[0]))
 
 
     def visit_model_element(self, tree):
     def visit_model_element(self, tree):
-        children = tree.get_children("MODEL_ID")
-        element_type = children[0].get_text()
+        children = Tree.get_children(tree, "MODEL_ID")
+        element_type = Tree.get_text(children[0])
         if len(children) == 2 or len(children) == 4:
         if len(children) == 2 or len(children) == 4:
-            element_name = children[1].get_text()
+            element_name = Tree.get_text(children[1])
         else:
         else:
             element_name = "__%s" % self.free_id
             element_name = "__%s" % self.free_id
             self.free_id += 1
             self.free_id += 1
@@ -44,8 +45,8 @@ class ModelVisitor(Visitor):
 
 
         if len(children) > 2:
         if len(children) > 2:
             # So we have a source and target; but aren't sure which is which, because the name is optional!
             # So we have a source and target; but aren't sure which is which, because the name is optional!
-            source_name = children[-2].get_text()
-            target_name = children[-1].get_text()
+            source_name = Tree.get_text(children[-2])
+            target_name = Tree.get_text(children[-1])
             if source_name not in self.names:
             if source_name not in self.names:
                 raise Exception("Source of link %s unknown: %s" % (element_name, source_name))
                 raise Exception("Source of link %s unknown: %s" % (element_name, source_name))
             if target_name not in self.names:
             if target_name not in self.names:
@@ -58,10 +59,10 @@ class ModelVisitor(Visitor):
         self.names.add(element_name)
         self.names.add(element_name)
         self.current_element.append(element_name)
         self.current_element.append(element_name)
 
 
-        if tree.get_children("inheritance"):
-            self.visit(tree.get_children("inheritance")[0])
+        if Tree.get_children(tree, "inheritance"):
+            self.visit(Tree.get_children(tree, "inheritance")[0])
             
             
-        for attr in tree.get_children("model_attribute"):
+        for attr in Tree.get_children(tree, "model_attribute"):
             self.visit(attr)
             self.visit(attr)
 
 
         self.current_element.pop()
         self.current_element.pop()
@@ -69,8 +70,8 @@ class ModelVisitor(Visitor):
         return element_name
         return element_name
 
 
     def visit_inheritance(self, tree):
     def visit_inheritance(self, tree):
-        for token in tree.get_children("MODEL_ID"):
-            superclass = token.get_text()
+        for token in Tree.get_children(tree, "MODEL_ID"):
+            superclass = Tree.get_text(token)
             if superclass not in self.names:
             if superclass not in self.names:
                 raise Exception("Superclass %s is undefined" % superclass)
                 raise Exception("Superclass %s is undefined" % superclass)
 
 
@@ -78,15 +79,15 @@ class ModelVisitor(Visitor):
             self.names.add("%s_inherits_from_%s" % (self.current_element[-1], superclass))
             self.names.add("%s_inherits_from_%s" % (self.current_element[-1], superclass))
 
 
     def visit_model_attribute(self, tree):
     def visit_model_attribute(self, tree):
-        children = tree.get_children("MODEL_ID")
-        is_definition = bool(tree.get_children("COLON"))
-        is_assign = bool(tree.get_children("model_attr_instance"))
-        is_nested = bool(tree.get_children("model_element"))
+        children = Tree.get_children(tree, "MODEL_ID")
+        is_definition = bool(Tree.get_children(tree, "COLON"))
+        is_assign = bool(Tree.get_children(tree, "model_attr_instance"))
+        is_nested = bool(Tree.get_children(tree, "model_element"))
 
 
         if is_definition:
         if is_definition:
-            attr_name = children[0].get_text()
-            attr_optional = len(tree.get_children("OPTIONAL")) > 0
-            attr_type = children[1].get_text()
+            attr_name = Tree.get_text(children[0])
+            attr_optional = len(Tree.get_children(tree, "OPTIONAL")) > 0
+            attr_type = Tree.get_text(children[1])
             if attr_type not in self.names:
             if attr_type not in self.names:
                 raise Exception("Unknown Attribute type!")
                 raise Exception("Unknown Attribute type!")
             self.constructors.extend(["model_define_attribute", self.current_element[-1], attr_name, attr_optional, attr_type])
             self.constructors.extend(["model_define_attribute", self.current_element[-1], attr_name, attr_optional, attr_type])
@@ -96,18 +97,18 @@ class ModelVisitor(Visitor):
                 # There are also some attributes to set!
                 # There are also some attributes to set!
                 self.current_element.append(full_attribute_name)
                 self.current_element.append(full_attribute_name)
 
 
-                for f in tree.get_children("model_attr_instance"):
+                for f in Tree.get_children(tree, "model_attr_instance"):
                     self.visit(f)
                     self.visit(f)
 
 
                 self.current_element.pop()
                 self.current_element.pop()
         elif is_assign:
         elif is_assign:
-            self.visit(tree.get_children("model_attr_instance")[0])
+            self.visit(Tree.get_children(tree, "model_attr_instance")[0])
         elif is_nested:
         elif is_nested:
-            if tree.get_children("MODEL_ID"):
-                contains_link = tree.get_children("MODEL_ID")[0].get_text()
+            if Tree.get_children(tree, "MODEL_ID"):
+                contains_link = Tree.get_text(Tree.get_children(tree, "MODEL_ID")[0])
             else:
             else:
                 contains_link = ""
                 contains_link = ""
-            entry = self.visit(tree.get_children("model_element")[0])
+            entry = self.visit(Tree.get_children(tree, "model_element")[0])
             self.constructors.extend(["instantiate_link", contains_link, "__%s" % self.free_id, self.current_element[-1], entry])
             self.constructors.extend(["instantiate_link", contains_link, "__%s" % self.free_id, self.current_element[-1], entry])
             self.names.add("__%s" % self.free_id)
             self.names.add("__%s" % self.free_id)
             self.free_id += 1
             self.free_id += 1
@@ -129,27 +130,27 @@ class ModelVisitor(Visitor):
             compiled = do_compile(".code.alc", directory + "/../grammars/actionlanguage.g", "CS")
             compiled = do_compile(".code.alc", directory + "/../grammars/actionlanguage.g", "CS")
             return compiled + [code]
             return compiled + [code]
 
 
-        children = tree.get_children("MODEL_ID")
-        attr_name = children[0].get_text()
-        if tree.get_children("value"):
+        children = Tree.get_children(tree, "MODEL_ID")
+        attr_name = Tree.get_text(children[0])
+        if Tree.get_children(tree, "value"):
             # Value attribute
             # Value attribute
-            attr_value = tree.get_children("value")[0].get_tail()[0]
-            if attr_value.head == "STRVALUE":
-                attr_value = attr_value.get_text()[1:-1]
-            elif attr_value.head == "LONG_STR":
-                attr_value = attr_value.get_text()[3:-3]
-            elif attr_value.head == "TRUE":
+            attr_value = Tree.get_tail(Tree.get_children(tree, "value")[0])[0]
+            if attr_value['head'] == "STRVALUE":
+                attr_value = Tree.get_text(attr_value)[1:-1]
+            elif attr_value['head'] == "LONG_STR":
+                attr_value = Tree.get_text(attr_value)[3:-3]
+            elif attr_value['head'] == "TRUE":
                 attr_value = True
                 attr_value = True
-            elif attr_value.head == "FALSE":
+            elif attr_value['head'] == "FALSE":
                 attr_value = False
                 attr_value = False
-            elif attr_value.head == "DEC_NUMBER":
-                attr_value = int(attr_value.get_text())
+            elif attr_value['head'] == "DEC_NUMBER":
+                attr_value = int(Tree.get_text(attr_value))
             elif attr_value.head == "FLOAT_NUMBER":
             elif attr_value.head == "FLOAT_NUMBER":
-                attr_value = float(attr_value.get_text())
+                attr_value = float(Tree.get_text(attr_value))
             else:
             else:
-                raise Exception(attr_value.head)
+                raise Exception(attr_value['head'])
             self.constructors.extend(["instantiate_attribute", self.current_element[-1], attr_name, attr_value])
             self.constructors.extend(["instantiate_attribute", self.current_element[-1], attr_name, attr_value])
-        elif tree.get_children("DOLLAR"):
+        elif Tree.get_children(tree, "DOLLAR"):
             # Coded attribute
             # Coded attribute
             self.constructors.extend(["instantiate_attribute_code", self.current_element[-1], attr_name])
             self.constructors.extend(["instantiate_attribute_code", self.current_element[-1], attr_name])
-            self.constructors.extend(constructors_compile(tree.get_children("ANYTHING_EXCEPT_DOLLAR")[0].get_text()))
+            self.constructors.extend(constructors_compile(Tree.get_text(Tree.get_children(tree, "ANYTHING_EXCEPT_DOLLAR")[0])))

+ 1 - 1
interface/HUTN/hutn_compiler/position.py

@@ -70,4 +70,4 @@ class Position(object):
             raise AttributeError("'Position' object has no attribute '"+str(item)+"'")
             raise AttributeError("'Position' object has no attribute '"+str(item)+"'")
 
 
     def deepcopy(self):
     def deepcopy(self):
-        pass
+        pass

+ 10 - 10
interface/HUTN/hutn_compiler/prettyprint_visitor.py

@@ -8,9 +8,9 @@ class PrintVisitor(Visitor):
         pass
         pass
 
 
     def visit(self, tree, level=0):
     def visit(self, tree, level=0):
-        if isinstance(tree, Tree):
-            self.result += '\n' + '\t' * level + tree.head
-            for child in tree.tail:
+        if isinstance(tree, dict):
+            self.result += '\n' + '\t' * level + tree['head']
+            for child in tree['tail']:
                 self.visit(child, level+1)
                 self.visit(child, level+1)
         else:
         else:
             self.result += '(' + repr(tree) + ')'
             self.result += '(' + repr(tree) + ')'
@@ -24,15 +24,15 @@ class PrettyPrintVisitor(Visitor):
         self.result = ""
         self.result = ""
 
 
     def visit(self, tree, level=0):
     def visit(self, tree, level=0):
-        if isinstance(tree, Tree):
-            if tree.is_rule() and len(tree.get_tail()) > 1:
-                self.result += '\n' + '\t' * level + tree.head
-                if not tree.head.startswith("implicit_autogenerated_"):
-                    for child in tree.tail:
+        if isinstance(tree, dict):
+            if tree.is_rule() and len(Tree.get_tail(tree)) > 1:
+                self.result += '\n' + '\t' * level + tree['head']
+                if not tree['head'].startswith("implicit_autogenerated_"):
+                    for child in tree['tail']:
                         self.visit(child, level+1)
                         self.visit(child, level+1)
             else:
             else:
-                if not tree.head.startswith("implicit_autogenerated_"):
-                    for child in tree.tail:
+                if not tree['head'].startswith("implicit_autogenerated_"):
+                    for child in tree['tail']:
                         self.visit(child, level)
                         self.visit(child, level)
         else:
         else:
             self.result += '\n' + '\t' * level + '(' + repr(tree) + ')'
             self.result += '\n' + '\t' * level + '(' + repr(tree) + ')'

+ 38 - 37
interface/HUTN/hutn_compiler/primitives_visitor.py

@@ -1,5 +1,6 @@
 import string
 import string
 from hutn_compiler.visitor import Visitor
 from hutn_compiler.visitor import Visitor
+from hutn_compiler.hutnparser import Tree
 import json
 import json
 
 
 class Action():
 class Action():
@@ -17,7 +18,7 @@ class PrimitivesVisitor(Visitor):
 
 
     def debug(self, node, tree, msg=""):
     def debug(self, node, tree, msg=""):
         if self.debug_symbols:
         if self.debug_symbols:
-            self.dict(node, "__debug", self.value("[%s] %s" % (tree.get_reference_line(), msg)))
+            self.dict(node, "__debug", self.value("[%s] %s" % (Tree.get_reference_line(tree), msg)))
 
 
     def node(self):
     def node(self):
         self.output.append(("N", self.free_id))
         self.output.append(("N", self.free_id))
@@ -71,24 +72,24 @@ class PrimitivesVisitor(Visitor):
         return "".join(output)
         return "".join(output)
 
 
     def set_primitive(self, tree, primitive):
     def set_primitive(self, tree, primitive):
-        tree.primitive = primitive
+        tree['primitive'] = primitive
 
 
     def get_primitive(self, tree):
     def get_primitive(self, tree):
-        return getattr(tree, 'primitive', None)
+        return tree.get('primitive', None)
 
 
     def forward_primitive_of_child(self, tree, i):
     def forward_primitive_of_child(self, tree, i):
         self.visit_children(tree)
         self.visit_children(tree)
-        self.set_primitive(tree, self.get_primitive(tree.get_tail()[i]))
+        self.set_primitive(tree, self.get_primitive(Tree.get_tail(tree)[i]))
 
 
     # a visit_* method for each non-terminal in the grammar
     # a visit_* method for each non-terminal in the grammar
     def visit_start(self, tree):
     def visit_start(self, tree):
         primitives = []
         primitives = []
-        for child in tree.get_children("funcdecl"):
+        for child in Tree.get_children(tree, "funcdecl"):
             p = self.pre_visit_funcdecl(child)
             p = self.pre_visit_funcdecl(child)
             if p:
             if p:
                 # funcdecl returns a (global, assign) pair
                 # funcdecl returns a (global, assign) pair
                 primitives.extend(p)
                 primitives.extend(p)
-        for child in tree.get_tail():
+        for child in Tree.get_tail(tree):
             self.visit(child)
             self.visit(child)
             p = self.get_primitive(child)
             p = self.get_primitive(child)
             if p is not None:
             if p is not None:
@@ -97,7 +98,7 @@ class PrimitivesVisitor(Visitor):
                     primitives.extend(p)
                     primitives.extend(p)
                 else:
                 else:
                     primitives.append(p)
                     primitives.append(p)
-                if child.head == "return":
+                if child['head'] == "return":
                     break
                     break
         self.first = primitives[0]
         self.first = primitives[0]
         for i in range(len(primitives)-1):
         for i in range(len(primitives)-1):
@@ -108,8 +109,8 @@ class PrimitivesVisitor(Visitor):
         self.visit_children(tree)
         self.visit_children(tree)
 
 
         a = self.value(Action("assign"))
         a = self.value(Action("assign"))
-        var = self.get_primitive(tree.get_tail()[0])
-        value = self.get_primitive(tree.get_tail()[-1])
+        var = self.get_primitive(Tree.get_tail(tree)[0])
+        value = self.get_primitive(Tree.get_tail(tree)[-1])
         self.dict(a, "var", var)
         self.dict(a, "var", var)
         self.dict(a, "value", value)
         self.dict(a, "value", value)
         self.debug(a, tree)
         self.debug(a, tree)
@@ -156,8 +157,8 @@ class PrimitivesVisitor(Visitor):
         self.visit_literal(tree)
         self.visit_literal(tree)
 
 
     def visit_actionname(self, tree):
     def visit_actionname(self, tree):
-        self.visit_literal(tree.get_tail()[0])
-        self.set_primitive(tree, self.get_primitive(tree.get_tail()[0]))
+        self.visit_literal(Tree.get_tail(tree)[0])
+        self.set_primitive(tree, self.get_primitive(Tree.get_tail(tree)[0]))
 
 
     def visit_string(self, tree):
     def visit_string(self, tree):
         self.visit_literal(tree)
         self.visit_literal(tree)
@@ -170,10 +171,10 @@ class PrimitivesVisitor(Visitor):
         #     self.set_id(tree, n)
         #     self.set_id(tree, n)
         # else:
         # else:
         c = self.value(Action("constant"))
         c = self.value(Action("constant"))
-        if tree.get_text()[0] == "!":
-            v = tree.get_text()[1:]
+        if Tree.get_text(tree)[0] == "!":
+            v = Tree.get_text(tree)[1:]
         else:
         else:
-            v = tree.get_text()
+            v = Tree.get_text(tree)
         #NOTE Wrap this in an Action, even though it might not be an action: this has to be seen directly in the Mv without additional wrapping
         #NOTE Wrap this in an Action, even though it might not be an action: this has to be seen directly in the Mv without additional wrapping
         n = self.value(Action(v))
         n = self.value(Action(v))
         self.dict(c, "node", n)
         self.dict(c, "node", n)
@@ -210,9 +211,9 @@ class PrimitivesVisitor(Visitor):
     def visit_func_call(self, tree):
     def visit_func_call(self, tree):
         self.visit_children(tree)
         self.visit_children(tree)
 
 
-        symbol = self.get_symbol(tree.get_tail()[0])
+        symbol = self.get_symbol(Tree.get_tail(tree)[0])
 
 
-        expressions = tree.get_children("expression")
+        expressions = Tree.get_children(tree, "expression")
         arg_nodes_reversed = []
         arg_nodes_reversed = []
 
 
         for i in reversed(range(len(expressions))):
         for i in reversed(range(len(expressions))):
@@ -233,7 +234,7 @@ class PrimitivesVisitor(Visitor):
             arg_nodes_reversed.append(arg_node)
             arg_nodes_reversed.append(arg_node)
 
 
         c = self.value(Action("call"))
         c = self.value(Action("call"))
-        a = self.get_primitive(tree.get_tail()[0])
+        a = self.get_primitive(Tree.get_tail(tree)[0])
         self.dict(c, "func", a)
         self.dict(c, "func", a)
         self.debug(c, tree)
         self.debug(c, tree)
 
 
@@ -253,15 +254,15 @@ class PrimitivesVisitor(Visitor):
         self.visit_children(tree)
         self.visit_children(tree)
         v = self.value(Action("output"))
         v = self.value(Action("output"))
         self.debug(v, tree)
         self.debug(v, tree)
-        value = self.get_primitive(tree.get_child("expression"))
+        value = self.get_primitive(Tree.get_child(tree, "expression"))
         self.dict(v, "value", value)
         self.dict(v, "value", value)
         self.set_primitive(tree, v)
         self.set_primitive(tree, v)
 
 
     def visit_ifelse(self, tree):
     def visit_ifelse(self, tree):
         self.visit_children(tree)
         self.visit_children(tree)
         expressions = [self.get_primitive(e) for e in
         expressions = [self.get_primitive(e) for e in
-                       tree.get_children("expression")]
-        blocks = [self.get_primitive(b) for b in tree.get_children("block")]
+                       Tree.get_children(tree, "expression")]
+        blocks = [self.get_primitive(b) for b in Tree.get_children(tree, "block")]
 
 
         first = None
         first = None
         prev = None
         prev = None
@@ -299,8 +300,8 @@ class PrimitivesVisitor(Visitor):
         self.while_stack.pop()
         self.while_stack.pop()
 
 
         self.debug(w, tree)
         self.debug(w, tree)
-        c = self.get_primitive(tree.get_child("expression"))
-        b = self.get_primitive(tree.get_child("block"))
+        c = self.get_primitive(Tree.get_child(tree, "expression"))
+        b = self.get_primitive(Tree.get_child(tree, "block"))
 
 
         self.dict(w, "cond", c)
         self.dict(w, "cond", c)
         self.dict(w, "body", b)
         self.dict(w, "body", b)
@@ -310,16 +311,16 @@ class PrimitivesVisitor(Visitor):
     def visit_block(self, tree):
     def visit_block(self, tree):
         self.visit_children(tree)
         self.visit_children(tree)
         primitives = []
         primitives = []
-        for child in tree.get_tail():
+        for child in Tree.get_tail(tree):
             p = self.get_primitive(child)
             p = self.get_primitive(child)
             if p:
             if p:
                 primitives.append(p)
                 primitives.append(p)
-                if child.head == "return":
+                if child['head'] == "return":
                     break
                     break
         for i in range(len(primitives)-1):
         for i in range(len(primitives)-1):
             self.dict(primitives[i], "next", primitives[i+1])
             self.dict(primitives[i], "next", primitives[i+1])
         if len(primitives) == 0:
         if len(primitives) == 0:
-            raise Exception("Block with no body found at %s" % tree.get_reference_line())
+            raise Exception("Block with no body found at %s" % Tree.get_reference_line(tree))
         self.set_primitive(tree, primitives[0])
         self.set_primitive(tree, primitives[0])
 
 
     def visit_func_body(self, tree):
     def visit_func_body(self, tree):
@@ -333,7 +334,7 @@ class PrimitivesVisitor(Visitor):
         # TODO: fix funcdecl special case: "X function f(...) = ..."
         # TODO: fix funcdecl special case: "X function f(...) = ..."
         # Note: replicates "Element x; x = ?primiteves/a" behavior
         # Note: replicates "Element x; x = ?primiteves/a" behavior
         # Dangerous: SemanticsVisitor handles it as a function
         # Dangerous: SemanticsVisitor handles it as a function
-        if not tree.get_child("func_body"):
+        if not Tree.get_child(tree, "func_body"):
             return
             return
 
 
         new_value = self.node()
         new_value = self.node()
@@ -361,11 +362,11 @@ class PrimitivesVisitor(Visitor):
         if symbol.name in ["__input", "__output"]:
         if symbol.name in ["__input", "__output"]:
             return
             return
 
 
-        func_body = tree.get_child("func_body")
+        func_body = Tree.get_child(tree, "func_body")
         if func_body:
         if func_body:
             self.visit_children(tree)
             self.visit_children(tree)
             vf = self.function_values[symbol.name]
             vf = self.function_values[symbol.name]
-            parameters = tree.get_children("parameter")
+            parameters = Tree.get_children(tree, "parameter")
             if parameters:
             if parameters:
                 ps = self.node()
                 ps = self.node()
                 self.dict(vf, "params", ps)
                 self.dict(vf, "params", ps)
@@ -377,7 +378,7 @@ class PrimitivesVisitor(Visitor):
                     self.dict(n, "name", self.value(string.ascii_lowercase[i]))
                     self.dict(n, "name", self.value(string.ascii_lowercase[i]))
             b = self.get_primitive(func_body)
             b = self.get_primitive(func_body)
 
 
-            if tree.get_children("MUTABLE"):
+            if Tree.get_children(tree, "MUTABLE"):
                 self.dict(vf, "mutable", self.node())
                 self.dict(vf, "mutable", self.node())
 
 
             self.dict(vf, "body", b)
             self.dict(vf, "body", b)
@@ -388,9 +389,9 @@ class PrimitivesVisitor(Visitor):
             root = self.value(symbol.name)
             root = self.value(symbol.name)
             symbol.node = root
             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"):
+            if Tree.get_child(tree, "ASSIGN"):
+                new_value = "?" + Tree.get_text(Tree.get_child(tree, "ANYTHING"))
+            elif Tree.get_child(tree, "ASSIGN") and not Tree.get_child(tree, "ANYTHING"):
                 new_value = self.node()
                 new_value = self.node()
             else:
             else:
                 return
                 return
@@ -426,15 +427,15 @@ class PrimitivesVisitor(Visitor):
 
 
         symbol.node = root
         symbol.node = root
 
 
-        if tree.get_children("ASSIGN"):
+        if Tree.get_children(tree, "ASSIGN"):
             resolve = self.value(Action("resolve"))
             resolve = self.value(Action("resolve"))
             self.dict(resolve, "var", root)
             self.dict(resolve, "var", root)
 
 
             assign = self.value(Action("assign"))
             assign = self.value(Action("assign"))
             self.dict(assign, "var", resolve)
             self.dict(assign, "var", resolve)
 
 
-            self.visit_atomvalue(tree.get_tail()[-1])
-            value = self.get_primitive(tree.get_tail()[-1])
+            self.visit_atomvalue(Tree.get_tail(tree)[-1])
+            value = self.get_primitive(Tree.get_tail(tree)[-1])
 
 
             if value is None:
             if value is None:
                 call = self.value(Action("call"))
                 call = self.value(Action("call"))
@@ -462,8 +463,8 @@ class PrimitivesVisitor(Visitor):
         self.visit_children(tree)
         self.visit_children(tree)
         r = self.value(Action("return"))
         r = self.value(Action("return"))
         self.debug(r, tree)
         self.debug(r, tree)
-        if len(tree.get_tail()) > 2:
-            v = self.get_primitive(tree.get_tail()[1])
+        if len(Tree.get_tail(tree)) > 2:
+            v = self.get_primitive(Tree.get_tail(tree)[1])
             self.dict(r, "value", v)
             self.dict(r, "value", v)
         self.set_primitive(tree, r)
         self.set_primitive(tree, r)
 
 

+ 137 - 134
interface/HUTN/hutn_compiler/semantics_visitor.py

@@ -3,6 +3,7 @@ import hutn_compiler.symbol_table as st
 import sys
 import sys
 import hutn_compiler.types_mv as types_mv
 import hutn_compiler.types_mv as types_mv
 from hutn_compiler.declare_functions_visitor import DeclareFunctionsVisitor
 from hutn_compiler.declare_functions_visitor import DeclareFunctionsVisitor
+from hutn_compiler.hutnparser import Tree
 from hutn_compiler.visitor import Visitor
 from hutn_compiler.visitor import Visitor
 
 
 
 
@@ -21,8 +22,7 @@ class SemanticsVisitor(Visitor):
         # to ensure that (returned type == declared type)
         # to ensure that (returned type == declared type)
         self.current_funcdecl = None
         self.current_funcdecl = None
 
 
-        self.declare_functions_visitor =\
-            DeclareFunctionsVisitor(self.symbol_table, self.inputfiles)
+        self.declare_functions_visitor = DeclareFunctionsVisitor(self.symbol_table, self.inputfiles)
 
 
     @staticmethod
     @staticmethod
     def incompatible_types(l_type, r_type):
     def incompatible_types(l_type, r_type):
@@ -41,34 +41,34 @@ class SemanticsVisitor(Visitor):
             raise RuntimeError(
             raise RuntimeError(
                 "{}:{}:{}: error: invalid operands to binary operator "
                 "{}:{}:{}: error: invalid operands to binary operator "
                 "(have {} and {})".format(self.inputfiles[0],
                 "(have {} and {})".format(self.inputfiles[0],
-                                          l.startpos['line'],
-                                          l.startpos['column'],
+                                          l['startpos']['line'],
+                                          l['startpos']['column'],
                                           str(l_type),
                                           str(l_type),
                                           str(r_type)))
                                           str(r_type)))
 
 
     def check_binary_ops_arithmetic(self, tree):
     def check_binary_ops_arithmetic(self, tree):
-        l, r = tree.get_tail()[0], tree.get_tail()[2]
+        l, r = Tree.get_tail(tree)[0], Tree.get_tail(tree)[2]
         self.do_check_binary_ops_arithmetic(l, r)
         self.do_check_binary_ops_arithmetic(l, r)
 
 
     def generalize_binary_ops_arithmetic(self, tree):
     def generalize_binary_ops_arithmetic(self, tree):
-        l, r = tree.get_tail()[0], tree.get_tail()[2]
+        l, r = Tree.get_tail(tree)[0], Tree.get_tail(tree)[2]
         l_type, r_type = self.get_type(l), self.get_type(r)
         l_type, r_type = self.get_type(l), self.get_type(r)
         return types_mv.generalize_arithmetic(l_type, r_type)
         return types_mv.generalize_arithmetic(l_type, r_type)
 
 
     def check_unary_ops_arithmetic(self, tree, operator_name):
     def check_unary_ops_arithmetic(self, tree, operator_name):
-        l = tree.get_tail()[1]
+        l = Tree.get_tail(tree)[1]
         l_type = self.get_type(l)
         l_type = self.get_type(l)
         if l_type.isNotNumber():
         if l_type.isNotNumber():
             raise RuntimeError(
             raise RuntimeError(
                 "{}:{}:{}: error: wrong type argument to unary {} "
                 "{}:{}:{}: error: wrong type argument to unary {} "
                 "({})".format(self.inputfiles[0],
                 "({})".format(self.inputfiles[0],
-                              l.startpos['line'],
-                              l.startpos['column'],
+                              l['startpos']['line'],
+                              l['startpos']['column'],
                               operator_name,
                               operator_name,
                               str(l_type)))
                               str(l_type)))
 
 
     def promote_unary_ops_arithmetic(self, tree):
     def promote_unary_ops_arithmetic(self, tree):
-        l = tree.get_tail()[1]
+        l = Tree.get_tail(tree)[1]
         l_type = self.get_type(l)
         l_type = self.get_type(l)
         try:
         try:
             return types_mv.promote_arithmetic(l_type)
             return types_mv.promote_arithmetic(l_type)
@@ -87,20 +87,20 @@ class SemanticsVisitor(Visitor):
             raise RuntimeError("{}:{}:{}: error: cannot assign a value of "
             raise RuntimeError("{}:{}:{}: error: cannot assign a value of "
                                "type '{}' to a variable of type '{}'"
                                "type '{}' to a variable of type '{}'"
                 .format(self.inputfiles[0],
                 .format(self.inputfiles[0],
-                        l.startpos['line'],
-                        l.startpos['column'],
+                        l['startpos']['line'],
+                        l['startpos']['column'],
                         str(r_type),
                         str(r_type),
                         str(l_type)))
                         str(l_type)))
 
 
     def check_assignment(self, tree):
     def check_assignment(self, tree):
-        l, r = tree.get_tail()[0], tree.get_tail()[2]
+        l, r = Tree.get_tail(tree)[0], Tree.get_tail(tree)[2]
         self.do_check_assignment(l, r)
         self.do_check_assignment(l, r)
 
 
     def check_return(self, tree):
     def check_return(self, tree):
         l = self.current_funcdecl
         l = self.current_funcdecl
 
 
-        if len(tree.get_tail()) > 2:
-            r = tree.get_tail()[1]
+        if len(Tree.get_tail(tree)) > 2:
+            r = Tree.get_tail(tree)[1]
             r_type = None
             r_type = None
         else:
         else:
             r = None
             r = None
@@ -112,8 +112,8 @@ class SemanticsVisitor(Visitor):
             raise RuntimeError(
             raise RuntimeError(
                 "{}:{}:{}: error: 'return' is used outside of a function"
                 "{}:{}:{}: error: 'return' is used outside of a function"
                 .format(self.inputfiles[0],
                 .format(self.inputfiles[0],
-                        tree.startpos['line'],
-                        tree.startpos['column']))
+                        tree['startpos']['line'],
+                        tree['startpos']['column']))
 
 
     def check_predicate(self, tree):
     def check_predicate(self, tree):
         if isinstance(self.get_type(tree), types_mv.Element):
         if isinstance(self.get_type(tree), types_mv.Element):
@@ -122,18 +122,18 @@ class SemanticsVisitor(Visitor):
             raise RuntimeError(
             raise RuntimeError(
                 "{}:{}:{}: error: predicates of type '{}' are not allowed"
                 "{}:{}:{}: error: predicates of type '{}' are not allowed"
                 .format(self.inputfiles[0],
                 .format(self.inputfiles[0],
-                        tree.startpos['line'],
-                        tree.startpos['column'],
+                        tree['startpos']['line'],
+                        tree['startpos']['column'],
                         self.get_type(tree)))
                         self.get_type(tree)))
 
 
     def replace_child_binary_op_with_call(self, tree, i=0):
     def replace_child_binary_op_with_call(self, tree, i=0):
         if i == -1:
         if i == -1:
             child = tree
             child = tree
         else:
         else:
-            child = tree.get_tail()[i]
-        if len(child.get_tail()) > 1:
+            child = Tree.get_tail(tree)[i]
+        if len(Tree.get_tail(child)) > 1:
             try:
             try:
-                l, op, r = child.get_tail()
+                l, op, r = Tree.get_tail(child)
             except:
             except:
                 # Something went wrong... this code is severely broken
                 # Something went wrong... this code is severely broken
                 return
                 return
@@ -143,8 +143,8 @@ class SemanticsVisitor(Visitor):
                 raise RuntimeError(
                 raise RuntimeError(
                     "{}:{}:{}: error: children were not casted".format(
                     "{}:{}:{}: error: children were not casted".format(
                         self.inputfiles[0],
                         self.inputfiles[0],
-                        tree.startpos['line'],
-                        tree.startpos['column']
+                        tree['startpos']['line'],
+                        tree['startpos']['column']
                     ))
                     ))
             call_name = SemanticsVisitor.call_name_binary(l_type, op)
             call_name = SemanticsVisitor.call_name_binary(l_type, op)
             call_tree = self.func_call(call_name, [l, r], tree)
             call_tree = self.func_call(call_name, [l, r], tree)
@@ -157,24 +157,24 @@ class SemanticsVisitor(Visitor):
                     "{}:{}:{}: error: cannot perform {}: function '{}' is "
                     "{}:{}:{}: error: cannot perform {}: function '{}' is "
                     "not found".format(
                     "not found".format(
                         self.inputfiles[0],
                         self.inputfiles[0],
-                        tree.startpos['line'],
-                        tree.startpos['column'],
-                        child.head,
+                        tree['startpos']['line'],
+                        tree['startpos']['column'],
+                        child['head'],
                         call_signature))
                         call_signature))
             if i == -1:
             if i == -1:
-                tree.head = call_tree.head
-                tree.tail = call_tree.tail
-                tree._tail = None
+                tree['head'] = call_tree['head']
+                tree['tail'] = call_tree['tail']
+                tree['_tail'] = None
             else:
             else:
-                tree.replace_child(child, call_tree)
-        self.set_type(tree, self.get_type(tree.get_tail()[i]))
+                Tree.replace_child(tree, child, call_tree)
+        self.set_type(tree, self.get_type(Tree.get_tail(tree)[i]))
 
 
     def replace_child_unary_op_with_call(self, tree):
     def replace_child_unary_op_with_call(self, tree):
-        child = tree.get_tail()[0]
-        if child.head == "keep_sign":
-            tree.replace_child(child, child.get_tail()[1])
+        child = Tree.get_tail(tree)[0]
+        if child['head'] == "keep_sign":
+            Tree.replace_child(tree, child, Tree.get_tail(child)[1])
         else:
         else:
-            op, l = child.get_tail()
+            op, l = Tree.get_tail(child)
             l_type = self.get_type(l)
             l_type = self.get_type(l)
             call_name = SemanticsVisitor.call_name_unary(l_type, op)
             call_name = SemanticsVisitor.call_name_unary(l_type, op)
             call_tree = self.func_call(call_name, [l], tree)
             call_tree = self.func_call(call_name, [l], tree)
@@ -187,15 +187,15 @@ class SemanticsVisitor(Visitor):
                     "{}:{}:{}: error: cannot perform {}: function '{}' is "
                     "{}:{}:{}: error: cannot perform {}: function '{}' is "
                     "not found".format(
                     "not found".format(
                         self.inputfiles[0],
                         self.inputfiles[0],
-                        tree.startpos['line'],
-                        tree.startpos['column'],
-                        child.head,
+                        tree['startpos']['line'],
+                        tree['startpos']['column'],
+                        child['head'],
                         call_signature))
                         call_signature))
-            tree.replace_child(child, call_tree)
-        self.set_type(tree, self.get_type(tree.get_tail()[0]))
+            Tree.replace_child(tree, child, call_tree)
+        self.set_type(tree, self.get_type(Tree.get_tail(tree)[0]))
 
 
     def cast_binary_ops_arithmetic(self, tree):
     def cast_binary_ops_arithmetic(self, tree):
-        l, op, r = tree.get_tail()
+        l, op, r = Tree.get_tail(tree)
         l_type, r_type = self.get_type(l), self.get_type(r)
         l_type, r_type = self.get_type(l), self.get_type(r)
         if type(l_type) != type(r_type):  # if two different numeric types
         if type(l_type) != type(r_type):  # if two different numeric types
             g_type = types_mv.generalize_arithmetic(l_type, r_type)
             g_type = types_mv.generalize_arithmetic(l_type, r_type)
@@ -203,42 +203,46 @@ class SemanticsVisitor(Visitor):
             self.perform_implicit_cast(tree, r, r_type, g_type)
             self.perform_implicit_cast(tree, r, r_type, g_type)
 
 
     def cast_binary_ops_logical(self, tree):
     def cast_binary_ops_logical(self, tree):
-        l, op, r = tree.get_tail()
+        l, op, r = Tree.get_tail(tree)
         l_type, r_type = self.get_type(l), self.get_type(r)
         l_type, r_type = self.get_type(l), self.get_type(r)
         self.perform_implicit_cast(tree, l, l_type, types_mv.Boolean())
         self.perform_implicit_cast(tree, l, l_type, types_mv.Boolean())
         self.perform_implicit_cast(tree, r, r_type, types_mv.Boolean())
         self.perform_implicit_cast(tree, r, r_type, types_mv.Boolean())
 
 
     def cast_unary_ops_arithmetic(self, tree):
     def cast_unary_ops_arithmetic(self, tree):
-        l = tree.get_tail()[1]
+        l = Tree.get_tail(tree)[1]
         l_type = self.get_type(l)
         l_type = self.get_type(l)
         p_type = self.promote_unary_ops_arithmetic(tree)
         p_type = self.promote_unary_ops_arithmetic(tree)
         self.perform_implicit_cast(tree, l, l_type, p_type)
         self.perform_implicit_cast(tree, l, l_type, p_type)
 
 
     def func_call(self, name, params, old_tree):
     def func_call(self, name, params, old_tree):
-        startpos = old_tree.startpos
-        endpos = old_tree.endpos
-        inputfile = old_tree.inputfile
-
-        tree = hp.Tree(
-            "func_call",
-            [
-                hp.Tree("rvalue",
-                        [
-                            hp.Tree("ID", [name], startpos, endpos, inputfile)
-                        ],
-                        startpos, endpos, inputfile),
-                # Tokens have no impact on visit_func_call. So leave them out.
-            ],
-            startpos, endpos, inputfile)
+        startpos = old_tree['startpos']
+        endpos = old_tree['endpos']
+        inputfile = old_tree['inputfile']
+
+        tree = {"head": "func_call",
+                "tail": [
+                    {"head": "rvalue",
+                     "tail": [
+                        {"head": "ID",
+                         "tail": [name],
+                         "startpos": startpos,
+                         "endpos": endpos,
+                         "inputfile": inputfile}],
+                     "startpos": startpos,
+                     "endpos": endpos,
+                     "inputfile": inputfile}],
+                "startpos": startpos,
+                "endpos": endpos,
+                "inputfile": inputfile}
 
 
         for p in params:
         for p in params:
             self.replace_child_binary_op_with_call(p, -1)
             self.replace_child_binary_op_with_call(p, -1)
 
 
-        params = [hp.Tree("expression", [p], startpos, endpos, inputfile) for p in params]
+        params = [{"head": "expression", "tail": [p], "startpos": startpos, "endpos": endpos, "inputfile": inputfile} for p in params]
 
 
-        tree.tail.extend(params)
+        tree['tail'].extend(params)
 
 
-        return hp.Tree("expression", [tree], startpos, endpos, inputfile)
+        return {"head": "expression", "tail": [tree], "startpos": startpos, "endpos": endpos, "inputfile": inputfile}
 
 
     @staticmethod
     @staticmethod
     def cast_name(from_type, to_type):
     def cast_name(from_type, to_type):
@@ -254,8 +258,8 @@ class SemanticsVisitor(Visitor):
             "{}:{}:{}: error: cannot perform implicit cast from '{}'"
             "{}:{}:{}: error: cannot perform implicit cast from '{}'"
             " to '{}': function '{}' is not found".format(
             " to '{}': function '{}' is not found".format(
                 self.inputfiles[0],
                 self.inputfiles[0],
-                tree.startpos['line'],
-                tree.startpos['column'],
+                tree['startpos']['line'],
+                tree['startpos']['column'],
                 str(to_type), str(from_type),
                 str(to_type), str(from_type),
                 cast_signature))
                 cast_signature))
 
 
@@ -270,7 +274,7 @@ class SemanticsVisitor(Visitor):
             self.visit(cast_tree)
             self.visit(cast_tree)
         except RuntimeError:
         except RuntimeError:
             self.raise_implicit_cast_error(from_type, to_type, child)
             self.raise_implicit_cast_error(from_type, to_type, child)
-        tree.replace_child(child, cast_tree)
+        Tree.replace_child(tree, child, cast_tree)
 
 
     types = {
     types = {
         "Integer": "integer",
         "Integer": "integer",
@@ -306,38 +310,38 @@ class SemanticsVisitor(Visitor):
     def call_name_binary(operand_type, operator):
     def call_name_binary(operand_type, operator):
         # String joins should also be possible
         # String joins should also be possible
         if str(operand_type) == "String":
         if str(operand_type) == "String":
-            if operator.head == "PLUS":
+            if operator['head'] == "PLUS":
                 return "string_join"
                 return "string_join"
 
 
-        if operator.head == "EQ":
+        if operator['head'] == "EQ":
             return "value_eq"
             return "value_eq"
-        elif operator.head == "NEQ":
+        elif operator['head'] == "NEQ":
             return "value_neq"
             return "value_neq"
 
 
         call_name = "{}_{}".format(SemanticsVisitor.types[str(operand_type)],
         call_name = "{}_{}".format(SemanticsVisitor.types[str(operand_type)],
-                                   SemanticsVisitor.binary_ops[operator.head])
+                                   SemanticsVisitor.binary_ops[operator['head']])
         return call_name
         return call_name
 
 
     @staticmethod
     @staticmethod
     def call_name_unary(operand_type, operator):
     def call_name_unary(operand_type, operator):
         call_name = "{}_{}".format(SemanticsVisitor.types[str(operand_type)],
         call_name = "{}_{}".format(SemanticsVisitor.types[str(operand_type)],
-                                   SemanticsVisitor.unary_ops[operator.head])
+                                   SemanticsVisitor.unary_ops[operator['head']])
 
 
         return call_name
         return call_name
 
 
     def dump(self):
     def dump(self):
-        return self.tree.get_text(with_implicit=True)
+        return Tree.get_text(self.tree, with_implicit=True)
         # return "No code generation here"
         # return "No code generation here"
 
 
     # a visit_* method for each non-terminal in the grammar
     # a visit_* method for each non-terminal in the grammar
     def visit_start(self, tree):
     def visit_start(self, tree):
         self.symbol_table.open_scope()
         self.symbol_table.open_scope()
-        self.inputfiles.append(tree.inputfile)
-        for child in tree.get_tail():
-            self.inputfiles[0] = child.inputfile
+        self.inputfiles.append(tree['inputfile'])
+        for child in Tree.get_tail(tree):
+            self.inputfiles[0] = child['inputfile']
             self.declare_functions_visitor.visit(child)
             self.declare_functions_visitor.visit(child)
-        for child in tree.get_tail():
-            self.inputfiles[0] = child.inputfile
+        for child in Tree.get_tail(tree):
+            self.inputfiles[0] = child['inputfile']
             self.visit(child)
             self.visit(child)
         self.inputfiles.pop()
         self.inputfiles.pop()
         self.symbol_table.close_scope()
         self.symbol_table.close_scope()
@@ -350,22 +354,21 @@ class SemanticsVisitor(Visitor):
         self.visit_vardecl(tree)
         self.visit_vardecl(tree)
 
 
     def visit_vardecl(self, tree):
     def visit_vardecl(self, tree):
-        type_spec = tree.get_child("type_specifier")
-        var_id = tree.get_child("ID")
+        type_spec = Tree.get_child(tree, "type_specifier")
+        var_id = Tree.get_child(tree, "ID")
 
 
-        var_type = types_mv.string_to_type(type_spec.get_text())
-        var_name = var_id.get_text()
+        var_type = types_mv.string_to_type(Tree.get_text(type_spec))
+        var_name = Tree.get_text(var_id)
 
 
-        symbol = st.Symbol(var_name, var_type,
-                        is_global=self.current_funcdecl is None)
+        symbol = st.Symbol(var_name, var_type, is_global=self.current_funcdecl is None)
 
 
         try:
         try:
             self.symbol_table.add(symbol)
             self.symbol_table.add(symbol)
         except Exception:
         except Exception:
             raise RuntimeError(
             raise RuntimeError(
                 "{}:{}:{}: error: redeclaration of '{}'".format(
                 "{}:{}:{}: error: redeclaration of '{}'".format(
-                    self.inputfiles[0], tree.startpos['line'],
-                    tree.startpos['column'], var_name))
+                    self.inputfiles[0], tree['startpos']['line'],
+                    tree['startpos']['column'], var_name))
 
 
         self.set_symbol(tree, symbol)
         self.set_symbol(tree, symbol)
 
 
@@ -375,7 +378,7 @@ class SemanticsVisitor(Visitor):
 
 
     def visit_expression(self, tree):
     def visit_expression(self, tree):
         self.visit_children(tree)
         self.visit_children(tree)
-        self.set_type(tree, self.get_type(tree.get_tail()[0]))
+        self.set_type(tree, self.get_type(Tree.get_tail(tree)[0]))
 
 
     def visit_binary_operation(self, tree):
     def visit_binary_operation(self, tree):
         self.visit_children(tree)
         self.visit_children(tree)
@@ -383,7 +386,7 @@ class SemanticsVisitor(Visitor):
 
 
     def visit_disjunction(self, tree):
     def visit_disjunction(self, tree):
         self.visit_children(tree)
         self.visit_children(tree)
-        if len(tree.get_tail()) == 1:
+        if len(Tree.get_tail(tree)) == 1:
             self.replace_child_binary_op_with_call(tree)
             self.replace_child_binary_op_with_call(tree)
         else:
         else:
             self.replace_child_binary_op_with_call(tree, 2)
             self.replace_child_binary_op_with_call(tree, 2)
@@ -392,7 +395,7 @@ class SemanticsVisitor(Visitor):
 
 
     def visit_conjunction(self, tree):
     def visit_conjunction(self, tree):
         self.visit_children(tree)
         self.visit_children(tree)
-        if len(tree.get_tail()) == 1:
+        if len(Tree.get_tail(tree)) == 1:
             self.replace_child_binary_op_with_call(tree)
             self.replace_child_binary_op_with_call(tree)
         else:
         else:
             self.replace_child_binary_op_with_call(tree, 2)
             self.replace_child_binary_op_with_call(tree, 2)
@@ -401,7 +404,7 @@ class SemanticsVisitor(Visitor):
 
 
     def visit_comparison(self, tree):
     def visit_comparison(self, tree):
         self.visit_children(tree)
         self.visit_children(tree)
-        if len(tree.get_tail()) == 1:
+        if len(Tree.get_tail(tree)) == 1:
             self.replace_child_binary_op_with_call(tree)
             self.replace_child_binary_op_with_call(tree)
         else:
         else:
             self.replace_child_binary_op_with_call(tree, 2)
             self.replace_child_binary_op_with_call(tree, 2)
@@ -411,7 +414,7 @@ class SemanticsVisitor(Visitor):
 
 
     def visit_relation(self, tree):
     def visit_relation(self, tree):
         self.visit_children(tree)
         self.visit_children(tree)
-        if len(tree.get_tail()) == 1:
+        if len(Tree.get_tail(tree)) == 1:
             self.replace_child_binary_op_with_call(tree)
             self.replace_child_binary_op_with_call(tree)
         else:
         else:
             self.replace_child_binary_op_with_call(tree, 2)
             self.replace_child_binary_op_with_call(tree, 2)
@@ -421,40 +424,40 @@ class SemanticsVisitor(Visitor):
 
 
     def visit_sum(self, tree):
     def visit_sum(self, tree):
         self.visit_children(tree)
         self.visit_children(tree)
-        if len(tree.get_tail()) == 1:
+        if len(Tree.get_tail(tree)) == 1:
             self.replace_child_binary_op_with_call(tree)
             self.replace_child_binary_op_with_call(tree)
         else:
         else:
             self.replace_child_binary_op_with_call(tree, 2)
             self.replace_child_binary_op_with_call(tree, 2)
             self.check_binary_ops_arithmetic(tree)
             self.check_binary_ops_arithmetic(tree)
             self.cast_binary_ops_arithmetic(tree)
             self.cast_binary_ops_arithmetic(tree)
             # after the cast both parameters have the same (generalized) type:
             # after the cast both parameters have the same (generalized) type:
-            self.set_type(tree, self.get_type(tree.get_tail()[0]))
+            self.set_type(tree, self.get_type(Tree.get_tail(tree)[0]))
 
 
     def visit_term(self, tree):
     def visit_term(self, tree):
         self.visit_children(tree)
         self.visit_children(tree)
-        if len(tree.get_tail()) == 1:
-            self.set_type(tree, self.get_type(tree.get_tail()[0]))
+        if len(Tree.get_tail(tree)) == 1:
+            self.set_type(tree, self.get_type(Tree.get_tail(tree)[0]))
         else:
         else:
             self.check_binary_ops_arithmetic(tree)
             self.check_binary_ops_arithmetic(tree)
             self.cast_binary_ops_arithmetic(tree)
             self.cast_binary_ops_arithmetic(tree)
             # after the cast both parameters have the same (generalized) type:
             # after the cast both parameters have the same (generalized) type:
-            self.set_type(tree, self.get_type(tree.get_tail()[0]))
+            self.set_type(tree, self.get_type(Tree.get_tail(tree)[0]))
 
 
     def visit_factor(self, tree):
     def visit_factor(self, tree):
         self.visit_children(tree)
         self.visit_children(tree)
-        if tree.get_child("primary") is not None:
-            self.set_type(tree, self.get_type(tree.get_tail()[0]))
+        if Tree.get_child(tree, "primary") is not None:
+            self.set_type(tree, self.get_type(Tree.get_tail(tree)[0]))
         else:
         else:
             self.replace_child_unary_op_with_call(tree)
             self.replace_child_unary_op_with_call(tree)
 
 
     def visit_logical_not(self, tree):
     def visit_logical_not(self, tree):
         self.visit_children(tree)
         self.visit_children(tree)
 
 
-        l = tree.get_tail()[1]
+        l = Tree.get_tail(tree)[1]
         l_type = self.get_type(l)
         l_type = self.get_type(l)
         self.perform_implicit_cast(tree, l, l_type, types_mv.Boolean())
         self.perform_implicit_cast(tree, l, l_type, types_mv.Boolean())
 
 
-        self.set_type(tree, self.get_type(tree.get_tail()[1]))
+        self.set_type(tree, self.get_type(Tree.get_tail(tree)[1]))
 
 
     def visit_invert_sign(self, tree):
     def visit_invert_sign(self, tree):
         self.visit_children(tree)
         self.visit_children(tree)
@@ -462,7 +465,7 @@ class SemanticsVisitor(Visitor):
         self.check_unary_ops_arithmetic(tree, "minus")
         self.check_unary_ops_arithmetic(tree, "minus")
         self.cast_unary_ops_arithmetic(tree)
         self.cast_unary_ops_arithmetic(tree)
 
 
-        self.set_type(tree, self.get_type(tree.get_tail()[1]))
+        self.set_type(tree, self.get_type(Tree.get_tail(tree)[1]))
 
 
     def visit_keep_sign(self, tree):
     def visit_keep_sign(self, tree):
         self.visit_children(tree)
         self.visit_children(tree)
@@ -470,19 +473,19 @@ class SemanticsVisitor(Visitor):
         self.check_unary_ops_arithmetic(tree, "plus")
         self.check_unary_ops_arithmetic(tree, "plus")
         self.cast_unary_ops_arithmetic(tree)
         self.cast_unary_ops_arithmetic(tree)
 
 
-        self.set_type(tree, self.get_type(tree.get_tail()[1]))
+        self.set_type(tree, self.get_type(Tree.get_tail(tree)[1]))
 
 
     def visit_primary(self, tree):
     def visit_primary(self, tree):
         self.visit_children(tree)
         self.visit_children(tree)
-        self.set_type(tree, self.get_type(tree.get_tail()[0]))
+        self.set_type(tree, self.get_type(Tree.get_tail(tree)[0]))
 
 
     def visit_parenthesized(self, tree):
     def visit_parenthesized(self, tree):
         self.visit_children(tree)
         self.visit_children(tree)
-        self.set_type(tree, self.get_type(tree.get_tail()[1]))
+        self.set_type(tree, self.get_type(Tree.get_tail(tree)[1]))
 
 
     def visit_atomvalue(self, tree):
     def visit_atomvalue(self, tree):
         self.visit_children(tree)
         self.visit_children(tree)
-        self.set_type(tree, self.get_type(tree.get_tail()[0]))
+        self.set_type(tree, self.get_type(Tree.get_tail(tree)[0]))
 
 
     def visit_type_specifier(self, tree):
     def visit_type_specifier(self, tree):
         self.set_type(tree, types_mv.Type())
         self.set_type(tree, types_mv.Type())
@@ -501,29 +504,29 @@ class SemanticsVisitor(Visitor):
 
 
     # there is no such rule in the grammar, we just avoid code duplicates
     # there is no such rule in the grammar, we just avoid code duplicates
     def visit_id(self, tree):
     def visit_id(self, tree):
-        name = tree.get_text()
+        name = Tree.get_text(tree)
         #TODO this is set to the function returnvalue, even if we use the function pointer...
         #TODO this is set to the function returnvalue, even if we use the function pointer...
         try:
         try:
             symbol = self.symbol_table.get(name)
             symbol = self.symbol_table.get(name)
         except KeyError:
         except KeyError:
             raise RuntimeError("{}:{}:{}: error: '{}' is not declared".format(
             raise RuntimeError("{}:{}:{}: error: '{}' is not declared".format(
-                self.inputfiles[0], tree.startpos['line'],
-                tree.startpos['column'], name))
+                self.inputfiles[0], tree['startpos']['line'],
+                tree['startpos']['column'], name))
         self.set_type(tree, symbol.type)
         self.set_type(tree, symbol.type)
         self.set_symbol(tree, symbol)
         self.set_symbol(tree, symbol)
 
 
     def visit_rvalue(self, tree):
     def visit_rvalue(self, tree):
-        if len(tree.get_tail()) > 1:
+        if len(Tree.get_tail(tree)) > 1:
             # Complex: dict_read operation needed
             # Complex: dict_read operation needed
-            child = tree.get_tail()[0]
-            node = tree.get_child("rvalue")
-            expression = tree.get_child("expression")
+            child = Tree.get_tail(tree)[0]
+            node = Tree.get_child(tree, "rvalue")
+            expression = Tree.get_child(tree, "expression")
             operation = "dict_read"
             operation = "dict_read"
             call_tree = self.func_call(operation, [node, expression], tree)
             call_tree = self.func_call(operation, [node, expression], tree)
             self.visit(call_tree)
             self.visit(call_tree)
-            tree.head = call_tree.head
-            tree._tail = call_tree.tail
-            tree.tail = call_tree.tail
+            tree['head'] = call_tree['head']
+            tree['_tail'] = call_tree['tail']
+            tree['tail'] = call_tree['tail']
             self.set_type(tree, self.get_type(node))
             self.set_type(tree, self.get_type(node))
         else:
         else:
             # Simple
             # Simple
@@ -535,7 +538,7 @@ class SemanticsVisitor(Visitor):
     def visit_func_call(self, tree):
     def visit_func_call(self, tree):
         self.visit_children(tree)
         self.visit_children(tree)
 
 
-        symbol = self.get_symbol(tree.get_tail()[0])
+        symbol = self.get_symbol(Tree.get_tail(tree)[0])
         self.set_type(tree, symbol.type)
         self.set_type(tree, symbol.type)
 
 
         if not symbol.is_func():
         if not symbol.is_func():
@@ -549,18 +552,18 @@ class SemanticsVisitor(Visitor):
             raise RuntimeError(
             raise RuntimeError(
                 "{}:{}:{}: error: '{}' is a variable of type '{}', not a "
                 "{}:{}:{}: error: '{}' is a variable of type '{}', not a "
                 "function".format(self.inputfiles[0],
                 "function".format(self.inputfiles[0],
-                                  tree.startpos['line'],
-                                  tree.startpos['column'],
+                                  tree['startpos']['line'],
+                                  tree['startpos']['column'],
                                   symbol.name,
                                   symbol.name,
                                   symbol.type))
                                   symbol.type))
 
 
-        expressions = tree.get_children("expression")
+        expressions = Tree.get_children(tree, "expression")
         if len(expressions) != len(symbol.params):
         if len(expressions) != len(symbol.params):
             raise RuntimeError(
             raise RuntimeError(
                 "{}:{}:{}: error: wrong number of arguments to "
                 "{}:{}:{}: error: wrong number of arguments to "
                 "function '{}'".format(self.inputfiles[0],
                 "function '{}'".format(self.inputfiles[0],
-                                       tree.startpos['line'],
-                                       tree.startpos['column'],
+                                       tree['startpos']['line'],
+                                       tree['startpos']['column'],
                                        symbol.signature()))
                                        symbol.signature()))
 
 
         """
         """
@@ -584,9 +587,9 @@ class SemanticsVisitor(Visitor):
         """
         """
 
 
         if symbol.name == "__input":
         if symbol.name == "__input":
-            tree.head = "input"
+            tree['head'] = "input"
         elif symbol.name == "__output":
         elif symbol.name == "__output":
-            tree.head = "output"
+            tree['head'] = "output"
 
 
     def visit_input(self, tree):
     def visit_input(self, tree):
         pass  # no need to visit it again
         pass  # no need to visit it again
@@ -605,7 +608,7 @@ class SemanticsVisitor(Visitor):
 
 
     def visit_ifelse(self, tree):
     def visit_ifelse(self, tree):
         self.visit_children(tree)
         self.visit_children(tree)
-        expressions = tree.get_children("expression")
+        expressions = Tree.get_children(tree, "expression")
         for expression in expressions:
         for expression in expressions:
             self.check_predicate(expression)
             self.check_predicate(expression)
 
 
@@ -613,7 +616,7 @@ class SemanticsVisitor(Visitor):
         self.while_counter += 1
         self.while_counter += 1
         self.visit_children(tree)
         self.visit_children(tree)
         self.while_counter -= 1
         self.while_counter -= 1
-        expression = tree.get_child("expression")
+        expression = Tree.get_child(tree, "expression")
         self.check_predicate(expression)
         self.check_predicate(expression)
 
 
     def visit_block(self, tree):
     def visit_block(self, tree):
@@ -627,7 +630,7 @@ class SemanticsVisitor(Visitor):
     def visit_funcdecl(self, tree):
     def visit_funcdecl(self, tree):
         # here we only visit the body cause the declaration is already done
         # here we only visit the body cause the declaration is already done
         # by declare_functions_visitor
         # by declare_functions_visitor
-        if tree.get_child('func_body') is not None:
+        if Tree.get_child(tree, 'func_body') is not None:
             self.current_funcdecl = tree
             self.current_funcdecl = tree
 
 
             self.symbol_table.open_scope()
             self.symbol_table.open_scope()
@@ -637,11 +640,11 @@ class SemanticsVisitor(Visitor):
             self.current_funcdecl = None
             self.current_funcdecl = None
 
 
     def visit_parameter(self, tree):
     def visit_parameter(self, tree):
-        param_id = tree.get_child("ID")
-        type_spec = tree.get_child("type_specifier")
+        param_id = Tree.get_child(tree, "ID")
+        type_spec = Tree.get_child(tree, "type_specifier")
 
 
-        param_type = types_mv.string_to_type(type_spec.get_text())
-        param_name = param_id.get_text()
+        param_type = types_mv.string_to_type(Tree.get_text(type_spec))
+        param_name = Tree.get_text(param_id)
 
 
         symbol = st.Symbol(param_name, param_type, is_global=False)
         symbol = st.Symbol(param_name, param_type, is_global=False)
 
 
@@ -650,8 +653,8 @@ class SemanticsVisitor(Visitor):
         except Exception:
         except Exception:
             raise RuntimeError(
             raise RuntimeError(
                 "{}:{}:{}: error: redeclaration of '{}'".format(
                 "{}:{}:{}: error: redeclaration of '{}'".format(
-                    self.inputfiles[0], tree.startpos['line'],
-                    tree.startpos['column'], param_name))
+                    self.inputfiles[0], tree['startpos']['line'],
+                    tree['startpos']['column'], param_name))
 
 
         self.set_symbol(tree, symbol)
         self.set_symbol(tree, symbol)
 
 
@@ -666,12 +669,12 @@ class SemanticsVisitor(Visitor):
         if self.while_counter == 0:
         if self.while_counter == 0:
             raise RuntimeError(
             raise RuntimeError(
                 "{}:{}:{}: error: break outside of while".format(
                 "{}:{}:{}: error: break outside of while".format(
-                    self.inputfiles[0], tree.startpos['line'],
-                    tree.startpos['column']))
+                    self.inputfiles[0], tree['startpos']['line'],
+                    tree['startpos']['column']))
 
 
     def visit_continue(self, tree):
     def visit_continue(self, tree):
         if self.while_counter == 0:
         if self.while_counter == 0:
             raise RuntimeError(
             raise RuntimeError(
                 "{}:{}:{}: error: continue outside of while".format(
                 "{}:{}:{}: error: continue outside of while".format(
-                    self.inputfiles[0], tree.startpos['line'],
-                    tree.startpos['column']))
+                    self.inputfiles[0], tree['startpos']['line'],
+                    tree['startpos']['column']))

+ 9 - 8
interface/HUTN/hutn_compiler/visitor.py

@@ -1,4 +1,5 @@
 import hutn_compiler.symbol_table as st
 import hutn_compiler.symbol_table as st
+from hutn_compiler.hutnparser import Tree
 
 
 
 
 class Visitor(object):
 class Visitor(object):
@@ -9,27 +10,27 @@ class Visitor(object):
         return ""
         return ""
 
 
     def visit(self, tree):
     def visit(self, tree):
-        if not tree.head.startswith("implicit_autogenerated_"):
-            val = tree.head
+        if not tree['head'].startswith("implicit_autogenerated_"):
+            val = tree['head']
             visit_val = getattr(self, 'visit_' + val)
             visit_val = getattr(self, 'visit_' + val)
             return visit_val(tree)
             return visit_val(tree)
 
 
     def visit_children(self, tree):
     def visit_children(self, tree):
-        for child in tree.get_tail():
-            if child.head.islower():  # visit only non-terminals
+        for child in Tree.get_tail(tree):
+            if child['head'].islower():  # visit only non-terminals
                 self.visit(child)
                 self.visit(child)
 
 
     def set_type(self, tree, type):
     def set_type(self, tree, type):
-        tree.type = type
+        tree['type'] = type
 
 
     def get_type(self, tree):
     def get_type(self, tree):
-        return getattr(tree, 'type', None)
+        return tree.get('type', None)
 
 
     def set_symbol(self, tree, symbol):
     def set_symbol(self, tree, symbol):
-        tree.symbol = symbol
+        tree['symbol'] = symbol
 
 
     def get_symbol(self, tree):
     def get_symbol(self, tree):
-        return getattr(tree, 'symbol', None)
+        return tree.get('symbol', None)
 
 
     @staticmethod
     @staticmethod
     def print_tree(tree):
     def print_tree(tree):