Ejemplo n.º 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
Ejemplo n.º 2
0
 def visit(self, node, scope=None, type_suggested=None):
     self.changed = False
     self.errors = []
     scope = Scope()
     for declaration in node.declarations:
         self.visit(declaration, scope.create_child())
     return scope, self.errors
Ejemplo n.º 3
0
def defined_info(name: str, scope: Scope, only_local=True):
    if only_local and not scope.is_local(name):
        return f"<Variable \"{name}\" not defined locally>"
    var = scope.find_variable(name)
    if not only_local and not var:
        return f"<Variable \"{name}\" not defined>"
    try:
        return f"{var.name}:{var.type.name}"
    except AttributeError:
        return f"<Error while accessing Variable \"{var.name}\" type: \"{var.type}\">"
Ejemplo n.º 4
0
    def visit(self, node):
        scope = Scope()
        self.context = copy.copy(node.context)

        #visit classes in order (from tree root to leaves)
        parent_children_dict = {}
        initial_nodes = []
        visited = {}
        self.class_to_visit = []
        self.class_visited = {}
        for declaration in node.declarations:
            try:
                visited[declaration.id.lex]  # checking if visited
            except:
                visited[declaration.id.lex] = True
                self.class_visited[declaration.id.lex] = False
                self.class_to_visit.append(declaration)
                if declaration.parent is None or declaration.parent.lex in [
                        "IO", "Int", "String", "Bool"
                ]:  # is node has no parent, mark it to visit it first later
                    initial_nodes.append(declaration)
                else:
                    try:
                        self.context.get_type(declaration.parent.lex)
                        try:
                            parent_children_dict[
                                declaration.parent.lex].append(declaration)
                        except:
                            parent_children_dict[declaration.parent.lex] = [
                                declaration
                            ]
                    except:  # add declarations where parent is not defined
                        initial_nodes.append(declaration)

        # initialize a list for classDeclNodes of typed ast
        self.tast_class_nodes = []

        for declaration in initial_nodes:  # first visit root nodes
            self.visit(declaration, scope.create_child(), parent_children_dict)

        while self.class_to_visit:  # visiting classes involved in ciclyc heritage
            declaration = self.class_to_visit[0]
            self.visit(declaration, scope.create_child(), parent_children_dict)

        program_node = (scope,
                        cool_type_nodes.ProgramNode(self.tast_class_nodes,
                                                    copy.copy(self.context)))

        self.context = None
        self.current_type = None
        self.current_method = None

        return program_node
Ejemplo n.º 5
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
Ejemplo n.º 6
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
Ejemplo n.º 7
0
    def visit(self, node, scopex: Scope()):
        scope: Scope = scopex.next_child()
        self.current_method = self.current_type.get_method(node.id)
        for idx, typex in zip(self.current_method.param_names,
                              self.current_method.param_types):
            var = scope.find_variable(idx)
            var.type = self.compare_types(var.type, typex)

        decl_inferred = node.inferenced_type
        expr_inferred = node.body.inferenced_type
        ret_type_decl = self.update_type(self.current_method.return_type)
        self.visit(node.body, scope)
        ret_type_expr = self.update_type(node.body.inferenced_type)
        conforms(ret_type_expr, ret_type_decl)

        print("Comapring inferenced type in FuncDecl")
        node.inferenced_type = self.compare_types(decl_inferred, ret_type_decl)
        print("Comapring Body inferenced type in FuncDecl")
        node.body.inferenced_type = self.compare_types(expr_inferred,
                                                       ret_type_expr)

        if isinstance(self.current_method.return_type, AutoType):
            auto_return = self.current_method.return_type
            ret_type_decl = conforms(ret_type_decl, ret_type_expr)
            print("Comapring inferenced type in FuncDecl Once Agagin")
            node.inferenced_type = self.compare_types(decl_inferred,
                                                      ret_type_decl)
            if is_subset(ret_type_decl, auto_return):
                self.current_method.return_type = ret_type_decl
        self.current_method = None
Ejemplo n.º 8
0
    def visit(self, node, scope: Scope):
        self.current_method = self.current_type.get_method(node.id)

        for idx, typex in zip(self.current_method.param_names,
                              self.current_method.param_types):
            scope.define_variable(idx, typex)

        self.visit(node.body, scope)

        ret_type_decl = self.update_type(self.current_method.return_type)
        ret_type_expr = self.update_type(node.body.computed_type)
        if not ret_type_expr.conforms_to(ret_type_decl):
            self.AddError(
                "Incompatible Return Types",
                INCOMPATIBLE_TYPES.replace('%s', ret_type_decl.name,
                                           1).replace('%s', ret_type_expr.name,
                                                      1))

        self.current_method = None
Ejemplo n.º 9
0
 def visit(self, node, scope: Scope, tabs=0):
     extra = computed_info(node)
     header = '\t' * tabs + f'\\__CaseDeclarationNode: case <expr> of ( <var> => <expr> ...){extra}\n'
     caseexpr = self.visit(node.expr, scope, tabs + 1)
     case = '\t' * (tabs + 1) + f'case:\n{caseexpr}\n'
     casevars = '\n'.join(
         self.visit(child, scope.next_child(), tabs + 1)
         for child in node.casevars)
     of = '\t' * (tabs + 1) + f'of:\n{casevars}'
     return header + case + of
    def visit(self, node, scope: Scope):
        self.visit(node.expr, scope)
        self.update_type(node.expr.inferenced_type)

        type_list = []
        for var in node.casevars:
            child = scope.create_child()
            self.visit(var, child)
            type_list.append(var.inferenced_type)

        node_type = join_list(type_list)
        node.inferenced_type = node_type
Ejemplo n.º 11
0
    def visit(self, node, scope: Scope):
        self.visit(node.expr, scope)

        var_types = []
        for var in node.casevars:
            child = scope.next_child()
            self.visit(var, child)
            var_types.append(var.inferenced_type)

        node_inferred = node.inferenced_type
        auto = join_list(var_types)
        if is_subset(auto, node_inferred):
            node.inferenced_type = self.compare_types(node_inferred, auto)
Ejemplo n.º 12
0
    def visit(self, node, scope: Scope):
        if node.define:
            node_type = scope.find_variable(node.id).type
        else:
            node_type = ErrorType()

        if node.expr:
            expr_inferr = node.expr.inferenced_type
            self.visit(node.expr, scope)
            expr_type = self.update_type(node.expr.inferenced_type)
            expr_type = conforms(expr_type, node_type)
            node.expr.inferenced_type = self.compare_types(
                expr_inferr, expr_type)

        node.inferenced_type = self.compare_types(node.inferenced_type,
                                                  node_type)
    def visit(self, node, scope: Scope):
        var = scope.find_variable(node.id)
        if not var:
            node.define = False
            var_type = ErrorType()
        else:
            node.define = True
            var_type = var.type

        self.visit(node.expr, scope)
        node_expr = self.update_type(node.expr.inferenced_type)

        if var and var.name != "self":
            node_expr = conforms(node_expr, var_type)
            node.expr.inferenced_type = node_expr
            if isinstance(var_type, AutoType):
                var_type = conforms(var_type, node_expr)
                var.type = var_type

        node.inferenced_type = var_type
Ejemplo n.º 14
0
    def visit(self, node: CaseDeclarationNode, scope: Scope):
        self.visit(node.expr, scope)
        case_expr_type = node.expr.computed_type if not isinstance(
            node.expr.computed_type, SelfType) else self.current_type
        if isinstance(case_expr_type, VoidType):
            self.AddError(f"Case expression evaluated void.")
            case_expr_type = ErrorType()

        var_names = set()
        general_type = None
        found = False
        for var in node.casevars:
            child = scope.create_child()
            self.visit(var, child)
            var_type = var.computed_type
            if var_type.name in var_names:
                self.AddError(
                    f"Equal types of \"{var_type.name}\" detected on case expression."
                )
            else:
                var_names.add(var.computed_type.name)

            try:
                general_type = general_type.least_common_ancestor(
                    var_type) if general_type else var_type
            except SemanticError as err:
                self.AddError(
                    f"In Case Expression, in branch \"{var.id}:{var.type}\":",
                    err.text)

            if not found and case_expr_type.conforms_to(var.computed_type):
                found = True

        if not found:
            self.AddError(
                f"No branch conforms to Case Expresion Type \"{case_expr_type.name}\""
            )
            node.computed_type = ErrorType()
        else:
            node.computed_type = general_type
Ejemplo n.º 15
0
    def visit(self, node: CaseDeclarationNode, scope: Scope):
        self.visit(node.expr, scope)
        case_expr_type = node.expr.computed_type
        if isinstance(case_expr_type,
                      VoidType):  #arreglar esto case expr es ahora una lista
            self.AddError(f"Case expression evaluated void.")
            case_expr_type = [ErrorType()]
            node.expr.computed_type = case_expr_type

        var_types = set()
        found = False
        for case_var in node.casevars:
            child = scope.next_child()
            self.visit(case_var, child)
            var = child.find_variable(case_var.id)
            var.type = self.all_pos_types(var.type)
            var_type = var.type
            if var_type[0] in var_types:
                self.AddError(
                    f"Equal types of \"{var_type.name}\" detected on case expression."
                )
            else:
                assert len(var_type) == 1, "Var type mayor que 1 big oof"
                var_types.add(var_type[0])

        for typex in var_types:
            for expr in case_expr_type:
                if expr.conforms_to(typex):
                    found = True
                    break
            if found:
                break
        else:
            self.AddError(f"No branch(" + ",".join(typex.name
                                                   for typex in var_types) +
                          ") conforms to possible Case Expresion types: " +
                          ", ".join([typex.name for typex in case_expr_type]))
            node.computed_type = [ErrorType()]
            return
        node.computed_type = self.all_pos_types(node.inferenced_type)
Ejemplo n.º 16
0
    def visit(self, node, scope: Scope):
        self.current_attrb = self.current_type.get_attribute(node.id)
        node_type = self.update_type(self.context.get_type(node.type))

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

        self.visit(node.expr, scope)
        expr_type = self.update_type(node.expr.computed_type)
        if not expr_type.conforms_to(node_type):
            self.errors.append(
                "Declaring Attribute:",
                INCOMPATIBLE_TYPES.replace('%s', expr_type.name,
                                           1).replace('%s', node_type.name, 1))
            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
Ejemplo n.º 17
0
    def visit(self, node, scope: Scope):
        if not node.define:
            var = None
            var_type = ErrorType()
        else:
            var = scope.find_variable(node.id)
            var_type = var.type

        expr_inferred = node.expr.inferenced_type
        self.visit(node.expr, scope)
        node_expr = self.update_type(node.expr.inferenced_type)

        if node.define:
            node_expr = conforms(node_expr, var_type)
            node.expr.inferenced_type = self.compare_types(
                expr_inferred, node_expr)
            if isinstance(var_type, AutoType):
                var_type = conforms(var_type, node_expr)
                var.type = self.compare_types(var.type, var_type)

        node.inferenced_type = self.compare_types(node.inferenced_type,
                                                  var_type)
Ejemplo n.º 18
0
 def visit(self, node, scope=None):
     scope = Scope()
     for declaration in node.declarations:
         self.visit(declaration, scope.create_child())
     return scope
Ejemplo n.º 19
0
 def visit(self, node: LetDeclarationNode, scopex: Scope):
     scope = scopex.create_child()
     for var in node.letvars:
         self.visit(var, scope)
     self.visit(node.expr, scope)
     node.computed_type = node.expr.computed_type
    def visit(self, node: ProgramNode) -> Scope:
        scope = Scope()
        for declaration in node.declarations:
            self.visit(declaration, scope.create_child())

        return scope
Ejemplo n.º 21
0
    def visit(self, node, scope: Scope):
        for declaration in node.declarations:
            self.visit(declaration, scope.next_child())

        scope.reset()
Ejemplo n.º 22
0
 def visit(self, node, scope: Scope, tabs=0):
     ans = '\t' * tabs + f'\\__ProgramNode [<class> ... <class>]'
     statements = '\n'.join(
         self.visit(child, scope.next_child(), tabs + 1)
         for child in node.declarations)
     return f'{ans}\n{statements}'
Ejemplo n.º 23
0
 def visit(self, node: ProgramNode, scope: Scope):
     self.types_updated = False
     for declaration in node.declarations:
         self.visit(declaration, scope.next_child())
     scope.reset()
     return self.types_updated