javaclass

Changeset

39:e64b08b9681f
2004-11-13 Paul Boddie raw files shortlog changelog graph Fixed 8-bit limited value rewriting. Added code generation avoidance for interfaces. Added an import hook mechanism for importing directories of classes.
bytecode.py (file) classhook.py (file)
     1.1 --- a/bytecode.py	Fri Nov 12 01:32:28 2004 +0100
     1.2 +++ b/bytecode.py	Sat Nov 13 19:19:46 2004 +0100
     1.3 @@ -64,6 +64,7 @@
     1.4                  value = element.value
     1.5              else:
     1.6                  value = element
     1.7 +            # NOTE: ValueError gets raised for bad values here.
     1.8              output.append(chr(value))
     1.9          return "".join(output)
    1.10  
    1.11 @@ -122,6 +123,15 @@
    1.12              # NOTE: EXTENDED_ARG not yet supported.
    1.13              raise ValueError, value
    1.14  
    1.15 +    def _rewrite_value(self, position, value):
    1.16 +        # NOTE: Assume a 16-bit value.
    1.17 +        if value <= 0xffff:
    1.18 +            self.output[position] = (value & 0xff)
    1.19 +            self.output[position + 1] = ((value & 0xff00) >> 8)
    1.20 +        else:
    1.21 +            # NOTE: EXTENDED_ARG not yet supported.
    1.22 +            raise ValueError, value
    1.23 +
    1.24      def setup_loop(self):
    1.25          self.loops.append(self.position)
    1.26          self.output.append(opmap["SETUP_LOOP"])
    1.27 @@ -134,16 +144,12 @@
    1.28          #print "<", self.blocks, current_loop_real_start
    1.29          # Fix the iterator delta.
    1.30          # NOTE: Using 3 as the assumed length of the FOR_ITER instruction.
    1.31 -        # NOTE: 8-bit limit.
    1.32          self.jump_absolute(current_loop_real_start)
    1.33 -        self.output[current_loop_real_start + 1] = self.position - current_loop_real_start - 3
    1.34 -        self.output[current_loop_real_start + 2] = 0
    1.35 +        self._rewrite_value(current_loop_real_start + 1, self.position - current_loop_real_start - 3)
    1.36          self.pop_block()
    1.37          # Fix the loop delta.
    1.38          # NOTE: Using 3 as the assumed length of the SETUP_LOOP instruction.
    1.39 -        # NOTE: 8-bit limit.
    1.40 -        self.output[current_loop_start + 1] = self.position - current_loop_start - 3
    1.41 -        self.output[current_loop_start + 2] = 0
    1.42 +        self._rewrite_value(current_loop_start + 1, self.position - current_loop_start - 3)
    1.43  
    1.44      def jump_to_label(self, status, name):
    1.45          # Record the instruction using the jump.
    1.46 @@ -162,9 +168,7 @@
    1.47      def start_label(self, name):
    1.48          # Fill in all jump instructions.
    1.49          for jump_instruction, following_instruction in self.jumps[name]:
    1.50 -            # NOTE: 8-bit limit.
    1.51 -            self.output[jump_instruction + 1] = self.position - following_instruction
    1.52 -            self.output[jump_instruction + 2] = 0
    1.53 +            self._rewrite_value(jump_instruction + 1, self.position - following_instruction)
    1.54          del self.jumps[name]
    1.55  
    1.56      def load_const_ret(self, value):
    1.57 @@ -213,9 +217,7 @@
    1.58          target = current_exception_target.get_value()
    1.59          #print "*", current_exception_start, target
    1.60          # NOTE: Using 3 as the assumed length of the SETUP_* instruction.
    1.61 -        # NOTE: 8-bit limit.
    1.62 -        self.output[current_exception_start + 1] = target - current_exception_start - 3
    1.63 -        self.output[current_exception_start + 2] = 0
    1.64 +        self._rewrite_value(current_exception_start + 1, target - current_exception_start - 3)
    1.65  
    1.66      def start_handler(self, exc_name):
    1.67          # Where handlers are begun, produce bytecode to test the type of
    1.68 @@ -534,6 +536,8 @@
    1.69          self.method = method
    1.70  
    1.71          # NOTE: Not guaranteed.
    1.72 +        if len(method.attributes) == 0:
    1.73 +            return
    1.74          attribute = method.attributes[0]
    1.75          code, exception_table = attribute.code, attribute.exception_table
    1.76  
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/classhook.py	Sat Nov 13 19:19:46 2004 +0100
     2.3 @@ -0,0 +1,95 @@
     2.4 +#!/usr/bin/env python
     2.5 +
     2.6 +import ihooks
     2.7 +import os, glob
     2.8 +from imp import PY_SOURCE, PKG_DIRECTORY, C_BUILTIN
     2.9 +import classfile, bytecode
    2.10 +import new
    2.11 +
    2.12 +class ClassHooks(ihooks.Hooks):
    2.13 +
    2.14 +    "A filesystem hooks class providing information about supported files."
    2.15 +
    2.16 +    def get_suffixes(self):
    2.17 +
    2.18 +        "Return the recognised suffixes."
    2.19 +
    2.20 +        return ihooks.Hooks.get_suffixes(self) + [(os.extsep + "class", "r", PY_SOURCE)]
    2.21 +
    2.22 +class ClassLoader(ihooks.ModuleLoader):
    2.23 +
    2.24 +    "A class providing support for searching directories for supported files."
    2.25 +
    2.26 +    def find_module_in_dir(self, name, dir):
    2.27 +
    2.28 +        """
    2.29 +        Find the module with the given 'name' in the given directory 'dir'.
    2.30 +        Since Java packages/modules are directories containing class files,
    2.31 +        return the required information tuple only when the path constructed
    2.32 +        from 'dir' and 'name' refers to a directory containing class files.
    2.33 +        """
    2.34 +
    2.35 +        dir = dir or ""
    2.36 +
    2.37 +        # Provide a special name for the current directory.
    2.38 +
    2.39 +        if name == "__this__":
    2.40 +            path = dir
    2.41 +        else:
    2.42 +            path = os.path.join(dir, name)
    2.43 +
    2.44 +        print "*", name, dir, path
    2.45 +        if os.path.isdir(path):
    2.46 +            if len(glob.glob(os.path.join(path, "*" + os.extsep + "class"))) != 0:
    2.47 +                return (None, path, ("", "", PKG_DIRECTORY))
    2.48 +        return None
    2.49 +
    2.50 +    def load_module(self, name, stuff):
    2.51 +
    2.52 +        """
    2.53 +        Load the module with the given 'name', whose 'stuff' which describes the
    2.54 +        location of the module is a tuple of the form (file, filename, (suffix,
    2.55 +        mode, data type)). Return a module object or raise an ImportError if a
    2.56 +        problem occurred in the import operation.
    2.57 +        """
    2.58 +
    2.59 +        # Just go into the directory and find the class files.
    2.60 +
    2.61 +        file, filename, info = stuff
    2.62 +
    2.63 +        # Prepare a dictionary of globals.
    2.64 +
    2.65 +        global_names = {}
    2.66 +        global_names.update(__builtins__.__dict__)
    2.67 +        module = new.module(name)
    2.68 +
    2.69 +        # Process each class file, producing a genuine Python class.
    2.70 +
    2.71 +        class_files = []
    2.72 +        for class_filename in glob.glob(os.path.join(filename, "*" + os.extsep + "class")):
    2.73 +            print "*", class_filename
    2.74 +            f = open(class_filename, "rb")
    2.75 +            s = f.read()
    2.76 +            f.close()
    2.77 +            class_file = classfile.ClassFile(s)
    2.78 +            translator = bytecode.ClassTranslator(class_file)
    2.79 +            cls = translator.process(global_names)
    2.80 +            module.__dict__[cls.__name__] = cls
    2.81 +
    2.82 +        return module
    2.83 +
    2.84 +class ClassImporter(ihooks.ModuleImporter):
    2.85 +
    2.86 +    def import_it(self, partname, fqname, parent, force_load=0):
    2.87 +        try:
    2.88 +            return parent.__dict__[partname]
    2.89 +
    2.90 +        except (KeyError, AttributeError):
    2.91 +            return ihooks.ModuleImporter.import_it(
    2.92 +                self, partname, fqname, parent, force_load
    2.93 +                )
    2.94 +
    2.95 +importer = ClassImporter(loader=ClassLoader(hooks=ClassHooks()))
    2.96 +importer.install()
    2.97 +
    2.98 +# vim: tabstop=4 expandtab shiftwidth=4