def visit(self, node: AttrDeclarationNode, scope: Scope, set_type=None):
        # print('attr declaration')
        if node.id == "self":
            self.errors.append(SEMANTIC_ERROR % (
                node.lineno, node.colno,
                f'"self" is used as attribute name in class "{self.current_type.name}".'
            ))
            if node.val is not None:
                self.visit(node.val, scope)
            return
        var, _ = scope.my_find_var(node.id)
        attr_type = self.context.get_type(node.type)
        if var is not None:
            self.errors.append(ATTR_ALREADY_DEFINED %
                               (node.lineno, node.colno, node.id))
        else:
            scope.define_variable(node.id, attr_type)

        if node.val is not None:
            return_type = self.visit(node.val, scope)
        else:
            return_type = attr_type

        if attr_type.name == BasicTypes.SELF.value:
            attr_type = self.current_type
        if return_type.name == BasicTypes.SELF.value:
            return_type = self.current_type
        if not return_type.conforms_to(attr_type):
            self.errors.append(
                INCOMPATIBLE_TYPES %
                (node.lineno, node.colno, return_type.name, attr_type.name))
Exemple #2
0
    def visit(self, node, scope=None):
        scope = Scope()
        self.current_function = self.register_function('main')
        instance = self.define_internal_local(scope=scope, name="instance")
        result = self.define_internal_local(scope=scope, name="result")
        self.register_instruction(CIL_AST.Allocate('Main', self.context.get_type('Main').tag, instance))
        self.register_instruction(CIL_AST.Call(result, 'Main_init', [CIL_AST.Arg(instance)], "Main"))
        self.register_instruction(
            CIL_AST.Call(result, self.to_function_name('main', 'Main'), [CIL_AST.Arg(instance)], "Main"))
        self.register_instruction(CIL_AST.Return(None))
        self.current_function = None

        self.register_data('Abort called from class ')
        self.register_data('\n')
        self.dotdata['empty_str'] = ''

        # Add built-in types in .TYPES section
        self.register_builtin_types(scope)

        # Add string equals function
        self.build_string_equals_function(scope)

        for klass in node.declarations:
            self.visit(klass, scope.create_child())

        return CIL_AST.Program(self.dottypes, self.dotdata, self.dotcode)
    def visit(self, node, scope):
        token = self.visit(node.obj, scope)

        if isinstance(token, VoidPod):
            raise RuntimeException(
                'Reference to an instance of a void object.')

        _o = self.context.get_type('Object')
        _s = self.context.get_type('String')
        _io = self.context.get_type('IO')

        if token.type.conforms_to(_o) and (_o.name,
                                           node.method) in cl_baseline:
            args = (token, ) + tuple(
                self.visit(arg, scope) for arg in node.args) + (self.context, )
            return cl_baseline[_o.name, node.method](*args)

        if token.type.conforms_to(_s) and (_s.name,
                                           node.method) in cl_baseline:
            args = (token, ) + tuple(
                self.visit(arg, scope) for arg in node.args) + (self.context, )
            return cl_baseline[_s.name, node.method](*args)

        if token.type.conforms_to(_io) and (_io.name,
                                            node.method) in cl_baseline:
            args = (token, ) + tuple(
                self.visit(arg, scope) for arg in node.args) + (self.context, )
            return cl_baseline[_io.name, node.method](*args)

        #si es una instantiate.f() meter en el scope hijo todos sus atributos
        _funcCall_scope = Scope()
        #para el caso [email protected]()
        if not node.parent is None:
            parent_t = self.context.get_type(node.parent)
            method = parent_t.get_method(node.method, parent_t, False)
        else:
            method = token.get_method(node.method, self.currentType, False)

        for _id, _t, _arg in zip(method.param_names, method.param_types,
                                 node.args):
            _funcCall_scope.define_variable(_id, _t).token = self.visit(
                _arg, scope)

        _funcCall_scope.define_variable('self', token.type).token = token

        self.stack.append(self.currentPod)
        self.currentPod = token

        result = self.visit(method.expr, _funcCall_scope)

        self.currentPod = self.stack.pop()
        return result
Exemple #4
0
    def visit(self, node, scope=None):
        if scope is None:
            scope = Scope()

        for declaration in node.declarations:
            current = self.context.get_type(declaration.id)
            parent = current.parent
            while parent is not None:
                current.depth += 1
                parent = parent.parent

        for declaration in node.declarations:
            self.visit(declaration, scope.create_child())

        return scope
 def visit(self, node, scope=None, set_type=None):
     to_revisit = []
     scope = Scope(self.scope_id)
     self.scope_id += 1
     for declaration in node.declarations:
         child_scope = scope.create_child(self.scope_id)
         self.scope_id += 1
         visited = self.visit(declaration, child_scope)
         if not visited:
             to_revisit.append(declaration)
     while to_revisit:
         declaration = to_revisit.pop(0)
         visited = self.visit(declaration, None)
         if not visited:
             to_revisit.append(declaration)
     return scope
    def visit(self, node: BranchNode, scope: Scope, types_used,
              return_of_case):
        error_type = self.context.get_type(BasicTypes.ERROR.value)
        try:
            var_type = self.context.get_type(node.type)
        except SemanticError as error:
            self.errors.append(TYPE_ERROR %
                               (node.lineno, node.colno, error.text))
            var_type = error_type

        if var_type.name != BasicTypes.ERROR.value:
            if var_type.name in types_used:
                self.errors.append(SEMANTIC_ERROR % (
                    node.lineno, node.colno,
                    f'In method "{self.current_method.name}", type "{self.current_type.name}", more than one '
                    f'branch variable has type "{var_type.name}". '))
            types_used.add(var_type.name)

        self.scope_id += 1
        child_scope = scope.create_child(self.scope_id)
        if node.id == "self":
            self.errors.append(TYPE_ERROR % (
                node.lineno, node.colno,
                f'In method "{self.current_method.name}", type "{self.current_type.name}", a branch has "self" as '
                f"variable name. "))
        else:
            child_scope.define_variable(node.id, var_type)

        expr_type = self.visit(node.action, child_scope)

        if return_of_case is None:
            return_of_case = expr_type
        return_of_case = self.context.find_first_common_ancestor(
            expr_type, return_of_case)
        return return_of_case
 def visit(self, node, scope: Scope, set_type=None):
     # print('variable')
     var, scope_id = scope.my_find_var(node.lex)
     if var is None:
         self.errors.append(
             VARIABLE_NOT_DEFINED %
             (node.lineno, node.colno, node.lex, self.current_method.name))
         error_type = self.context.get_type(BasicTypes.ERROR.value)
         return error_type
     else:
         node.computed_type = var.type
         return var.type
def test_execution(program_file: str, debug: bool = False):
    program = read_file(program_file)

    context = Context()
    errors = []

    ast = parse(program, debug)
    if ast is None:
        # error en el lexer o en el parser
        #
        errors.append('Syntactic Errors')
    else:
        TypeCollector(context, errors).visit(ast)
        TypeBuilder(context, errors).visit(ast)
        # CyclicDependency(context, errors)
        if not errors:
            InferenceTypeChecker(context, errors).visit(ast, Scope())
            print(CodeBuilder().visit(ast, 0))
            Execution(context).visit(ast, Scope())
        else:
            print('\n'.join(errors))
Exemple #9
0
 def __init__(self, program, lexer, parser, verbose=False):
     self.context: Context = Context()
     self.scope: Scope = Scope()
     self.program = program
     self.parser = parser
     self.lexer = lexer
     self.ast = self.parser.parse(self.lexer, self.program)
     self.errors = self.lexer.errors + self.parser.errors
     
     if len(self.errors) != 0:
         return
     
     if self.ast is None:
         return
             
     self.depicter = Depicter()
     if verbose:
         print(self.depicter.visit(self.ast, 0), '\n')
         print()
     
     self.typeCollector = TypeCollector(self.context, self.errors)
     self.typeCollector.visit(self.ast)
     if len(self.errors) == 0:
         self.typeBuilder = TypeBuilder(self.context, self.errors)
         self.typeBuilder.visit(self.ast)
         scope = Scope()
         if len(self.errors) == 0:
             self.typeChecker = TypeChecker(self.context, self.errors)
             self.typeChecker.visit( self.ast, scope)
             if len(self.errors) == 0:
                 self.coolToCil = COOLToCILVisitor(self.context)
                 cil_ast = self.coolToCil.visit(self.ast, scope)
                 
                 self.cilToMips = CILToMipsVisitor()
                 self.mipsCode = self.cilToMips.visit(cil_ast)
     return
def check_semantics(program: str, debug: bool = False):
    context = Context()
    scope = Scope()
    errors = []

    ast = parse(program, debug)
    if parser.errorok:
        errors = ['Syntactic Error']
    else:
        TypeCollector(context, errors).visit(ast)
        TypeBuilder(context, errors).visit(ast)
        # CyclicDependency(context, errors)
        if not errors:
            TypeChecker(context, errors).visit(ast, scope)

    return ast, errors, context, scope
 def visit(self, node, scope: Scope, set_type=None):
     # print('assign')
     error_type = self.context.get_type(BasicTypes.ERROR.value)
     if node.id == "self":
         self.errors.append(
             SEMANTIC_ERROR %
             (node.lineno, node.colno, f'"self" variable is read-only'))
         expr_type = self.visit(node.expr, scope)
         return expr_type
     var, scope_id = scope.my_find_var(node.id)
     if var is None:
         self.errors.append(
             VARIABLE_NOT_DEFINED %
             (node.lineno, node.colno, node.id, self.current_method.name))
         var_type = error_type
     else:
         var_type = var.type
     expr_type = self.visit(node.expr, scope)
     if not expr_type.conforms_to(var_type):
         self.errors.append(
             INCOMPATIBLE_TYPES %
             (node.lineno, node.colno, expr_type.name, var_type.name))
     node.computed_type = expr_type
     return expr_type
def final_execution(program_file, program_file_out, debug: bool = False, verbose=False):
    context = Context()
    scope = Scope()
    
    errors, program, tokens = tokenize(program_file, debug, verbose)


    if errors or lexer_errors:
        for (_, line, lexpos, value) in lexer_errors:
            totallines = program.count('\n')
            col = get_tokencolumn(program, lexpos) if get_tokencolumn(program, lexpos) > 1 else 2
            print_errors(f'({line}, {col - 1}) - LexicographicError: ERROR \"{value}\"')
        for e in errors:
            print_errors(e)
        exit(1)

    ast = parse(program, debug=debug)

    # if it has no instructions
    if ast is None and not parser_errors:
        print_errors("(0, 0) - SyntacticError: ERROR at or near EOF")
        exit(1)

    if parser_errors:  
        for (line, lexpos, _, value) in parser_errors:
            totallines = program.count('\n')
            col = get_tokencolumn(program, lexpos) if get_tokencolumn(program, lexpos) > 1 else 2
            print_errors(f'({line - totallines}, {col-1}) - SyntacticError: ERROR at or near "{value}"')
        exit(1)

    else:
        PositionateTokensInAST(tokens).visit(ast)
        TypeCollector(context, errors, program).visit(ast)
        if errors:
            for item in errors:
                print_errors(item)
            exit(1)
        TypeBuilder(context, errors, program).visit(ast)
        cyclicDependency(context, errors, program, ast)
        if errors:
            for item in errors:
                print_errors(item)
            exit(1)
        TypeBuilderFeature(context, errors, program).visit(ast)
        if errors:
            for item in errors:
                print_errors(item)
            exit(1)
        # CyclicDependency(context, errors)
        MethodChecker(context, errors, program).visit(ast)
        InferenceTypeChecker(context, errors, program).visit(ast, scope)

        TypeChecker(context, errors, program).visit(ast, scope)
        
        if errors:
            for item in errors:
                print_errors(item)
            exit(1)

        ### code generation ###  
        
        dict_attr, dict_method = {}, {}
        CollectDeclarationsDict(dict_attr, dict_method, context).visit(ast)
        get_declarations_dict(dict_attr, dict_method)
        
        COOLToCILVisitor(context).visit(ast,scope)