Ejemplo n.º 1
0
    def _fix_decl_name_type(self, decl, typename):
        """
        Fixes a declaration. Modifies decl.
        """
        # Reach the underlying basic type
        type = decl
        while not isinstance(type, ast.VarDecl):
            type = type.type

        decl.name = type.declname

        # The typename is a list of types. If any type in this
        # list isn't an Type, it must be the only
        # type in the list.
        # If all the types are basic, they're collected in the
        # Type holder.
        for tn in typename:
            if not isinstance(tn, ast.Type):
                if len(typename) > 1:
                    self._parse_error("Invalid multiple types specified", tn.coord)
                else:
                    type.type = tn
                    return decl

        if not typename:
            # Functions default to returning int
            if not isinstance(decl.type, ast.FuncDecl):
                self._parse_error("Missing type in declaration", decl.coord)
            type.type = ast.Type("int", coord=decl.coord)
        else:
            # At this point, we know that typename is a list of Type
            # nodes. Concatenate all the names into a single list.
            type.type = ast.Type(typename[0].names, coord=typename[0].coord)
        return decl
Ejemplo n.º 2
0
    def vFunctionCall(self, node):
        node.symtab = self.curr_symtab
        self.visit(node.params)
        if node.callee:
            self.visit(node.callee)
        if node.id == 'sort' and node.params and len(
                node.params.children) >= 2:
            par1 = node.params.children[0]
            if isinstance(par1,
                          ast.FunctionCall) and par1.callee and isinstance(
                              par1.callee.resolveType(), ast.VectorType):

                tpeSorted = par1.callee.resolveType().subtype.resolveType()
                node.isSortCall = True
                node.sortComp = 'standardless'
                if len(node.params.children) == 3 and isinstance(
                        node.params.children[2], ast.Identifier):
                    node.sortComp = 'f_' + node.params.children[
                        2].id + '_' + tpeSorted.type + '_' + tpeSorted.type
                node.sortFuncName = self.curr_symtab.addSortCall(
                    par1.callee.resolveType(), node.sortComp)
                node.sortVector = par1.callee
                node.sortType = par1.callee.resolveType()
                if len(node.params.children) > 2:
                    (a, b) = self.findFunction(
                        node.symtab, 'f_' + node.params.children[2].id,
                        [node.sortType.subtype, node.sortType.subtype])
                    #(node.sortFuncOrigName, node.sortFuncType) =  self.findFunction(node.symtab, 'f_' + node.params.children[2].id, [node.sortType.subtype, node.sortType.subtype])
                    node.sortFuncOrigName = a
                    node.sortFuncType = b
                else:
                    node.sortFuncOrigName = ""
                    node.sortFuncType = ast.Type('error')
                #print node.sortFuncOrigName
                #print node.sortFuncType
                #print node.sortFuncType.type
        else:
            funcnames = node.symtab.get('__functionnames__')
            if isinstance(funcnames, ast.Type) and funcnames.type == 'error':
                return
            funcs = funcnames.get(node.id, None)
            if funcs:
                bestCandidate = None
                bestCandidateType = ast.Type('error')
                for long_name, tpe in funcs.iteritems():

                    if len(tpe.params) == len(node.params.children):
                        good = True
                        #print tpe.params
                        for i in range(0, len(tpe.params)):
                            if not node.params.children[i].resolveType(
                            ).canCoerceType(tpe.params[i].resolveType()):
                                good = False
                        if good:
                            bestCandidate = long_name
                            bestCandidateType = tpe
                if bestCandidate:
                    node.id = bestCandidate
                    node.type = bestCandidateType
Ejemplo n.º 3
0
def p_var_id(p):
    'var : ID dim_star'
    global current_class, current_context, current_modifiers, current_type
    global current_vartable, current_variable_kind
    if p[2] == 0:
        ftype = current_type
    else:
        ftype = ast.Type(current_type, params=p[2])
    if (current_context == 'class'):
        if (current_class.lookup_field(p[1])):
            signal_error(
                'Duplicate definition of field {0} in class!'.format(p[1]),
                p.lineno(1))
        else:
            (v, s) = current_modifiers
            f = ast.Field(p[1], current_class, v, s, ftype)
            current_class.add_field(p[1], f)
    else:
        # we're in a method/constructor
        # Then, current_vartable is the current table of variables
        if (current_vartable.find_in_current_block(p[1])):
            signal_error(
                'Duplicate definition of variable {0} within the same block!'.
                format(p[1]), p.lineno(1))
        else:
            current_vartable.add_var(p[1], current_variable_kind, ftype)
Ejemplo n.º 4
0
 def p_type_specifier(self, p):
     """ type_specifier : VOID
                        | CHAR
                        | INT
                        | FLOAT
     """
     p[0] = ast.Type([p[1]], coord=self._token_coord(p, 1))
Ejemplo n.º 5
0
def p_type_id(p):
    'type :  ID'
    global current_type
    baseclass = ast.lookup(ast.classtable, p[1])
    if (baseclass == None):
        signal_error('Class {0} does not exist!'.format(p[1]), p.lineno(1))
    p[0] = current_type = ast.Type(baseclass.name)
Ejemplo n.º 6
0
    def findFunction(self, symtab, id, node_params):

        funcnames = symtab.get('__functionnames__')
        #print funcnames
        bestCandidate = None
        bestCandidateType = ast.Type('error')
        if isinstance(funcnames, ast.Type) and funcnames.type == 'error':
            return (bestCandidate, bestCandidateType)
        funcs = funcnames.get(id, None)
        #print id
        if funcs:
            #print "here1"

            for long_name, tpe in funcs.iteritems():

                if len(tpe.params) == len(node_params):
                    good = True
                    #print tpe.params
                    for i in range(0, len(tpe.params)):
                        if not node_params[i].resolveType().canCoerceType(
                                tpe.params[i].resolveType()):
                            good = False
                    if good:
                        bestCandidate = long_name
                        bestCandidateType = tpe
            #if bestCandidate:
            #node.id = bestCandidate
            #node.type = bestCandidateType

        return (bestCandidate, bestCandidateType)
Ejemplo n.º 7
0
def p_new_array(p):
    'new_array : NEW type dim_expr_plus dim_star'
    if (p[4] == 0):
        t = p[2]
    else:
        t = ast.Type(p[2], params=p[4])
    p[0] = ast.NewArrayExpr(t, p[3], p.lineno(1))
Ejemplo n.º 8
0
 def vProgram(self, node):
     self.root_symtab = Symtab()
     doubleType = ast.Type('double')
     doubleType.symtab = self.root_symtab
     self.root_symtab.entries['M_PI'] = doubleType
     self.curr_symtab = self.root_symtab
     self.vNodeList(node)
     node.symtab = self.root_symtab
Ejemplo n.º 9
0
def p_type_02(t):
    '''type : VOID
        | INT
        | FLOAT
        | DOUBLE
        | CHAR
        | BOOL
        | STRING'''
    t[0] = ast.Type(t[1])
Ejemplo n.º 10
0
 def vAssignmentStatement(self, node):
     if isinstance(
             node.expr,
             ast.Constructor) and node.expr.type.resolveType().isVector():
         self.w('New')
         self.w('(')
         self.visit(node.lval)
         cons = node.expr
         while isinstance(cons, ast.Constructor):
             self.w(',')
             #print cons.params
             self.visit(cons.params.children[0])
             if len(cons.params.children) == 1:
                 cons = None
                 break
             else:
                 cons = cons.params.children[1]
         if cons != None:
             print '****************Need to initialize******************'
         self.w(')')
     elif isinstance(node.expr, ast.AssignmentStatement):
         self.visit(node.expr)
         self.p(';')
         tmp = node.expr
         if isinstance(node.expr.lval, str):
             node.expr = ast.Identifier(node.expr.lval)
         else:
             node.expr = node.expr.lval
         node.expr.symtab = node.symtab
         self.visit(node)
         node.expr = tmp
     else:
         ident = node.lval
         ident.symtab = node.symtab
         oldexpr = node.expr
         if node.operator != '=':
             node.expr = ast.BinaryOp(
                 ident, self.assignmentOperators[node.operator],
                 ast.Parenthesis(node.expr))
             node.expr.symtab = node.symtab
         tpe_ident = ident.resolveType().type
         tpe_expr = node.expr.resolveType().type
         #if isinstance(ident.resolveType(), ast.StructType):
         #print ident.resolveType().id
         #print tpe_ident
         #if isinstance(node.expr.resolveType().resolveType(), ast.StructType):
         #print node.expr.resolveType().resolveType().id
         #print tpe_expr
         if tpe_ident != tpe_expr and not (
             (tpe_ident == 'float' and tpe_expr == 'double') or
             (tpe_ident == 'double' and tpe_expr == 'float')):
             node.expr = ast.CastExpression(ast.Type(tpe_ident), node.expr)
             node.expr.symtab = node.symtab
         self.visit(node.lval)
         self.w(':=')
         self.visit(node.expr)
         node.expr = oldexpr
Ejemplo n.º 11
0
def p_method_decl_header_void(p):
    'method_header : mod VOID ID'
    global current_context, current_vartable
    current_context = 'method'
    (v, s) = current_modifiers
    m = ast.Method(p[3], current_class, v, s, ast.Type('void'))
    current_class.add_method(m)
    current_vartable = m.vars
    p[0] = m
Ejemplo n.º 12
0
 def type_spec(self):
     """type_spec : INTEGER
                  | REAL
     """
     token = self.current_token
     if self.current_token.type == TokenType.INTEGER:
         self.eat(TokenType.INTEGER)
     else:
         self.eat(TokenType.REAL)
     node = ast.Type(token)
     return node
Ejemplo n.º 13
0
    def vBinaryOp(self, node):  # falta and or xor bit a bit
        pascalOp = self.t[node.oper]
        if (pascalOp == 'AND') or (
                pascalOp == 'OR'
        ):  # podriamos necesitar para todos los operadores hacer un in!
            self.w('(')
            self.visit(node.left)
            self.w(')')
            self.w(pascalOp)
            self.w('(')
            self.visit(node.right)
            self.w(')')
        elif (pascalOp == 'DIV'):
            left_type = node.left.resolveType().type
            right_type = node.right.resolveType().type
            divOp = 'DIV'
            if (left_type == 'float' or left_type == 'double'
                    or right_type == 'float' or right_type == 'double'):
                divOp = '/'

            self.visit(node.left)
            self.w(divOp)
            self.visit(node.right)
        elif pascalOp == '-' or pascalOp == '+' or pascalOp == '=':
            left_type = node.left.resolveType().type
            right_type = node.right.resolveType().type
            #print "left " + left_type
            #print "right " + right_type
            if (left_type == 'char'):
                node.left = ast.CastExpression(ast.Type('int'), node.left)

            if (right_type == 'char'):
                node.right = ast.CastExpression(ast.Type('int'), node.right)

            self.visit(node.left)
            self.w(pascalOp)
            self.visit(node.right)
        else:
            self.visit(node.left)
            self.w(pascalOp)
            self.visit(node.right)
Ejemplo n.º 14
0
    def get(self, name):
        """Retrieves the symbol with the given name from the symbol
        table, recursing upwards through parent symbol tables if it is
        not found in the current one."""

        if self.entries.has_key(name):
            return self.entries[name]
        else:
            if self.parent != None:
                return self.parent.get(name)
            else:
                return ast.Type('error')
Ejemplo n.º 15
0
 def vWhileStatement(self, node):
     self.w('WHILE')
     if not node.cond.resolveType().isBool():
         cast = ast.CastExpression(ast.Type('bool'), node.cond)
         cast.type.symtab = node.symtab
         cast.symtab = node.symtab
         self.visit(cast)
     else:
         self.visit(node.cond)
     self.w('DO')
     self.pi('BEGIN')
     self.visit(node.loop)
     self.pu()
     self.w('END')
Ejemplo n.º 16
0
 def vIfStatement(self, node):
     self.w('IF')
     if not node.cond.resolveType().isBool():
         cast = ast.CastExpression(ast.Type('bool'), node.cond)
         cast.type.symtab = node.symtab
         cast.symtab = node.symtab
         self.visit(cast)
     else:
         self.visit(node.cond)
     #self.visit(node.cond)
     self.w('THEN')
     self.pi('BEGIN')
     self.visit(node.then)
     self.pu(';')
     self.w('END')
     if node.elze:
         self.p()
         self.w('ELSE')
         self.pi('BEGIN')
         self.visit(node.elze)
         self.pu(';')
         self.w('END')
Ejemplo n.º 17
0
def p_type_float(p):
    'type :  FLOAT'
    global current_type
    p[0] = current_type = ast.Type('float')
Ejemplo n.º 18
0
def p_type_bool(p):
    'type :  BOOLEAN'
    global current_type
    p[0] = current_type = ast.Type('boolean')
Ejemplo n.º 19
0
def p_type_int(p):
    'type :  INT'
    global current_type
    p[0] = current_type = ast.Type('int')
Ejemplo n.º 20
0
def gen_code(stmt):
    global current_loop_continue_label, current_enter_then_label, current_break_out_else_label
    # stmt.end_reg is the destination register for each expression
    stmt.end_reg = None
    push_labels()

    if isinstance(stmt, ast.BlockStmt):
        for stmt_line in stmt.stmtlist:
            gen_code(stmt_line)

    elif isinstance(stmt, ast.ExprStmt):
        gen_code(stmt.expr)

    elif isinstance(stmt, ast.AssignExpr):
        gen_code(stmt.rhs)
        gen_code(stmt.lhs)

        if stmt.lhs.type == ast.Type('float') and stmt.rhs.type == ast.Type('int'):
            conv = absmc.ConvertInstr('itof', stmt.rhs.end_reg)
            stmt.rhs.end_reg = conv.dst

        if not isinstance(stmt.lhs, ast.FieldAccessExpr):
            absmc.MoveInstr('move', stmt.lhs.end_reg, stmt.rhs.end_reg)
        else:
            absmc.HeapInstr('hstore', stmt.lhs.base.end_reg, stmt.lhs.offset_reg, stmt.rhs.end_reg)

    elif isinstance(stmt, ast.VarExpr):
        stmt.end_reg = stmt.var.reg

    elif isinstance(stmt, ast.ConstantExpr):
        reg = absmc.Register()

        if stmt.kind == 'int':
            absmc.MoveInstr('move_immed_i', reg, stmt.int, True)
        elif stmt.kind == 'float':
            absmc.MoveInstr('move_immed_f', reg, stmt.float, True)
        elif stmt.kind == 'string':
            pass
        elif stmt.kind == 'True':
            absmc.MoveInstr('move_immed_i', reg, 1, True)
        elif stmt.kind == 'False':
            absmc.MoveInstr('move_immed_i', reg, 0, True)
        elif stmt.kind == 'Null':
            absmc.MoveInstr('move_immed_i', reg, 'Null', True)


        stmt.end_reg = reg

    elif isinstance(stmt, ast.BinaryExpr):
        if stmt.bop not in ['and', 'or']:
            gen_code(stmt.arg1)
            gen_code(stmt.arg2)

            reg = absmc.Register()
            flt = ast.Type('float')
            intg = ast.Type('int')
            if stmt.arg1.type == flt or stmt.arg2.type == flt:
                expr_type = 'f'
            else:
                expr_type = 'i'

            if stmt.arg1.type == intg and stmt.arg2.type == flt:
                conv = absmc.Convert('itof', stmt.arg1.end_reg)
                stmt.arg1.end_reg = conv.dst
            elif stmt.arg1.type == flt and stmt.arg2.type == intg:
                conv = absmc.Convert('itof', stmt.arg2.end_reg)
                stmt.arg2.end_reg = conv.dst

            if stmt.bop in ['add', 'sub', 'mul', 'div', 'gt', 'geq', 'lt', 'leq']:
                absmc.ArithInstr(stmt.bop, reg, stmt.arg1.end_reg, stmt.arg2.end_reg, expr_type)

            elif stmt.bop == 'eq' or stmt.bop == 'neq':
                absmc.ArithInstr('sub', reg, stmt.arg1.end_reg, stmt.arg2.end_reg, expr_type)

            if stmt.bop == 'eq':

                # check if r2 == r3
                # 1. perform sub r1, r2, r3 (done above)
                # 2. branch to set_one if r1 is zero
                # 3. else, fall through and set r1 to zero
                # 4. jump out so we don't set r1 to one by accident

                ieq_set = absmc.BranchLabel(stmt.lines, 'SET_EQ')
                ieq_out = absmc.BranchLabel(stmt.lines, 'SET_EQ_OUT')

                absmc.BranchInstr('bz', ieq_set, reg)
                absmc.MoveInstr('move_immed_i', reg, 0, True)
                absmc.BranchInstr('jmp', ieq_out)

                ieq_set.add_to_code()
                absmc.MoveInstr('move_immed_i', reg, 1, True)

                ieq_out.add_to_code()

        if stmt.bop == 'and':
            and_skip = absmc.BranchLabel(stmt.lines, 'AND_SKIP')
            gen_code(stmt.arg1)
            reg = absmc.Register()
            absmc.MoveInstr('move', reg, stmt.arg1.end_reg)
            absmc.BranchInstr('bz', and_skip, stmt.arg1.end_reg)
            gen_code(stmt.arg2)
            absmc.MoveInstr('move', reg, stmt.arg2.end_reg)
            and_skip.add_to_code()

        if stmt.bop == 'or':
            or_skip = absmc.BranchLabel(stmt.lines, 'OR_SKIP')
            gen_code(stmt.arg1)
            reg = absmc.Register()
            absmc.MoveInstr('move', reg, stmt.arg1.end_reg)
            absmc.BranchInstr('bnz', or_skip, stmt.arg1.end_reg)
            gen_code(stmt.arg2)
            absmc.MoveInstr('move', reg, stmt.arg2.end_reg)
            or_skip.add_to_code()

        stmt.end_reg = reg

    elif isinstance(stmt, ast.ForStmt):

        # for-loop:
        # for (i = 0; i < 10; i++) {
        #   body
        # }

        # set i's reg equal to 0
        # create a label after this, as this is where we jump back to at end of loop
        # also create the 'out' label which is what we jump to when breaking out of loop
        # generate code for the 'cond' (test if i's reg is less than 10's reg)
        # test if the cond evaluated to false with 'bz', if so, break out of loop
        # else, fall through into the body of the for-loop
        # when body is over, generate code to update the var (i++)
        # jump unconditionally back to the cond_label, where we eval if i is still < 10
        gen_code(stmt.init)

        cond_label = absmc.BranchLabel(stmt.lines, 'FOR_COND')
        current_enter_then_label = entry_label = absmc.BranchLabel(stmt.lines, 'FOR_ENTRY')
        current_loop_continue_label = continue_label = absmc.BranchLabel(stmt.lines, 'FOR_UPDATE')
        current_break_out_else_label = out_label = absmc.BranchLabel(stmt.lines, 'FOR_OUT')

        cond_label.add_to_code()

        gen_code(stmt.cond)
        absmc.BranchInstr('bz', out_label, stmt.cond.end_reg)

        entry_label.add_to_code()
        gen_code(stmt.body)

        continue_label.add_to_code()
        gen_code(stmt.update)

        absmc.BranchInstr('jmp', cond_label)

        out_label.add_to_code()

    elif isinstance(stmt, ast.AutoExpr):
        gen_code(stmt.arg)

        if stmt.when == 'post':
            tmp_reg = absmc.Register()
            absmc.MoveInstr('move', tmp_reg, stmt.arg.end_reg)

        one_reg = absmc.Register()

        # Load 1 into a register
        absmc.MoveInstr('move_immed_i', one_reg, 1, True)

        absmc.ArithInstr('add' if stmt.oper == 'inc' else 'sub', stmt.arg.end_reg, stmt.arg.end_reg, one_reg)

        if stmt.when == 'post':
            stmt.end_reg = tmp_reg
        else:
            stmt.end_reg = stmt.arg.end_reg

    elif isinstance(stmt, ast.SkipStmt):
        pass

    elif isinstance(stmt, ast.ReturnStmt):
        current_method.returned = True
        if stmt.expr is None:
            absmc.ProcedureInstr('ret')
            return
        gen_code(stmt.expr)

        # Load the result into a0
        absmc.MoveInstr('move', absmc.Register('a', 0), stmt.expr.end_reg)

        # Return to caller
        absmc.ProcedureInstr('ret')

    elif isinstance(stmt, ast.WhileStmt):

        current_loop_continue_label = cond_label = absmc.BranchLabel(stmt.lines, 'WHILE_COND')
        current_enter_then_label = entry_label = absmc.BranchLabel(stmt.lines, 'WHILE_ENTRY')
        current_break_out_else_label = out_label = absmc.BranchLabel(stmt.lines, 'WHILE_OUT')

        cond_label.add_to_code()

        gen_code(stmt.cond)

        absmc.BranchInstr('bz', out_label, stmt.cond.end_reg)

        entry_label.add_to_code()

        gen_code(stmt.body)

        absmc.BranchInstr('jmp', cond_label)

        out_label.add_to_code()

    elif isinstance(stmt, ast.BreakStmt):
        absmc.BranchInstr('jmp', current_break_out_else_label)

    elif isinstance(stmt, ast.ContinueStmt):
        absmc.BranchInstr('jmp', current_loop_continue_label)

    elif isinstance(stmt, ast.IfStmt):

        # if (x == y)
        #   ++x;
        # else
        #   --x;

        # generate 2 labels, for the else part, and the out part
        # test if x == y
        # if not true, jump to the else part
        # if true, we're falling through to the then part, then must jump
        # out right before hitting the else part straight to the out part

        current_enter_then_label = then_part = absmc.BranchLabel(stmt.lines, 'THEN_PART')
        current_break_out_else_label = else_part = absmc.BranchLabel(stmt.lines, 'ELSE_PART')
        out_label = absmc.BranchLabel(stmt.lines, 'IF_STMT_OUT')

        gen_code(stmt.condition)

        absmc.BranchInstr('bz', else_part, stmt.condition.end_reg)

        then_part.add_to_code()
        gen_code(stmt.thenpart)

        absmc.BranchInstr('jmp', out_label)

        else_part.add_to_code()

        gen_code(stmt.elsepart)

        out_label.add_to_code()

    elif isinstance(stmt, ast.FieldAccessExpr):
        gen_code(stmt.base)

        cls = ast.lookup(ast.classtable, stmt.base.type.typename)
        field = ast.lookup(cls.fields, stmt.fname)

        offset_reg = absmc.Register()
        ret_reg = absmc.Register()

        absmc.MoveInstr('move_immed_i', offset_reg, field.offset, True)
        absmc.HeapInstr('hload', ret_reg, stmt.base.end_reg, offset_reg)

        stmt.offset_reg = offset_reg
        stmt.end_reg = ret_reg

    elif isinstance(stmt, ast.ClassReferenceExpr):
        stmt.end_reg = absmc.Register('sap')

    elif isinstance(stmt, ast.NewObjectExpr):
        recd_addr_reg = absmc.Register()
        size_reg = absmc.Register()
        absmc.MoveInstr('move_immed_i', size_reg, stmt.classref.size, True)
        absmc.HeapInstr('halloc', recd_addr_reg, size_reg)

        if stmt.constr_id is None:
            stmt.end_reg = recd_addr_reg
            return

        saved_regs = []

        saved_regs.append(recd_addr_reg)

        # add a0 if the current method is not static
        if current_method.storage != 'static':
            saved_regs.append(absmc.Register('a', 0))

        # for each var in each block of the current method, add to save list
        for block in range(0, len(current_method.vars.vars)):
            for var in current_method.vars.vars[block].values():
                saved_regs.append(var.reg)

        # save each reg in the saved list
        for reg in saved_regs:
            absmc.ProcedureInstr('save', reg)

        absmc.MoveInstr('move', absmc.Register('a', 0), recd_addr_reg)

        arg_reg_index = 1

        for arg in stmt.args:
            gen_code(arg)
            absmc.MoveInstr('move', absmc.Register('a', arg_reg_index), arg.end_reg)
            arg_reg_index += 1

        absmc.ProcedureInstr('call', 'C_{}'.format(stmt.constr_id))

        # restore regs from the now-reversed save list
        for reg in reversed(saved_regs):
            absmc.ProcedureInstr('restore', reg)

        stmt.end_reg = recd_addr_reg

    elif isinstance(stmt, ast.ThisExpr):
        stmt.end_reg = absmc.Register('a', 0)

    elif isinstance(stmt, ast.MethodInvocationExpr):
        gen_code(stmt.base)

        cls = ast.lookup(ast.classtable, stmt.base.type.typename)
        for method in cls.methods:
            if stmt.mname == method.name:
                break

        saved_regs = []

        arg_reg_index = 0

        # first arg goes into a1 if desired method is not static
        if method.storage != 'static':
            arg_reg_index += 1

        # add a0 if the current method is not static
        if current_method.storage != 'static':
            saved_regs.append(absmc.Register('a', 0))

        # for each var in each block of the current method, add to save list
        for block in range(0, len(current_method.vars.vars)):
            for var in current_method.vars.vars[block].values():
                saved_regs.append(var.reg)

        # save each reg in the saved list
        for reg in saved_regs:
            absmc.ProcedureInstr('save', reg)

        if method.storage != 'static':
            absmc.MoveInstr('move', absmc.Register('a', 0), stmt.base.end_reg)

        for arg in stmt.args:
            gen_code(arg)
            absmc.MoveInstr('move', absmc.Register('a', arg_reg_index), arg.end_reg)
            arg_reg_index += 1

        absmc.ProcedureInstr('call', 'M_{}_{}'.format(method.name, method.id))

        # Store the result in a temporary register
        stmt.end_reg = absmc.Register()
        absmc.MoveInstr('move', stmt.end_reg, absmc.Register('a', 0))

        # restore regs from the reversed save list
        for reg in reversed(saved_regs):
            absmc.ProcedureInstr('restore', reg)

    elif isinstance(stmt, ast.UnaryExpr):
        gen_code(stmt.arg)

        ret = absmc.Register()
        if stmt.uop == 'uminus':
            zero_reg = absmc.Register()
            if stmt.arg.type == ast.Type('float'):
                prefix = 'f'
            else:
                prefix = 'i'
            # if uminus, put 0 - <reg> into the return reg
            absmc.MoveInstr('move_immed_{}'.format(prefix), zero_reg, 0, True)
            absmc.ArithInstr('sub', ret, zero_reg, stmt.arg.end_reg, prefix)
        else:
            # if it's a 0, branch to set 1
            # if it's a 1, we're falling through, setting to 0, and jumping out
            set_one_label = absmc.BranchLabel(stmt.lines, 'SET_ONE')
            out_label = absmc.BranchLabel(stmt.lines, 'UNARY_OUT')

            absmc.BranchInstr('bz', set_one_label, stmt.arg.end_reg)
            absmc.MoveInstr('move_immed_i', ret, 0, True)
            absmc.BranchInstr('jmp', out_label)

            set_one_label.add_to_code()

            absmc.MoveInstr('move_immed_i', ret, 1, True)

            out_label.add_to_code()

        stmt.end_reg = ret

    elif isinstance(stmt, ast.SuperExpr):
        stmt.end_reg = absmc.Register('a', 0)

    elif isinstance(stmt, ast.ArrayAccessExpr):
        # Create fake register.
        stmt.end_reg = absmc.Register('n', 0)
        print 'Found an array access. Arrays are not supported.'

    elif isinstance(stmt, ast.NewArrayExpr):
        # Create fake register.
        stmt.end_reg = absmc.Register('n', 0)
        print 'Found an array creation. Arrays are not supported.'

    else:
        print 'need instance ' + str(type(stmt))

    pop_labels()
Ejemplo n.º 21
0
def p_type(p):
    '''type : HASH TYPENAME'''
    p[0] = ast.Type(p[2], lineno=p.lineno(1))
Ejemplo n.º 22
0
    def vVariableDeclaration(self, node):
        tpe = node.type.resolveType()
        tpe.symtab = node.symtab
        if tpe.isVector() and node.params:
            self.w('VAR')
            self.w(node.id)
            self.w(':')
            if tpe.isVector() or tpe.isString():
                #print "initVectorType" + tpe.type
                tpe = self.initializeVectorType(tpe, node)
                tpe.symtab = node.symtab

            self.visit(tpe)

            if tpe.isVector() and node.params:
                self.p(';')
                self.w('New')
                self.w('(')
                self.w(node.id)
                t = tpe
                while t.isVector():
                    if t.size != None:
                        self.w(',')
                        self.visit(t.size)
                    else:
                        print 'Vectors need to be initialized fully at creation.'
                        break
                    t = t.subtype
                self.w(')')
            if (tpe.isVector() or tpe.isString()) and node.params and len(
                    node.params.children) == 2:
                self.w(';')
                if self.needsInitialization(node):
                    self.p(';')
                    self.initializeVector(node, node.type.resolveType(), [], 1,
                                          node.id)

            return
        if tpe.constant and node.isTopLevel:
            self.w('CONST')
        else:
            self.w('VAR')
        self.w(node.id)
        self.w(':')
        if tpe.isVector() or tpe.isString():
            #print "initVectorType" + tpe.type
            tpe = self.initializeVectorType(tpe, node)
            tpe.symtab = node.symtab

        self.visit(tpe)
        if tpe.isVector() and node.params:
            self.w('(')
            t = tpe
            while t.isVector():
                self.visit(t.size)
                if t.subtype.isVector():
                    self.w(',')
                t = t.subtype
            self.w(')')
        elif tpe.isString():
            if tpe.size:
                self.w('[')
                if not tpe.size.resolveType().isInt():
                    tpe_int = ast.Type('int')
                    tpe_int.symtab = node.symtab
                    cast = ast.CastExpression(tpe_int, tpe.size)
                    cast.symtab = node.symtab
                    self.visit(cast)
                else:
                    self.visit(tpe.size)
                self.w(']')

        if (tpe.isVector() or tpe.isString()) and node.params and len(
                node.params.children) == 2:
            if self.needsInitialization(node):
                self.p(';')
                self.initializeVector(node, node.type.resolveType(), [], 1,
                                      node.id)

        elif node.init:
            expr = node.init
            tpe_expr = expr.resolveType()
            tpe_ident = node.type
            if tpe_ident.type != tpe_expr.type and not (
                    tpe_ident.isFloatingPoint()
                    and tpe_expr.isFloatingPoint()):
                expr = ast.CastExpression(tpe_ident, node.init)
            self.w('=')
            self.visit(expr)
Ejemplo n.º 23
0
 def makebool(value):
     b = ast.BoolConst(value)
     b.ty = ast.Type('bool')
     return b
Ejemplo n.º 24
0
def expr_error(expr):
    '''Return whether or not the expression has a type or resolution error.

    Also ensures that the type of the expression is calculated. Call this
    first if you need to use the type of an expression.'''
    expr.type = None

    if isinstance(expr, ast.ConstantExpr):
        if expr.kind == 'int' or expr.kind == 'float' or expr.kind == 'string':
            expr.type = ast.Type(expr.kind)
        elif expr.kind == 'Null':
            expr.type = ast.Type('null')
        elif expr.kind == 'True' or expr.kind == 'False':
            expr.type = ast.Type('boolean')
        else:
            expr.type = ast.Type('error')
            signal_error('Unknown type {}'.format(expr.type), expr.lines)

    elif isinstance(expr, ast.VarExpr):
        expr.type = expr.var.type

    elif isinstance(expr, ast.UnaryExpr):
        arg = expr.arg
        arg_err = expr_error(arg)
        if arg_err:
            expr.type = ast.Type('error')
        elif expr.uop == 'uminus':
            if arg.type.is_numeric():
                expr.type = arg.type
            else:
                signal_error(
                    'Expecting an integer or float argument to unary '
                    'minus. Found {}'.format(arg.type), expr.lines)
                expr.type = ast.Type('error')
        elif expr.uop == 'neg':
            if arg.type == ast.Type('boolean'):
                expr.type = arg.type
            else:
                signal_error(
                    'Expecting a boolean argument to ! (negation). '
                    'Found {}'.format(arg.type), expr.lines)
                expr.type = ast.Type('error')

    elif isinstance(expr, ast.BinaryExpr):
        op_names = {
            'add': '+',
            'sub': '-',
            'mul': '*',
            'div': '/',
            'and': '&&',
            'or': '||',
            'eq': '==',
            'neq': '!=',
            'lt': '<',
            'leq': '<=',
            'gt': '>',
            'geq': '>='
        }
        bop = expr.bop
        arg1 = expr.arg1
        arg2 = expr.arg2
        arg1_err = expr_error(arg1)
        arg2_err = expr_error(arg2)
        if arg1_err or arg2_err:
            expr.type = ast.Type('error')
        elif bop == 'add' or bop == 'sub' or bop == 'mul' or bop == 'div':
            type1 = arg1.type
            type2 = arg2.type
            if type1.is_numeric() and type2.is_numeric():
                if type1 == ast.Type('float') or type2 == ast.Type('float'):
                    expr.type = ast.Type('float')
                else:
                    expr.type = ast.Type('int')
            else:
                signal_error(
                    'Expecting float or integer arguments for the '
                    'operator "{}". Found {} on the left and {} on '
                    'the right.'.format(op_names[bop], type1, type2),
                    expr.lines)
                expr.type = ast.Type('error')
        elif bop == 'and' or bop == 'or':
            type1 = arg1.type
            type2 = arg2.type
            if type1 == ast.Type('boolean') and type2 == ast.Type('boolean'):
                expr.type = ast.Type('boolean')
            else:
                signal_error(
                    'Expecting boolean arguments for the operator '
                    '"{}". Found {} on the left and {} on the '
                    'right.'.format(op_names[bop], type1, type2), expr.lines)
        elif bop == 'lt' or bop == 'leq' or bop == 'gt' or bop == 'geq':
            type1 = arg1.type
            type2 = arg2.type
            if type1.is_numeric() and type2.is_numeric():
                expr.type = ast.Type('boolean')
            else:
                signal_error(
                    'Expecting int or float arguments for the'
                    'operator "{}". Found {} on the left and {} on '
                    'the right.'.format(op_names[bop], type1, type2),
                    expr.lines)
                expr.type = ast.Type('error')
        elif bop == 'eq' or bop == 'neq':
            type1 = arg1.type
            type2 = arg2.type
            if type1.subtype_of(type2) or type2.subtype_of(type1):
                expr.type = ast.Type('boolean')
            else:
                signal_error(
                    'Expecting compatible arguments for the operator '
                    '"{}". One argument must be the subtype of the '
                    'other. Found {} on the left and {} on the '
                    'right.'.format(op_names[bop], type1, type2), expr.lines)
                expr.type = ast.Type('error')

    elif isinstance(expr, ast.FieldAccessExpr):

        err = expr_error(expr.base)
        if err:
            expr.type = ast.Type('error')
            return True

        cls = ast.lookup(ast.classtable, expr.base.type.typename)

        cur_cls = cls
        while cur_cls is not None:
            field = ast.lookup(cur_cls.fields, expr.fname)
            if field is not None:

                # Ensure it's not static, and not accessed by Class.foo, and it's accessable
                if (expr.base.type.kind == 'class') and (field.storage != 'static') \
                        and ((field.visibility != 'private') or (expr.base.type.typename == current_class.name)):
                    break

                # Ensure it's static, and accessed by Class.foo, and it's accessable
                if (expr.base.type.kind == 'class-literal') and (field.storage == 'static') \
                        and ((field.visibility != 'private') or (expr.base.type.typename == current_class.name)):
                    break
            field = None
            cur_cls = cur_cls.superclass

        if field is None:
            signal_error('Could not resolve field {}'.format(expr.fname),
                         expr.lines)
            expr.type = ast.Type('error')
            return True

        expr.type = ast.Type(field.type)

    elif isinstance(expr, ast.ThisExpr):
        expr.type = ast.Type(current_class.name)

    elif isinstance(expr, ast.MethodInvocationExpr):

        err = expr_error(expr.base)
        if err:
            expr.type = ast.Type('error')
            return True

        cls = ast.lookup(ast.classtable, expr.base.type.typename)
        method = None
        cur_cls = cls

        while cur_cls is not None:
            for i in cur_cls.methods:
                if expr.mname == i.name:
                    method = i
                    break

            if method is not None:
                if (expr.base.type.kind == 'class') and (method.storage != 'static') \
                        and ((method.visibility != 'private') or (expr.base.type.typename == current_class.name)):
                    break

                if (expr.base.type.kind == 'class-literal') and (method.storage == 'static') \
                        and ((method.visibility != 'private') or (expr.base.type.typename == current_class.name)):
                    break
            method = None
            cur_cls = cur_cls.superclass

        if method is None:
            expr.type = ast.Type('error')
            signal_error('Could not resolve method \'{}\''.format(expr.mname),
                         expr.lines)
            return True

        method_params = method.vars.vars[0].values()

        # Ensure number of params match
        if len(method_params) != len(expr.args):
            expr.type = ast.Type('error')
            signal_error(
                'Method \'{}\' expects {} args, received {}'.format(
                    method.name, len(method_params), len(expr.args)),
                expr.lines)
            return True

        for i in range(0, len(method_params)):

            arg_err = expr_error(expr.args[i])
            if arg_err:
                expr.type = ast.Type('error')
                return True

            nth_param = ast.Type(method_params[i].type)
            nth_arg = ast.Type(expr.args[i].type)

            if not nth_arg.subtype_of(nth_param):
                expr.type = ast.Type('error')
                signal_error(
                    'Method argument number {0} is not a subtype '
                    'of construtor parameter number {0}. Expects \'{1}\', received \'{2}\'.'
                    .format(i + 1, nth_param.typename,
                            nth_arg.typename), expr.lines)
                return True

        expr.type = ast.Type(method.rtype)

    elif isinstance(expr, ast.AssignExpr):

        lhs_err = expr_error(expr.lhs)
        rhs_err = expr_error(expr.rhs)

        if lhs_err or rhs_err:
            expr.type = ast.Type('error')
            return True

        lhs = ast.Type(expr.lhs.type)
        rhs = ast.Type(expr.rhs.type)

        if not rhs.subtype_of(lhs):
            expr.type = ast.Type('error')
            signal_error('{} not a subtype of {}'.format(rhs, lhs), expr.lines)
        else:
            expr.type = ast.Type(rhs)

    elif isinstance(expr, ast.NewObjectExpr):

        cls = ast.lookup(ast.classtable, expr.classref.name)

        expr.constr_id = None

        # After ensuring the # of args match, if there's no constructor, allow it
        if len(cls.constructors) == 0 and len(expr.args) == 0:
            expr.type = ast.Type(expr.classref.name)
            return False

        if cls.constructors[0].visibility == 'private':
            expr.type = ast.Type('error')
            signal_error(
                'Constructor for class {} is private'.format(cls.name),
                expr.lines)
            return True

        # Ensure number of args match
        if len(cls.constructors[0].vars.vars[0]) != len(expr.args):
            expr.type = ast.Type('error')
            signal_error(
                'Constructor for class {} expects {} arguments, received {}'.
                format(cls.name, len(cls.constructors[0].vars.vars[0]),
                       len(expr.args)), expr.lines)
            return True

        constr_params = cls.constructors[0].vars.vars[0].values()
        # Ensure each arg is a subtype of each param
        for i in range(0, len(constr_params)):

            arg_err = expr_error(expr.args[i])
            if arg_err:
                expr.type = ast.Type('error')
                return True

            nth_param = ast.Type(constr_params[i].type)
            nth_arg = ast.Type(expr.args[i].type)

            if not nth_arg.subtype_of(nth_param):
                expr.type = ast.Type('error')
                signal_error(
                    'Constructor argument number {0} is not a subtype '
                    'of construtor parameter number {0}. Expects \'{1}\', received \'{2}\'.'
                    .format(i + 1, nth_param.typename,
                            nth_arg.typename), expr.lines)
                return True

        expr.constr_id = cls.constructors[0].id

        expr.type = ast.Type(expr.classref.name)

    elif isinstance(expr, ast.ClassReferenceExpr):
        expr.type = ast.Type(expr.classref.name, None, True)

    elif isinstance(expr, ast.SuperExpr):
        if current_class.superclass is None:
            signal_error(
                'Class {} has no superclass.'.format(current_class.name),
                expr.lines)
            expr.type = ast.Type('error')
        else:
            expr.type = ast.Type(current_class.superclass.name)

    elif isinstance(expr, ast.AutoExpr):

        err = expr_error(expr.arg)
        if err:
            expr.type = ast.Type('error')
            return True

        if expr.arg.type.is_numeric():
            expr.type = ast.Type(expr.arg.type)
        else:
            expr.type = ast.Type('error')
            signal_error(
                'Auto expression must be int or float; received {}'.format(
                    expr.arg.type), expr.lines)

    elif isinstance(expr, ast.ArrayAccessExpr) or isinstance(
            expr, ast.NewArrayExpr):
        expr.type = ast.Type('error')
        signal_error("Array expression found, this is not supported!",
                     expr.lines)

    return expr.type.is_error()
Ejemplo n.º 25
0
def get_random_type():
    return ast.Type(get_rand_int(1, ast.Type.count()))