예제 #1
0
def method_invocation(element):
    if element[0].tag == "name":
        name = name_to_str(element.find("name"))
        to_file(element)
        declaration_site = element.env.get_declaration_site_for_method_name(
            name,
            argument_list(element))
        element.attrib["type"] = element.env.get_type_for_declaration_site(
            declaration_site)
        element.declaration = declaration_site
    elif element[0].tag == "primary":
        primary_type = element[0].attrib["type"]
        error_if(is_primitive(primary_type),
              "Cannot invoke method on primitive " + primary_type)
        declaration_site = element.env.get_declaration_site_for_class_name(
            primary_type)
        identifier = element.find("tok_identifier").text
        method_declaration = \
            declaration_site.env.get_declaration_site_for_method_name(
            identifier,
            argument_list(element))
        element.attrib["type"] = \
            method_declaration.env.get_type_for_declaration_site(
            method_declaration)
        element.declaration = method_declaration
    else:
        assert False
예제 #2
0
def typecheck_other_conditions(tree):
    """Takes an abstract syntax tree which has Environments associated with it
    and typechecks it. Raises JoosSyntaxException if the tree does not
    typecheck."""
    # A constructor in a class other than java.lang.Object implicitly calls the
    # zero-argument constructor of its superclass. Check that this
    # zero-argument constructor exists.
    #
    # Check that the name of a constructor is the same as the name of its
    # enclosing class.

    for ctor in tree.findall(".//constructor_declaration"):
        clazz = ctor.env.findclass(ctor.get("name"))
        superclazz = clazz.superclass
        error_if(not superclazz.env.find_constructor(tuple([])),
              "No zero-argument constructor")

    for lhs in tree.findall(".//assignment/left_hand_side"):
        if lhs.find("./name") is None:
            continue
        type_name = name_to_str(lhs.find("./name"))
        type_decl = lhs.env.get_declaration_site_for_variable_name(type_name, lhs.find("./name"))

        error_if("final" in modifiers(type_decl),
              "Final field on LHS")

    #Check that no objects of abstract classes are created.
    for expr in tree.findall(".//class_instance_creation_expression"):
        expr_type = name_to_str(expr.find("./name"))
        instantiated_class = tree.env.findclass(expr_type)

        error_if("abstract" in modifiers(instantiated_class) or
              instantiated_class.tag == "interface",
              "Cannot instantiate abstract classes.")

        class_name = instantiated_class.get("canonical_name")
        ctor_decl = expr.env.get_declaration_site_for_constructor_name(
            class_name,
            argument_list(expr))

        error_if(expr.env.find_package_name() !=
                 ctor_decl.env.find_package_name()
                 and "protected" in modifiers(ctor_decl),
              "Invocation of Protected Constructor.")

    # Check that the implicit this variable is not accessed in a static method
    # or in the initializer of a static field.
    for smethod in \
            [x for x in tree.findall(".//method") if "static" in modifiers(x)]:
        error_if(smethod.find(".//tok_this") is not None,
              "Cannot acces this in static method.")
    for field in \
            [x for x in tree.findall(".//field") if "static" in modifiers(x)]:
        error_if(field.find(".//tok_this") is not None,
              "Cannot acces this in static field.")

    #if_then_stmts = tree.find(".//if_then_statement/expression//assignment")
    #error_if(if_then_stmts is not None,
           #"No assignment in if_then expressions")
    while_stmts = tree.find(".//while_statement/expression//assignment")
예제 #3
0
def method_invocation(subtree):
    method = subtree.declaration
    subtree.slot = generate_new_stack_slot(subtree)
    pushes = push_arguments(subtree)
    if "static" not in modifiers(method):
        if subtree[0].tag == "name":
            name(subtree[0], args=argument_list(subtree))
        pushes.append("push " + stack_slot_to_operand(subtree[0].slot))

    return_slot = stack_slot_to_operand(subtree.slot)
    if "native" in modifiers(method):
        call = "call " + mangle_native_fn_name(subtree.declaration)
        argument_slot = subtree.find("./argument_list").slot
        operand = stack_slot_to_operand(argument_slot)
        pushes = ["mov eax, {slot}".format(slot=operand)]
    elif "static" in modifiers(method):
        call = "call " + mangle_fn_name(subtree.declaration)
    else:
        call = """
mov eax, {this_ptr}
mov eax, [eax]
add eax, {method_offset}
mov eax, [eax]
call eax
""".format(
            this_ptr=stack_slot_to_operand(subtree[0].slot), method_offset=str(4 * method.mega_vtable_offset)
        )

    subtree.assembly = """
; method invocation {dbg}
{push_arguments}
{call}
mov {return_slot}, eax
; end method invocation
""".format(
        dbg=collect_debug_text(subtree), call=call, push_arguments="\n".join(pushes), return_slot=return_slot
    )
예제 #4
0
def resolve_constructor_name(element):
    return element.env.get_declaration_site_for_constructor_name(
            name_to_str(element.find("name")),
            argument_list(element))