Пример #1
0
    def visit(self, node: ast.MethodDeclarationNode, scope: Scope):
        self.current_method = self.current_type.get_method(node.id)

        # Parameters can hide the attribute declaration, that's why we are not checking if there is defined,
        # instead we are checking for local declaration. Also it is checked that the static type of a parameter is
        # different of SELF_TYPE.

        scope.define_variable('self', self.current_type)

        for param_name, param_type in zip(self.current_method.param_names,
                                          self.current_method.param_types):
            if not scope.is_local(param_name):
                if param_type.name == 'SELF_TYPE':
                    self.errors.append(err.INVALID_PARAM_TYPE % 'SELF_TYPE')
                    scope.define_variable(param_name, ErrorType())
                else:
                    scope.define_variable(
                        param_name, self.context.get_type(param_type.name))
            else:
                self.errors.append(err.LOCAL_ALREADY_DEFINED %
                                   (param_name, self.current_method.name))

        return_type = self.context.get_type(
            node.return_type
        ) if node.return_type != 'SELF_TYPE' else self.current_type

        expr_type = self.visit(node.body, scope)

        if not expr_type.conforms_to(return_type):
            self.errors.append(err.INCOMPATIBLE_TYPES %
                               (expr_type.name, return_type.name))
Пример #2
0
    def visit(self, node: ast.LetNode, scope: Scope):
        for _id, _type, _expr in node.declarations:
            try:
                var_static_type = self.context.get_type(
                    _type) if _type != 'SELF_TYPE' else self.current_type
            except SemanticError as e:
                self.errors.append(e.text)
                var_static_type = ErrorType()

            if scope.is_local(_id):
                self.errors.append(err.LOCAL_ALREADY_DEFINED %
                                   (_id, self.current_method.name))
            else:
                scope.define_variable(_id, var_static_type)

            expr_type = self.visit(
                _expr, scope.create_child()) if _expr is not None else None
            if expr_type is not None and not expr_type.conforms_to(
                    var_static_type):
                self.errors.append(err.INCOMPATIBLE_TYPES %
                                   (expr_type.name, var_static_type.name))

        return self.visit(node.expr, scope.create_child())