コード例 #1
0
ファイル: environment.py プロジェクト: thurn/cs444-compiler
def build_envs(files):
    """Lexes/Parses/does checking for all files in files."""
    global find_all_in_package_cache
    find_all_in_package_cache = {}
    trees = [ElementTree.ElementTree(file="Array.xml").getroot()]
    files = ["$Array.java"] + files
    trees[0].filename = "$Array.java"

    for f in files[1:]:
        if f in cached_trees:
            trees += [cached_trees[f]]
        else:
            CurrentFile.name = f
            tree = parse(lex(open(f).read()), f)
            cached_trees[f] = tree
            trees += [tree]
    name_to_class = {}

    for tree in trees:
        CurrentFile.name = tree.filename
        clazz = find_type_decl(tree)
        name = clazz.get("canonical_name")
        error_if(name in name_to_class, "Duplicate class defined.")
        if name.find(".") != -1:
            name_to_class[name] = clazz

    for x in range(0, len(trees)):
        CurrentFile.name = trees[x].filename
        if trees[x] not in cached_environments:
            build_environments(trees[x], trees, name_to_class)
            cached_environments[files[x]] = trees[x].env

    for tree in trees:
        CurrentFile.name = tree.filename
        clazz = find_type_decl(tree)
        clazz.env.add_superclass_methods()
        clazz.env.add_superclass_fields()
        check_types(tree)
        check_hierarchy(tree)

    return trees
コード例 #2
0
ファイル: environment.py プロジェクト: thurn/cs444-compiler
    def initialize_compilation_unit_environment(self, name_to_class, tree,
                                                trees):
        pkg = ""

        if tree.find(".//package//name"):
            pkg = name_to_str(tree.find(".//package//name"))

        self.package_name = pkg
        this_clazz = find_type_decl(tree)
        self.classes_this[this_clazz.get("name")] = this_clazz
        self.classes_this["this"] = this_clazz
        self.classes_package = find_all_in_package(pkg, trees)

        self.add_single_type_import_statements(pkg, this_clazz, tree, trees)

        imported = []
        self.add_import_star_statements(imported, tree, trees)
        add_dict(find_all_in_package(pkg, trees), self.classes_package)
        add_dict(name_to_class, self.classes_fully_qualified)
コード例 #3
0
ファイル: environment.py プロジェクト: thurn/cs444-compiler
def find_all_in_package(packagename, trees):
    """Returns all classses in packagename."""
    global find_all_in_package_cache
    if packagename in find_all_in_package_cache:
        return find_all_in_package_cache[packagename]
    retn = {}
    prefix = False
    for tree in trees:
        clazz = find_type_decl(tree)
        if clazz is None:
            continue
        if tree.find(".//package/name") is not None:
            package_name = name_to_str(tree.find(".//package/name"))
            if package_name == packagename:
                retn[clazz.get("name")] = clazz
            elif (packagename == package_name[:len(packagename)]
                  and package_name[len(packagename)] == "."):
                prefix = True
        elif packagename == "":
            retn[clazz.get("name")] = clazz
    error_if(not prefix and len(retn.keys()) == 0,
             "No class in %s" % packagename)
    find_all_in_package_cache[packagename] = retn
    return retn
コード例 #4
0
ファイル: environment.py プロジェクト: thurn/cs444-compiler
    def __findclass(self, fullname, trees):
        """Returns the 'class' object for the class.

        Fullname: fully qualified name of a class
        pkg: package to look in
        trees: set of ASTs to look in

        """
        name = fullname[fullname.rfind(".") + 1:]
        pkg = fullname[:fullname.rfind(".")]
        for tree in trees:
            clazz = find_type_decl(tree)
            if clazz is None:
                continue
            if name == clazz.get("name"):
                package_name = ""
                if tree.find(".//package/name") is not None:
                    package_name = name_to_str(tree.find(".//package/name"))
                if ((package_name == "" and fullname == name) or
                    (package_name == "java.lang" and fullname == name) or
                    pkg == package_name or
                    fullname[:len(fullname) - len(name) - 1] == package_name):
                    return clazz
        error_if(True, "No class to import / Class Not Found.")
コード例 #5
0
ファイル: generate.py プロジェクト: thurn/cs444-compiler
def check_and_generate(files):
    init_globals()  # reset global state
    try:
        out = open("output/out.s", "w")

        trees = typechecker.check_files(files)
        initializer_list = []

        mega_vtable_offset = 1
        type_tag = 0
        string_literal_index = 0
        for tree in trees:
            clazz = find_type_decl(tree)
            clazz.type_tag = type_tag
            method_list.class_list += [clazz]
            type_tag += 1
            methods = (
                tree.findall(".//method")
                + tree.findall(".//constructor_declaration")
                + tree.findall(".//abstract_method")
            )
            for method in methods:
                method.mega_vtable_offset = mega_vtable_offset
                mega_vtable_offset += 1
                method_list.method_list += [method]
                if "static" in modifiers(method):
                    slot = -2
                else:
                    slot = -3
                for param in method.findall(".//param"):
                    param.slot = slot
                    slot -= 1

            counters.mega_vtable_members = mega_vtable_offset

            for string_literal in tree.findall(".//string_literal"):
                string_literal.index = string_literal_index
                string_literal_index += 1

        out.write(instanceof_table(trees))

        for tree in trees:
            CurrentFile.name = tree.filename
            CurrentFile.mangled_name = CurrentFile.name.replace(".", "_").replace("$", "_").replace("/", "_")
            CurrentFile.static_slot = 0

            for this in tree.findall(".//tok_this"):
                this.slot = -2

            generate(tree)
            to_file(tree, tree.filename + ".xml")

            out.write("section .data\n")
            for clazz in tree.findall(".//class"):
                out.write(mega_vtable_for_class(clazz))

            out.write("section .text\n")
            initializer_name = "static_init_" + CurrentFile.mangled_name
            out.write(
                """
; global {initializer_name}
{initializer_name}:
push ebp
mov ebp, esp
sub esp, {frame_size}
""".format(
                    initializer_name=initializer_name, frame_size=CurrentFile.static_slot * 4
                )
            )
            initializer_list.append(initializer_name)

            for field in tree.findall(".//field"):
                if "static" in modifiers(field):
                    mangled_name = mangle_field_name(field)
                    out.write(
                        """
; initializing {mangled_name}
{field_assembly}
mov eax, {mangled_name}
mov ebx, {assigned_value}
mov DWORD [eax], ebx
""".format(
                            mangled_name=mangled_name,
                            field_assembly=field.assembly,
                            assigned_value=stack_slot_to_operand(field.slot),
                        )
                    )

            out.write(
                """
leave
ret
; done global static initialization
"""
            )

            for constructor in tree.findall(".//constructor_declaration"):
                out.write(constructor.assembly + "\n")

            for method in tree.findall(".//method"):
                if method.find("block") is not None:
                    out.write(method.assembly + "\n")

            out.write("\nsection .data\n")
            for string_literal in tree.findall(".//string_literal"):
                string_value = string_literal.get("value")
                expanded_value = expand_string_literal(string_value)
                out.write("\n; string literal " + string_value + "\n")
                out.write("__string_literal_" + str(string_literal.index) + ":\n")
                out.write("dd _vtable_java_lang_$Array_ ; vtable pointer\n")
                out.write("dd -3 ; type tag for char\n")
                out.write("dd " + str(len(expanded_value)) + " ; string length\n")
                for character in expanded_value:
                    out.write("dd " + str(hex(ord(character))) + "\n")
                out.write("")

            out.write("\nsection .bss\n")
            for field in tree.findall(".//field"):
                if "static" in modifiers(field):
                    mangled_name = mangle_field_name(field)
                    out.write("""{mangled_name} resb 4""".format(mangled_name=mangled_name) + "\n")

        out.write("section .text\n")
        out.write("; prelude\n")
        out.write("extern __malloc\n")
        out.write("extern __debexit\n")
        out.write("extern __exception\n")
        out.write("extern NATIVEjava.io.OutputStream.nativeWrite\n")
        out.write("global _start\n")
        out.write("_start:\n")
        out.write("call install_segv_handler\n")

        for initializer in initializer_list:
            out.write("call " + initializer + "\n")

        class_name = mangle_class_name(find_type_decl(trees[1]).get("canonical_name"))
        out.write("call " + class_name + "test_\n")
        out.write("mov ebx, eax\n")
        out.write("mov eax, 1\n")
        out.write("int 0x80 ; invoke exit(1)\n")
        out.write("; end prelude\n")
        out.write(
            """
%define __NR_signal 48
%define SIGSEGV     11
global install_segv_handler
install_segv_handler:
  mov eax, __NR_signal
  mov ebx, SIGSEGV
  mov ecx, __exception
  int 0x80
  ret
"""
        )

        return 0
    except JoosSyntaxException, e:
        if Testing.testing:
            return 42
        else:
            out.write("\n" + e.msg + "\n")
            raise
コード例 #6
0
ファイル: environment.py プロジェクト: thurn/cs444-compiler
def check_types(tree):
    """Checks for type and other errors in tree."""
    toks = tree.findall(".//package//tok_identifier")
    name = ""

    for ident in range(0, len(toks)):
        name += toks[ident].text
        error_if(name in tree.env.classes_fully_qualified and
              name.find(".") != -1,
                  "Package prefix conflicts with class name.")
        if ident < len(toks) - 1:
            name += "."

    clazz = find_type_decl(tree)
    if clazz is None:
        return

    for _ in all_with_modifier(clazz, "method", "abstract"):
        error_if("abstract" not in modifiers(clazz),
              "Abstract methods must be in abstract classes.")

    for it in clazz.findall(".//implements/name") + clazz.findall(
            ".//extends/name") + clazz.findall(
            ".//extends_interfaces/name"):
        name = name_to_str(it)
        error_if(clazz.env.findclass(name) is None,
              "No class %s defined." % name)

    for type_use in clazz.findall(".//type") + clazz.findall(
            ".//class_instance_creation_expression/name"):
        name = ""
        toks = type_use.findall(".//tok_identifier")

        for ident in range(0, len(toks)):
            name += toks[ident].text
            if ident < len(toks) - 1:
                error_if(tree.env.findclass(name),
                      "Prefixes of fully qualified type resolves to type.")
            name += "."

        if type_use.find(".//name") is not None:
            clazz_name = name_to_str(type_use.find(".//name"))
            error_if(not clazz.env.findclass(clazz_name),
                  "Type " + clazz_name + " doesn't exist.")

    for i_type in clazz.findall(".//implements/name"):
        i_name = name_to_str(i_type)
        error_if(clazz.env.findclass(i_name) is not None and
              clazz.env.findclass(i_name).tag != "interface",
              "Must implement an interface class.")

    for c_type in clazz.findall(".//extends_interfaces/name"):
        c_name = name_to_str(c_type)
        error_if(clazz.env.findclass(c_name).tag != "interface",
              "Must extend an interface class.")
        error_if(clazz == clazz.env.findclass(c_name),
              "Class cannot extend itself")

    for inf in tree.findall(".//implements/name"):
        name = name_to_str(inf)
        error_if(clazz.env.findclass(name).tag != "interface",
              "%s is not an interface." % name)

    for clz in tree.findall(".//class_type/name") + tree.findall(
            ".//implements/name"):
        name = name_to_str(clz)
        error_if((tree.env.findclass(name) is None) or
              (tree.env.findclass(
                      name).tag == "class"),
              "%s is not an interface." % name)