Example #1
0
def irgen(node,
          irprogram=None,
          irfunction=None,
          jump_dest=None,
          jump_right=None,
          negation=False):
    if isinstance(node, Program):
        irprogram = IRProgram()
        for v in node.vars:  # TODO use addGlobal(?)
            # Create IRVariable for globale variables
            irvar = None
            if len(v.getArray()) != 0:
                # create array-type
                dims = v.getArray()
                arr_type = v.type.getBaseType()
                for dim in dims:
                    arr_type = arr_type.getArrayType(dim)
                irvar = irprogram.getIRVar(v.name.name, arr_type, True)
            else:
                irvar = irprogram.getIRVar(v.name.name, v.type, True)
            irprogram.variables.append(irvar)
            v.setIRVar(irvar)
        for f in node.funcs:  # TODO use addFunc(?)
            irprogram.functions.append(irgen(f, irprogram))
        return irprogram
    elif isinstance(node, Function):
        irfunction = IRFunction(node.name.name, irprogram)
        for par in node.arglist:
            irpar = irprogram.getIRVar(par.name.name, par.type)
            irfunction.addParam(irpar)
            par.setIRVar(irpar)
        irgen(node.block, irprogram, irfunction)
        return irfunction
    elif isinstance(node, VarDecl):
        # Edited: node.name to node.name.name
        if len(node.getArray()) != 0:
            # create array-type
            dims = node.getArray()
            arr_type = node.type.getBaseType()
            for dim in dims:
                arr_type = arr_type.getArrayType(dim)
            irvar = irprogram.getIRVar(node.name.name, arr_type)
        else:
            irvar = irprogram.getIRVar(node.name.name, node.type)
        node.setIRVar(irvar)
        irfunction.addVar(irvar)
    elif isinstance(node, Block):
        for x in node.children():
            irgen(x, irprogram, irfunction)
    elif isinstance(node, Identifier):
        if node.decl.getIRVar() is not None:
            return node.decl.getIRVar()
        else:
            print(
                "ERROR Identifier: Cant find IRVariable object to identifier")
    elif isinstance(node, ToInt):
        tmp = irgen(node.successor, irprogram, irfunction)
        virtReg = irprogram.getFreeVirtReg(irfunction, Type.getIntType())
        irfunction.addInstr(CR2I(virtReg, tmp))
        irfunction.virtRegs[virtReg.name] = virtReg
        return virtReg
    elif isinstance(node, ToReal):
        tmp = irgen(node.successor, irprogram, irfunction)
        virtReg = irprogram.getFreeVirtReg(irfunction, Type.getRealType())
        irfunction.addInstr(CI2R(virtReg, tmp))
        irfunction.virtRegs[virtReg.name] = virtReg
        return virtReg
    elif isinstance(node, Literal):
        return ConstValue(node.val, node.type)
    elif isinstance(node, LValue):
        decl = node.name.getDecl()
        derefs = None
        if isinstance(decl, Identifier):
            derefs = decl.getArrayDeref()
        else:
            derefs = decl.array

        if len(derefs) != 0:
            # is array
            virtReg = irprogram.getFreeVirtReg(irfunction,
                                               decl.type.getBaseType())
            base = getBase(node, irprogram, irfunction)
            offset = getOffset(node, irprogram, irfunction)
            irfunction.addInstr(CLOAD(virtReg, base, offset))
            return virtReg
        else:
            return irgen(node.name, irprogram, irfunction)

    elif isinstance(node, ArithExpr):
        # Evaluate leftern subtree
        leftReg = irgen(node.left, irprogram, irfunction)
        # Evaluate rightern subtree
        rightReg = irgen(node.right, irprogram, irfunction)

        if rightReg.type != leftReg.type:
            print("ArithExpr: Subexpressions have different type :'(")

        destReg = irprogram.getFreeVirtReg(irfunction, rightReg.type)

        if node.op.val == "+":
            irfunction.addInstr(CADD(destReg, leftReg, rightReg))
        elif node.op.val == "-":
            irfunction.addInstr(CSUB(destReg, leftReg, rightReg))
        elif node.op.val == "*":
            irfunction.addInstr(CMUL(destReg, leftReg, rightReg))
        elif node.op.val == "/":
            irfunction.addInstr(CDIV(destReg, leftReg, rightReg))
        else:
            print("ArithExpr: Another mysterious error: No valid operand")

        return destReg

    elif isinstance(node, FuncCall):
        virts = []
        for p in reversed(node.par_list):
            virts.append(irgen(p, irprogram, irfunction))

        for v in virts:
            irfunction.addInstr(CPUSH(v))

        returnType = node.func_name.getDecl().getType()
        destReg = irprogram.getFreeVirtReg(irfunction, returnType)
        irfunction.addInstr(CCALL(destReg, node.func_name.name))
        return destReg
    elif isinstance(node, ReturnStmt):
        irfunction.addInstr(CRET(irgen(node.expr, irprogram, irfunction)))
    elif isinstance(node, CondExpr):
        if node.op.val == "||":
            l_right_cond = irprogram.genLabel()
            irgen(node.left, irprogram, irfunction, jump_dest, l_right_cond)
            irfunction.addInstr(l_right_cond)
            irgen(node.right, irprogram, irfunction, jump_dest, jump_right)
            irfunction.addInstr(CBRA(jump_right))
        elif node.op.val == "&&":
            l_right_cond = irprogram.genLabel()
            irgen(node.left, irprogram, irfunction, l_right_cond, jump_right,
                  True)
            irfunction.addInstr(l_right_cond)
            irgen(node.right, irprogram, irfunction, jump_dest, jump_right)
            irfunction.addInstr(CBRA(jump_right))
        # Evaluate rightern subtree
        else:
            leftReg = irgen(node.left, irprogram, irfunction)
            rightReg = irgen(node.right, irprogram, irfunction)
            if node.op.val == "<=":
                if negation:
                    irfunction.addInstr(CBGT(jump_right, leftReg, rightReg))
                else:
                    irfunction.addInstr(CBLE(jump_dest, leftReg, rightReg))
            elif node.op.val == "=":
                if negation:
                    irfunction.addInstr(CBNE(jump_right, leftReg, rightReg))
                else:
                    irfunction.addInstr(CBEQ(jump_dest, leftReg, rightReg))
            elif node.op.val == "!=":
                if negation:
                    irfunction.addInstr(CBEQ(jump_right, leftReg, rightReg))
                else:
                    irfunction.addInstr(CBNE(jump_dest, leftReg, rightReg))
            elif node.op.val == "<":
                if negation:
                    irfunction.addInstr(CBGE(jump_right, leftReg, rightReg))
                else:
                    irfunction.addInstr(CBLT(jump_dest, leftReg, rightReg))
            elif node.op.val == ">":
                if negation:
                    irfunction.addInstr(CBLE(jump_right, leftReg, rightReg))
                else:
                    irfunction.addInstr(CBGT(jump_dest, leftReg, rightReg))
            elif node.op.val == ">=":
                if negation:
                    irfunction.addInstr(CBLT(jump_right, leftReg, rightReg))
                else:
                    irfunction.addInstr(CBGE(jump_dest, leftReg, rightReg))

    elif isinstance(node, IfStmt):
        l_then = irprogram.genLabel()
        l_else = irprogram.genLabel()
        l_end = irprogram.genLabel()
        irgen(node.cond, irprogram, irfunction, l_then, l_else)
        irfunction.addInstr(CBRA(l_else))
        irfunction.addInstr(l_then)
        irgen(node.trueblock, irprogram, irfunction)
        irfunction.addInstr(CBRA(l_end))
        irfunction.addInstr(l_else)
        irgen(node.falseblock, irprogram, irfunction)
        irfunction.addInstr(l_end)
    elif isinstance(node, WhileStmt):
        l_cond = irprogram.genLabel()
        l_then = irprogram.genLabel()
        l_end = irprogram.genLabel()
        irfunction.addInstr(l_cond)
        irgen(node.cond, irprogram, irfunction, l_then, l_end)
        irfunction.addInstr(CBRA(l_end))
        irfunction.addInstr(l_then)
        irgen(node.block, irprogram, irfunction)
        irfunction.addInstr(CBRA(l_cond))
        irfunction.addInstr(l_end)
    elif isinstance(node, AssignStmt):
        # get the left side of an assigment
        src = irgen(node.expr, irprogram, irfunction)
        decl = node.lvalue.name.getDecl()
        derefs = decl.array
        if len(derefs) != 0:
            # is array
            base = getBase(node.lvalue, irprogram, irfunction)
            offset = getOffset(node.lvalue, irprogram, irfunction)
            irfunction.addInstr(CSTORE(base, offset, src))
        else:
            dest = irgen(node.lvalue, irprogram, irfunction)
            irfunction.addInstr(CASSGN(dest, src))
    else:
        for x in node.children():
            irgen(x, irprogram, irfunction)
Example #2
0
def typeChecking(node):
    """traverse the AST and add conversion nodes"""
    if isinstance(node, Identifier):
        ident = node.getDecl()
        if isinstance(ident, VarDecl):
            return ident.type
        elif isinstance(ident, Function):
            ''' TODO:this call might be wrong'''
            return typeChecking(ident)

    elif isinstance(node, FuncCall):
        ''' Get corresponding Function Object'''
        funcObj = node.func_name.getDecl()
        if len(funcObj.arglist) != len(node.par_list):
            '''Number of parameter for function call does not match
            '''
            raise InputError("Number of parameter does not match at " +
                             str(node.func_name))
        for x in node.par_list:
            typeChecking(x)
        return funcObj.getType()
    elif isinstance(node, ArithExpr):
        leftType = typeChecking(node.left)
        rightType = typeChecking(node.right)

        if leftType.isArray():
            leftType = leftType.getBaseType()
        if rightType.isArray():
            rightType = leftType.getBaseType()
        ''' Return type of result from arith expression
        '''
        if leftType != rightType:
            if leftType == Type.getIntType():
                '''Add ToReal node on left side
                '''
                node.left = ToReal(node.left)
            else:
                '''Add ToReal node on right side
                '''
                node.right = ToReal(node.right)
            return Type.getRealType()
        if leftType == Type.getIntType():
            return Type.getIntType()
        else:
            return Type.getRealType()
    elif isinstance(node, AssignStmt):
        leftType = typeChecking(node.lvalue)
        rightType = typeChecking(node.expr)

        if leftType.isArray():
            leftType = leftType.getBaseType()
        if rightType.isArray():
            rightType = leftType.getBaseType()

        if leftType != rightType:
            if leftType == Type.getIntType():
                '''Add ToInt cast on right side
                '''
                node.expr = ToInt(node.expr)
            else:
                '''Add ToReal cast on right side
                '''
                node.expr = ToReal(node.expr)
    elif isinstance(node, Function):
        global functionReturnType
        functionReturnType = node.getType()
        ''' check the arguments of the function, e.g. array forbidden
        '''
        for a in node.arglist:
            if len(a.array) != 0:
                raise InputError("Argument is an array: " + str(node.name))
        typeChecking(node.block)
    elif isinstance(node, VarDecl):
        accessors = node.getArray()
        for a in accessors:
            if Type.getIntType() != typeChecking(a):
                raise InputError("Invalid array access in VarDecl: " +
                                 str(node.name))
    elif isinstance(node, LValue):
        accessors = node.getArrayDeref()
        decl = node.name.getDecl()
        if isinstance(decl, VarDecl):
            if len(node.getArrayDeref()) != len(decl.getArray()):
                raise InputError("Invalid array access in LValue: " +
                                 str(node.name))

        for a in accessors:
            if Type.getRealType() == typeChecking(a):
                raise InputError("Invalid array access in LValue: " +
                                 str(node.name))
            else:
                typeChecking(a)

        if isinstance(node.name.getDecl(), Function):
            raise InputError("The function misses its arguments: " +
                             str(node.name))

        return decl.type

    elif isinstance(node, Program):
        for c in node.children():
            typeChecking(c)
    elif isinstance(node, ReturnStmt):
        returnType = typeChecking(node.expr)

        if returnType != functionReturnType:
            if returnType == Type.getIntType():
                node.expr = ToReal(node.expr)
            else:
                node.expr = ToInt(node.expr)
    elif isinstance(node, IntLiteral):
        return Type.getIntType()
    elif isinstance(node, FloatLiteral):
        return Type.getRealType()
    else:
        for x in node.children():
            typeChecking(x)