Пример #1
0
    def visitVarDef(self, node):
        # variables must be primitive type
        if node._type.is_array():
            raise NodeError(node, 'Error: missing size for array definition')

        # cannot define void variables
        if node._type == self.tvoid:
            raise NodeError(node, 'Error: variable must be non-void')

        # Variable initialization must match variable type
        self.visit_children(node)
        self.check_type(node.value, node._type)
Пример #2
0
    def visitAssignment(self, node):
        self.visit_children(node)

        # functions cannot be re-assigned
        if isinstance(node.ref.ty, FunType):
            raise NodeError(node, 'Error: cannot reassign function')

        # array pointers cannot be re-assigned
        if node.ref.ty.is_array():
            raise NodeError(node, 'Error: cannot reassign array variable')

        # assigned value must match variable type
        self.check_type(node.value, node.ref.ty)
Пример #3
0
    def visitReturn(self, node):
        # returned type must match function type
        self.visit_children(node)
        retty = self.curfn._type.return_type
        is_void = str(retty) == 'void'

        if node.value and is_void:
            raise NodeError(node.value,
                            'Error: void function must not return a value')
        elif node.value:
            self.check_type(node.value, retty)
        elif not is_void:
            raise NodeError(node,
                            'Error: non-void function must not return void')
Пример #4
0
    def visitFunDef(self, node):
        # functions can only return basic types
        if node._type.return_type.is_array():
            raise NodeError(
                node, 'Error: functions can only return basic type or void')

        self.curfn = node
        self.visit_children(node)
        self.curfn = None

        # a non-void function must return a value
        if node._type.return_type != self.tvoid:
            stat = node.body.statements
            if not len(stat) or not isinstance(stat[-1], Return):
                raise NodeError(
                    node, 'Error: non-void function must end with return')
Пример #5
0
    def visitFunCall(self, node):
        self.visit_children(node)
        funty = node.definition._type

        if not isinstance(funty, FunType):
            raise NodeError(node, 'Error: %s is not a function' % node.name)

        typed_args = node.args
        nargs = len(node.args)
        nparams = len(funty.params)
        defargs = (node.definition.location, 'Note: function is defined here')

        # number of arguments must match number of parameters in definition
        if funty.varargs:
            if nargs < nparams:
                raise BackrefError(
                    node.location, 'Not enough arguments for varargs function',
                    *defargs)

            typed_args = node.args[:len(funty.params)]

        elif nargs != nparams:
            errnode = node.args[nparams] if nargs > nparams else node
            raise BackrefError(
                errnode.location,
                'Expected %d arguments, got %d' % (nparams, nargs), *defargs)

        # argument types must match defined parameter types
        for arg, param in zip(typed_args, funty.params):
            self.check_type(arg, param._type)

        # resulting expression has return type of function
        node.ty = funty.return_type
Пример #6
0
    def visitGlobalDef(self, node):
        self.visit_children(node)

        # global definitions cannot be arrays or void
        if node._type.is_array():
            raise NodeError(node, 'Error: global must have basic type')

        if node._type == self.tvoid:
            raise NodeError(node, 'Error: global must be non-void')

        # initializer must match global type
        self.check_type(node.value, node._type)

        # initializer must be constant
        if not isinstance(node.value, Const):
            raise NodeError(node.value,
                            'Error: global initializer must be constant')
Пример #7
0
 def visitIndex(self, node):
     # array index must have int type, base must have array type
     self.visit_children(node)
     if not node.base.ty.is_array():
         raise NodeError(node.base, 'Expected array type, got %s',
                         node.base.ty)
     self.check_type(node.index, self.tint)
     node.ty = node.base.ty.base
Пример #8
0
    def find_in_scope(self, node):
        for scope in reversed(self.scopes):
            if node.name in scope:
                #print('%s -> %s' % (node.name, repr(scope[node.name])))
                node.definition = scope[node.name]
                return

        raise NodeError(node, 'Error: %s is undefined' % node.name)
Пример #9
0
 def visitParam(self, node):
     # cannot define void parameters
     if str(node._type).startswith('void'):
         raise NodeError(node, 'Error: parameter must be non-void')
Пример #10
0
 def visitGlobalDec(self, node):
     # cannot define void globals
     if str(node._type).startswith('void'):
         raise NodeError(node, 'Error: global must be non-void')
Пример #11
0
 def check_type(self, node, *expected):
     if node.ty not in expected:
         raise NodeError(node, 'Type mismatch: expected %s, got %s',
                         '/'.join(map(str, expected)), node.ty)
Пример #12
0
 def visitContinue(self, node):  #! added visitBreak
     if (self.loop_count <= 0):
         raise NodeError(node, 'Error: continue not in loop')
Пример #13
0
 def visitBreak(self, node):  #! added visitBreak
     if (self.loop_count <= 0):
         raise NodeError(node, 'Error: break not in loop')
Пример #14
0
    def visitArrayDef(self, node):
        # cannot define void arrays
        if node._type.base == self.tvoid:
            raise NodeError(node, 'Error: array must be non-void')

        self.visit_children(node)
Пример #15
0
 def visitContinue(self, node):
     if not self.in_loop:
         raise NodeError(node, 'Error: continue must be inside loop')
Пример #16
0
 def visitBreak(self, node):
     if not self.in_loop:
         raise NodeError(node, 'Error: break must be inside loop')