Exemplo n.º 1
0
 def parse(self, filename):
     self.class_file = ClassFile()
     with open(filename, "rb") as f:
         self.class_file.magic = f.read(4)
         self.class_file.minor_version = convert_bytes_to_int(f.read(2))
         self.class_file.major_versio = convert_bytes_to_int(f.read(2))
         self.class_file.constant_pool_count = convert_bytes_to_int(
             f.read(2))
         for _ in range(self.class_file.constant_pool_count - 1):
             self.class_file.add_constant_pool(self.parse_constant_pool(f))
         self.class_file.access_flags = convert_bytes_to_int(f.read(2))
         self.class_file.this_class = convert_bytes_to_int(f.read(2))
         self.class_file.super_class = convert_bytes_to_int(f.read(2))
         self.class_file.interfaces_count = convert_bytes_to_int(f.read(2))
         for _ in range(self.class_file.interfaces_count):
             self.class_file.add_interfaces(int.from_bytes(f.read(2)))
         self.class_file.fields_count = convert_bytes_to_int(f.read(2))
         for _ in range(self.class_file.fields_count):
             self.class_file.add_field(self.parse_field())
         self.class_file.methods_count = convert_bytes_to_int(f.read(2))
         for _ in range(self.class_file.methods_count):
             self.class_file.add_method(self.parse_methods(f))
         self.class_file.attributes_count = convert_bytes_to_int(f.read(2))
         for _ in range(self.class_file.attributes_count):
             self.class_file.add_attribute(self.parse_attributes(f))
     return self.class_file
Exemplo n.º 2
0
 def __init__(self, file_name, functions):
     self.file_name = file_name.replace(".bas","")
     self.class_name = self.file_name.capitalize()
     self.functions = functions
     self.code = ClassFile(self.class_name, self.file_name)
     self.method_bytecode = b""
     self.vars = {"args": 0};
Exemplo n.º 3
0
def create_code(file_name, message):
    """Write the compile code to a class file"""
    code = ClassFile(file_name.capitalize(), file_name)
    method_bytecode = b"\x2a\xb7" + struct.pack("!h", 
        code.add_method_to_const_pool("java/lang/Object", "<init>", "()V")
    ) + b"\xb1"
    code.add_method(0x0000, "<init>", "()V", 1, 1, method_bytecode)
    
    method_bytecode = b"\xb2" + struct.pack("!h", code.add_field_to_const_pool("java/lang/System", "out", "Ljava/io/PrintStream;")) + b"\x12" + struct.pack("B", code.add_string_ref_to_const_pool(message)) + b"\xb6" + struct.pack("!h", code.add_method_to_const_pool("java/io/PrintStream", "println", "(Ljava/lang/String;)V")) + b"\xb1"
    code.add_method(0x0009, "main", "([Ljava/lang/String;)V", 2, 1, method_bytecode)
    
    open(file_name.capitalize() + ".class", "wb").write(code.write_class())
Exemplo n.º 4
0
class Compiler:
    def __init__(self, file_name, functions):
        self.file_name = file_name.replace(".bas","")
        self.class_name = self.file_name.capitalize()
        self.functions = functions
        self.code = ClassFile(self.class_name, self.file_name)
        self.method_bytecode = b""
        self.vars = {"args": 0};

    def parse(self, _fileinput):
        self.AST = parse_to_AST(_fileinput)
        self._tree_walker(self.AST)

    def _tree_walker(self, tree):
        if type(tree) == list:
            for node in tree:
                self._tree_walker(node)
        if type(tree) == Symbol:
            for function in self.functions:
                if function.__name__ == tree.__name__:
                    function(self, tree.what)
            self._tree_walker(tree.what)

    def _add_var(self, var_name):
        if var_name in self.vars:
            return self.vars[var_name]
        idx = len(self.vars)
        self.vars[var_name] = idx
        return idx

    def save(self):
        method_bytecode = b"\x2a\xb7" + struct.pack("!h",
            self.code.add_method_to_const_pool("java/lang/Object", "<init>", "()V")
        ) + b"\xb1"
        self.code.add_method(0x0000, "<init>", "()V", 1, 1, method_bytecode)
        self.method_bytecode += b"\xb1"
        # TODO: Keep track of stack size
        self.code.add_method(0x0009, "main", "([Ljava/lang/String;)V", 100, len(self.vars), self.method_bytecode)

        open(self.class_name + ".class", "wb").write(self.code.write_class())
Exemplo n.º 5
0
class Parser():
    constant_pool_tags = {
        'CONSTANT_Utf8': 1,
        'CONSTANT_Class': 7,
        'CONSTANT_String': 8,
        'CONSTANT_Fieldref': 9,
        'CONSTANT_Methodref': 10,
        'CONSTANT_NameAndType': 12
    }

    def __init__(self):
        self.constant_parser = {
            self.constant_pool_tags['CONSTANT_Utf8']:
            lambda f: self.parse_utf8(f),
            self.constant_pool_tags['CONSTANT_Class']:
            lambda f: self.parse_class(f),
            self.constant_pool_tags['CONSTANT_String']:
            lambda f: self.parse_string(f),
            self.constant_pool_tags['CONSTANT_Fieldref']:
            lambda f: self.parse_field_ref(f),
            self.constant_pool_tags['CONSTANT_Methodref']:
            lambda f: self.parse_method_ref(f),
            self.constant_pool_tags['CONSTANT_NameAndType']:
            lambda f: self.parse_name_and_type(f)
        }
        self.attribute_parser = {
            'Code': lambda f: self.parse_code(f),
            'LineNumberTable': lambda f: self.parse_line_number_table(f),
            'SourceFile': lambda f: self.parse_source_file(f)
        }

    def parse(self, filename):
        self.class_file = ClassFile()
        with open(filename, "rb") as f:
            self.class_file.magic = f.read(4)
            self.class_file.minor_version = convert_bytes_to_int(f.read(2))
            self.class_file.major_versio = convert_bytes_to_int(f.read(2))
            self.class_file.constant_pool_count = convert_bytes_to_int(
                f.read(2))
            for _ in range(self.class_file.constant_pool_count - 1):
                self.class_file.add_constant_pool(self.parse_constant_pool(f))
            self.class_file.access_flags = convert_bytes_to_int(f.read(2))
            self.class_file.this_class = convert_bytes_to_int(f.read(2))
            self.class_file.super_class = convert_bytes_to_int(f.read(2))
            self.class_file.interfaces_count = convert_bytes_to_int(f.read(2))
            for _ in range(self.class_file.interfaces_count):
                self.class_file.add_interfaces(int.from_bytes(f.read(2)))
            self.class_file.fields_count = convert_bytes_to_int(f.read(2))
            for _ in range(self.class_file.fields_count):
                self.class_file.add_field(self.parse_field())
            self.class_file.methods_count = convert_bytes_to_int(f.read(2))
            for _ in range(self.class_file.methods_count):
                self.class_file.add_method(self.parse_methods(f))
            self.class_file.attributes_count = convert_bytes_to_int(f.read(2))
            for _ in range(self.class_file.attributes_count):
                self.class_file.add_attribute(self.parse_attributes(f))
        return self.class_file

    def parse_constant_pool(self, file_object):
        tag = convert_bytes_to_int(file_object.read(1))
        return self.constant_parser[tag](file_object)

    def parse_utf8(self, file_object):
        length = convert_bytes_to_int(file_object.read(2))
        bytes_list = [file_object.read(1) for _ in range(length)]
        return {
            'tag': self.constant_pool_tags['CONSTANT_Utf8'],
            'length': length,
            'bytes': bytes_list
        }

    def parse_class(self, file_object):
        return {
            'tag': self.constant_pool_tags['CONSTANT_Class'],
            'name_index': convert_bytes_to_int(file_object.read(2))
        }

    def parse_string(self, file_object):
        return {
            'tag': self.constant_pool_tags['CONSTANT_String'],
            'string_index': convert_bytes_to_int(file_object.read(2))
        }

    def parse_field_ref(self, file_object):
        return {
            'tag': self.constant_pool_tags['CONSTANT_Fieldref'],
            'class_index': convert_bytes_to_int(file_object.read(2)),
            'name_and_type_index': convert_bytes_to_int(file_object.read(2))
        }

    def parse_method_ref(self, file_object):
        return {
            'tag': self.constant_pool_tags['CONSTANT_Methodref'],
            'class_index': convert_bytes_to_int(file_object.read(2)),
            'name_and_type_index': convert_bytes_to_int(file_object.read(2))
        }

    def parse_name_and_type(self, file_object):
        return {
            'tag': self.constant_pool_tags['CONSTANT_NameAndType'],
            'name_index': convert_bytes_to_int(file_object.read(2)),
            'descriptor_index': convert_bytes_to_int(file_object.read(2))
        }

    def parse_field(self):
        # Not implemented because this isn't used in hello world
        pass

    def parse_methods(self, file_object):
        return {
            'access_flags': convert_bytes_to_int(file_object.read(2)),
            'name_index': convert_bytes_to_int(file_object.read(2)),
            'descriptor_index': convert_bytes_to_int(file_object.read(2)),
            'attributes_count': convert_bytes_to_int(file_object.read(2)),
            'attributes': self.parse_attributes(file_object)
        }

    def parse_attributes(self, file_object):
        attribute_name_index = convert_bytes_to_int(file_object.read(2))
        attribute_length = convert_bytes_to_int(file_object.read(4))
        attribute_name = self.class_file.constant_pool[attribute_name_index][
            'bytes']
        attribute_name = ''.join(
            map(lambda x: x.decode('UTF-8'), attribute_name))
        attributes = {
            'attribute_name_index': attribute_name_index,
            'attribute_length': attribute_length,
        }
        attributes.update(self.attribute_parser[attribute_name](file_object))
        return attributes

    def parse_code(self, file_object):
        max_stack = convert_bytes_to_int(file_object.read(2))
        max_locals = convert_bytes_to_int(file_object.read(2))
        code_length = convert_bytes_to_int(file_object.read(4))
        codes = [file_object.read(1) for _ in range(code_length)]
        exception_table_length = convert_bytes_to_int(file_object.read(2))
        exception_table = [
            file_object.read(1) for _ in range(exception_table_length)
        ]
        attributes_count = convert_bytes_to_int(file_object.read(2))
        attributes = [
            self.parse_attributes(file_object) for _ in range(attributes_count)
        ]

        return {
            'max_stack': max_stack,
            'max_locals': max_locals,
            'code_length': code_length,
            'codes': codes,
            'exception_table_length': exception_table_length,
            'exception_table': exception_table,
            'attributes_count': attributes_count,
            'attributes': attributes
        }

    def parse_exception_table(self, file_object):
        return {
            'start_pc': convert_bytes_to_int(file_object.read(2)),
            'end_pc': convert_bytes_to_int(file_object.read(2)),
            'handler_pc': convert_bytes_to_int(file_object.read(2)),
            'catch_type': convert_bytes_to_int(file_object.read(2))
        }

    def parse_line_number_table(self, file_object):
        line_number_table_length = convert_bytes_to_int(file_object.read(2))
        line_number_table = [{
            'start_pc':
            convert_bytes_to_int(file_object.read(2)),
            'line_number':
            convert_bytes_to_int(file_object.read(2))
        } for _ in range(line_number_table_length)]
        return {
            'line_number_table_length': line_number_table_length,
            'line_number_table': line_number_table
        }

    def parse_source_file(self, file_object):
        return {'sourcefile_index': convert_bytes_to_int(file_object.read(2))}