1.1 --- a/bytecode.py Mon Nov 15 00:54:28 2004 +0100
1.2 +++ b/bytecode.py Mon Nov 15 01:00:53 2004 +0100
1.3 @@ -377,6 +377,12 @@
1.4 self._write_value(count)
1.5 self.update_stack_depth(-count)
1.6
1.7 + def call_function_var(self, count):
1.8 + self.output.append(opmap["CALL_FUNCTION_VAR"])
1.9 + self.position += 1
1.10 + self._write_value(count)
1.11 + self.update_stack_depth(-count-1)
1.12 +
1.13 def binary_subscr(self):
1.14 self.output.append(opmap["BINARY_SUBSCR"])
1.15 self.position += 1
1.16 @@ -1140,8 +1146,10 @@
1.17 def getstatic(self, arguments, program):
1.18 index = (arguments[0] << 8) + arguments[1]
1.19 target_name = self.class_file.constants[index - 1].get_python_name()
1.20 - program.load_name("self")
1.21 - program.load_attr("__class__")
1.22 + # Get the class name instead of the fully qualified name.
1.23 + full_class_name = str(self.class_file.this_class.get_python_name())
1.24 + class_name = full_class_name.split(".")[-1]
1.25 + program.load_global(class_name) # Stack: classref
1.26 # NOTE: Using the string version of the name which may contain incompatible characters.
1.27 program.load_attr(str(target_name))
1.28
1.29 @@ -1322,9 +1330,7 @@
1.30 # NOTE: Using the string version of the name which may contain incompatible characters.
1.31 program.load_attr(str(target_name)) # Stack: tuple, method
1.32 program.rot_two() # Stack: method, tuple
1.33 - program.load_global("apply") # Stack: method, tuple, apply
1.34 - program.rot_three() # Stack: apply, method, tuple
1.35 - program.call_function(2)
1.36 + program.call_function_var(0) # Stack: result
1.37
1.38 def invokeinterface(self, arguments, program):
1.39 # NOTE: This implementation does not perform the necessary checks for
1.40 @@ -1347,6 +1353,7 @@
1.41 target = self.class_file.constants[index - 1]
1.42 original_name = target.get_name()
1.43 target_name = target.get_python_name()
1.44 + method_name = self.method.get_name()
1.45
1.46 # Get the number of parameters from the descriptor.
1.47
1.48 @@ -1371,11 +1378,11 @@
1.49 program.dup_top() # Stack: tuple, tuple
1.50 program.load_const(0) # Stack: tuple, tuple, 0
1.51 program.binary_subscr() # Stack: tuple, reference
1.52 - program.dup_top() # Stack: tuple, reference, reference
1.53
1.54 # Is it self?
1.55
1.56 - program.load_fast(0) # Stack: tuple, reference, reference, self
1.57 + program.dup_top() # Stack: tuple, reference, reference
1.58 + program.load_fast(0) # Stack: tuple, reference, reference, self|cls
1.59 program.compare_op("is") # Stack: tuple, reference, result
1.60 program.jump_to_label(1, "is-self")
1.61 program.pop_top() # Stack: tuple, reference
1.62 @@ -1387,9 +1394,7 @@
1.63 program.rot_two() # Stack: reference, tuple
1.64 program.load_const(1) # Stack: reference, tuple, 1
1.65 program.slice_1() # Stack: reference, tuple[1:]
1.66 - program.load_global("apply") # Stack: reference, tuple, apply
1.67 - program.rot_three() # Stack: apply, reference, tuple
1.68 - program.call_function(2)
1.69 + program.call_function_var(0) # Stack: result
1.70 # NOTE: Combinations of new, dup tend to produce interfering extra
1.71 # NOTE: class references.
1.72 program.rot_two() # Stack: objectref, classref
1.73 @@ -1400,6 +1405,7 @@
1.74 program.jump_to_label(None, "done")
1.75
1.76 # Is self.
1.77 +
1.78 program.start_label("is-self")
1.79 program.pop_top() # Stack: tuple, reference
1.80 program.pop_top() # Stack: tuple
1.81 @@ -1426,6 +1432,7 @@
1.82 program.pop_top() # Stack: tuple, bases
1.83 program.pop_top() # Stack: tuple
1.84 program.pop_top() # Stack:
1.85 +
1.86 program.start_label("done")
1.87
1.88 def invokestatic(self, arguments, program):
1.89 @@ -1440,8 +1447,11 @@
1.90 # Stack: arg1, arg2, ...
1.91 program.build_tuple(count) # Stack: tuple
1.92 # Use the class to provide access to static methods.
1.93 - program.load_name("self") # Stack: tuple, self
1.94 - program.load_attr("__class__") # Stack: tuple, class
1.95 + # Get the class name instead of the fully qualified name.
1.96 + # NOTE: Need to find the class that declared the field being accessed.
1.97 + full_class_name = str(self.class_file.this_class.get_python_name())
1.98 + class_name = full_class_name.split(".")[-1]
1.99 + program.load_global(class_name) # Stack: tuple, classref
1.100 self._invoke(target_name, program)
1.101
1.102 def invokevirtual (self, arguments, program):
1.103 @@ -1697,8 +1707,11 @@
1.104 def putstatic(self, arguments, program):
1.105 index = (arguments[0] << 8) + arguments[1]
1.106 target_name = self.class_file.constants[index - 1].get_python_name()
1.107 - program.load_name("self")
1.108 - program.load_attr("__class__")
1.109 + # Get the class name instead of the fully qualified name.
1.110 + # NOTE: Need to find the class that declared the field being accessed.
1.111 + full_class_name = str(self.class_file.this_class.get_python_name())
1.112 + class_name = full_class_name.split(".")[-1]
1.113 + program.load_global(class_name) # Stack: classref
1.114 # NOTE: Using the string version of the name which may contain incompatible characters.
1.115 program.store_attr(str(target_name))
1.116
1.117 @@ -1851,9 +1864,7 @@
1.118 program.build_tuple(3) # Stack: arguments, tuple
1.119 program.load_global("map") # Stack: arguments, tuple, map
1.120 program.rot_two() # Stack: arguments, map, tuple
1.121 - program.load_global("apply") # Stack: arguments, map, tuple, apply
1.122 - program.rot_three() # Stack: arguments, apply, map, tuple
1.123 - program.call_function(2) # Stack: arguments, list (mapping arguments to types)
1.124 + program.call_function_var(0) # Stack: arguments, list (mapping arguments to types)
1.125 # Loop over each pair.
1.126 program.get_iter() # Stack: arguments, iter
1.127 program.for_iter() # Stack: arguments, iter, (argument, type)
1.128 @@ -1890,9 +1901,7 @@
1.129 program.build_tuple(2) # Stack: arguments, iter, (argument, type)
1.130 program.load_global("isinstance") # Stack: arguments, iter, (argument, type), isinstance
1.131 program.rot_two() # Stack: arguments, iter, isinstance, (argument, type)
1.132 - program.load_global("apply") # Stack: arguments, iter, isinstance, (argument, type), apply
1.133 - program.rot_three() # Stack: arguments, iter, apply, isinstance, (argument, type)
1.134 - program.call_function(2) # Stack: arguments, iter, result
1.135 + program.call_function_var(0) # Stack: arguments, iter, result
1.136 program.jump_to_label(1, "match")
1.137 program.pop_top() # Stack: arguments, iter
1.138 program.load_const(0) # Stack: arguments, iter, 0
1.139 @@ -1912,9 +1921,7 @@
1.140 program.load_attr(str(method.get_python_name()))
1.141 # Stack: arguments, arguments, method
1.142 program.rot_two() # Stack: arguments, method, arguments
1.143 - program.load_global("apply") # Stack: arguments, method, arguments, apply
1.144 - program.rot_three() # Stack: arguments, apply, method, arguments
1.145 - program.call_function(2) # Stack: arguments, result
1.146 + program.call_function_var(0) # Stack: arguments, result
1.147 program.return_value()
1.148 # Try the next method if arguments or parameters were missing or incorrect.
1.149 program.start_label("failed")
1.150 @@ -1946,27 +1953,56 @@
1.151 """
1.152
1.153 namespace = {}
1.154 +
1.155 + # Make the fields.
1.156 +
1.157 + for field in self.class_file.fields:
1.158 + if classfile.has_flags(field.access_flags, [classfile.STATIC]):
1.159 + field_name = str(field.get_python_name())
1.160 + namespace[field_name] = None
1.161 +
1.162 + # Make the methods.
1.163 +
1.164 real_methods = {}
1.165 for method in self.class_file.methods:
1.166 + real_method_name = str(method.get_name())
1.167 t, w = self.translate_method(method)
1.168 +
1.169 + # Fix up special class initialisation methods.
1.170 +
1.171 + if real_method_name == "<clinit>":
1.172 + flags = 3
1.173 + else:
1.174 + flags = 67
1.175 nlocals = w.max_locals + 1
1.176 nargs = len(method.get_descriptor()[0]) + 1
1.177 +
1.178 method_name = str(method.get_python_name())
1.179
1.180 # NOTE: Add line number table later.
1.181
1.182 - code = new.code(nargs, nlocals, w.max_stack_depth, 67, w.get_output(), tuple(w.get_constants()), tuple(w.get_names()),
1.183 + code = new.code(nargs, nlocals, w.max_stack_depth, flags, w.get_output(), tuple(w.get_constants()), tuple(w.get_names()),
1.184 tuple(self.make_varnames(nlocals)), self.filename, method_name, 0, "")
1.185
1.186 # NOTE: May need more globals.
1.187
1.188 fn = new.function(code, global_names)
1.189 - namespace[method_name] = fn
1.190 - real_method_name = str(method.get_name())
1.191 +
1.192 + # Remember the real method name and the corresponding methods produced.
1.193 +
1.194 if not real_methods.has_key(real_method_name):
1.195 real_methods[real_method_name] = []
1.196 real_methods[real_method_name].append((method, fn))
1.197
1.198 + # Fix up special class initialisation methods.
1.199 +
1.200 + if real_method_name == "<clinit>":
1.201 + fn = classmethod(fn)
1.202 +
1.203 + # Add the method to the class's namespace.
1.204 +
1.205 + namespace[method_name] = fn
1.206 +
1.207 # Define superclasses.
1.208
1.209 bases = self.get_base_classes(global_names)
1.210 @@ -1974,7 +2010,8 @@
1.211 # Define method dispatchers.
1.212
1.213 for real_method_name, methods in real_methods.items():
1.214 - self.make_method(real_method_name, methods, global_names, namespace)
1.215 + if real_method_name != "<clinit>":
1.216 + self.make_method(real_method_name, methods, global_names, namespace)
1.217
1.218 # Use only the last part of the fully qualified name.
1.219
1.220 @@ -1982,6 +2019,7 @@
1.221 class_name = full_class_name.split(".")[-1]
1.222 cls = new.classobj(class_name, bases, namespace)
1.223 global_names[cls.__name__] = cls
1.224 +
1.225 return cls
1.226
1.227 def get_base_classes(self, global_names):
1.228 @@ -1999,15 +2037,16 @@
1.229 else:
1.230 full_class_name = str(self.class_file.super_class.get_python_name())
1.231 class_name_parts = full_class_name.split(".")
1.232 + class_name = class_name_parts[-1]
1.233 class_module_name = ".".join(class_name_parts[:-1])
1.234 if class_module_name == "":
1.235 - class_module_name = "__this__"
1.236 - class_name = class_name_parts[-1]
1.237 - print "Importing", class_module_name, class_name
1.238 - obj = __import__(class_module_name, global_names, {}, [])
1.239 - for class_name_part in class_name_parts[1:] or [class_name]:
1.240 - print "*", obj, class_name_part
1.241 - obj = getattr(obj, class_name_part)
1.242 + obj = global_names[class_name]
1.243 + else:
1.244 + print "Importing", class_module_name, class_name
1.245 + obj = __import__(class_module_name, global_names, {}, [])
1.246 + for class_name_part in class_name_parts[1:] or [class_name]:
1.247 + print "*", obj, class_name_part
1.248 + obj = getattr(obj, class_name_part)
1.249 return (obj,)
1.250
1.251 def make_varnames(self, nlocals):
1.252 @@ -2034,8 +2073,7 @@
1.253 if __name__ == "__main__":
1.254 import sys
1.255 import dis
1.256 - global_names = {}
1.257 - global_names.update(__builtins__.__dict__)
1.258 + global_names = globals()
1.259 #global_names["isinstance"] = _isinstance
1.260 #global_names["map"] = _map
1.261 for filename in sys.argv[1:]: