예제 #1
0
    def __check_scope_and_type(self, _class):
        """
            Check scope and type for each class.

            If it's a method, goes recursively inside the body.

            When a scope is created?
            With a new block, let, case,

            OBS: Every attribute is private and every method is public.
        """

        for feature in _class.feature_list:
            _type = returned_type(feature, _class)

            if isAttribute(feature):
                value_type = get_expression_type(feature.body, _class,
                                                 self.scope)
                # Test if the attribute value type is the same as declared.
                if feature.type != value_type:
                    raise AttributeTypeError(feature, value_type)

                self.scope.add(feature.name, _type)

            elif isMethod(feature):
                self.scope.add(feature.name, _type)

                # Add arguments to scope. name:type
                for formal in feature.formal_list:
                    self.scope.add(formal[0], formal[1])

                self.__check_children(feature.body, _class)
예제 #2
0
    def __check_scope_and_type(self, _class):
        """
            Check scope and type for each class.

            If it's a method, goes recursively inside the body.

            When a scope is created?
            With a new block, let, case,

            OBS: Every attribute is private and every method is public.
        """

        for feature in _class.feature_list:
            _type = returned_type(feature, _class)

            if isAttribute(feature):
                value_type = get_expression_type(
                    feature.body, _class, self.scope
                )
                # Test if the attribute value type is the same as declared.
                if feature.type != value_type:
                    raise AttributeTypeError(feature, value_type)

                self.scope.add(feature.name, _type)

            elif isMethod(feature):
                self.scope.add(feature.name, _type)

                # Add arguments to scope. name:type
                for formal in feature.formal_list:
                    self.scope.add(formal[0], formal[1])

                self.__check_children(feature.body, _class)
예제 #3
0
    def __check_children(self, expression, _class):
        if isinstance(expression, Block):
            self.scope.new()

            for expr in expression.body:
                self.__check_children(expr, _class)

            self.scope.destroy()

        elif isinstance(expression, Dispatch):
            self.__check_children(expression.body, _class)

            # Get return type
            if expression.body == 'self':
                _class_name = _class.name
            else:
                try:
                    _class_name = expression.body.return_type
                except AttributeError:
                    # If the expression is an Object and there is no
                    # return_type variable, so, need get the type.
                    _class_name = get_expression_type(
                        expression.body, _class, self.scope
                    )

            # Get the whole class' structure
            _class_content = self.classes[_class_name]

            called_method = False

            # Parse the structure untill match the method name
            for feature in _class_content.feature_list:
                if isMethod(feature) and feature.name == expression.method:
                    called_method = True

                    if len(feature.formal_list) != len(expression.expr_list):
                        raise NumberOfArgumentError(feature.name, _class_name)

                    formals = zip(
                        feature.formal_list, expression.expr_list,
                    )

                    # Test if the arguments types are not equals
                    for feat, called in formals:
                        expression_type = get_expression_type(
                            called, _class, self.scope
                        )
                        # feat[0] is the name and feat[1] the type
                        if feat[1] != expression_type:
                            raise ArgumentTypeError(feature, _class_name)

                    # For default, the method returns the host class. SELF_TYPE
                    last_type = _class_name

                    feature_type = returned_type(feature, _class)

                    # If exists a body, means that exists one or more
                    # expressions inside the method.
                    if feature.body:
                        try:
                            # If have a Block, must look the last expression,
                            # because it is the type that will be returned.
                            last_expression = feature.body.body[-1]
                        except AttributeError:
                            last_expression = feature.body

                        last_type = get_expression_type(
                            last_expression, _class, self.scope
                        )

                    # If the returns types are not equals, raise an error
                    if feature_type != last_type:
                        raise ReturnedTypeError(
                            feature.name, _class_name, feature_type, last_type
                        )

            # If didn't match the method name...
            if not called_method:
                raise UndefinedMethodError(expression.method, _class_name)

        elif isinstance(expression, Let):
            self.scope.new()
            self.scope.add(expression.object, expression.type)

            # Test if the declared type is the same type as
            # the given value
            value_type = get_expression_type(
                expression.init, _class, self.scope
            )
            if expression.type != value_type:
                raise DeclaredTypeError(expression.type, value_type)

            self.__check_children(expression.body, _class)

            self.scope.destroy()

        elif isinstance(expression, While):
            self.__check_children(expression.predicate, _class)
            self.__check_children(expression.body, _class)
            # If the methods above did not raise an error, means that
            # the body's type is Int or an Object.
            # If is an Object and the root type is not a Bool,
            # must raise an error.
            self.__raise_if_not_bool(expression, _class, 'While')

        elif isinstance(expression, Lt) or isinstance(expression, Le):
            first_type, second_type = self.__get_params_types(
                expression, _class
            )

            if first_type != 'Int' or second_type != 'Int':
                raise TypeCheckError(first_type, second_type, _class)

        elif isinstance(expression, Eq):
            """
                The comparison = is a special case.
                If either <expr1> or <expr2> has static type Int, Bool,
                or String, then the other must have the same static type.
            """
            first_type, second_type = self.__get_params_types(
                expression, _class
            )
            types = ['String', 'Int', 'Bool']
            if first_type not in types or second_type not in types:
                raise EqualTypeCheckError(first_type, second_type, _class)

            if first_type != second_type:
                raise EqualCheckError(first_type, second_type, _class)

        elif any(isinstance(expression, X) for X in [Plus, Sub, Mult, Div]):
            """
                The static types of the two sub-expressions must be Int.

                Cool has only integer division.
            """
            first_type, second_type = self.__get_params_types(
                expression, _class
            )

            if first_type != 'Int' or second_type != 'Int':
                raise ArithmeticError(first_type, second_type, _class)

        elif isinstance(expression, Assign):
            self.__check_children(expression.body, _class)
            # If the method above did not raise an error, means that
            # the body type is Int. Just need to test name type now.
            name_type = get_expression_type(
                expression.name, _class, self.scope
            )

            if name_type != 'Int':
                raise AssignError(name_type, 'Int', _class)

        elif isinstance(expression, If):
            self.__check_children(expression.predicate, _class)
            self.__check_children(expression.then_body, _class)
            self.__check_children(expression.else_body, _class)
            # If the methods above did not raise an error, means that
            # the body type is Int or an Object.
            # If is an Object and the root type is not a Bool,
            # must raise an error.
            self.__raise_if_not_bool(expression, _class, 'If')
예제 #4
0
 def __get_methods(self, _class):
     return [i for i in _class.feature_list if isMethod(i)]
예제 #5
0
    def __check_children(self, expression, _class):
        if isinstance(expression, Block):
            self.scope.new()

            for expr in expression.body:
                self.__check_children(expr, _class)

            self.scope.destroy()

        elif isinstance(expression, Dispatch):
            self.__check_children(expression.body, _class)

            # Get return type
            if expression.body == 'self':
                _class_name = _class.name
            else:
                _class_name = expression.body.return_type

            # Get the whole class' structure
            _class_content = self.classes[_class_name]

            called_method = False

            # Parse the structure untill match the method name
            for feature in _class_content.feature_list:
                if isMethod(feature) and feature.name == expression.method:
                    called_method = True

                    if len(feature.formal_list) != len(expression.expr_list):
                        raise NumberOfArgumentError(feature.name, _class_name)

                    formals = zip(
                        feature.formal_list,
                        expression.expr_list,
                    )

                    # Test if the arguments types are not equals
                    for feat, called in formals:
                        expression_type = get_expression_type(
                            called, _class, self.scope)
                        # feat[0] is the name and feat[1] the type
                        if feat[1] != expression_type:
                            raise ArgumentTypeError(feature, _class_name)

                    # Test if the returns types are not equals
                    called_method_type = _class_name
                    feature_type = returned_type(feature, _class)

                    if feature_type != called_method_type:
                        raise ReturnedTypeError(feature.name, _class_name)

            # If didn't match the method name...
            if not called_method:
                raise UndefinedMethodError(expression.method, _class_name)

        elif isinstance(expression, Let):
            self.scope.new()
            self.scope.add(expression.object, expression.type)

            # Test if the declared type is the same type as
            # the given value
            value_type = get_expression_type(expression.init, _class,
                                             self.scope)
            if expression.type != value_type:
                raise DeclaredTypeError(expression.type, value_type)

            self.__check_children(expression.body, _class)

            self.scope.destroy()

        elif isinstance(expression, While):
            self.__check_children(expression.predicate, _class)
            self.__check_children(expression.body, _class)
            # If the methods above did not raise an error, means that
            # the body type is Int or an Object.
            # If is an Object and is not a Bool, must raise an error.
            self.__raise_if_not_bool(expression, _class, 'While')

        elif isinstance(expression, Lt) or isinstance(expression, Le):
            first_type, second_type = self.__get_params_types(
                expression, _class)

            if first_type != 'Int' or second_type != 'Int':
                raise TypeCheckError(first_type, second_type, _class)

        elif isinstance(expression, Eq):
            """
                The comparison = is a special case.
                If either <expr1> or <expr2> has static type Int, Bool,
                or String, then the other must have the same static type.
            """
            first_type, second_type = self.__get_params_types(
                expression, _class)
            types = ['String', 'Int', 'Bool']
            if first_type not in types or second_type not in types:
                raise EqualTypeCheckError(first_type, second_type, _class)

            if first_type != second_type:
                raise EqualCheckError(first_type, second_type, _class)

        elif any(isinstance(expression, X) for X in [Plus, Sub, Mult, Div]):
            """
                The static types of the two sub-expressions must be Int.

                Cool has only integer division.
            """
            first_type, second_type = self.__get_params_types(
                expression, _class)

            if first_type != 'Int' or second_type != 'Int':
                raise ArithmeticError(first_type, second_type, _class)

        elif isinstance(expression, Assign):
            self.__check_children(expression.body, _class)
            # If the method above did not raise an error, means that
            # the body type is Int. Just need to test name type now.
            name_type = get_expression_type(expression.name, _class,
                                            self.scope)

            if name_type != 'Int':
                raise AssignError(name_type, 'Int', _class)

        elif isinstance(expression, If):
            self.__check_children(expression.predicate, _class)
            self.__check_children(expression.then_body, _class)
            self.__check_children(expression.else_body, _class)
            # If the methods above did not raise an error, means that
            # the body type is Int or an Object.
            # If is an Object and is not a Bool, must raise an error.
            self.__raise_if_not_bool(expression, _class, 'If')
예제 #6
0
 def __get_methods(self, _class):
     return [i for i in _class.feature_list if isMethod(i)]