|
@@ -3,6 +3,7 @@ import hutn_compiler.symbol_table as st
|
|
|
import sys
|
|
|
import hutn_compiler.types_mv as types_mv
|
|
|
from hutn_compiler.declare_functions_visitor import DeclareFunctionsVisitor
|
|
|
+from hutn_compiler.hutnparser import Tree
|
|
|
from hutn_compiler.visitor import Visitor
|
|
|
|
|
|
|
|
@@ -21,8 +22,7 @@ class SemanticsVisitor(Visitor):
|
|
|
# to ensure that (returned type == declared type)
|
|
|
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
|
|
|
def incompatible_types(l_type, r_type):
|
|
@@ -41,34 +41,34 @@ class SemanticsVisitor(Visitor):
|
|
|
raise RuntimeError(
|
|
|
"{}:{}:{}: error: invalid operands to binary operator "
|
|
|
"(have {} and {})".format(self.inputfiles[0],
|
|
|
- l.startpos['line'],
|
|
|
- l.startpos['column'],
|
|
|
+ l['startpos']['line'],
|
|
|
+ l['startpos']['column'],
|
|
|
str(l_type),
|
|
|
str(r_type)))
|
|
|
|
|
|
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)
|
|
|
|
|
|
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)
|
|
|
return types_mv.generalize_arithmetic(l_type, r_type)
|
|
|
|
|
|
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)
|
|
|
if l_type.isNotNumber():
|
|
|
raise RuntimeError(
|
|
|
"{}:{}:{}: error: wrong type argument to unary {} "
|
|
|
"({})".format(self.inputfiles[0],
|
|
|
- l.startpos['line'],
|
|
|
- l.startpos['column'],
|
|
|
+ l['startpos']['line'],
|
|
|
+ l['startpos']['column'],
|
|
|
operator_name,
|
|
|
str(l_type)))
|
|
|
|
|
|
def promote_unary_ops_arithmetic(self, tree):
|
|
|
- l = tree.get_tail()[1]
|
|
|
+ l = Tree.get_tail(tree)[1]
|
|
|
l_type = self.get_type(l)
|
|
|
try:
|
|
|
return types_mv.promote_arithmetic(l_type)
|
|
@@ -87,20 +87,20 @@ class SemanticsVisitor(Visitor):
|
|
|
raise RuntimeError("{}:{}:{}: error: cannot assign a value of "
|
|
|
"type '{}' to a variable of type '{}'"
|
|
|
.format(self.inputfiles[0],
|
|
|
- l.startpos['line'],
|
|
|
- l.startpos['column'],
|
|
|
+ l['startpos']['line'],
|
|
|
+ l['startpos']['column'],
|
|
|
str(r_type),
|
|
|
str(l_type)))
|
|
|
|
|
|
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)
|
|
|
|
|
|
def check_return(self, tree):
|
|
|
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
|
|
|
else:
|
|
|
r = None
|
|
@@ -112,8 +112,8 @@ class SemanticsVisitor(Visitor):
|
|
|
raise RuntimeError(
|
|
|
"{}:{}:{}: error: 'return' is used outside of a function"
|
|
|
.format(self.inputfiles[0],
|
|
|
- tree.startpos['line'],
|
|
|
- tree.startpos['column']))
|
|
|
+ tree['startpos']['line'],
|
|
|
+ tree['startpos']['column']))
|
|
|
|
|
|
def check_predicate(self, tree):
|
|
|
if isinstance(self.get_type(tree), types_mv.Element):
|
|
@@ -122,18 +122,18 @@ class SemanticsVisitor(Visitor):
|
|
|
raise RuntimeError(
|
|
|
"{}:{}:{}: error: predicates of type '{}' are not allowed"
|
|
|
.format(self.inputfiles[0],
|
|
|
- tree.startpos['line'],
|
|
|
- tree.startpos['column'],
|
|
|
+ tree['startpos']['line'],
|
|
|
+ tree['startpos']['column'],
|
|
|
self.get_type(tree)))
|
|
|
|
|
|
def replace_child_binary_op_with_call(self, tree, i=0):
|
|
|
if i == -1:
|
|
|
child = tree
|
|
|
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:
|
|
|
- l, op, r = child.get_tail()
|
|
|
+ l, op, r = Tree.get_tail(child)
|
|
|
except:
|
|
|
# Something went wrong... this code is severely broken
|
|
|
return
|
|
@@ -143,8 +143,8 @@ class SemanticsVisitor(Visitor):
|
|
|
raise RuntimeError(
|
|
|
"{}:{}:{}: error: children were not casted".format(
|
|
|
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_tree = self.func_call(call_name, [l, r], tree)
|
|
@@ -157,24 +157,24 @@ class SemanticsVisitor(Visitor):
|
|
|
"{}:{}:{}: error: cannot perform {}: function '{}' is "
|
|
|
"not found".format(
|
|
|
self.inputfiles[0],
|
|
|
- tree.startpos['line'],
|
|
|
- tree.startpos['column'],
|
|
|
- child.head,
|
|
|
+ tree['startpos']['line'],
|
|
|
+ tree['startpos']['column'],
|
|
|
+ child['head'],
|
|
|
call_signature))
|
|
|
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:
|
|
|
- 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):
|
|
|
- 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:
|
|
|
- op, l = child.get_tail()
|
|
|
+ op, l = Tree.get_tail(child)
|
|
|
l_type = self.get_type(l)
|
|
|
call_name = SemanticsVisitor.call_name_unary(l_type, op)
|
|
|
call_tree = self.func_call(call_name, [l], tree)
|
|
@@ -187,15 +187,15 @@ class SemanticsVisitor(Visitor):
|
|
|
"{}:{}:{}: error: cannot perform {}: function '{}' is "
|
|
|
"not found".format(
|
|
|
self.inputfiles[0],
|
|
|
- tree.startpos['line'],
|
|
|
- tree.startpos['column'],
|
|
|
- child.head,
|
|
|
+ tree['startpos']['line'],
|
|
|
+ tree['startpos']['column'],
|
|
|
+ child['head'],
|
|
|
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):
|
|
|
- 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)
|
|
|
if type(l_type) != type(r_type): # if two different numeric types
|
|
|
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)
|
|
|
|
|
|
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)
|
|
|
self.perform_implicit_cast(tree, l, l_type, types_mv.Boolean())
|
|
|
self.perform_implicit_cast(tree, r, r_type, types_mv.Boolean())
|
|
|
|
|
|
def cast_unary_ops_arithmetic(self, tree):
|
|
|
- l = tree.get_tail()[1]
|
|
|
+ l = Tree.get_tail(tree)[1]
|
|
|
l_type = self.get_type(l)
|
|
|
p_type = self.promote_unary_ops_arithmetic(tree)
|
|
|
self.perform_implicit_cast(tree, l, l_type, p_type)
|
|
|
|
|
|
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:
|
|
|
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
|
|
|
def cast_name(from_type, to_type):
|
|
@@ -254,8 +258,8 @@ class SemanticsVisitor(Visitor):
|
|
|
"{}:{}:{}: error: cannot perform implicit cast from '{}'"
|
|
|
" to '{}': function '{}' is not found".format(
|
|
|
self.inputfiles[0],
|
|
|
- tree.startpos['line'],
|
|
|
- tree.startpos['column'],
|
|
|
+ tree['startpos']['line'],
|
|
|
+ tree['startpos']['column'],
|
|
|
str(to_type), str(from_type),
|
|
|
cast_signature))
|
|
|
|
|
@@ -270,7 +274,7 @@ class SemanticsVisitor(Visitor):
|
|
|
self.visit(cast_tree)
|
|
|
except RuntimeError:
|
|
|
self.raise_implicit_cast_error(from_type, to_type, child)
|
|
|
- tree.replace_child(child, cast_tree)
|
|
|
+ Tree.replace_child(tree, child, cast_tree)
|
|
|
|
|
|
types = {
|
|
|
"Integer": "integer",
|
|
@@ -306,38 +310,38 @@ class SemanticsVisitor(Visitor):
|
|
|
def call_name_binary(operand_type, operator):
|
|
|
# String joins should also be possible
|
|
|
if str(operand_type) == "String":
|
|
|
- if operator.head == "PLUS":
|
|
|
+ if operator['head'] == "PLUS":
|
|
|
return "string_join"
|
|
|
|
|
|
- if operator.head == "EQ":
|
|
|
+ if operator['head'] == "EQ":
|
|
|
return "value_eq"
|
|
|
- elif operator.head == "NEQ":
|
|
|
+ elif operator['head'] == "NEQ":
|
|
|
return "value_neq"
|
|
|
|
|
|
call_name = "{}_{}".format(SemanticsVisitor.types[str(operand_type)],
|
|
|
- SemanticsVisitor.binary_ops[operator.head])
|
|
|
+ SemanticsVisitor.binary_ops[operator['head']])
|
|
|
return call_name
|
|
|
|
|
|
@staticmethod
|
|
|
def call_name_unary(operand_type, operator):
|
|
|
call_name = "{}_{}".format(SemanticsVisitor.types[str(operand_type)],
|
|
|
- SemanticsVisitor.unary_ops[operator.head])
|
|
|
+ SemanticsVisitor.unary_ops[operator['head']])
|
|
|
|
|
|
return call_name
|
|
|
|
|
|
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"
|
|
|
|
|
|
# a visit_* method for each non-terminal in the grammar
|
|
|
def visit_start(self, tree):
|
|
|
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)
|
|
|
- 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.inputfiles.pop()
|
|
|
self.symbol_table.close_scope()
|
|
@@ -350,22 +354,21 @@ class SemanticsVisitor(Visitor):
|
|
|
self.visit_vardecl(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:
|
|
|
self.symbol_table.add(symbol)
|
|
|
except Exception:
|
|
|
raise RuntimeError(
|
|
|
"{}:{}:{}: 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)
|
|
|
|
|
@@ -375,7 +378,7 @@ class SemanticsVisitor(Visitor):
|
|
|
|
|
|
def visit_expression(self, 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):
|
|
|
self.visit_children(tree)
|
|
@@ -383,7 +386,7 @@ class SemanticsVisitor(Visitor):
|
|
|
|
|
|
def visit_disjunction(self, 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)
|
|
|
else:
|
|
|
self.replace_child_binary_op_with_call(tree, 2)
|
|
@@ -392,7 +395,7 @@ class SemanticsVisitor(Visitor):
|
|
|
|
|
|
def visit_conjunction(self, 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)
|
|
|
else:
|
|
|
self.replace_child_binary_op_with_call(tree, 2)
|
|
@@ -401,7 +404,7 @@ class SemanticsVisitor(Visitor):
|
|
|
|
|
|
def visit_comparison(self, 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)
|
|
|
else:
|
|
|
self.replace_child_binary_op_with_call(tree, 2)
|
|
@@ -411,7 +414,7 @@ class SemanticsVisitor(Visitor):
|
|
|
|
|
|
def visit_relation(self, 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)
|
|
|
else:
|
|
|
self.replace_child_binary_op_with_call(tree, 2)
|
|
@@ -421,40 +424,40 @@ class SemanticsVisitor(Visitor):
|
|
|
|
|
|
def visit_sum(self, 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)
|
|
|
else:
|
|
|
self.replace_child_binary_op_with_call(tree, 2)
|
|
|
self.check_binary_ops_arithmetic(tree)
|
|
|
self.cast_binary_ops_arithmetic(tree)
|
|
|
# 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):
|
|
|
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:
|
|
|
self.check_binary_ops_arithmetic(tree)
|
|
|
self.cast_binary_ops_arithmetic(tree)
|
|
|
# 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):
|
|
|
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:
|
|
|
self.replace_child_unary_op_with_call(tree)
|
|
|
|
|
|
def visit_logical_not(self, tree):
|
|
|
self.visit_children(tree)
|
|
|
|
|
|
- l = tree.get_tail()[1]
|
|
|
+ l = Tree.get_tail(tree)[1]
|
|
|
l_type = self.get_type(l)
|
|
|
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):
|
|
|
self.visit_children(tree)
|
|
@@ -462,7 +465,7 @@ class SemanticsVisitor(Visitor):
|
|
|
self.check_unary_ops_arithmetic(tree, "minus")
|
|
|
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):
|
|
|
self.visit_children(tree)
|
|
@@ -470,19 +473,19 @@ class SemanticsVisitor(Visitor):
|
|
|
self.check_unary_ops_arithmetic(tree, "plus")
|
|
|
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):
|
|
|
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):
|
|
|
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):
|
|
|
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):
|
|
|
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
|
|
|
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...
|
|
|
try:
|
|
|
symbol = self.symbol_table.get(name)
|
|
|
except KeyError:
|
|
|
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_symbol(tree, symbol)
|
|
|
|
|
|
def visit_rvalue(self, tree):
|
|
|
- if len(tree.get_tail()) > 1:
|
|
|
+ if len(Tree.get_tail(tree)) > 1:
|
|
|
# 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"
|
|
|
call_tree = self.func_call(operation, [node, expression], 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))
|
|
|
else:
|
|
|
# Simple
|
|
@@ -535,7 +538,7 @@ class SemanticsVisitor(Visitor):
|
|
|
def visit_func_call(self, 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)
|
|
|
|
|
|
if not symbol.is_func():
|
|
@@ -549,18 +552,18 @@ class SemanticsVisitor(Visitor):
|
|
|
raise RuntimeError(
|
|
|
"{}:{}:{}: error: '{}' is a variable of type '{}', not a "
|
|
|
"function".format(self.inputfiles[0],
|
|
|
- tree.startpos['line'],
|
|
|
- tree.startpos['column'],
|
|
|
+ tree['startpos']['line'],
|
|
|
+ tree['startpos']['column'],
|
|
|
symbol.name,
|
|
|
symbol.type))
|
|
|
|
|
|
- expressions = tree.get_children("expression")
|
|
|
+ expressions = Tree.get_children(tree, "expression")
|
|
|
if len(expressions) != len(symbol.params):
|
|
|
raise RuntimeError(
|
|
|
"{}:{}:{}: error: wrong number of arguments to "
|
|
|
"function '{}'".format(self.inputfiles[0],
|
|
|
- tree.startpos['line'],
|
|
|
- tree.startpos['column'],
|
|
|
+ tree['startpos']['line'],
|
|
|
+ tree['startpos']['column'],
|
|
|
symbol.signature()))
|
|
|
|
|
|
"""
|
|
@@ -584,9 +587,9 @@ class SemanticsVisitor(Visitor):
|
|
|
"""
|
|
|
|
|
|
if symbol.name == "__input":
|
|
|
- tree.head = "input"
|
|
|
+ tree['head'] = "input"
|
|
|
elif symbol.name == "__output":
|
|
|
- tree.head = "output"
|
|
|
+ tree['head'] = "output"
|
|
|
|
|
|
def visit_input(self, tree):
|
|
|
pass # no need to visit it again
|
|
@@ -605,7 +608,7 @@ class SemanticsVisitor(Visitor):
|
|
|
|
|
|
def visit_ifelse(self, tree):
|
|
|
self.visit_children(tree)
|
|
|
- expressions = tree.get_children("expression")
|
|
|
+ expressions = Tree.get_children(tree, "expression")
|
|
|
for expression in expressions:
|
|
|
self.check_predicate(expression)
|
|
|
|
|
@@ -613,7 +616,7 @@ class SemanticsVisitor(Visitor):
|
|
|
self.while_counter += 1
|
|
|
self.visit_children(tree)
|
|
|
self.while_counter -= 1
|
|
|
- expression = tree.get_child("expression")
|
|
|
+ expression = Tree.get_child(tree, "expression")
|
|
|
self.check_predicate(expression)
|
|
|
|
|
|
def visit_block(self, tree):
|
|
@@ -627,7 +630,7 @@ class SemanticsVisitor(Visitor):
|
|
|
def visit_funcdecl(self, tree):
|
|
|
# here we only visit the body cause the declaration is already done
|
|
|
# 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.symbol_table.open_scope()
|
|
@@ -637,11 +640,11 @@ class SemanticsVisitor(Visitor):
|
|
|
self.current_funcdecl = None
|
|
|
|
|
|
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)
|
|
|
|
|
@@ -650,8 +653,8 @@ class SemanticsVisitor(Visitor):
|
|
|
except Exception:
|
|
|
raise RuntimeError(
|
|
|
"{}:{}:{}: 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)
|
|
|
|
|
@@ -666,12 +669,12 @@ class SemanticsVisitor(Visitor):
|
|
|
if self.while_counter == 0:
|
|
|
raise RuntimeError(
|
|
|
"{}:{}:{}: 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):
|
|
|
if self.while_counter == 0:
|
|
|
raise RuntimeError(
|
|
|
"{}:{}:{}: error: continue outside of while".format(
|
|
|
- self.inputfiles[0], tree.startpos['line'],
|
|
|
- tree.startpos['column']))
|
|
|
+ self.inputfiles[0], tree['startpos']['line'],
|
|
|
+ tree['startpos']['column']))
|