Пример #1
0
    def visit(self, node, scope: Scope):
        try:
            node_type = self.context.get_type(
                node.type) if node.type != "SELF_TYPE" else self.current_type
        except SemanticError as err:
            self.errors.append(err.text)
            node_type = [ErrorType()]
        self.check_id(node.id)
        if node.define and scope.is_local(node.id):
            var = scope.find_variable(node.id)
            var.type = self.all_pos_types(var.type)

        if node.expr:
            self.visit(node.expr, scope)
            expr_type = node.expr.computed_type
            node_type = self.all_pos_types(node_type)

            error_expr = expr_type.copy()
            error_type = node_type.copy()
            self.establish_conform(expr_type, node_type)
            if len(expr_type) * len(node_type) == 0:
                self.AddError(
                    f"Declaring Let Variable {node.id}. Incompatible types between possible declared types ("
                    + ", ".join([typex.name for typex in error_type]) +
                    ") and possible expression types (" +
                    ", ".join([typex.name for typex in error_expr]) + ")")
                node_type = [ErrorType()]

        node.computed_type = node_type
Пример #2
0
    def visit(self, node, scope):
        var = scope.find_variable(node.id)
        if node.define:
            var.type = self.all_pos_types(var.type)
            var_type = var.type
            self.visit(node.expr, scope)
            expr_type = node.expr.computed_type

            error_expr = expr_type.copy()
            error_type = var_type.copy()
            self.establish_conform(var_type, expr_type)
            if len(var_type) * len(expr_type) == 0:
                self.AddError(
                    f"Cant assign new value to {node.id}. Incompatible types between defined variable declared types ("
                    + ", ".join([typex.name for typex in error_type]) +
                    ") and possible expression types (" +
                    ", ".join([typex.name for typex in error_expr]) + ")")
                var_type = [ErrorType()]
            if var.name == 'self':
                self.AddError("Cant Assign:", SELF_IS_READONLY)
                var_type = [ErrorType()]
        else:
            self.AddError("Cant Assign:",
                          VARIABLE_NOT_DEFINED.replace('%s', node.id, 1))
            var_type = [ErrorType()]
        node.computed_type = var_type  #No es necesario hacerle un al pos
Пример #3
0
    def visit(self, node):
        self.current_type = self.context.get_type(node.id)

        if not node.parent is None:
            try:
                parent = self.context.get_type(node.parent)
                if parent in self.basic_types:
                    self.errors.append('Class ' + node.id +
                                       ' cant inherit from ' + parent.name)
                    parent = ErrorType()
                self.current_type.set_parent(parent)

                actual_type = self.current_type.parent
                while not actual_type is None:
                    if actual_type.parent == self.current_type:
                        self.errors.append('Circular dependency at class ' +
                                           node.id)
                        self.current_type.set_parent(ErrorType())
                    actual_type = actual_type.parent

            except SemanticError as error:
                self.errors.append(error.text)

        else:
            self.current_type.set_parent(self.context.get_type('Object'))

        for feature in node.features:
            self.visit(feature)
Пример #4
0
    def visit(self, node: IfDeclarationNode, scope: Scope):
        self.visit(node.ifexpr, scope)
        ifexpr_type = node.ifexpr.computed_type
        bool_type = self.context.get_type("Bool")
        if not ifexpr_type.conforms_to(bool_type):
            self.AddError(
                "If predicate is not Bool:",
                INCOMPATIBLE_TYPES.replace('%s', ifexpr_type.name,
                                           1).replace('%s', bool_type.name, 1))
            ifexpr_type = ErrorType()

        self.visit(node.thenexpr, scope)
        then_type = node.thenexpr.computed_type
        then_type = self.update_type(then_type)

        self.visit(node.elseexpr, scope)
        else_type = node.elseexpr.computed_type
        else_type = self.update_type(else_type)

        typex = else_type.least_common_ancestor(then_type)
        if typex == None:
            self.AddError(
                "The \"then\" and \"else\" expressions have different types with no common ancestor."
            )
            node.computed_type = ErrorType()
        else:
            node.computed_type = typex
Пример #5
0
    def visit(self, node, scope):
        try:
            node_type = self.context.get_type(
                node.type)  # if node.type != "SELF_TYPE" else SelfType()
        except SemanticError as err:
            self.errors.append(err.text)
            node_type = ErrorType()

        if scope.is_local(node.id):
            self.AddError(f"Declaring Variable \"{node.id}\":",
                          LOCAL_ALREADY_DEFINED.replace('%s', node.id, 1))
        else:
            scope.define_variable(node.id, node_type)

        if node.expr:
            self.visit(node.expr, scope)
            expr_type = node.expr.computed_type
            if not expr_type.conforms_to(node_type):
                self.AddError(
                    f"Declaring Variable \"{node.id}\":",
                    INCOMPATIBLE_TYPES.replace('%s', expr_type.name,
                                               1).replace(
                                                   '%s', node_type.name, 1))
                node_type = ErrorType()

        node.computed_type = node_type
Пример #6
0
    def establish_conform(self, expr, decl, *common_ancestors):
        if len(decl) == 0:
            decl = [ErrorType()]
        if len(expr) == 0:
            expr = [ErrorType()]

        if not common_ancestors:
            common_ancestors = self.get_common_ancestors(expr, decl)

        self.conform_list(decl, common_ancestors)
        self.conform_list(expr, common_ancestors, left_to_right=True)
Пример #7
0
 def visit(self, node, scope):
     var = scope.find_variable(node.id)
     if var:
         node.computed_type = self.update(node)
         var.type = node.computed_type
     else:
         node.computed_type = ErrorType()
         var.type = ErrorType()
     if node.expr:
         self.visit(node.expr, scope)
     self.log(f"Attribute Node {node.id} {node.computed_type.name}")
Пример #8
0
 def visit(self, node, scope):
     var = scope.find_variable(node.id)
     if var and node.define:
         node.computed_type = self.update(node)
         var.type = self.update_var(var.type)
     else:
         node.computed_type = ErrorType()
         var.type = ErrorType()
     self.log(f"Let Var Node {node.id}: {node.computed_type.name}")
     if node.expr:
         self.visit(node.expr, scope)
Пример #9
0
    def visit(self, node, scope):
        # Evaluate object
        obj_type = self.visit(node.obj, scope)

        # Check object type conforms to cast type
        cast_type = obj_type
        if node.type is not None:
            try:
                cast_type = self.context.get_type(node.type)
                if isinstance(cast_type, AutoType):
                    raise SemanticError(
                        'AUTO_TYPE can\'t be the type on this type of dispatch'
                    )
                if isinstance(cast_type, SelfType):
                    cast_type = SelfType(self.current_type)
            except SemanticError as ex:
                cast_type = ErrorType()
                self.errors.append(ex.text)
        if not self.check_conformance(obj_type, cast_type):
            self.errors.append(INCOMPATIBLE_TYPES %
                               (obj_type.name, cast_type.name))

        # if the obj that is calling the function is autotype, let it pass
        if isinstance(cast_type, AutoType):
            return cast_type

        if isinstance(cast_type, SelfType):
            cast_type = self.current_type

        # Check this function is defined for cast_type
        try:
            method = cast_type.get_method(node.id)
            if not len(node.args) == len(method.param_types):
                self.errors.append(INVALID_OPERATION %
                                   (method.name, cast_type.name))
                return ErrorType()
            for i, arg in enumerate(node.args):
                computed_type = self.visit(arg, scope)
                if not self.check_conformance(computed_type,
                                              method.param_types[i]):
                    self.errors.append(
                        INCOMPATIBLE_TYPES %
                        (computed_type.name, method.param_types[i].name))

            # check self_type
            rtype = method.return_type
            if isinstance(rtype, SelfType):
                rtype = obj_type

            return rtype

        except SemanticError as ex:
            self.errors.append(ex.text)
            return ErrorType()
Пример #10
0
    def visit(self, node, scope):
        var = scope.find_variable(node.lex)
        if var is None:
            node_row, node_col = node.token.location
            self.errors.append(
                NameError(
                    node_row, node_col, VARIABLE_NOT_DEFINED %
                    (node.lex, self.current_method.name)))
            return (ErrorType(),
                    cool_type_nodes.VariableNode(node.lex, ErrorType()))

        return (var.type, cool_type_nodes.VariableNode(node.lex, var.type))
Пример #11
0
 def update(self, node, strict=True):
     try:
         typex = node.computed_type
     except AttributeError:
         node.computed_type = ErrorType()
         return ErrorType()
     if isinstance(typex, Type):
         return typex
     if len(typex) == 0:
         return ErrorType()
     if strict:
         return self.find_lowest_ancestor(typex)
     return typex[-1]
Пример #12
0
    def visit(self, node):
        ## Building param-names and param-types of the method
        param_names = []
        param_types = []
        node.index = []
        for param in node.params:
            n, t = param
            node.index.append(None)

            # Checking param name can't be self
            if n == "self":
                self.errors.append(SELF_IS_READONLY)

            while True:
                if n in param_names:
                    n = f'1{n}'
                else:
                    param_names.append(n)
                    break

            try:
                t = self.context.get_type(t)
                if isinstance(t, SelfType):
                    t = SelfType(self.current_type)
                elif isinstance(t, AutoType):
                    node.index[-1] = self.manager.assign_id(self.obj_type)
            except SemanticError as ex:
                self.errors.append(ex.text)
                t = ErrorType()
            param_types.append(t)

        # Checking return type
        try:
            rtype = self.context.get_type(node.type)
            if isinstance(rtype, SelfType):
                rtype = SelfType(self.current_type)
        except SemanticError as ex:
            self.errors.append(ex.text)
            rtype = ErrorType()

        node.idx = self.manager.assign_id(self.obj_type) if isinstance(
            rtype, AutoType) else None

        # Defining the method in the current type. There can not be another method with the same name.
        try:
            self.current_type.define_method(node.id, param_names, param_types,
                                            rtype, node.index, node.idx)
        except SemanticError as ex:
            self.errors.append(ex.text)
Пример #13
0
    def visit(self, node, scope):
        int_type = self.context.get_type("Int")
        typex, exp_node = self.visit(node.expr, scope)

        if typex != int_type and not typex.name == "AUTO_TYPE":
            node_row, node_col = node.expr.token.location
            self.errors.append(
                TypeError(
                    node_row, node_col,
                    f"Expression after '~' must be Int, current is {typex.name}"
                ))
            return (ErrorType(),
                    cool_type_nodes.NegNode(exp_node, ErrorType()))

        return (int_type, cool_type_nodes.NegNode(exp_node, int_type))
Пример #14
0
    def visit(self, node, scope):
        bool_type = self.context.get_type("Bool")
        typex, exp_node = self.visit(node.expr, scope)

        if typex != bool_type and not typex.name == "AUTO_TYPE":
            line, col = node.expr.token.location
            self.errors.append(
                TypeError(
                    line, col,
                    f"Expression after 'not' must be Bool, current is {typex.name}"
                ))
            return (ErrorType(),
                    cool_type_nodes.NotNode(exp_node, ErrorType()))

        return (bool_type, cool_type_nodes.NotNode(exp_node, bool_type))
Пример #15
0
    def visit(self, node, scope, type_suggested=None):
        try:
            t, method = self.current_type.get_method(node.id)
        except SemanticError as error:
            self.errors.append(error.text)
            return ErrorType()

        call_args_types = [self.visit(arg, scope, None) for arg in node.args]
        method_args_types = [param_type for param_type in method.param_types]
        if not len(call_args_types) == len(method_args_types):
            self.errors.append(METHOD_NOT_DEFINED %
                               (node.id, self.current_type.name))
        else:
            for i in range(len(call_args_types)):
                if not call_args_types[i].conforms_to(method_args_types[i]):
                    self.errors.append(
                        INCOMPATIBLE_TYPES %
                        (call_args_types[i].name, method_args_types[i].name))

        ret_type = method.return_type
        if method.return_type.name == 'SELF_TYPE':
            ret_type = self.current_type
        else:
            if method.return_type == self.at:
                try:
                    ret_type = self.changed_methods[(method.name, t)]
                except KeyError:
                    pass

        return ret_type
Пример #16
0
    def visit(self, node):
        # Checking attribute type
        try:
            attr_type = self.context.get_type(node.type)
            if isinstance(attr_type, SelfType):
                attr_type = SelfType(self.current_type)
        except SemanticError as ex:
            self.errors.append(ex.text)
            attr_type = ErrorType()

        node.idx = self.manager.assign_id(self.obj_type) if isinstance(
            attr_type, AutoType) else None

        #Checking attribute can't be named self
        if node.id == "self":
            self.errors.append(SELF_IS_READONLY)

        # Checking attribute name. No other attribute can have the same name
        flag = False
        try:
            self.current_type.define_attribute(node.id, attr_type, node.idx)
            flag = True
        except SemanticError as ex:
            self.errors.append(ex.text)

        while not flag:
            node.id = f'1{node.id}'
            try:
                self.current_type.define_attribute(node.id, attr_type,
                                                   node.idx)
                flag = True
            except SemanticError:
                pass
Пример #17
0
def common_ancestor(type_list):

    visited = []

    actual_type = type_list[0]
    print(type_list)

    for t in type_list:
        if t.name == '<error>':
            return ErrorType()
        if not t.name == 'AUTO_TYPE':
            actual_type = t

    visited.append(actual_type)

    while not actual_type.parent is None:
        actual_type = actual_type.parent
        visited.append(actual_type)

    for t in visited:
        ok = True
        for types in type_list:
            if not types.conforms_to(t):
                ok = False
                break
        if ok:
            print(t.name)
            return t
Пример #18
0
    def visit(self, node, scopex: Scope):
        scope = scopex.next_child()
        self.current_method = self.current_type.get_method(node.id)
        self.current_method.return_type = self.all_pos_types(
            self.current_method.return_type)

        for i in range(len(self.current_method.param_names)):
            idx, typex = (self.current_method.param_names[i],
                          self.current_method.param_types[i])
            var = scope.find_variable(idx)
            var.type = self.all_pos_types(var.type)
            self.current_method.param_types[i] = var.type

        self.visit(node.body, scope)

        ret_type_expr = node.body.computed_type
        ret_type_decl = self.current_method.return_type

        error_type = ret_type_decl.copy()
        error_expr = ret_type_expr.copy()
        self.establish_conform(ret_type_expr, ret_type_decl)
        if len(ret_type_decl) * len(ret_type_expr) == 0:
            self.errors.append(
                f"Declaring Function {node.id} in class {self.current_type.name}: incompatible types between possible declared return types ("
                + ", ".join([typex.name for typex in error_type]) +
                ") and possible expression return types (" +
                ", ".join([typex.name for typex in error_expr]) + ")")
            node.computed_type = ErrorType()
        else:
            node.computed_type = ret_type_decl
        self.current_method = None
Пример #19
0
    def visit(self, node, scope: Scope):
        self.current_attrb = self.current_type.get_attribute(node.id)
        node_type = self.all_pos_types(self.current_attrb.type)

        if not node.expr:
            node.computed_type = node_type
            self.current_attrb = None
            return

        self.visit(node.expr, scope)
        expr_type = node.expr.computed_type

        error_type = node_type.copy()
        error_expr = expr_type.copy()

        self.establish_conform(expr_type, node_type)
        if len(expr_type) * len(node_type) == 0:
            self.errors.append(
                f"Declaring Attribute {node.id} in class {self.current_type.name}. Incompatible types between possible declared types ("
                + ", ".join([typex.name for typex in error_type]) +
                ") and possible expression types (" +
                ", ".join([typex.name for typex in error_expr]) + ")")
            node.computed_type = ErrorType()
        else:
            node.computed_type = node_type
        var = scope.find_variable(node.id)
        var.type = node.computed_type
        self.current_attrb = None
Пример #20
0
    def visit(self, node, scope):
        if node.id.lex == "self":
            node_row, node_col = node.token.location
            self.errors.append(
                SemanticError(node_row, node_col,
                              "Cannot assign to 'self'. " + SELF_IS_READONLY))
        var_type = None
        if not scope.is_defined(node.id.lex):
            node_row, node_col = node.id.location
            self.errors.append(
                NameError(
                    node_row, node_col, VARIABLE_NOT_DEFINED %
                    (node.id.lex, self.current_method.name)))
            var_type = ErrorType()
        else:
            var_type = scope.find_variable(node.id.lex).type

        expr_type, exp_node = self.visit(node.expr, scope)
        if not expr_type.conforms_to(var_type):
            node_row, node_col = node.token.location
            self.errors.append(
                TypeError(
                    node_row, node_col,
                    f"Inferred type {expr_type.name} of assigned expression does not conforms to type {var_type.name} of variable '{node.id.lex}'"
                ))

        return (expr_type,
                cool_type_nodes.AssignNode(node.id.lex, exp_node, expr_type))
Пример #21
0
    def visit(self, node, scope):
        if_inferred = node.ifexpr.inferenced_type
        self.visit(node.ifexpr, scope)
        ifexpr_type = self.update_type(node.ifexpr.inferenced_type)
        bool_type = self.context.get_type("Bool")
        if isinstance(ifexpr_type, AutoType):
            ifexpr_type.set_upper_limmit([bool_type])
        node.ifexpr.inferenced_type = self.compare_types(
            if_inferred, ifexpr_type)

        self.visit(node.thenexpr, scope)
        then_type = self.update_type(node.thenexpr.inferenced_type)

        self.visit(node.elseexpr, scope)
        else_type = self.update_type(node.elseexpr.inferenced_type)

        node_inferred = node.inferenced_type

        joined = join(then_type, else_type)
        if not isinstance(joined, ErrorType):
            type_sets, heads = joined
            auto = AutoType("IF", heads, type_sets)
        else:
            auto = ErrorType()

        if is_subset(auto, node_inferred):
            node.inferenced_type = self.compare_types(node_inferred, auto)
Пример #22
0
 def get_type(self, ntype, comp_error_mesg):
     try:
         return self.context.get_type(ntype.lex)
     except SError as error:
         node_row, node_col = ntype.location
         self.errors.append(TypeError(node_row, node_col, f"Type {ntype.lex} " + comp_error_mesg + " is not defined."))
         return ErrorType()
Пример #23
0
    def visit(self, node, scope):
        if node.id == "self":
            node_row, node_col = node.token.location
            self.errors.append(
                SemanticError(
                    node_row, node_col,
                    "'self' cannot be bound in a 'let' expression. " +
                    SELF_IS_READONLY))

        static_type = None
        try:
            static_type = self.context.get_type(node.type.lex)
            if static_type.name == "SELF_TYPE":
                static_type = self.current_type

        except SError as e:
            node_row, node_col = node.type.location
            self.errors.append(TypeError(node_row, node_col, e.text))
            static_type = ErrorType()

        if node.expr != None:
            typex, node_exp = self.visit(node.expr, scope)
            if not typex.conforms_to(static_type):
                line, col = node.expr.token.location
                self.errors.append(
                    TypeError(
                        line, col,
                        INCOMPATIBLE_TYPES % (typex.name, static_type.name)))
        else:
            node_exp = None

        scope.define_variable(node.id, static_type)
        return (static_type,
                cool_type_nodes.VarDeclarationNode(node.id, node.type.lex,
                                                   node_exp, static_type))
Пример #24
0
    def visit(self, node, scope):
        nscope = scope.create_child()

        node.idx_list = [None] * len(node.id_list)
        for i, item in enumerate(node.id_list):
            idx, typex, expr = item
            # create a new_scope for every variable defined
            new_scope = nscope.create_child()

            if idx == 'self':
                self.errors.append(SELF_IS_READONLY)
                idx = f'1{idx}'
                node.id_list[i] = (idx, typex, expr)

            try:
                typex = self.context.get_type(typex)
                if isinstance(typex, SelfType):
                    typex = SelfType(self.current_type)
            except SemanticError as ex:
                self.errors.append(ex.text)
                typex = ErrorType()

            if isinstance(typex, AutoType):
                node.idx_list[i] = self.manager.assign_id(self.obj_type)

            if expr is not None:
                expr_type = self.visit(expr, new_scope)
                if not self.check_conformance(expr_type, typex):
                    self.errors.append(INCOMPATIBLE_TYPES %
                                       (expr_type.name, typex.name))

            new_scope.define_variable(idx, typex, node.idx_list[i])
            nscope = new_scope

        return self.visit(node.body, nscope)
Пример #25
0
    def visit(self, node, scope, type_suggested=None):
        try:
            var_type = self.context.get_type(node.type)
        except SemanticError as error:
            self.errors.append(error.text)
            var_type = ErrorType()

        if scope.is_local(node.id):
            self.errors.append(LOCAL_ALREADY_DEFINED %
                               (node.id, self.current_method.name))
        else:
            scope.define_variable(node.id, var_type)

        if not node.expr is None:
            type_expr = self.visit(node.expr, scope, None)

            if not type_expr.conforms_to(var_type):
                self.errors.append(INCOMPATIBLE_TYPES %
                                   (type_expr.name, var_type.name))
            if type_expr == self.at and var_type == self.at:
                self.errors.append(AUTO_TYPE_ERROR % (node.id))
            if var_type == self.at and not type_expr == self.at:
                node.type = type_expr.name
                return type_expr

        return var_type
Пример #26
0
    def visit(self, node, scope):
        self.visit(node.left, scope)
        left_type = node.left.computed_type

        self.visit(node.right, scope)
        right_type = node.right.computed_type

        left_error = left_type.copy()
        right_error = right_type.copy()
        int_type = self.context.get_type("Int")
        self.conform_list(left_type, int_type)
        self.conform_list(right_type, int_type)
        if len(left_type) * len(right_type) == 0:
            s = "Performing Arithmetic Operation:"
            if not len(left_type):
                s += ("\n   -None of the left memeber possible values(" +
                      ",".join(typex.name
                               for typex in left_error) + ") conforms to Int")
            if not len(right_type):
                s += ("\n   -None of the right memeber possible values(" +
                      ",".join(typex.name
                               for typex in right_error) + ") conforms to Int")
            self.AddError(s)
            node_type = [ErrorType()]
        else:
            node_type = [int_type]

        node.computed_type = node_type
 def visit(self, node, scope):
     try:
         node_type = self.context.get_type(node.lex,
                                           selftype=False,
                                           autotype=False)
     except SemanticError as err:
         node_type = ErrorType()
     node.inferenced_type = node_type
Пример #28
0
 def visit(self, node, scope):
     if node.define:
         var = scope.find_variable(node.lex)
         var.type = self.all_pos_types(var.type)
         node.computed_type = var.type
     else:
         self.AddError(VARIABLE_NOT_DEFINED.replace('%s', node.lex, 1))
         node.computed_type = [ErrorType()]
Пример #29
0
 def visit(self, node, scope):
     try:
         node_type = self.context.get_type(
             node.lex) if node.lex != "SELF_TYPE" else SelfType()
     except SemanticError as err:
         self.AddError(f"Unable to instantiate:", err.text)
         node_type = ErrorType()
     node.computed_type = node_type
Пример #30
0
    def visit(self, node, scope):
        try:
            typex = self.context.get_type(node.lex.lex)
            if typex.name == "SELF_TYPE":
                return self.current_type
            return (typex,
                    cool_type_nodes.InstantiateNode(node.lex.lex, typex))

        except SError as error:
            node_row, node_col = node.lex.location
            self.errors.append(
                TypeError(
                    node_row, node_col,
                    f"Type {node.lex.lex} of 'new' expression is not defined.")
            )
            return (ErrorType(),
                    cool_type_nodes.InstantiateNode(node.lex.lex, ErrorType()))