def visit(self, node):
     for i, x in enumerate(node.params):
         if x.id == 'self':
             er = SemanticError(PARAM_NAME_SELF)
             self.add_semantic_error(er, x.row, x.column)
         try:
             x.type = self.context.get_type(x.type,
                                            current_type=self.current_type)
         except SemanticError as er:
             er = TypeCoolError(UNDEFINED_PARAM_TYPE, x.type, x.id)
             x.type = ErrorType()
             self.add_semantic_error(er, x.row, x.column)
         if x.id in [n.id for n in node.params[:i]]:
             er = SemanticError(METHOD_REPEATED_ARGS_NAME, x.id)
             self.add_semantic_error(er, x.row, x.column)
     try:
         node.type = self.context.get_type(node.type,
                                           current_type=self.current_type)
     except SemanticError as er:
         er = TypeCoolError(UNDEFINED_RETURN_TYPE, node.type, node.id)
         node.type = ErrorType()
         self.add_semantic_error(er, node.type_row, node.type_column)
     try:
         method = self.current_type.define_method(
             node.id, [x.id for x in node.params],
             [x.type for x in node.params], node.type)
         method.node = node
     except SemanticError as er:
         self.add_semantic_error(er, node.row, node.column)
 def visit(self, node, scope):
     try:
         node.type = self.context.get_type(node.lex,
                                           current_type=self.current_type)
     except SemanticError as er:
         er = TypeCoolError(UNDEFINED_NEW_TYPE, node.lex)
         node.type = ErrorType()
         self.add_semantic_error(er, node.type_row, node.type_column)
 def visit(self, node, scope):
     if scope.is_defined(node.lex):
         var = scope.find_variable(node.lex)
         node.type = var.type
     else:
         node.type = ErrorType()
         er = NameCoolError(VARIABLE_NOT_DEFINED, node.lex)
         self.add_semantic_error(er, node.row, node.column)
 def visit(self, node):
     if node.id == 'self':
         er = SemanticError(ATTRIBUTE_NAME_SELF)
         node.type = ErrorType()
         self.add_semantic_error(er, node.row, node.column)
         return
     try:
         node.type = self.context.get_type(node.type,
                                           current_type=self.current_type)
     except SemanticError as er:
         er = TypeCoolError(ATTRIBUTE_TYPE_UNDEFINED, node.type, node.id)
         node.type = ErrorType()
         self.add_semantic_error(er, node.row, node.column)
     try:
         attribute = self.current_type.define_attribute(node.id, node.type)
         attribute.node = node
     except SemanticError as er:
         self.add_semantic_error(er, node.row, node.column)
    def visit(self, node: CheckNode, scope):
        if node.id == 'self':
            er = SemanticError(SELF_IS_READONLY)
            self.add_semantic_error(er, node.row, node.column)

        try:
            node.type = self.context.get_type(node.type,
                                              current_type=self.current_type)
        except SemanticError:
            er = TypeCoolError(UNDEFINED_CLASS_CASE_BRANCH, node.type)
            self.add_semantic_error(er, node.row, node.column)
            node.type = ErrorType()

        node.scope = scope.create_child()
        node.scope.define_variable(node.id, node.type)

        self.visit(node.expr, node.scope)
    def visit(self, node, scope):
        self.visit(node.left, scope)
        self.visit(node.right, scope)

        if not self.operator.operation_defined(node, node.left.type,
                                               node.right.type):
            node.type = ErrorType()
            operator = self.operator.get_operator(node)
            if operator == self.operator.get_operator(EqualNode(None, None)):
                er_message = INVALID_EQUAL_BASIC_TYPE_OPERATION
                er_args = ()
            else:
                er_message = INVALID_BINARY_OPERATION
                er_args = (operator, node.left.type.name, node.right.type.name)
            er = TypeCoolError(er_message, *er_args)
            self.add_semantic_error(er, node.row, node.column)
        else:
            node.type = self.operator.type_of_operation(
                node, node.left.type, node.right.type)
    def visit(self, node, scope):
        self.visit(node.member, scope)

        if not self.operator.operation_defined(node, node.member.type):
            node.type = ErrorType()
            node_operator = self.operator.get_operator(node)
            correct_types = self.operator.operations.get_valid_operators_of(
                node_operator)
            unary_correct_types = [x for x in correct_types if len(x) == 1]
            if len(unary_correct_types) == 0:
                correct_type_name = "No Type"
            else:
                correct_type_name = " or ".join(
                    [x[0].name for x in unary_correct_types])

            er = TypeCoolError(INVALID_UNARY_OPERATION, node_operator,
                               node.member.type.name, correct_type_name)
            if not isinstance(node.member.type, ErrorType):
                self.add_semantic_error(er, node.row, node.column)
        else:
            node.type = self.operator.type_of_operation(node, node.member.type)
    def visit(self, node, scope):
        # obj,id,args
        self.visit(node.obj, scope)
        for arg in node.args:
            self.visit(arg, scope)

        try:
            if node.at:
                node.at = self.context.get_type(node.at)
                if not node.obj.type.conforms_to(node.at, self.current_type):
                    er = TypeCoolError(STATIC_DISPATCH_INCOMPATIBLE_TYPES,
                                       node.obj.type.name, node.at.name)
                    self.add_semantic_error(er, node.obj.row, node.obj.column)
                dispatch_type = node.at
            else:
                dispatch_type = node.obj.type
            try:
                method = dispatch_type.get_method(node.id, len(node.args),
                                                  self.current_type)
                not_conform = [(x, y.type, name) for x, y, name in zip(
                    method.param_types, node.args, method.param_names)
                               if not y.type.conforms_to(x, self.current_type)]
                for x, y, name in not_conform:
                    er = TypeCoolError(INCOMPATIBLE_PARAMS_TYPES, method.name,
                                       y.name, name, x.name)
                    self.add_semantic_error(er, node.row, node.column)
                node.type = method.return_type if method.return_type.name != "SELF_TYPE" else node.obj.type
            except SemanticError as er:
                if not any(meth for meth, typex in dispatch_type.all_methods()
                           if meth.name == node.id):
                    raise AttributeCoolError(DISPATCH_UNDEFINED_METHOD,
                                             node.id)
                else:
                    raise SemanticError(DISPATCH_METHOD_WRONG_ARGS, node.id)

        except SemanticError as er:
            node.type = ErrorType()
            self.add_semantic_error(er, node.row, node.column)
    def visit(self, node, scope, let_variable=False):
        if node.id == 'self':
            if let_variable:
                err = SemanticError(LET_BOUND_SELF)
            else:
                err = SemanticError(SELF_IS_READONLY)
            self.add_semantic_error(err, node.row, node.column)

        try:
            node.type = self.context.get_type(node.type,
                                              current_type=self.current_type)
        except SemanticError as er:
            if let_variable:
                er = TypeCoolError(LET_BOUND_TYPE_NOT_DEFINED, node.type,
                                   node.id)
            node.type = ErrorType()
            self.add_semantic_error(er, node.row, node.column)
        if not node.expr and node.type.name != "AUTO_TYPE":
            node.expr = node.type.default
            node.expr.type = node.type  # if type is void then is not assigned in the visit else the type is overridden

        if scope.is_local(node.id):
            er = SemanticError(LOCAL_ALREADY_DEFINED, node.id,
                               self.current_method.name)
            self.add_semantic_error(er, node.row, node.column)
        else:
            scope.define_variable(node.id, node.type)

        if not node.expr and node.type.name == "AUTO_TYPE":
            return  # No default expr can be assing at this moment

        self.visit(node.expr, scope)

        if not node.expr.type.conforms_to(node.type, self.current_type):
            er = TypeCoolError(INCOMPATIBLE_TYPES, node.expr.type.name,
                               node.id, node.type.name)
            self.add_semantic_error(er, node.row, node.column)