1.1 --- a/bytecode.py Sat Nov 13 20:59:44 2004 +0100
1.2 +++ b/bytecode.py Sat Nov 13 21:00:48 2004 +0100
1.3 @@ -1351,8 +1351,10 @@
1.4 program.start_label("is-self")
1.5 program.pop_top() # Stack: tuple, reference
1.6 program.pop_top() # Stack: tuple
1.7 - program.load_global(str(self.class_file.this_class.get_python_name()))
1.8 - # Stack: tuple, classref
1.9 + # Get the class name instead of the fully qualified name.
1.10 + full_class_name = str(self.class_file.this_class.get_python_name())
1.11 + class_name = full_class_name.split(".")[-1]
1.12 + program.load_global(class_name) # Stack: tuple, classref
1.13 program.load_attr("__bases__") # Stack: tuple, bases
1.14 program.dup_top() # Stack: tuple, bases, bases
1.15 program.load_global("len") # Stack: tuple, bases, bases, len
1.16 @@ -1374,41 +1376,6 @@
1.17 program.pop_top() # Stack:
1.18 program.start_label("done")
1.19
1.20 - """
1.21 - def invokespecial(self, arguments, program):
1.22 - # NOTE: This implementation does not perform the necessary checks for
1.23 - # NOTE: signature-based polymorphism.
1.24 - # NOTE: Java rules not specifically obeyed.
1.25 - index = (arguments[0] << 8) + arguments[1]
1.26 - target = self.class_file.constants[index - 1]
1.27 - target_name = target.get_python_name()
1.28 - # Get the number of parameters from the descriptor.
1.29 - count = len(target.get_descriptor()[0])
1.30 - # Stack: objectref, arg1, arg2, ...
1.31 - program.build_tuple(count + 1) # Stack: tuple
1.32 - # Use the class to provide access to static methods.
1.33 - program.load_name("self") # Stack: tuple, self
1.34 - program.load_attr("__class__") # Stack: tuple, class
1.35 - program.load_attr("__bases__") # Stack: tuple, base-classes
1.36 - program.dup_top() # Stack: tuple, base-classes, base-classes
1.37 - program.load_global("len") # Stack: tuple, base-classes, base-classes, len
1.38 - program.rot_two() # Stack: tuple, base-classes, len, base-classes
1.39 - program.call_function(1) # Stack: tuple, base-classes, count
1.40 - program.load_const(0) # Stack: tuple, base-classes, count, 0
1.41 - program.compare_op("==") # Stack: tuple, base-classes, result
1.42 - program.jump_to_label(1, "next")
1.43 - program.pop_top() # Stack: tuple, base-classes
1.44 - program.load_const(0) # Stack: tuple, base-classes, 0
1.45 - program.binary_subscr() # Stack: tuple, superclass
1.46 - self._invoke(target_name, program)
1.47 - program.jump_to_label(None, "next2")
1.48 - program.start_label("next")
1.49 - program.pop_top() # Stack: tuple, base-classes
1.50 - program.pop_top() # Stack: tuple
1.51 - program.pop_top() # Stack:
1.52 - program.start_label("next2")
1.53 - """
1.54 -
1.55 def invokestatic(self, arguments, program):
1.56 # NOTE: This implementation does not perform the necessary checks for
1.57 # NOTE: signature-based polymorphism.
1.58 @@ -1706,17 +1673,37 @@
1.59 disassembler.process(method, BytecodeDisassemblerProgram())
1.60
1.61 class ClassTranslator:
1.62 +
1.63 + """
1.64 + A class which provides a wrapper around a class file and the means to
1.65 + translate the represented class into a Python class.
1.66 + """
1.67 +
1.68 def __init__(self, class_file):
1.69 +
1.70 + "Initialise the object with the given 'class_file'."
1.71 +
1.72 self.class_file = class_file
1.73 self.filename = str(self.class_file.attributes[0].get_name())
1.74
1.75 def translate_method(self, method):
1.76 +
1.77 + "Translate the given 'method' - an object obtained from the class file."
1.78 +
1.79 translator = BytecodeTranslator(self.class_file)
1.80 writer = BytecodeWriter()
1.81 translator.process(method, writer)
1.82 return translator, writer
1.83
1.84 def make_method(self, method_name, methods, global_names, namespace):
1.85 +
1.86 + """
1.87 + Make a dispatcher method with the given 'method_name', providing
1.88 + dispatch to the supplied type-sensitive 'methods', accessing the given
1.89 + 'global_names' where necessary, and storing the new method in the
1.90 + 'namespace' provided.
1.91 + """
1.92 +
1.93 if method_name == "<init>":
1.94 method_name = "__init__"
1.95 # Where only one method exists, just make an alias.
1.96 @@ -1838,6 +1825,11 @@
1.97 namespace[method_name] = fn
1.98
1.99 def process(self, global_names):
1.100 +
1.101 + """
1.102 + Process the class, storing it in the 'global_names' dictionary provided.
1.103 + """
1.104 +
1.105 namespace = {}
1.106 real_methods = {}
1.107 for method in self.class_file.methods:
1.108 @@ -1863,11 +1855,21 @@
1.109 # Define method dispatchers.
1.110 for real_method_name, methods in real_methods.items():
1.111 self.make_method(real_method_name, methods, global_names, namespace)
1.112 - cls = new.classobj(str(self.class_file.this_class.get_python_name()), bases, namespace)
1.113 + # Use only the last part of the fully qualified name.
1.114 + full_class_name = str(self.class_file.this_class.get_python_name())
1.115 + class_name = full_class_name.split(".")[-1]
1.116 + cls = new.classobj(class_name, bases, namespace)
1.117 global_names[cls.__name__] = cls
1.118 return cls
1.119
1.120 def make_varnames(self, nlocals):
1.121 +
1.122 + """
1.123 + A utility method which invents variable names for the given number -
1.124 + 'nlocals' - of local variables in a method. Returns a list of such
1.125 + variable names.
1.126 + """
1.127 +
1.128 l = ["self"]
1.129 for i in range(1, nlocals):
1.130 l.append("_l%s" % i)