# HG changeset patch # User Paul Boddie # Date 1100369986 -3600 # Node ID e64b08b9681fb8153bbfbc873136f926c24b0c9b # Parent 70d73e61fd757133fe3c81ed91b743c85f4911ca Fixed 8-bit limited value rewriting. Added code generation avoidance for interfaces. Added an import hook mechanism for importing directories of classes. diff -r 70d73e61fd75 -r e64b08b9681f bytecode.py --- a/bytecode.py Fri Nov 12 01:32:28 2004 +0100 +++ b/bytecode.py Sat Nov 13 19:19:46 2004 +0100 @@ -64,6 +64,7 @@ value = element.value else: value = element + # NOTE: ValueError gets raised for bad values here. output.append(chr(value)) return "".join(output) @@ -122,6 +123,15 @@ # NOTE: EXTENDED_ARG not yet supported. raise ValueError, value + def _rewrite_value(self, position, value): + # NOTE: Assume a 16-bit value. + if value <= 0xffff: + self.output[position] = (value & 0xff) + self.output[position + 1] = ((value & 0xff00) >> 8) + else: + # NOTE: EXTENDED_ARG not yet supported. + raise ValueError, value + def setup_loop(self): self.loops.append(self.position) self.output.append(opmap["SETUP_LOOP"]) @@ -134,16 +144,12 @@ #print "<", self.blocks, current_loop_real_start # Fix the iterator delta. # NOTE: Using 3 as the assumed length of the FOR_ITER instruction. - # NOTE: 8-bit limit. self.jump_absolute(current_loop_real_start) - self.output[current_loop_real_start + 1] = self.position - current_loop_real_start - 3 - self.output[current_loop_real_start + 2] = 0 + self._rewrite_value(current_loop_real_start + 1, self.position - current_loop_real_start - 3) self.pop_block() # Fix the loop delta. # NOTE: Using 3 as the assumed length of the SETUP_LOOP instruction. - # NOTE: 8-bit limit. - self.output[current_loop_start + 1] = self.position - current_loop_start - 3 - self.output[current_loop_start + 2] = 0 + self._rewrite_value(current_loop_start + 1, self.position - current_loop_start - 3) def jump_to_label(self, status, name): # Record the instruction using the jump. @@ -162,9 +168,7 @@ def start_label(self, name): # Fill in all jump instructions. for jump_instruction, following_instruction in self.jumps[name]: - # NOTE: 8-bit limit. - self.output[jump_instruction + 1] = self.position - following_instruction - self.output[jump_instruction + 2] = 0 + self._rewrite_value(jump_instruction + 1, self.position - following_instruction) del self.jumps[name] def load_const_ret(self, value): @@ -213,9 +217,7 @@ target = current_exception_target.get_value() #print "*", current_exception_start, target # NOTE: Using 3 as the assumed length of the SETUP_* instruction. - # NOTE: 8-bit limit. - self.output[current_exception_start + 1] = target - current_exception_start - 3 - self.output[current_exception_start + 2] = 0 + self._rewrite_value(current_exception_start + 1, target - current_exception_start - 3) def start_handler(self, exc_name): # Where handlers are begun, produce bytecode to test the type of @@ -534,6 +536,8 @@ self.method = method # NOTE: Not guaranteed. + if len(method.attributes) == 0: + return attribute = method.attributes[0] code, exception_table = attribute.code, attribute.exception_table diff -r 70d73e61fd75 -r e64b08b9681f classhook.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/classhook.py Sat Nov 13 19:19:46 2004 +0100 @@ -0,0 +1,95 @@ +#!/usr/bin/env python + +import ihooks +import os, glob +from imp import PY_SOURCE, PKG_DIRECTORY, C_BUILTIN +import classfile, bytecode +import new + +class ClassHooks(ihooks.Hooks): + + "A filesystem hooks class providing information about supported files." + + def get_suffixes(self): + + "Return the recognised suffixes." + + return ihooks.Hooks.get_suffixes(self) + [(os.extsep + "class", "r", PY_SOURCE)] + +class ClassLoader(ihooks.ModuleLoader): + + "A class providing support for searching directories for supported files." + + def find_module_in_dir(self, name, dir): + + """ + Find the module with the given 'name' in the given directory 'dir'. + Since Java packages/modules are directories containing class files, + return the required information tuple only when the path constructed + from 'dir' and 'name' refers to a directory containing class files. + """ + + dir = dir or "" + + # Provide a special name for the current directory. + + if name == "__this__": + path = dir + else: + path = os.path.join(dir, name) + + print "*", name, dir, path + if os.path.isdir(path): + if len(glob.glob(os.path.join(path, "*" + os.extsep + "class"))) != 0: + return (None, path, ("", "", PKG_DIRECTORY)) + return None + + def load_module(self, name, stuff): + + """ + Load the module with the given 'name', whose 'stuff' which describes the + location of the module is a tuple of the form (file, filename, (suffix, + mode, data type)). Return a module object or raise an ImportError if a + problem occurred in the import operation. + """ + + # Just go into the directory and find the class files. + + file, filename, info = stuff + + # Prepare a dictionary of globals. + + global_names = {} + global_names.update(__builtins__.__dict__) + module = new.module(name) + + # Process each class file, producing a genuine Python class. + + class_files = [] + for class_filename in glob.glob(os.path.join(filename, "*" + os.extsep + "class")): + print "*", class_filename + f = open(class_filename, "rb") + s = f.read() + f.close() + class_file = classfile.ClassFile(s) + translator = bytecode.ClassTranslator(class_file) + cls = translator.process(global_names) + module.__dict__[cls.__name__] = cls + + return module + +class ClassImporter(ihooks.ModuleImporter): + + def import_it(self, partname, fqname, parent, force_load=0): + try: + return parent.__dict__[partname] + + except (KeyError, AttributeError): + return ihooks.ModuleImporter.import_it( + self, partname, fqname, parent, force_load + ) + +importer = ClassImporter(loader=ClassLoader(hooks=ClassHooks())) +importer.install() + +# vim: tabstop=4 expandtab shiftwidth=4