Ejemplo n.º 1
0
def typecheck_mult(node, c, method, t_i, c_i):
    expected_node = ['MultiplyExpression', 'DivideExpression', 'ModuloExpression']
    if node.name not in expected_node:
        logging.error("FATAL ERROR: expected", expected_node) 
        sys.exit(1)
    
    if len(node.children) == 0:
        logging.error("FATAL ERROR: %s has no children in typecheck_mult()" %
            expected_node) 
        sys.exit(1) 

    elif len(node.children) != 2:
        logging.error('FATAL ERROR: typecheck_mult got %s node with %d children' %
            (node.name, len(node.children)))
        sys.exit(1)

    else:
        t1 = typecheck_expr(node[0], c, method, t_i, c_i)
        t2 = typecheck_expr(node[1], c, method, t_i, c_i)
        if primitives.is_numeric(t1) and primitives.is_numeric(t2):
            node.typ = 'Int'
            return node.typ
        else:
            logging.error("typecheck failed: mult/div/mod not num")
            sys.exit(42)
Ejemplo n.º 2
0
def typecheck_relational(node, c, method, t_i, c_i):
    expected_node = ['LessThanExpression', 'LessThanEqualExpression',
        'GreaterThanExpression', 'GreaterThanEqualExpression']
    if node.name not in expected_node:
        logging.error("FATAL ERROR: typecheck_relational() expected", expected_node) 
        sys.exit(1)
    
    if len(node.children) == 0:
        logging.error("FATAL ERROR: has no children", expected_node) 
        sys.exit(1) 

    elif len(node.children) != 2:
        logging.error('FATAL ERROR: typecheck_relational() on expression %s with %d children' %
            (node.name, len(node.children)))
        sys.exit(1)

    else:
        t1 = typecheck_expr(node[0], c, method, t_i, c_i)
        t2 = typecheck_expr(node[1], c, method, t_i, c_i)
        if primitives.is_numeric(t1) and primitives.is_numeric(t2):
            node.typ = 'Boolean'
            return node.typ
        else:
            logging.error("typecheck failed: Relational:", t1, t2)
            sys.exit(42)
Ejemplo n.º 3
0
def typecheck_add(node, c, method, t_i, c_i):
    expected_node = ['AddExpression', 'SubtractExpression']
    if node.name not in expected_node:
        logging.error("FATAL ERROR: expected", expected_node) 
        sys.exit(1)
    
    if len(node.children) == 0:
        logging.error("FATAL ERROR: %s has no children" % expected_node) 
        sys.exit(1) 

    elif len(node.children) != 2:
        logging.error('FATAL ERROR: typecheck_add() on expression %s with %d children' %
            (node.name, len(node.children)))
        sys.exit(1)

    else:
        t1 = typecheck_expr(node[0], c, method, t_i, c_i)
        t2 = typecheck_expr(node[1], c, method, t_i, c_i)
        if node.name == 'AddExpression' and \
            (t1 == "java.lang.String" or t2 == "java.lang.String"):
            if t1 != "Void" and t2 != "Void":
                node.typ = 'java.lang.String'
                return node.typ
            else:
                logging.error("typecheck failed: string add void")
                sys.exit(42)
        elif primitives.is_numeric(t1) and primitives.is_numeric(t2):
            node.typ = 'Int'
            return node.typ
        else:
            logging.error("typecheck failed: Add:", t1, t2)
            sys.exit(42)
Ejemplo n.º 4
0
def gen_add_expr(info, node, method_obj):
    output = []

    # Numbers, just add.
    if primitives.is_numeric(node[0].typ) and primitives.is_numeric(node[1].typ):
        output.extend(gen_binary_expr_common(info, node, method_obj))
        output.append('add eax, ebx')
    
    # If they are objects, we do the following:
    # 1. Use String.valueOf() on each operand.
    # 2. Do a LHS.concat(RHS), which returns a new string.
    elif node[0].typ == 'java.lang.String' or node[1].typ == 'java.lang.String':

        # Convert LHS to a string.
        output.extend(gen_string_valueof(info, node[0], method_obj))
        output.append('push eax')

        # Convert RHS to a string.
        output.extend(gen_string_valueof(info, node[1], method_obj))
        output.append('push eax')

        # Receiver is LHS, Argument is RHS (already done!), just need to call
        # the correct method.
        output.append('call METHOD~java.lang.String.concat~java.lang.String')
        
        # Jump back.
        output.append('add esp, 8')

    else:
        logging.error('FATAL ERROR: invalid add')
        sys.exit(1)

    return output
Ejemplo n.º 5
0
def typecheck_equality(node, c, method, t_i, c_i):
    expected_node = ['EqualExpression', 'NotEqualExpression']
    if node.name not in expected_node:
        logging.error("FATAL ERROR: expected", expected_node) 
        sys.exit(1)
    
    if len(node.children) == 0:
        logging.error("FATAL ERROR: has no children", expected_node) 
        sys.exit(1) 

    elif len(node.children) != 2:
        logging.error('FATAL ERROR: typecheck_equality on %d children' %
            len(node.children))
        sys.exit(1)

    else:
        t1 = typecheck_expr(node[0], c, method, t_i, c_i)
        t2 = typecheck_expr(node[1], c, method, t_i, c_i)
        if primitives.is_numeric(t1) and primitives.is_numeric(t2):
            node.typ = "Boolean"
            return node.typ
        elif t1 == "Boolean" and t2 == "Boolean":
            node.typ = "Boolean"
            return node.typ
        elif is_assignable(t1, t2, c_i) or is_assignable(t2, t1, c_i): 
            node.typ = "Boolean"
            return node.typ
        else:
            logging.error("typecheck failed: equality between", t1, t2)
            sys.exit(42)
Ejemplo n.º 6
0
def typecheck_cast_expression(node, c, method, t_i, c_i):
    if node.name != 'CastExpression':
        logging.error('FATAL: Invalid node %s for typecheck_cast_expression' %
            node.name)
        sys.exit(1)

    expr_type = typecheck_expr(node[1], c, method, t_i, c_i)
    if (primitives.is_numeric(expr_type) and primitives.is_numeric(node[0].canon)) \
        or is_assignable(expr_type, node[0].canon, c_i) \
        or is_assignable(node[0].canon, expr_type, c_i):
        return node[0].canon
    else:
        logging.error('Cast expression of type %s into %s' %
            (expr_type, node[0].canon))
        sys.exit(42)
Ejemplo n.º 7
0
def typecheck_array_access(node, c, method, t_i, c_i):
    if node.name != 'ArrayAccess':
        logging.error('FATAL ERROR: invalid node %s for array access' %
            node.name)
        sys.exit(1)

    receiver_type = None
    if node[0][0].name == 'Name':
        receiver_type = typecheck_name(node[0][0])
    else:
        receiver_type = typecheck_expr(node[0][0], c, method,
            t_i, c_i)

    # Must be array type.
    if not is_array_type(receiver_type):
        logging.error('Cannot index into non-array type')
        sys.exit(42)

    # Expression must be a number.
    expr_type = typecheck_expr(node[1], c, method, t_i, c_i)
    
    if not primitives.is_numeric(expr_type):
        logging.error('Array access with non-numeric type %s' % expr_type)
        sys.exit(42)

    node.typ = get_arraytype(receiver_type)
    return node.typ
Ejemplo n.º 8
0
def is_assignable(type1, type2, c_i):
    # Call other helper for anything having to do with arrays.
    if is_array_type(type1) or is_array_type(type2):
        return is_array_assignable(type1, type2, c_i)

    if type1 in ['Void', 'Null'] or type2 == 'Void':
        return False
    elif type1 == type2:
        return True
    elif primitives.is_reference(type1) and type2 == 'Null':
        return True
    elif primitives.is_numeric(type1) and primitives.is_numeric(type2):
        return primitives.is_widening_conversion(type1, type2)
    elif primitives.is_reference(type1) and primitives.is_reference(type2):
        return is_nonstrict_subclass(type1, type2, c_i)
    else:
        return False
Ejemplo n.º 9
0
def typecheck_creation(node, c, method, t_i, c_i):
    expected_node = 'CreationExpression'
    if node.name != expected_node:
        logging.error("FATAL ERROR: expected", expected_node) 
        sys.exit(1)

    creation_type = node[0].canon
    if is_array_type(creation_type):
        if len(node[1].children) > 1:
            logging.error('Too many args to array creation')
            sys.exit(42)
        if len(node[1].children) == 1:
            expr_type = typecheck_expr(node[1][0], c,
                method, t_i, c_i)
            if not primitives.is_numeric(expr_type):
                logging.error('Invalid array creation argument')
                sys.exit(42)
        node.typ = creation_type
        return node.typ

    else:
        cons_name = creation_type.split('.')[-1]

        # Check that we don't call constructor of an abstract class.
        if 'Abstract' in c_i[creation_type].mods:
            logging.error('Cannot call constructor of abstract class')
            sys.exit(42)
        
        arg_types = []
        for arg_expr in node[1].children:
            arg_types.append(typecheck_expr(arg_expr, c, method,
                t_i, c_i))

        cons_decl = name_resolve.constructor_accessable(c_i, t_i,
            creation_type, cons_name, arg_types, c.name, False)

        cons = class_hierarchy.Temp_Constructor(cons_name, arg_types)
        # TODO: Check that cons is not protected, and if it is, we have access
        # to call it.
        if cons_decl != None and cons in c_i[creation_type].declare:
            node.typ = creation_type
            return node.typ
        else:
            logging.error('Invalid constructor call')
            sys.exit(42)
Ejemplo n.º 10
0
def gen_string_valueof(info, node, method_obj):
    output = []

    # Evaluate node. Result is in eax.
    output.extend(gen_expr(info, node, method_obj))
    
    # Based on the type, call the correct method. Primitives have their own
    # version, objects all use the java.lang.Object version.
    valueof_method_lbl = ''
    if primitives.is_numeric(node.typ) or node.typ == 'Boolean' or \
        node.typ == 'java.lang.String':
        valueof_method_lbl = 'STATICMETHOD~java.lang.String.valueOf~%s' % node.typ
    else:
        valueof_method_lbl = 'STATICMETHOD~java.lang.String.valueOf~java.lang.Object'
    output.append('push eax')
    output.append('call %s' % valueof_method_lbl) # resulting string is in eax
    output.append('add esp, 4')

    return output # result is in eax
Ejemplo n.º 11
0
def typecheck_unary(node, c, method, t_i, c_i):
    if node.name not in ['NotExpression', 'NegateExpression']:
        logging.error("FATAL ERROR: typecheck_unary()") 
        sys.exit(1)
    
    if len(node.children) == 0:
        logging.error("FATAL ERROR: UnaryExpression has no children") 
        sys.exit(1) 

    if node.name == 'NotExpression':
        t = typecheck_expr(node[0], c, method, t_i, c_i)
        if t != "Boolean":
            logging.error("typecheck failed: NotOp expects boolean; got:",t)
            sys.exit(42)
        node.typ = t
        return t

    elif node.name == 'NegateExpression':
        t = typecheck_expr(node[0], c, method, t_i, c_i)
        if not primitives.is_numeric(t):
            logging.error("typecheck failed: SubtractOp expects number; got:",t)
            sys.exit(42)
        node.typ = t
        return t
Ejemplo n.º 12
0
def try_eval_expr(node):
    if node.name == 'Literal':
        if node[0].name == 'BooleanLiteral':
            return node[0].value.value == "true"
        elif node[0].name == 'DecimalIntegerLiteral':
            return int(node[0].value.value)
        else:
            pass # TODO STRINGS AND SHIT F**K
    elif node.name == 'OrExpression':
        expr1 = try_eval_expr(node[0])
        expr2 = try_eval_expr(node[1])
        if expr1 != None and expr2 != None:
            ret = expr1 == True or expr2 == True
            return ret
    elif node.name == 'AndExpression':
        expr1 = try_eval_expr(node[0])
        expr2 = try_eval_expr(node[1])
        if expr1 != None and expr2 != None:
            ret = expr1 == True and expr2 == True
            return ret
    elif node.name in ['EqualExpression', 'NotEqualExpression']:
        expr1 = None
        expr2 = None
        if node[0].typ == 'Boolean' or primitives.is_numeric(node[0].typ):
            expr1 = try_eval_expr(node[0])
            expr2 = try_eval_expr(node[1])
            if expr1 != None and expr2 != None:
                if node.name == 'EqualExpression':
                    return expr1 == expr2
                else:
                    return expr1 != expr2
            else:
                return None
        else:
            return None
    elif node.name in ['LessThanExpression', 'LessThanEqualExpression',
        'GreaterThanExpression', 'GreaterThanEqualExpression']:
        expr1 = None
        expr2 = None
        if primitives.is_numeric(node[0].typ):
            expr1 = try_eval_expr(node[0])
            expr2 = try_eval_expr(node[1])
            if expr1 != None and expr2 != None:
                if node.name == 'LessThanExpression':
                    return expr1 < expr2
                elif node.name == 'GreaterThanExpression':
                    return expr1 > expr2
                elif node.name == 'LessThanEqualExpression':
                    return expr1 <= expr2
                elif node.name == 'GreaterThanEqualExpression':
                    return expr1 >= expr2
            else:
                return None
    elif node.name in ['AddExpression', 'SubtractExpression']:
        expr1 = None
        expr2 = None
        if primitives.is_numeric(node[0].typ):
            expr1 = try_eval_expr(node[0])
            expr2 = try_eval_expr(node[1])
            if expr1 != None and expr2 != None:
                if node.name == 'AddExpression':
                    return expr1 + expr2
                elif node.name == 'SubtractExpression':
                    return expr1 - expr2
            else:
                return None
    elif node.name in ['MultiplyExpression', 'DivideExpression',
        'ModuloExpression']:
        expr1 = None
        expr2 = None
        if primitives.is_numeric(node[0].typ):
            expr1 = try_eval_expr(node[0])
            expr2 = try_eval_expr(node[1])
            if expr1 != None and expr2 != None:
                if node.name == 'MultiplyExpression':
                    return expr1 * expr2
                elif node.name == 'DivideExpression':
                    return expr1 / expr2
                elif node.name == 'ModuloExpression':
                    return None # TODO WHAT MODULO TOO HARD I GIVE UP - Holden
            else:
                return None
    elif node.name in ['NegateExpression', 'NotExpression']:
        # TODO FUUUUUUUUUUUUUUUUU
        pass
    elif node.name == 'CastExpression':
        return try_eval_expr(node[1])
    elif node.name == 'PostfixExpression':
        return try_eval_expr(node[0])

    return None