Exemplo n.º 1
0
    def visit_funcdecl(self, node):
        func_name = node.name
        func_type = self.search_scopes(node.return_type.value)

        if self.search_scopes(func_name) is not None:
            error('file={} line={}: Cannot redefine a declared function: {}'.
                  format(self.file_name, node.line_num, func_name))

        if func_type and func_type.name == FUNC:
            func_type.func = FuncSymbol(
                ANON, self.visit(node.return_type.func_ret_type),
                node.parameters, node.body, node.parameter_defaults)

        self.define(
            func_name,
            FuncSymbol(func_name, func_type, node.parameters, node.body,
                       node.parameter_defaults))
        self.new_scope()
        if node.varargs:
            varargs_type = self.search_scopes(LIST)
            varargs_type.type = node.varargs[1].value
            varargs = CollectionSymbol(
                node.varargs[0], varargs_type,
                self.search_scopes(node.varargs[1].value))
            varargs.val_assigned = True
            self.define(varargs.name, varargs)
        for k, v in node.parameters.items():
            var_type = self.search_scopes(v.value)
            if var_type is self.search_scopes(FUNC):
                sym = FuncSymbol(k, v.func_ret_type, v.func_params, None)
            elif isinstance(var_type, TypeSymbol):
                var_type.accessed = True
                if var_type.type is self.search_scopes(FUNC):
                    sym = FuncSymbol(k, var_type.type.return_type,
                                     v.func_params, None)
                else:
                    raise NotImplementedError
            else:
                sym = VarSymbol(k, var_type)
            sym.val_assigned = True
            self.define(sym.name, sym)
        return_types = self.visit(node.body)
        return_types = list(flatten(return_types))
        if self.return_flag:
            self.return_flag = False
            for ret_type in return_types:
                infered_type = self.infer_type(ret_type)
                if infered_type is not func_type and not types_compatible(
                        infered_type, func_type):
                    error(
                        'file={} line={}: The actual return type does not match the declared return type: {}'
                        .format(self.file_name, node.line_num, func_name))
        elif func_type is not None:
            error(
                'file={} line={}: No return value was specified for function: {}'
                .format(self.file_name, node.line_num, func_name))
        func_symbol = FuncSymbol(func_name, func_type, node.parameters,
                                 node.body, node.parameter_defaults)
        self.define(func_name, func_symbol, 1)
        self.drop_top_scope()
Exemplo n.º 2
0
 def visit_vardecl(self, node):
     type_name = node.type.value
     type_symbol = self.search_scopes(type_name)
     var_name = node.value.value
     if type_name in (LIST, TUPLE):
         var_symbol = CollectionSymbol(var_name, type_symbol, node.type.func_params['0'].value)
         var_symbol.read_only = type_name == TUPLE
     else:
         var_symbol = VarSymbol(var_name, type_symbol)
     self.define(var_symbol.name, var_symbol)
Exemplo n.º 3
0
    def visit_externfuncdecl(self, node):
        func_name = node.name
        func_type = self.search_scopes(node.return_type.value)

        if self.search_scopes(func_name) is not None:
            error('file={} line={}: Cannot redefine a declared function: {}'.
                  format(self.file_name, node.line_num, func_name))

        if func_type and func_type.name == FUNC:
            func_type.func = FuncSymbol(
                ANON, self.visit(node.return_type.func_ret_type),
                node.parameters, node.body, node.parameter_defaults)

        self.define(func_name,
                    FuncSymbol(func_name, func_type, node.parameters, None))
        self.new_scope()
        if node.varargs:
            varargs_type = self.search_scopes(LIST)
            varargs_type.type = node.varargs[1].value
            varargs = CollectionSymbol(
                node.varargs[0], varargs_type,
                self.search_scopes(node.varargs[1].value))
            varargs.val_assigned = True
            self.define(varargs.name, varargs)
        for k, v in node.parameters.items():
            var_type = self.search_scopes(v.value)
            if var_type is self.search_scopes(FUNC):
                sym = FuncSymbol(k, v.func_ret_type, None, None)
            elif isinstance(var_type, TypeSymbol):
                var_type.accessed = True
                if var_type.type is self.search_scopes(FUNC):
                    sym = FuncSymbol(k, var_type.type.return_type, None, None)
                else:
                    raise NotImplementedError
            else:
                sym = VarSymbol(k, var_type)
            sym.val_assigned = True
            self.define(sym.name, sym)

        func_symbol = FuncSymbol(func_name, func_type, node.parameters, None)
        self.define(func_name, func_symbol, 1)
        self.drop_top_scope()
Exemplo n.º 4
0
    def visit_assign(self, node):  # TODO clean up this mess of a function
        collection_type = None
        field_assignment = None
        collection_assignment = None
        if isinstance(node.left, VarDecl):
            var_name = node.left.value.value
            value = self.infer_type(node.left.type)
            value.accessed = True
            if isinstance(node.right, Collection) or isinstance(
                    node.right, Range):
                _, collection_type = self.visit(node.right)

            if value.name in (TUPLE,
                              LIST) and (not isinstance(node.right, Range)
                                         and node.right.type != value.name):
                error(
                    'file={} line={}: Contradicting {}-{} declaration'.format(
                        self.file_name, node.line_num, value.name,
                        node.right.type))
        elif hasattr(node.right, 'name') and isinstance(
                self.search_scopes(node.right.name),
            (StructSymbol, EnumSymbol, ClassSymbol)):
            var_name = node.left.value
            value = self.search_scopes(node.right.name)
            value.accessed = True
        elif isinstance(node.right, Collection) or isinstance(
                node.right, Range):
            var_name = node.left.value
            value, collection_type = self.visit(node.right)
        elif isinstance(node.left, DotAccess):
            field_assignment = True
            var_name = self.visit(node.left)
            value = self.visit(node.right)
        elif isinstance(node.right, DotAccess):
            var_name = node.left.value
            value = self.search_scopes(node.right.obj)
            value.accessed = True
            value = self.infer_type(value)
        elif isinstance(node.left, CollectionAccess):
            collection_assignment = True
            var_name = node.left.collection.value
            value = self.visit(node.right)
        else:
            var_name = node.left.value
            value = self.visit(node.right)
            if isinstance(value, VarSymbol):
                value = value.type
        lookup_var = self.search_scopes(var_name)
        if not lookup_var:
            if collection_type:
                col_sym = CollectionSymbol(var_name, value, collection_type)
                col_sym.val_assigned = True
                self.define(var_name, col_sym)
            elif field_assignment:
                if var_name is value:
                    return
                else:
                    error(
                        'file={} line={} Type Error: What are you trying to do?!?! (fix this message)'
                        .format(self.file_name, node.line_num))
            elif isinstance(value, FuncSymbol):
                value.name = var_name
                self.define(var_name, value)
            elif hasattr(value, 'name') and value.name == FUNC:
                var = self.visit(node.right)
                if isinstance(var, FuncSymbol):
                    self.define(var_name, var)
                elif isinstance(var, BuiltinTypeSymbol):
                    self.define(var_name, var.func)
                else:
                    val_info = self.search_scopes(node.right.value)
                    func_sym = FuncSymbol(var_name, val_info.type.return_type,
                                          val_info.parameters, val_info.body,
                                          val_info.parameter_defaults)
                    self.define(var_name, func_sym)
            else:
                var_sym = VarSymbol(var_name, value, node.left.read_only)
                var_sym.val_assigned = True
                self.define(var_name, var_sym)
        else:
            if isinstance(node.left, VarDecl):
                error(
                    'file={} line={}: Cannot redefine the type of a declared variable: {}'
                    .format(self.file_name, node.line_num, var_name))

            if collection_assignment:
                col = self.search_scopes(node.left.collection.value)
                if col.type.name == TUPLE:
                    error(
                        'file={} line={}: Cannot change the elements of a tuple: {}'
                        .format(self.file_name, node.line_num, var_name))
                elif lookup_var.item_types == value:
                    return
            if lookup_var.read_only:
                error(
                    'file={} line={}: Cannot change the value of a variable declared constant: {}'
                    .format(self.file_name, node.line_num, var_name))

            lookup_var.val_assigned = True
            if lookup_var.type in (self.search_scopes(DOUBLE),
                                   self.search_scopes(FLOAT)):
                if value in (self.search_scopes(INT),
                             self.search_scopes(DOUBLE),
                             self.search_scopes(FLOAT)):
                    return
            if lookup_var.type is value:
                return
            if hasattr(value, 'type') and lookup_var.type is value.type:
                return
            if isinstance(value, TypeSymbol):
                value.accessed = True
                if value.type is self.search_scopes(FUNC):
                    if value.type.return_type == lookup_var.type:
                        return
            if hasattr(value, 'value'):
                if value.value == lookup_var.type.name:
                    return
            error(
                'file={} line={} Type Error: Not good things happening (fix this message)'
                .format(self.file_name, node.line_num))