javaclass

bytecode.py

80:cfb9fe666890
2004-12-09 Paul Boddie Changed the special notation for Java-callable methods so that methods may be more easily written in Python. Added various method implementations so that javax.servlet.http.Cookie can at least be instantiated.
     1 #!/usr/bin/env python     2      3 """     4 Java bytecode conversion. Specification found at the following URL:     5 http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc.html     6      7 NOTE: Synchronized constructs are not actually supported.     8 """     9     10 import classfile    11 from dis import opmap, cmp_op # for access to Python bytecode values and operators    12 from UserDict import UserDict    13 import new    14     15 # Bytecode production classes.    16     17 class BytecodeWriter:    18     19     "A Python bytecode writer."    20     21     def __init__(self):    22         # A stack of loop start instructions corresponding to loop blocks.    23         self.loops = []    24     25         # A stack of loop block or exception block start positions.    26         self.blocks = []    27     28         # A stack of exception block handler pointers.    29         self.exception_handlers = []    30     31         # A dictionary mapping labels to jump instructions referencing such labels.    32         self.jumps = {}    33     34         # The output values, including "lazy" subvalues which will need evaluating.    35         self.output = []    36     37         # The current Python bytecode instruction position.    38         self.position = 0    39     40         # Stack depth estimation.    41         self.stack_depth = 0    42         self.max_stack_depth = 0    43     44         # Local variable estimation.    45         self.max_locals = 0    46     47         # Mapping from values to indexes.    48         self.constants = {}    49     50         # Mapping from names to indexes.    51         # NOTE: This may be acquired from elsewhere.    52         #self.globals = {}    53     54         # Mapping from names to indexes.    55         self.names = {}    56     57         # A list of constants used as exception handler return addresses.    58         self.constants_for_exceptions = []    59     60         # A list of external names.    61         self.external_names = []    62     63     def get_output(self):    64         output = []    65         for element in self.output:    66             if isinstance(element, LazySubValue):    67                 value = element.value    68             else:    69                 value = element    70             # NOTE: ValueError gets raised for bad values here.    71             output.append(chr(value))    72         return "".join(output)    73     74     def get_constants(self):    75         l = self._get_list(self._invert(self.constants))    76         result = []    77         for i in l:    78             if isinstance(i, LazyValue):    79                 result.append(i.get_value())    80             else:    81                 result.append(i)    82         return result    83     84     #def get_globals(self):    85     #    return self._get_list(self._invert(self.globals))    86     87     def get_names(self):    88         return self._get_list(self._invert(self.names))    89     90     def _invert(self, d):    91         inverted = {}    92         for k, v in d.items():    93             inverted[v] = k    94         return inverted    95     96     def _get_list(self, d):    97         l = []    98         for i in range(0, len(d.keys())):    99             l.append(d[i])   100         return l   101    102     # Administrative methods.   103    104     def update_stack_depth(self, change):   105         self.stack_depth += change   106         if self.stack_depth > self.max_stack_depth:   107             self.max_stack_depth = self.stack_depth   108    109     def update_locals(self, index):   110         if index > self.max_locals:   111             self.max_locals = index   112    113     # Special methods.   114    115     def _write_value(self, value):   116         if isinstance(value, LazyValue):   117             # NOTE: Assume a 16-bit value.   118             self.output.append(value.values[0])   119             self.output.append(value.values[1])   120             self.position += 2   121         elif value <= 0xffff:   122             self.output.append(value & 0xff)   123             self.output.append((value & 0xff00) >> 8)   124             self.position += 2   125         else:   126             # NOTE: EXTENDED_ARG not yet supported.   127             raise ValueError, value   128    129     def _rewrite_value(self, position, value):   130         # NOTE: Assume a 16-bit value.   131         if value <= 0xffff:   132             self.output[position] = (value & 0xff)   133             self.output[position + 1] = ((value & 0xff00) >> 8)   134         else:   135             # NOTE: EXTENDED_ARG not yet supported.   136             raise ValueError, value   137    138     # Higher level methods.   139    140     def use_external_name(self, name):   141         # NOTE: Remove array and object indicators.   142         self.external_names.append(name)   143    144     def setup_loop(self):   145         self.loops.append(self.position)   146         self.output.append(opmap["SETUP_LOOP"])   147         self.position += 1   148         self._write_value(0) # To be filled in later   149    150     def end_loop(self):   151         current_loop_start = self.loops.pop()   152         current_loop_real_start = self.blocks.pop()   153         #print "<", self.blocks, current_loop_real_start   154         # Fix the iterator delta.   155         # NOTE: Using 3 as the assumed length of the FOR_ITER instruction.   156         self.jump_absolute(current_loop_real_start)   157         self._rewrite_value(current_loop_real_start + 1, self.position - current_loop_real_start - 3)   158         self.pop_block()   159         # Fix the loop delta.   160         # NOTE: Using 3 as the assumed length of the SETUP_LOOP instruction.   161         self._rewrite_value(current_loop_start + 1, self.position - current_loop_start - 3)   162    163     def jump_to_label(self, status, name):   164         # Record the instruction using the jump.   165         jump_instruction = self.position   166         if status is None:   167             self.jump_forward()   168         elif status:   169             self.jump_if_true()   170         else:   171             self.jump_if_false()   172         # Record the following instruction, too.   173         if not self.jumps.has_key(name):   174             self.jumps[name] = []   175         self.jumps[name].append((jump_instruction, self.position))   176    177     def start_label(self, name):   178         # Fill in all jump instructions.   179         for jump_instruction, following_instruction in self.jumps[name]:   180             self._rewrite_value(jump_instruction + 1, self.position - following_instruction)   181         del self.jumps[name]   182    183     def load_const_ret(self, value):   184         self.constants_for_exceptions.append(value)   185         self.load_const(value)   186    187     def ret(self, index):   188         self.load_fast(index)   189    190         # Previously, the constant stored on the stack by jsr/jsr_w was stored   191         # in a local variable. In the JVM, extracting the value from the local   192         # variable and jumping can be done at runtime. In the Python VM, any   193         # jump target must be known in advance and written into the bytecode.   194    195         for constant in self.constants_for_exceptions:   196             self.dup_top()              # Stack: actual-address, actual-address   197             self.load_const(constant)   # Stack: actual-address, actual-address, suggested-address   198             self.compare_op("==")       # Stack: actual-address, result   199             self.jump_to_label(0, "const")   200             self.pop_top()              # Stack: actual-address   201             self.pop_top()              # Stack:   202             self.jump_absolute(constant)   203             self.start_label("const")   204             self.pop_top()              # Stack: actual-address   205    206         # NOTE: If we get here, something is really wrong.   207    208         self.pop_top()              # Stack:   209    210     def setup_except(self, target):   211         self.blocks.append(self.position)   212         self.exception_handlers.append(target)   213         #print "-", self.position, target   214         self.output.append(opmap["SETUP_EXCEPT"])   215         self.position += 1   216         self._write_value(0) # To be filled in later   217    218     def setup_finally(self, target):   219         self.blocks.append(self.position)   220         self.exception_handlers.append(target)   221         #print "-", self.position, target   222         self.output.append(opmap["SETUP_FINALLY"])   223         self.position += 1   224         self._write_value(0) # To be filled in later   225    226     def end_exception(self):   227         current_exception_start = self.blocks.pop()   228         # Convert the "lazy" absolute value.   229         current_exception_target = self.exception_handlers.pop()   230         target = current_exception_target.get_value()   231         #print "*", current_exception_start, target   232         # NOTE: Using 3 as the assumed length of the SETUP_* instruction.   233         self._rewrite_value(current_exception_start + 1, target - current_exception_start - 3)   234    235     def start_handler(self, exc_name):   236    237         # Where handlers are begun, produce bytecode to test the type of   238         # the exception.   239         # NOTE: Since RAISE_VARARGS and END_FINALLY are not really documented,   240         # NOTE: we store the top of the stack and use it later to trigger the   241         # NOTE: magic processes when re-raising.   242         self.use_external_name(exc_name)   243    244         self.rot_two()                      # Stack: raised-exception, exception   245         self.dup_top()                      # Stack: raised-exception, exception, exception   246         # Handled exceptions are wrapped before being thrown.   247         self.load_global("Exception")       # Stack: raised-exception, exception, exception, Exception   248         self.compare_op("exception match")  # Stack: raised-exception, exception, result   249         self.jump_to_label(0, "next")   250         self.pop_top()                      # Stack: raised-exception, exception   251         self.dup_top()                      # Stack: raised-exception, exception, exception   252         self.load_attr("args")              # Stack: raised-exception, exception, args   253         self.load_const(0)                  # Stack: raised-exception, exception, args, 0   254         self.binary_subscr()                # Stack: raised-exception, exception, exception-object   255         self.load_global(str(exc_name))     # Stack: raised-exception, exception, exception-object, handled-exception   256         self.load_global("isinstance")      # Stack: raised-exception, exception, exception-object, handled-exception, isinstance   257         self.rot_three()                    # Stack: raised-exception, exception, isinstance, exception-object, handled-exception   258         self.call_function(2)               # Stack: raised-exception, exception, result   259         self.jump_to_label(1, "handler")   260         self.start_label("next")   261         self.pop_top()                      # Stack: raised-exception, exception   262         self.rot_two()                      # Stack: exception, raised-exception   263         self.end_finally()   264         self.start_label("handler")   265         self.pop_top()                      # Stack: raised-exception, exception   266    267     # Complicated methods.   268    269     def load_const(self, value):   270         self.output.append(opmap["LOAD_CONST"])   271         if not self.constants.has_key(value):   272             self.constants[value] = len(self.constants.keys())   273         self.position += 1   274         self._write_value(self.constants[value])   275         self.update_stack_depth(1)   276    277     def load_global(self, name):   278         self.output.append(opmap["LOAD_GLOBAL"])   279         if not self.names.has_key(name):   280             self.names[name] = len(self.names.keys())   281         self.position += 1   282         self._write_value(self.names[name])   283         self.update_stack_depth(1)   284    285     def load_attr(self, name):   286         self.output.append(opmap["LOAD_ATTR"])   287         if not self.names.has_key(name):   288             self.names[name] = len(self.names.keys())   289         self.position += 1   290         self._write_value(self.names[name])   291    292     def load_name(self, name):   293         self.output.append(opmap["LOAD_NAME"])   294         if not self.names.has_key(name):   295             self.names[name] = len(self.names.keys())   296         self.position += 1   297         self._write_value(self.names[name])   298         self.update_stack_depth(1)   299    300     def load_fast(self, index):   301         self.output.append(opmap["LOAD_FAST"])   302         self.position += 1   303         self._write_value(index)   304         self.update_stack_depth(1)   305         self.update_locals(index)   306    307     def store_attr(self, name):   308         self.output.append(opmap["STORE_ATTR"])   309         if not self.names.has_key(name):   310             self.names[name] = len(self.names.keys())   311         self.position += 1   312         self._write_value(self.names[name])   313         self.update_stack_depth(-1)   314    315     def store_fast(self, index):   316         self.output.append(opmap["STORE_FAST"])   317         self.position += 1   318         self._write_value(index)   319         self.update_stack_depth(-1)   320         self.update_locals(index)   321    322     def for_iter(self):   323         self.blocks.append(self.position)   324         #print ">", self.blocks   325         self.output.append(opmap["FOR_ITER"])   326         self.position += 1   327         self._write_value(0) # To be filled in later   328         self.update_stack_depth(1)   329    330     def break_loop(self):   331         self.output.append(opmap["BREAK_LOOP"])   332         self.position += 1   333         self.jump_absolute(self.blocks[-1])   334    335     # Normal bytecode generators.   336    337     def get_iter(self):   338         self.output.append(opmap["GET_ITER"])   339         self.position += 1   340    341     def jump_if_false(self, offset=0):   342         self.output.append(opmap["JUMP_IF_FALSE"])   343         self.position += 1   344         self._write_value(offset) # May be filled in later   345    346     def jump_if_true(self, offset=0):   347         self.output.append(opmap["JUMP_IF_TRUE"])   348         self.position += 1   349         self._write_value(offset) # May be filled in later   350    351     def jump_forward(self, offset=0):   352         self.output.append(opmap["JUMP_FORWARD"])   353         self.position += 1   354         self._write_value(offset) # May be filled in later   355    356     def jump_absolute(self, address=0):   357         self.output.append(opmap["JUMP_ABSOLUTE"])   358         self.position += 1   359         self._write_value(address) # May be filled in later   360    361     def build_tuple(self, count):   362         self.output.append(opmap["BUILD_TUPLE"])   363         self.position += 1   364         self._write_value(count)   365         self.update_stack_depth(-(count - 1))   366    367     def build_list(self, count):   368         self.output.append(opmap["BUILD_LIST"])   369         self.position += 1   370         self._write_value(count)   371         self.update_stack_depth(-(count - 1))   372    373     def pop_top(self):   374         self.output.append(opmap["POP_TOP"])   375         self.position += 1   376         self.update_stack_depth(-1)   377    378     def dup_top(self):   379         self.output.append(opmap["DUP_TOP"])   380         self.position += 1   381         self.update_stack_depth(1)   382    383     def dup_topx(self, count):   384         self.output.append(opmap["DUP_TOPX"])   385         self.position += 1   386         self._write_value(count)   387         self.update_stack_depth(count)   388    389     def rot_two(self):   390         self.output.append(opmap["ROT_TWO"])   391         self.position += 1   392    393     def rot_three(self):   394         self.output.append(opmap["ROT_THREE"])   395         self.position += 1   396    397     def rot_four(self):   398         self.output.append(opmap["ROT_FOUR"])   399         self.position += 1   400    401     def call_function(self, count):   402         self.output.append(opmap["CALL_FUNCTION"])   403         self.position += 1   404         self._write_value(count)   405         self.update_stack_depth(-count)   406    407     def call_function_var(self, count):   408         self.output.append(opmap["CALL_FUNCTION_VAR"])   409         self.position += 1   410         self._write_value(count)   411         self.update_stack_depth(-count-1)   412    413     def binary_subscr(self):   414         self.output.append(opmap["BINARY_SUBSCR"])   415         self.position += 1   416         self.update_stack_depth(-1)   417    418     def binary_add(self):   419         self.output.append(opmap["BINARY_ADD"])   420         self.position += 1   421         self.update_stack_depth(-1)   422    423     def binary_divide(self):   424         self.output.append(opmap["BINARY_DIVIDE"])   425         self.position += 1   426         self.update_stack_depth(-1)   427    428     def binary_multiply(self):   429         self.output.append(opmap["BINARY_MULTIPLY"])   430         self.position += 1   431         self.update_stack_depth(-1)   432    433     def binary_modulo(self):   434         self.output.append(opmap["BINARY_MODULO"])   435         self.position += 1   436         self.update_stack_depth(-1)   437    438     def binary_subtract(self):   439         self.output.append(opmap["BINARY_SUBTRACT"])   440         self.position += 1   441         self.update_stack_depth(-1)   442    443     def binary_and(self):   444         self.output.append(opmap["BINARY_AND"])   445         self.position += 1   446         self.update_stack_depth(-1)   447    448     def binary_or(self):   449         self.output.append(opmap["BINARY_XOR"])   450         self.position += 1   451         self.update_stack_depth(-1)   452    453     def binary_lshift(self):   454         self.output.append(opmap["BINARY_LSHIFT"])   455         self.position += 1   456         self.update_stack_depth(-1)   457    458     def binary_rshift(self):   459         self.output.append(opmap["BINARY_RSHIFT"])   460         self.position += 1   461         self.update_stack_depth(-1)   462    463     def binary_xor(self):   464         self.output.append(opmap["BINARY_XOR"])   465         self.position += 1   466         self.update_stack_depth(-1)   467    468     def store_subscr(self):   469         self.output.append(opmap["STORE_SUBSCR"])   470         self.position += 1   471         self.update_stack_depth(-3)   472    473     def unary_negative(self):   474         self.output.append(opmap["UNARY_NEGATIVE"])   475         self.position += 1   476    477     def slice_0(self):   478         self.output.append(opmap["SLICE+0"])   479         self.position += 1   480    481     def slice_1(self):   482         self.output.append(opmap["SLICE+1"])   483         self.position += 1   484    485     def compare_op(self, op):   486         self.output.append(opmap["COMPARE_OP"])   487         self.position += 1   488         self._write_value(list(cmp_op).index(op))   489         self.update_stack_depth(-1)   490    491     def return_value(self):   492         self.output.append(opmap["RETURN_VALUE"])   493         self.position += 1   494         self.update_stack_depth(-1)   495    496     def raise_varargs(self, count):   497         self.output.append(opmap["RAISE_VARARGS"])   498         self.position += 1   499         self._write_value(count)   500    501     def pop_block(self):   502         self.output.append(opmap["POP_BLOCK"])   503         self.position += 1   504    505     def end_finally(self):   506         self.output.append(opmap["END_FINALLY"])   507         self.position += 1   508    509     def unpack_sequence(self, count):   510         self.output.append(opmap["UNPACK_SEQUENCE"])   511         self.position += 1   512         self._write_value(count)   513    514     # Debugging.   515    516     def print_item(self):   517         self.output.append(opmap["PRINT_ITEM"])   518         self.position += 1   519    520 # Utility classes and functions.   521    522 class LazyDict(UserDict):   523     def __getitem__(self, key):   524         if not self.data.has_key(key):   525             # NOTE: Assume 16-bit value.   526             self.data[key] = LazyValue(2)   527         return self.data[key]   528     def __setitem__(self, key, value):   529         if self.data.has_key(key):   530             existing_value = self.data[key]   531             if isinstance(existing_value, LazyValue):   532                 existing_value.set_value(value)   533                 return   534         self.data[key] = value   535    536 class LazyValue:   537     def __init__(self, nvalues):   538         self.values = []   539         for i in range(0, nvalues):   540             self.values.append(LazySubValue())   541     def set_value(self, value):   542         # NOTE: Assume at least 16-bit value. No "filling" performed.   543         if value <= 0xffff:   544             self.values[0].set_value(value & 0xff)   545             self.values[1].set_value((value & 0xff00) >> 8)   546         else:   547             # NOTE: EXTENDED_ARG not yet supported.   548             raise ValueError, value   549     def get_value(self):   550         value = 0   551         values = self.values[:]   552         for i in range(0, len(values)):   553             value = (value << 8) + values.pop().value   554         return value   555    556 class LazySubValue:   557     def __init__(self):   558         self.value = 0   559     def set_value(self, value):   560         self.value = value   561    562 def signed(value, limit):   563    564     """   565     Return the signed integer from the unsigned 'value', where 'limit' (a value   566     one greater than the highest possible positive integer) is used to determine   567     whether a negative or positive result is produced.   568     """   569    570     d, r = divmod(value, limit)   571     if d == 1:   572         mask = limit * 2 - 1   573         return -1 - (value ^ mask)   574     else:   575         return value   576    577 def signed2(value):   578     return signed(value, 0x8000)   579    580 def signed4(value):   581     return signed(value, 0x80000000)   582    583 # Bytecode conversion.   584    585 class BytecodeReader:   586    587     "A generic Java bytecode reader."   588    589     def __init__(self, class_file):   590         self.class_file = class_file   591         self.position_mapping = LazyDict()   592    593     def process(self, method, program):   594         self.java_position = 0   595         self.in_finally = 0   596         self.method = method   597    598         # NOTE: Potentially unreliable way of getting necessary information.   599    600         code, exception_table = None, None   601         for attribute in method.attributes:   602             if isinstance(attribute, classfile.CodeAttributeInfo):   603                 code, exception_table = attribute.code, attribute.exception_table   604                 break   605         if code is None:   606             return   607    608         # Produce a structure which permits fast access to exception details.   609    610         exception_block_start = {}   611         exception_block_end = {}   612         exception_block_handler = {}   613         reversed_exception_table = exception_table[:]   614         reversed_exception_table.reverse()   615    616         # Later entries have wider coverage than earlier entries.   617    618         for exception in reversed_exception_table:   619    620             # Index start positions.   621    622             if not exception_block_start.has_key(exception.start_pc):   623                 exception_block_start[exception.start_pc] = []   624             exception_block_start[exception.start_pc].append(exception)   625    626             # Index end positions.   627    628             if not exception_block_end.has_key(exception.end_pc):   629                 exception_block_end[exception.end_pc] = []   630             exception_block_end[exception.end_pc].append(exception)   631    632             # Index handler positions.   633    634             if not exception_block_handler.has_key(exception.handler_pc):   635                 exception_block_handler[exception.handler_pc] = []   636             exception_block_handler[exception.handler_pc].append(exception)   637    638         # Process each instruction in the code.   639    640         while self.java_position < len(code):   641             self.position_mapping[self.java_position] = program.position   642    643             # Insert exception handling constructs.   644    645             block_starts = exception_block_start.get(self.java_position, [])   646             for exception in block_starts:   647    648                 # Note that the absolute position is used.   649    650                 if exception.catch_type == 0:   651                     program.setup_finally(self.position_mapping[exception.handler_pc])   652                 else:   653                     program.setup_except(self.position_mapping[exception.handler_pc])   654    655             if block_starts:   656                 self.in_finally = 0   657    658             # Insert exception handler details.   659             # NOTE: Ensure that pop_block is reachable by possibly inserting it at the start of finally handlers.   660             # NOTE: Insert a check for the correct exception at the start of each handler.   661    662             for exception in exception_block_handler.get(self.java_position, []):   663                 program.end_exception()   664                 if exception.catch_type == 0:   665                     self.in_finally = 1   666                 else:   667                     program.start_handler(self.class_file.constants[exception.catch_type - 1].get_python_name())   668    669             # Process the bytecode at the current position.   670    671             bytecode = ord(code[self.java_position])   672             mnemonic, number_of_arguments = self.java_bytecodes[bytecode]   673             number_of_arguments = self.process_bytecode(mnemonic, number_of_arguments, code, program)   674             next_java_position = self.java_position + 1 + number_of_arguments   675    676             # Insert exception block end details.   677    678             for exception in exception_block_end.get(next_java_position, []):   679    680                 # NOTE: Insert jump beyond handlers.   681                 # NOTE: program.jump_forward/absolute(...)   682                 # NOTE: Insert end finally at end of handlers as well as where "ret" occurs.   683    684                 if exception.catch_type != 0:   685                     program.pop_block()   686    687             # Only advance the JVM position after sneaking in extra Python   688             # instructions.   689    690             self.java_position = next_java_position   691    692     def process_bytecode(self, mnemonic, number_of_arguments, code, program):   693         if number_of_arguments is not None:   694             arguments = []   695             for j in range(0, number_of_arguments):   696                 arguments.append(ord(code[self.java_position + 1 + j]))   697    698             # Call the handler.   699    700             getattr(self, mnemonic)(arguments, program)   701             return number_of_arguments   702         else:   703             # Call the handler.   704    705             return getattr(self, mnemonic)(code[self.java_position+1:], program)   706    707     java_bytecodes = {   708         # code : (mnemonic, number of following bytes, change in stack)   709         0 : ("nop", 0),   710         1 : ("aconst_null", 0),   711         2 : ("iconst_m1", 0),   712         3 : ("iconst_0", 0),   713         4 : ("iconst_1", 0),   714         5 : ("iconst_2", 0),   715         6 : ("iconst_3", 0),   716         7 : ("iconst_4", 0),   717         8 : ("iconst_5", 0),   718         9 : ("lconst_0", 0),   719         10 : ("lconst_1", 0),   720         11 : ("fconst_0", 0),   721         12 : ("fconst_1", 0),   722         13 : ("fconst_2", 0),   723         14 : ("dconst_0", 0),   724         15 : ("dconst_1", 0),   725         16 : ("bipush", 1),   726         17 : ("sipush", 2),   727         18 : ("ldc", 1),   728         19 : ("ldc_w", 2),   729         20 : ("ldc2_w", 2),   730         21 : ("iload", 1),   731         22 : ("lload", 1),   732         23 : ("fload", 1),   733         24 : ("dload", 1),   734         25 : ("aload", 1),   735         26 : ("iload_0", 0),   736         27 : ("iload_1", 0),   737         28 : ("iload_2", 0),   738         29 : ("iload_3", 0),   739         30 : ("lload_0", 0),   740         31 : ("lload_1", 0),   741         32 : ("lload_2", 0),   742         33 : ("lload_3", 0),   743         34 : ("fload_0", 0),   744         35 : ("fload_1", 0),   745         36 : ("fload_2", 0),   746         37 : ("fload_3", 0),   747         38 : ("dload_0", 0),   748         39 : ("dload_1", 0),   749         40 : ("dload_2", 0),   750         41 : ("dload_3", 0),   751         42 : ("aload_0", 0),   752         43 : ("aload_1", 0),   753         44 : ("aload_2", 0),   754         45 : ("aload_3", 0),   755         46 : ("iaload", 0),   756         47 : ("laload", 0),   757         48 : ("faload", 0),   758         49 : ("daload", 0),   759         50 : ("aaload", 0),   760         51 : ("baload", 0),   761         52 : ("caload", 0),   762         53 : ("saload", 0),   763         54 : ("istore", 1),   764         55 : ("lstore", 1),   765         56 : ("fstore", 1),   766         57 : ("dstore", 1),   767         58 : ("astore", 1),   768         59 : ("istore_0", 0),   769         60 : ("istore_1", 0),   770         61 : ("istore_2", 0),   771         62 : ("istore_3", 0),   772         63 : ("lstore_0", 0),   773         64 : ("lstore_1", 0),   774         65 : ("lstore_2", 0),   775         66 : ("lstore_3", 0),   776         67 : ("fstore_0", 0),   777         68 : ("fstore_1", 0),   778         69 : ("fstore_2", 0),   779         70 : ("fstore_3", 0),   780         71 : ("dstore_0", 0),   781         72 : ("dstore_1", 0),   782         73 : ("dstore_2", 0),   783         74 : ("dstore_3", 0),   784         75 : ("astore_0", 0),   785         76 : ("astore_1", 0),   786         77 : ("astore_2", 0),   787         78 : ("astore_3", 0),   788         79 : ("iastore", 0),   789         80 : ("lastore", 0),   790         81 : ("fastore", 0),   791         82 : ("dastore", 0),   792         83 : ("aastore", 0),   793         84 : ("bastore", 0),   794         85 : ("castore", 0),   795         86 : ("sastore", 0),   796         87 : ("pop", 0),   797         88 : ("pop2", 0),   798         89 : ("dup", 0),   799         90 : ("dup_x1", 0),   800         91 : ("dup_x2", 0),   801         92 : ("dup2", 0),   802         93 : ("dup2_x1", 0),   803         94 : ("dup2_x2", 0),   804         95 : ("swap", 0),   805         96 : ("iadd", 0),   806         97 : ("ladd", 0),   807         98 : ("fadd", 0),   808         99 : ("dadd", 0),   809         100 : ("isub", 0),   810         101 : ("lsub", 0),   811         102 : ("fsub", 0),   812         103 : ("dsub", 0),   813         104 : ("imul", 0),   814         105 : ("lmul", 0),   815         106 : ("fmul", 0),   816         107 : ("dmul", 0),   817         108 : ("idiv", 0),   818         109 : ("ldiv", 0),   819         110 : ("fdiv", 0),   820         111 : ("ddiv", 0),   821         112 : ("irem", 0),   822         113 : ("lrem", 0),   823         114 : ("frem", 0),   824         115 : ("drem", 0),   825         116 : ("ineg", 0),   826         117 : ("lneg", 0),   827         118 : ("fneg", 0),   828         119 : ("dneg", 0),   829         120 : ("ishl", 0),   830         121 : ("lshl", 0),   831         122 : ("ishr", 0),   832         123 : ("lshr", 0),   833         124 : ("iushr", 0),   834         125 : ("lushr", 0),   835         126 : ("iand", 0),   836         127 : ("land", 0),   837         128 : ("ior", 0),   838         129 : ("lor", 0),   839         130 : ("ixor", 0),   840         131 : ("lxor", 0),   841         132 : ("iinc", 2),   842         133 : ("i2l", 0),   843         134 : ("i2f", 0),   844         135 : ("i2d", 0),   845         136 : ("l2i", 0),   846         137 : ("l2f", 0),   847         138 : ("l2d", 0),   848         139 : ("f2i", 0),   849         140 : ("f2l", 0),   850         141 : ("f2d", 0),   851         142 : ("d2i", 0),   852         143 : ("d2l", 0),   853         144 : ("d2f", 0),   854         145 : ("i2b", 0),   855         146 : ("i2c", 0),   856         147 : ("i2s", 0),   857         148 : ("lcmp", 0),   858         149 : ("fcmpl", 0),   859         150 : ("fcmpg", 0),   860         151 : ("dcmpl", 0),   861         152 : ("dcmpg", 0),   862         153 : ("ifeq", 2),   863         154 : ("ifne", 2),   864         155 : ("iflt", 2),   865         156 : ("ifge", 2),   866         157 : ("ifgt", 2),   867         158 : ("ifle", 2),   868         159 : ("if_icmpeq", 2),   869         160 : ("if_icmpne", 2),   870         161 : ("if_icmplt", 2),   871         162 : ("if_icmpge", 2),   872         163 : ("if_icmpgt", 2),   873         164 : ("if_icmple", 2),   874         165 : ("if_acmpeq", 2),   875         166 : ("if_acmpne", 2),   876         167 : ("goto", 2),   877         168 : ("jsr", 2),   878         169 : ("ret", 1),   879         170 : ("tableswitch", None), # variable number of arguments   880         171 : ("lookupswitch", None), # variable number of arguments   881         172 : ("ireturn", 0),   882         173 : ("lreturn", 0),   883         174 : ("freturn", 0),   884         175 : ("dreturn", 0),   885         176 : ("areturn", 0),   886         177 : ("return_", 0),   887         178 : ("getstatic", 2),   888         179 : ("putstatic", 2),   889         180 : ("getfield", 2),   890         181 : ("putfield", 2),   891         182 : ("invokevirtual", 2),   892         183 : ("invokespecial", 2),   893         184 : ("invokestatic", 2),   894         185 : ("invokeinterface", 4),   895         187 : ("new", 2),   896         188 : ("newarray", 1),   897         189 : ("anewarray", 2),   898         190 : ("arraylength", 0),   899         191 : ("athrow", 0),   900         192 : ("checkcast", 2),   901         193 : ("instanceof", 2),   902         194 : ("monitorenter", 0),   903         195 : ("monitorexit", 0),   904         196 : ("wide", None), # 3 or 5 arguments, stack changes according to modified element   905         197 : ("multianewarray", 3),   906         198 : ("ifnull", 2),   907         199 : ("ifnonnull", 2),   908         200 : ("goto_w", 4),   909         201 : ("jsr_w", 4),   910         }   911    912 class BytecodeDisassembler(BytecodeReader):   913    914     "A Java bytecode disassembler."   915    916     bytecode_methods = [spec[0] for spec in BytecodeReader.java_bytecodes.values()]   917    918     def __getattr__(self, name):   919         if name in self.bytecode_methods:   920             print "%5s %s" % (self.java_position, name),   921             return self.generic   922         else:   923             raise AttributeError, name   924    925     def generic(self, arguments, program):   926         print arguments   927    928     def lookupswitch(self, code, program):   929         print "%5s lookupswitch" % (self.java_position,),   930         d, r = divmod(self.java_position + 1, 4)   931         to_boundary = (4 - r) % 4   932         code = code[to_boundary:]   933         default = classfile.u4(code[0:4])   934         npairs = classfile.u4(code[4:8])   935         print default, npairs   936         return to_boundary + 8 + npairs * 8   937    938     def tableswitch(self, code, program):   939         print "%5s tableswitch" % (self.java_position,),   940         d, r = divmod(self.java_position + 1, 4)   941         to_boundary = (4 - r) % 4   942         code = code[to_boundary:]   943         default = classfile.u4(code[0:4])   944         low = classfile.u4(code[4:8])   945         high = classfile.u4(code[8:12])   946         print default, low, high   947         return to_boundary + 12 + (high - low + 1) * 4   948    949 class BytecodeDisassemblerProgram:   950     position = 0   951     def setup_except(self, target):   952         print "(setup_except %s)" % target   953     def setup_finally(self, target):   954         print "(setup_finally %s)" % target   955     def end_exception(self):   956         print "(end_exception)"   957     def start_handler(self, exc_name):   958         print "(start_handler %s)" % exc_name   959     def pop_block(self):   960         print "(pop_block)"   961    962 class BytecodeTranslator(BytecodeReader):   963    964     "A Java bytecode translator which uses a Python bytecode writer."   965    966     def _load_class_name(self, full_class_name, program):   967         this_class_name = str(self.class_file.this_class.get_python_name())   968         class_parts = full_class_name.split(".")   969         if full_class_name != this_class_name:   970             program.use_external_name(full_class_name)   971             program.load_global(class_parts[0])   972             for class_part in class_parts[1:]:   973                 program.load_attr(class_part)   # Stack: classref   974         else:   975             program.load_global(class_parts[-1])   976    977     def aaload(self, arguments, program):   978         # NOTE: No type checking performed.   979         program.binary_subscr()   980    981     def aastore(self, arguments, program):   982         # NOTE: No type checking performed.   983         # Stack: arrayref, index, value   984         program.rot_three() # Stack: value, arrayref, index   985         program.store_subscr()   986    987     def aconst_null(self, arguments, program):   988         program.load_const(None)   989    990     def aload(self, arguments, program):   991         program.load_fast(arguments[0])   992    993     def aload_0(self, arguments, program):   994         program.load_fast(0)   995    996     def aload_1(self, arguments, program):   997         program.load_fast(1)   998    999     def aload_2(self, arguments, program):  1000         program.load_fast(2)  1001   1002     def aload_3(self, arguments, program):  1003         program.load_fast(3)  1004   1005     def anewarray(self, arguments, program):  1006         # NOTE: Does not raise NegativeArraySizeException.  1007         # NOTE: Not using the index to type the list/array.  1008         index = (arguments[0] << 8) + arguments[1]  1009         self._newarray(program)  1010   1011     def _newarray(self, program):  1012         program.build_list(0)       # Stack: count, list  1013         program.rot_two()           # Stack: list, count  1014         program.setup_loop()  1015         program.load_global("range")  1016         program.load_const(0)       # Stack: list, count, range, 0  1017         program.rot_three()         # Stack: list, 0, count, range  1018         program.rot_three()         # Stack: list, range, 0, count  1019         program.call_function(2)    # Stack: list, range_list  1020         program.get_iter()          # Stack: list, iter  1021         program.for_iter()          # Stack: list, iter, value  1022         program.pop_top()           # Stack: list, iter  1023         program.rot_two()           # Stack: iter, list  1024         program.dup_top()           # Stack: iter, list, list  1025         program.load_attr("append") # Stack: iter, list, append  1026         program.load_const(None)    # Stack: iter, list, append, None  1027         program.call_function(1)    # Stack: iter, list, None  1028         program.pop_top()           # Stack: iter, list  1029         program.rot_two()           # Stack: list, iter  1030         program.end_loop()          # Back to for_iter above  1031   1032     def areturn(self, arguments, program):  1033         program.return_value()  1034   1035     def arraylength(self, arguments, program):  1036         program.load_global("len")  # Stack: arrayref, len  1037         program.rot_two()           # Stack: len, arrayref  1038         program.call_function(1)  1039   1040     def astore(self, arguments, program):  1041         program.store_fast(arguments[0])  1042   1043     def astore_0(self, arguments, program):  1044         program.store_fast(0)  1045   1046     def astore_1(self, arguments, program):  1047         program.store_fast(1)  1048   1049     def astore_2(self, arguments, program):  1050         program.store_fast(2)  1051   1052     def astore_3(self, arguments, program):  1053         program.store_fast(3)  1054   1055     def athrow(self, arguments, program):  1056         # NOTE: NullPointerException not raised where null/None is found on the stack.  1057         # If this instruction appears in a finally handler, use end_finally instead.  1058         if self.in_finally:  1059             program.end_finally()  1060         else:  1061             # Wrap the exception in a Python exception.  1062             program.load_global("Exception")    # Stack: objectref, Exception  1063             program.rot_two()                   # Stack: Exception, objectref  1064             program.call_function(1)            # Stack: exception  1065             program.raise_varargs(1)  1066             # NOTE: This seems to put another object on the stack.  1067   1068     baload = aaload  1069     bastore = aastore  1070   1071     def bipush(self, arguments, program):  1072         program.load_const(arguments[0])  1073   1074     caload = aaload  1075     castore = aastore  1076   1077     def checkcast(self, arguments, program):  1078         index = (arguments[0] << 8) + arguments[1]  1079         target_name = self.class_file.constants[index - 1].get_python_name()  1080         program.use_external_name(target_name)  1081   1082         # NOTE: Using the string version of the name which may contain incompatible characters.  1083         target_components = str(target_name).split("/")  1084   1085         program.dup_top()                   # Stack: objectref, objectref  1086         program.load_global("isinstance")   # Stack: objectref, objectref, isinstance  1087         program.rot_two()                   # Stack: objectref, isinstance, objectref  1088         program.load_global(target_components[0])  1089         for target_component in target_components[1:]:  1090             program.load_attr(target_component)  1091         program.call_function(2)            # Stack: objectref  1092   1093     def d2f(self, arguments, program):  1094         pass  1095   1096     def d2i(self, arguments, program):  1097         program.load_global("int")  # Stack: value, int  1098         program.rot_two()           # Stack: int, value  1099         program.call_function(1)    # Stack: result  1100   1101     d2l = d2i # Preserving Java semantics  1102   1103     def dadd(self, arguments, program):  1104         # NOTE: No type checking performed.  1105         program.binary_add()  1106   1107     daload = aaload  1108     dastore = aastore  1109   1110     def dcmpg(self, arguments, program):  1111         # NOTE: No type checking performed.  1112         program.compare_op(">")  1113   1114     def dcmpl(self, arguments, program):  1115         # NOTE: No type checking performed.  1116         program.compare_op("<")  1117   1118     def dconst_0(self, arguments, program):  1119         program.load_const(0.0)  1120   1121     def dconst_1(self, arguments, program):  1122         program.load_const(1.0)  1123   1124     def ddiv(self, arguments, program):  1125         # NOTE: No type checking performed.  1126         program.binary_divide()  1127   1128     dload = aload  1129     dload_0 = aload_0  1130     dload_1 = aload_1  1131     dload_2 = aload_2  1132     dload_3 = aload_3  1133   1134     def dmul(self, arguments, program):  1135         # NOTE: No type checking performed.  1136         program.binary_multiply()  1137   1138     def dneg(self, arguments, program):  1139         # NOTE: No type checking performed.  1140         program.unary_negative()  1141   1142     def drem(self, arguments, program):  1143         # NOTE: No type checking performed.  1144         program.binary_modulo()  1145   1146     dreturn = areturn  1147     dstore = astore  1148     dstore_0 = astore_0  1149     dstore_1 = astore_1  1150     dstore_2 = astore_2  1151     dstore_3 = astore_3  1152   1153     def dsub(self, arguments, program):  1154         # NOTE: No type checking performed.  1155         program.binary_subtract()  1156   1157     def dup(self, arguments, program):  1158         program.dup_top()  1159   1160     def dup_x1(self, arguments, program):  1161         # Ignoring computational type categories.  1162         program.dup_top()  1163         program.rot_three()  1164   1165     def dup_x2(self, arguments, program):  1166         # Ignoring computational type categories.  1167         program.dup_top()  1168         program.rot_four()  1169   1170     dup2 = dup # Ignoring computational type categories  1171     dup2_x1 = dup_x1 # Ignoring computational type categories  1172     dup2_x2 = dup_x2 # Ignoring computational type categories  1173   1174     def f2d(self, arguments, program):  1175         pass # Preserving Java semantics  1176   1177     def f2i(self, arguments, program):  1178         program.load_global("int")  # Stack: value, int  1179         program.rot_two()           # Stack: int, value  1180         program.call_function(1)    # Stack: result  1181   1182     f2l = f2i # Preserving Java semantics  1183     fadd = dadd  1184     faload = daload  1185     fastore = dastore  1186     fcmpg = dcmpg  1187     fcmpl = dcmpl  1188     fconst_0 = dconst_0  1189     fconst_1 = dconst_1  1190   1191     def fconst_2(self, arguments, program):  1192         program.load_const(2.0)  1193   1194     fdiv = ddiv  1195     fload = dload  1196     fload_0 = dload_0  1197     fload_1 = dload_1  1198     fload_2 = dload_2  1199     fload_3 = dload_3  1200     fmul = dmul  1201     fneg = dneg  1202     frem = drem  1203     freturn = dreturn  1204     fstore = dstore  1205     fstore_0 = dstore_0  1206     fstore_1 = dstore_1  1207     fstore_2 = dstore_2  1208     fstore_3 = dstore_3  1209     fsub = dsub  1210   1211     def getfield(self, arguments, program):  1212         index = (arguments[0] << 8) + arguments[1]  1213         target_name = self.class_file.constants[index - 1].get_python_name()  1214         # NOTE: Using the string version of the name which may contain incompatible characters.  1215         program.load_attr(str(target_name))  1216   1217     def getstatic(self, arguments, program):  1218         index = (arguments[0] << 8) + arguments[1]  1219         target = self.class_file.constants[index - 1]  1220         target_name = target.get_python_name()  1221   1222         # Get the class name instead of the fully qualified name.  1223   1224         full_class_name = target.get_class().get_python_name()  1225         self._load_class_name(full_class_name, program)  1226         # NOTE: Using the string version of the name which may contain incompatible characters.  1227         program.load_attr(str(target_name))  1228   1229     def goto(self, arguments, program):  1230         offset = signed2((arguments[0] << 8) + arguments[1])  1231         java_absolute = self.java_position + offset  1232         program.jump_absolute(self.position_mapping[java_absolute])  1233   1234     def goto_w(self, arguments, program):  1235         offset = signed4((arguments[0] << 24) + (arguments[1] << 16) + (arguments[2] << 8) + arguments[3])  1236         java_absolute = self.java_position + offset  1237         program.jump_absolute(self.position_mapping[java_absolute])  1238   1239     def i2b(self, arguments, program):  1240         pass  1241   1242     def i2c(self, arguments, program):  1243         pass  1244   1245     def i2d(self, arguments, program):  1246         program.load_global("float")    # Stack: value, float  1247         program.rot_two()               # Stack: float, value  1248         program.call_function(1)        # Stack: result  1249   1250     i2f = i2d # Not distinguishing between float and double  1251   1252     def i2l(self, arguments, program):  1253         pass # Preserving Java semantics  1254   1255     def i2s(self, arguments, program):  1256         pass # Not distinguishing between int and short  1257   1258     iadd = fadd  1259     iaload = faload  1260   1261     def iand(self, arguments, program):  1262         # NOTE: No type checking performed.  1263         program.binary_and()  1264   1265     iastore = fastore  1266   1267     def iconst_m1(self, arguments, program):  1268         program.load_const(-1)  1269   1270     def iconst_0(self, arguments, program):  1271         program.load_const(0)  1272   1273     def iconst_1(self, arguments, program):  1274         program.load_const(1)  1275   1276     def iconst_2(self, arguments, program):  1277         program.load_const(2)  1278   1279     def iconst_3(self, arguments, program):  1280         program.load_const(3)  1281   1282     def iconst_4(self, arguments, program):  1283         program.load_const(4)  1284   1285     def iconst_5(self, arguments, program):  1286         program.load_const(5)  1287   1288     idiv = fdiv  1289   1290     def _if_xcmpx(self, arguments, program, op):  1291         offset = signed2((arguments[0] << 8) + arguments[1])  1292         java_absolute = self.java_position + offset  1293         program.compare_op(op)  1294         program.jump_to_label(0, "next") # skip if false  1295         program.pop_top()  1296         program.jump_absolute(self.position_mapping[java_absolute])  1297         program.start_label("next")  1298         program.pop_top()  1299   1300     def if_acmpeq(self, arguments, program):  1301         # NOTE: No type checking performed.  1302         self._if_xcmpx(arguments, program, "is")  1303   1304     def if_acmpne(self, arguments, program):  1305         # NOTE: No type checking performed.  1306         self._if_xcmpx(arguments, program, "is not")  1307   1308     def if_icmpeq(self, arguments, program):  1309         # NOTE: No type checking performed.  1310         self._if_xcmpx(arguments, program, "==")  1311   1312     def if_icmpne(self, arguments, program):  1313         # NOTE: No type checking performed.  1314         self._if_xcmpx(arguments, program, "!=")  1315   1316     def if_icmplt(self, arguments, program):  1317         # NOTE: No type checking performed.  1318         self._if_xcmpx(arguments, program, "<")  1319   1320     def if_icmpge(self, arguments, program):  1321         # NOTE: No type checking performed.  1322         self._if_xcmpx(arguments, program, ">=")  1323   1324     def if_icmpgt(self, arguments, program):  1325         # NOTE: No type checking performed.  1326         self._if_xcmpx(arguments, program, ">")  1327   1328     def if_icmple(self, arguments, program):  1329         # NOTE: No type checking performed.  1330         self._if_xcmpx(arguments, program, "<=")  1331   1332     def ifeq(self, arguments, program):  1333         # NOTE: No type checking performed.  1334         program.load_const(0)  1335         self._if_xcmpx(arguments, program, "==")  1336   1337     def ifne(self, arguments, program):  1338         # NOTE: No type checking performed.  1339         program.load_const(0)  1340         self._if_xcmpx(arguments, program, "!=")  1341   1342     def iflt(self, arguments, program):  1343         # NOTE: No type checking performed.  1344         program.load_const(0)  1345         self._if_xcmpx(arguments, program, "<")  1346   1347     def ifge(self, arguments, program):  1348         # NOTE: No type checking performed.  1349         program.load_const(0)  1350         self._if_xcmpx(arguments, program, ">=")  1351   1352     def ifgt(self, arguments, program):  1353         # NOTE: No type checking performed.  1354         program.load_const(0)  1355         self._if_xcmpx(arguments, program, ">")  1356   1357     def ifle(self, arguments, program):  1358         # NOTE: No type checking performed.  1359         program.load_const(0)  1360         self._if_xcmpx(arguments, program, "<=")  1361   1362     def ifnonnull(self, arguments, program):  1363         # NOTE: No type checking performed.  1364         program.load_const(None)  1365         self._if_xcmpx(arguments, program, "is not")  1366   1367     def ifnull(self, arguments, program):  1368         # NOTE: No type checking performed.  1369         program.load_const(None)  1370         self._if_xcmpx(arguments, program, "is")  1371   1372     def iinc(self, arguments, program):  1373         # NOTE: No type checking performed.  1374         program.load_fast(arguments[0])  1375         program.load_const(arguments[1])  1376         program.binary_add()  1377         program.store_fast(arguments[0])  1378   1379     iload = fload  1380     iload_0 = fload_0  1381     iload_1 = fload_1  1382     iload_2 = fload_2  1383     iload_3 = fload_3  1384     imul = fmul  1385     ineg = fneg  1386   1387     def instanceof(self, arguments, program):  1388         index = (arguments[0] << 8) + arguments[1]  1389         target_name = self.class_file.constants[index - 1].get_python_name()  1390         program.use_external_name(target_name)  1391   1392         # NOTE: Using the string version of the name which may contain incompatible characters.  1393         target_components = str(target_name).split("/")  1394   1395         program.load_global("isinstance")   # Stack: objectref, isinstance  1396         program.rot_two()                   # Stack: isinstance, objectref  1397         program.load_global(target_components[0])  1398         for target_component in target_components[1:]:  1399             program.load_attr(target_component)  1400         program.call_function(2)            # Stack: result  1401   1402     def _invoke(self, target_name, program):  1403         # NOTE: Using the string version of the name which may contain incompatible characters.  1404         program.load_attr(str(target_name)) # Stack: tuple, method  1405         program.rot_two()                   # Stack: method, tuple  1406         program.call_function_var(0)        # Stack: result  1407   1408     def invokeinterface(self, arguments, program):  1409         # NOTE: This implementation does not perform the necessary checks for  1410         # NOTE: signature-based polymorphism.  1411         # NOTE: Java rules not specifically obeyed.  1412         index = (arguments[0] << 8) + arguments[1]  1413         # NOTE: "count" == nargs + 1, apparently.  1414         count = arguments[2] - 1  1415         target_name = self.class_file.constants[index - 1].get_python_name()  1416         # Stack: objectref, arg1, arg2, ...  1417         program.build_tuple(count)          # Stack: objectref, tuple  1418         program.rot_two()                   # Stack: tuple, objectref  1419         # NOTE: The interface information is not used to discover the correct  1420         # NOTE: method.  1421         self._invoke(target_name, program)  1422   1423     def invokespecial(self, arguments, program):  1424         # NOTE: This implementation does not perform the necessary checks for  1425         # NOTE: signature-based polymorphism.  1426         # NOTE: Java rules not specifically obeyed.  1427         index = (arguments[0] << 8) + arguments[1]  1428         target = self.class_file.constants[index - 1]  1429         original_name = target.get_name()  1430         target_name = target.get_python_name()  1431   1432         # Get the number of parameters from the descriptor.  1433   1434         count = len(target.get_descriptor()[0])  1435   1436         # First, we build a tuple of the reference and arguments.  1437   1438         program.build_tuple(count + 1)          # Stack: tuple  1439   1440         # Get the class name instead of the fully qualified name.  1441         # NOTE: Not bothering with Object initialisation.  1442   1443         full_class_name = target.get_class().get_python_name()  1444         if full_class_name not in ("java.lang.Object", "java.lang.Exception"):  1445             self._load_class_name(full_class_name, program)  1446             self._invoke(target_name, program)  1447   1448         # Remove Python None return value.  1449   1450         if str(original_name) == "<init>":  1451             program.pop_top()  1452   1453     def invokestatic(self, arguments, program):  1454         # NOTE: This implementation does not perform the necessary checks for  1455         # NOTE: signature-based polymorphism.  1456         # NOTE: Java rules not specifically obeyed.  1457         index = (arguments[0] << 8) + arguments[1]  1458         target = self.class_file.constants[index - 1]  1459         target_name = target.get_python_name()  1460   1461         # Get the number of parameters from the descriptor.  1462   1463         count = len(target.get_descriptor()[0])  1464   1465         # Stack: arg1, arg2, ...  1466   1467         program.build_tuple(count)              # Stack: tuple  1468   1469         # Use the class to provide access to static methods.  1470         # Get the class name instead of the fully qualified name.  1471   1472         full_class_name = target.get_class().get_python_name()  1473         if full_class_name not in ("java.lang.Object", "java.lang.Exception"):  1474             self._load_class_name(full_class_name, program)  1475             self._invoke(target_name, program)  1476   1477     def invokevirtual (self, arguments, program):  1478         # NOTE: This implementation does not perform the necessary checks for  1479         # NOTE: signature-based polymorphism.  1480         # NOTE: Java rules not specifically obeyed.  1481         index = (arguments[0] << 8) + arguments[1]  1482         target = self.class_file.constants[index - 1]  1483         target_name = target.get_python_name()  1484         # Get the number of parameters from the descriptor.  1485         count = len(target.get_descriptor()[0])  1486         # Stack: objectref, arg1, arg2, ...  1487         program.build_tuple(count)          # Stack: objectref, tuple  1488         program.rot_two()                   # Stack: tuple, objectref  1489         self._invoke(target_name, program)  1490   1491     def ior(self, arguments, program):  1492         # NOTE: No type checking performed.  1493         program.binary_or()  1494   1495     irem = frem  1496     ireturn = freturn  1497   1498     def ishl(self, arguments, program):  1499         # NOTE: No type checking performed.  1500         # NOTE: Not verified.  1501         program.binary_lshift()  1502   1503     def ishr(self, arguments, program):  1504         # NOTE: No type checking performed.  1505         # NOTE: Not verified.  1506         program.binary_rshift()  1507   1508     istore = fstore  1509     istore_0 = fstore_0  1510     istore_1 = fstore_1  1511     istore_2 = fstore_2  1512     istore_3 = fstore_3  1513     isub = fsub  1514     iushr = ishr # Ignoring distinctions between arithmetic and logical shifts  1515   1516     def ixor(self, arguments, program):  1517         # NOTE: No type checking performed.  1518         program.binary_xor()  1519   1520     def jsr(self, arguments, program):  1521         offset = signed2((arguments[0] << 8) + arguments[1])  1522         java_absolute = self.java_position + offset  1523         # Store the address of the next instruction.  1524         program.load_const_ret(self.position_mapping[self.java_position + 3])  1525         program.jump_absolute(self.position_mapping[java_absolute])  1526   1527     def jsr_w(self, arguments, program):  1528         offset = signed4((arguments[0] << 24) + (arguments[1] << 16) + (arguments[2] << 8) + arguments[3])  1529         java_absolute = self.java_position + offset  1530         # Store the address of the next instruction.  1531         program.load_const_ret(self.position_mapping[self.java_position + 5])  1532         program.jump_absolute(self.position_mapping[java_absolute])  1533   1534     l2d = i2d  1535     l2f = i2f  1536   1537     def l2i(self, arguments, program):  1538         pass # Preserving Java semantics  1539   1540     ladd = iadd  1541     laload = iaload  1542     land = iand  1543     lastore = iastore  1544   1545     def lcmp(self, arguments, program):  1546         # NOTE: No type checking performed.  1547         program.dup_topx(2)                 # Stack: value1, value2, value1, value2  1548         program.compare_op(">")             # Stack: value1, value2, result  1549         program.jump_to_label(0, "equals")  1550         # True - produce result and branch.  1551         program.pop_top()                   # Stack: value1, value2  1552         program.pop_top()                   # Stack: value1  1553         program.pop_top()                   # Stack:  1554         program.load_const(1)               # Stack: 1  1555         program.jump_to_label(None, "next")  1556         # False - test equality.  1557         program.start_label("equals")  1558         program.pop_top()                   # Stack: value1, value2  1559         program.dup_topx(2)                 # Stack: value1, value2, value1, value2  1560         program.compare_op("==")            # Stack: value1, value2, result  1561         program.jump_to_label(0, "less")  1562         # True - produce result and branch.  1563         program.pop_top()                   # Stack: value1, value2  1564         program.pop_top()                   # Stack: value1  1565         program.pop_top()                   # Stack:  1566         program.load_const(0)               # Stack: 0  1567         program.jump_to_label(None, "next")  1568         # False - produce result.  1569         program.start_label("less")  1570         program.pop_top()                   # Stack: value1, value2  1571         program.pop_top()                   # Stack: value1  1572         program.pop_top()                   # Stack:  1573         program.load_const(-1)              # Stack: -1  1574         program.start_label("next")  1575   1576     lconst_0 = iconst_0  1577     lconst_1 = iconst_1  1578   1579     def ldc(self, arguments, program):  1580         const = self.class_file.constants[arguments[0] - 1]  1581         if isinstance(const, classfile.StringInfo):  1582             program.use_external_name("java.lang.String")  1583             program.load_global("java")  1584             program.load_attr("lang")  1585             program.load_attr("String")  1586             program.load_const(const.get_value())  1587             program.call_function(1)  1588         else:  1589             program.load_const(const)  1590   1591     def ldc_w(self, arguments, program):  1592         const = self.class_file.constants[(arguments[0] << 8) + arguments[1] - 1]  1593         if isinstance(const, classfile.StringInfo):  1594             program.use_external_name("java.lang.String")  1595             program.load_global("java")  1596             program.load_attr("lang")  1597             program.load_attr("String")  1598             program.load_const(const.get_value())  1599             program.call_function(1)  1600         else:  1601             program.load_const(const)  1602   1603     ldc2_w = ldc_w  1604     ldiv = idiv  1605     lload = iload  1606     lload_0 = iload_0  1607     lload_1 = iload_1  1608     lload_2 = iload_2  1609     lload_3 = iload_3  1610     lmul = imul  1611     lneg = ineg  1612   1613     def lookupswitch(self, code, program):  1614   1615         # Find the offset to the next 4 byte boundary in the code.  1616   1617         d, r = divmod(self.java_position + 1, 4)  1618         to_boundary = (4 - r) % 4  1619   1620         # Get the pertinent arguments.  1621   1622         code = code[to_boundary:]  1623         default = classfile.u4(code[0:4])  1624         npairs = classfile.u4(code[4:8])  1625   1626         # Process the pairs.  1627         # NOTE: This is not the most optimal implementation.  1628   1629         pair_index = 8  1630         for pair in range(0, npairs):  1631             match = classfile.u4(code[pair_index:pair_index+4])  1632             offset = classfile.s4(code[pair_index+4:pair_index+8])  1633             # Calculate the branch target.  1634             java_absolute = self.java_position + offset  1635             # Generate branching code.  1636             program.dup_top()                                           # Stack: key, key  1637             program.load_const(match)                                   # Stack: key, key, match  1638             program.compare_op("==")                                    # Stack: key, result  1639             program.jump_to_label(0, "end")  1640             program.pop_top()                                           # Stack: key  1641             program.pop_top()                                           # Stack:  1642             program.jump_absolute(self.position_mapping[java_absolute])  1643             # Generate the label for the end of the branching code.  1644             program.start_label("end")  1645             program.pop_top()                                           # Stack: key  1646             # Update the index.  1647             pair_index += 4  1648   1649         # Generate the default.  1650   1651         java_absolute = self.java_position + default  1652         program.jump_absolute(self.position_mapping[java_absolute])  1653         return pair_index + to_boundary  1654   1655     lor = ior  1656     lrem = irem  1657     lreturn = ireturn  1658     lshl = ishl  1659     lshr = ishr  1660     lstore = istore  1661     lstore_0 = istore_0  1662     lstore_1 = istore_1  1663     lstore_2 = istore_2  1664     lstore_3 = istore_3  1665     lsub = isub  1666     lushr = iushr  1667     lxor = ixor  1668   1669     def monitorenter(self, arguments, program):  1670         # NOTE: To be implemented.  1671         pass  1672   1673     def monitorexit(self, arguments, program):  1674         # NOTE: To be implemented.  1675         pass  1676   1677     def multianewarray(self, arguments, program):  1678         index = (arguments[0] << 8) + arguments[1]  1679         dimensions = arguments[2]  1680         # Stack: count1, ..., countN-1, countN  1681         self._newarray(program)             # Stack: count1, ..., countN-1, list  1682         for dimension in range(1, dimensions):  1683             program.rot_two()               # Stack: count1, ..., list, countN-1  1684             program.build_list(0)           # Stack: count1, ..., list, countN-1, new-list  1685             program.rot_three()             # Stack: count1, ..., new-list, list, countN-1  1686             program.setup_loop()  1687             program.load_const(0)           # Stack: count1, ..., new-list, list, countN-1, 0  1688             program.rot_two()               # Stack: count1, ..., new-list, list, 0, countN-1  1689             program.load_global("range")    # Stack: count1, ..., new-list, list, 0, countN-1, range  1690             program.rot_three()             # Stack: count1, ..., new-list, list, range, 0, countN-1  1691             program.call_function(2)        # Stack: count1, ..., new-list, list, range-list  1692             program.get_iter()              # Stack: count1, ..., new-list, list, iter  1693             program.for_iter()              # Stack: count1, ..., new-list, list, iter, value  1694             program.pop_top()               # Stack: count1, ..., new-list, list, iter  1695             program.rot_three()             # Stack: count1, ..., iter, new-list, list  1696             program.slice_0()               # Stack: count1, ..., iter, new-list, list[:]  1697             program.dup_top()               # Stack: count1, ..., iter, new-list, list[:], list[:]  1698             program.rot_three()             # Stack: count1, ..., iter, list[:], new-list, list[:]  1699             program.rot_two()               # Stack: count1, ..., iter, list[:], list[:], new-list  1700             program.dup_top()               # Stack: count1, ..., iter, list[:], list[:], new-list, new-list  1701             program.load_attr("append")     # Stack: count1, ..., iter, list[:], list[:], new-list, append  1702             program.rot_three()             # Stack: count1, ..., iter, list[:], append, list[:], new-list  1703             program.rot_three()             # Stack: count1, ..., iter, list[:], new-list, append, list[:]  1704             program.call_function(1)        # Stack: count1, ..., iter, list[:], new-list, None  1705             program.pop_top()               # Stack: count1, ..., iter, list[:], new-list  1706             program.rot_two()               # Stack: count1, ..., iter, new-list, list[:]  1707             program.rot_three()             # Stack: count1, ..., list[:], iter, new-list  1708             program.rot_three()             # Stack: count1, ..., new-list, list[:], iter  1709             program.end_loop()              # Stack: count1, ..., new-list, list[:], iter  1710             program.pop_top()               # Stack: count1, ..., new-list  1711   1712     def new(self, arguments, program):  1713         # This operation is considered to be the same as the calling of the  1714         # initialisation method of the given class with no arguments.  1715   1716         index = (arguments[0] << 8) + arguments[1]  1717         target_name = self.class_file.constants[index - 1].get_python_name()  1718         program.use_external_name(target_name)  1719   1720         # NOTE: Using the string version of the name which may contain incompatible characters.  1721         program.load_global("object")  1722         program.load_attr("__new__")  1723         self._load_class_name(target_name, program)  1724         program.call_function(1)  1725   1726     def newarray(self, arguments, program):  1727         # NOTE: Does not raise NegativeArraySizeException.  1728         # NOTE: Not using the arguments to type the list/array.  1729         self._newarray(program)  1730   1731     def nop(self, arguments, program):  1732         pass  1733   1734     def pop(self, arguments, program):  1735         program.pop_top()  1736   1737     pop2 = pop # ignoring Java stack value distinctions  1738   1739     def putfield(self, arguments, program):  1740         index = (arguments[0] << 8) + arguments[1]  1741         target_name = self.class_file.constants[index - 1].get_python_name()  1742         program.rot_two()  1743         # NOTE: Using the string version of the name which may contain incompatible characters.  1744         program.store_attr(str(target_name))  1745   1746     def putstatic(self, arguments, program):  1747         index = (arguments[0] << 8) + arguments[1]  1748         target = self.class_file.constants[index - 1]  1749         target_name = target.get_python_name()  1750   1751         # Get the class name instead of the fully qualified name.  1752   1753         full_class_name = target.get_class().get_python_name()  1754         self._load_class_name(full_class_name, program)  1755         # NOTE: Using the string version of the name which may contain incompatible characters.  1756         program.store_attr(str(target_name))  1757   1758     def ret(self, arguments, program):  1759         program.ret(arguments[0])  1760         # Indicate that the finally handler is probably over.  1761         # NOTE: This is seemingly not guaranteed.  1762         self.in_finally = 0  1763   1764     def return_(self, arguments, program):  1765         program.load_const(None)  1766         program.return_value()  1767   1768     saload = laload  1769     sastore = lastore  1770   1771     def sipush(self, arguments, program):  1772         program.load_const((arguments[0] << 8) + arguments[1])  1773   1774     def swap(self, arguments, program):  1775         program.rot_two()  1776   1777     def tableswitch(self, code, program):  1778   1779         # Find the offset to the next 4 byte boundary in the code.  1780   1781         d, r = divmod(self.java_position + 1, 4)  1782         to_boundary = (4 - r) % 4  1783   1784         # Get the pertinent arguments.  1785   1786         code = code[to_boundary:]  1787         default = classfile.u4(code[0:4])  1788         low = classfile.u4(code[4:8])  1789         high = classfile.u4(code[8:12])  1790   1791         # Process the jump entries.  1792         # NOTE: This is not the most optimal implementation.  1793   1794         jump_index = 12  1795         for jump in range(low, high + 1):  1796             offset = classfile.s4(code[jump_index:jump_index + 4])  1797   1798             # Calculate the branch target.  1799   1800             java_absolute = self.java_position + offset  1801   1802             # Generate branching code.  1803   1804             program.dup_top()                                           # Stack: key, key  1805             program.load_const(jump)                                    # Stack: key, key, jump  1806             program.compare_op("==")                                    # Stack: key, result  1807             program.jump_to_label(0, "end")  1808             program.pop_top()                                           # Stack: key  1809             program.pop_top()                                           # Stack:  1810             program.jump_absolute(self.position_mapping[java_absolute])  1811   1812             # Generate the label for the end of the branching code.  1813   1814             program.start_label("end")  1815             program.pop_top()                                           # Stack: key  1816   1817             # Update the index.  1818   1819             jump_index += 4  1820   1821         # Generate the default.  1822   1823         java_absolute = self.java_position + default  1824         program.jump_absolute(self.position_mapping[java_absolute])  1825         return jump_index + to_boundary  1826   1827     def wide(self, code, program):  1828         # NOTE: To be implemented.  1829         return number_of_arguments  1830   1831 def disassemble(class_file, method):  1832     disassembler = BytecodeDisassembler(class_file)  1833     disassembler.process(method, BytecodeDisassemblerProgram())  1834   1835 class ClassTranslator:  1836   1837     """  1838     A class which provides a wrapper around a class file and the means to  1839     translate the represented class into a Python class.  1840     """  1841   1842     def __init__(self, class_file):  1843   1844         "Initialise the object with the given 'class_file'."  1845   1846         self.class_file = class_file  1847         self.filename = str(self.class_file.attributes[0].get_name())  1848   1849     def translate_method(self, method):  1850   1851         "Translate the given 'method' - an object obtained from the class file."  1852   1853         translator = BytecodeTranslator(self.class_file)  1854         writer = BytecodeWriter()  1855         translator.process(method, writer)  1856         return translator, writer  1857   1858     def make_method(self, real_method_name, methods, global_names, namespace):  1859   1860         """  1861         Make a dispatcher method with the given 'real_method_name', providing  1862         dispatch to the supplied type-sensitive 'methods', accessing the given  1863         'global_names' where necessary, and storing the new method in the  1864         'namespace' provided.  1865         """  1866   1867         if real_method_name == "<init>":  1868             method_name = "__init__"  1869         else:  1870             method_name = real_method_name  1871   1872         # Where only one method exists, just make an alias.  1873   1874         if len(methods) == 1:  1875             method, fn = methods[0]  1876             namespace[method_name] = fn  1877             return  1878   1879         # Write a simple bytecode dispatching mechanism.  1880   1881         program = BytecodeWriter()  1882   1883         # Remember whether any of the methods are static.  1884         # NOTE: This should be an all or nothing situation.  1885   1886         method_is_static = 0  1887   1888         # NOTE: The code below should use dictionary-based dispatch for better performance.  1889   1890         for method, fn in methods:  1891             method_is_static = real_method_name != "<init>" and method_is_static or classfile.has_flags(method.access_flags, [classfile.STATIC])  1892   1893             if method_is_static:  1894                 program.load_fast(0)                # Stack: arguments  1895             else:  1896                 program.load_fast(1)                # Stack: arguments  1897   1898             program.setup_loop()  1899             program.load_const(1)                   # Stack: arguments, 1  1900   1901             if method_is_static:  1902                 program.store_fast(1)               # Stack: arguments (found = 1)  1903             else:  1904                 program.store_fast(2)               # Stack: arguments (found = 1)  1905   1906             # Emit a list of parameter types.  1907   1908             descriptor_types = method.get_descriptor()[0]  1909             for descriptor_type in descriptor_types:  1910                 base_type, object_type, array_type = descriptor_type  1911                 python_type = classfile.descriptor_base_type_mapping[base_type]  1912                 if python_type == "instance":  1913                     # NOTE: This will need extending.  1914                     python_type = object_type  1915                 program.load_global(python_type)    # Stack: arguments, type, ...  1916             program.build_list(len(descriptor_types))  1917                                                     # Stack: arguments, types  1918             # Make a map of arguments and types.  1919             program.load_const(None)                # Stack: arguments, types, None  1920             program.rot_three()                     # Stack: None, arguments, types  1921             program.build_tuple(3)                  # Stack: tuple  1922             program.load_global("map")              # Stack: tuple, map  1923             program.rot_two()                       # Stack: map, tuple  1924             program.call_function_var(0)            # Stack: list (mapping arguments to types)  1925             # Loop over each pair.  1926             program.get_iter()                      # Stack: iter  1927             program.for_iter()                      # Stack: iter, (argument, type)  1928             program.unpack_sequence(2)              # Stack: iter, type, argument  1929             program.dup_top()                       # Stack: iter, type, argument, argument  1930             program.load_const(None)                # Stack: iter, type, argument, argument, None  1931             program.compare_op("is")                # Stack: iter, type, argument, result  1932             # Missing argument?  1933             program.jump_to_label(0, "present")  1934             program.pop_top()                       # Stack: iter, type, argument  1935             program.pop_top()                       # Stack: iter, type  1936             program.pop_top()                       # Stack: iter  1937             program.load_const(0)                   # Stack: iter, 0  1938   1939             if method_is_static:  1940                 program.store_fast(1)               # Stack: iter (found = 0)  1941             else:  1942                 program.store_fast(2)               # Stack: iter (found = 0)  1943   1944             program.break_loop()  1945             # Argument was present.  1946             program.start_label("present")  1947             program.pop_top()                       # Stack: iter, type, argument  1948             program.rot_two()                       # Stack: iter, argument, type  1949             program.dup_top()                       # Stack: iter, argument, type, type  1950             program.load_const(None)                # Stack: iter, argument, type, type, None  1951             program.compare_op("is")                # Stack: iter, argument, type, result  1952             # Missing parameter type?  1953             program.jump_to_label(0, "present")  1954             program.pop_top()                       # Stack: iter, argument, type  1955             program.pop_top()                       # Stack: iter, argument  1956             program.pop_top()                       # Stack: iter  1957             program.load_const(0)                   # Stack: iter, 0  1958   1959             if method_is_static:  1960                 program.store_fast(1)               # Stack: iter (found = 0)  1961             else:  1962                 program.store_fast(2)               # Stack: iter (found = 0)  1963   1964             program.break_loop()  1965             # Parameter was present.  1966             program.start_label("present")  1967             program.pop_top()                       # Stack: iter, argument, type  1968             program.build_tuple(2)                  # Stack: iter, (argument, type)  1969             program.load_global("isinstance")       # Stack: iter, (argument, type), isinstance  1970             program.rot_two()                       # Stack: iter, isinstance, (argument, type)  1971             program.call_function_var(0)            # Stack: iter, result  1972             program.jump_to_label(1, "match")  1973             program.pop_top()                       # Stack: iter  1974             program.load_const(0)                   # Stack: iter, 0  1975   1976             if method_is_static:  1977                 program.store_fast(1)               # Stack: iter (found = 0)  1978             else:  1979                 program.store_fast(2)               # Stack: iter (found = 0)  1980   1981             program.break_loop()  1982             # Argument type and parameter type matched.  1983             program.start_label("match")  1984             program.pop_top()                       # Stack: iter  1985             program.end_loop()                      # Stack:  1986             # If all the parameters matched, call the method.  1987   1988             if method_is_static:  1989                 program.load_fast(1)                # Stack: match  1990             else:  1991                 program.load_fast(2)                # Stack: match  1992   1993             program.jump_to_label(0, "failed")  1994             # All the parameters matched.  1995             program.pop_top()                       # Stack:  1996   1997             if method_is_static:  1998                 program.load_fast(0)                # Stack: arguments  1999                 program.load_global(str(self.class_file.this_class.get_python_name()))  2000                                                     # Stack: arguments, class  2001             else:  2002                 program.load_fast(1)                # Stack: arguments  2003                 program.load_fast(0)                # Stack: arguments, self  2004   2005             program.load_attr(str(method.get_python_name()))  2006                                                     # Stack: arguments, method  2007             program.rot_two()                       # Stack: method, arguments  2008             program.call_function_var(0)            # Stack: result  2009             program.return_value()  2010             # Try the next method if arguments or parameters were missing or incorrect.  2011             program.start_label("failed")  2012             program.pop_top()                       # Stack:  2013   2014         # Raise an exception if nothing matched.  2015         # NOTE: Improve this.  2016   2017         program.load_const("No matching method")  2018         program.raise_varargs(1)  2019         program.load_const(None)  2020         program.return_value()  2021   2022         # Add the code as a method in the namespace.  2023         # NOTE: One actual parameter, flags as 71 apparently means that a list  2024         # NOTE: parameter is used in a method.  2025   2026         if method_is_static:  2027             nargs = 0  2028         else:  2029             nargs = 1  2030         nlocals = program.max_locals + 1  2031   2032         code = new.code(nargs, nlocals, program.max_stack_depth, 71, program.get_output(),  2033             tuple(program.get_constants()), tuple(program.get_names()), tuple(self.make_varnames(nlocals, method_is_static)),  2034             self.filename, method_name, 0, "")  2035         fn = new.function(code, global_names)  2036   2037         if method_is_static:  2038             fn = staticmethod(fn)  2039   2040         namespace[method_name] = fn  2041   2042     def process(self, global_names):  2043   2044         """  2045         Process the class, storing it in the 'global_names' dictionary provided.  2046         Return a tuple containing the class and a list of external names  2047         referenced by the class's methods.  2048         """  2049   2050         namespace = {}  2051   2052         # Make the fields.  2053   2054         for field in self.class_file.fields:  2055             if classfile.has_flags(field.access_flags, [classfile.STATIC]):  2056                 field_name = str(field.get_python_name())  2057                 namespace[field_name] = None  2058   2059         # Make the methods.  2060   2061         real_methods = {}  2062         external_names = []  2063   2064         for method in self.class_file.methods:  2065             real_method_name = str(method.get_name())  2066             method_name = str(method.get_python_name())  2067   2068             translator, writer = self.translate_method(method)  2069   2070             # Add external names to the master list.  2071   2072             for external_name in writer.external_names:  2073                 if external_name not in external_names:  2074                     external_names.append(external_name)  2075   2076             # Fix up special class initialisation methods and static methods.  2077   2078             method_is_static = real_method_name != "<init>" and classfile.has_flags(method.access_flags, [classfile.STATIC])  2079             if method_is_static:  2080                 nargs = len(method.get_descriptor()[0])  2081             else:  2082                 nargs = len(method.get_descriptor()[0]) + 1  2083             nlocals = writer.max_locals + 1  2084             flags = 67  2085   2086             # NOTE: Add line number table later.  2087   2088             code = new.code(nargs, nlocals, writer.max_stack_depth, flags, writer.get_output(),  2089                 tuple(writer.get_constants()), tuple(writer.get_names()),  2090                 tuple(self.make_varnames(nlocals, method_is_static)), self.filename, method_name, 0, "")  2091   2092             # NOTE: May need more globals.  2093   2094             fn = new.function(code, global_names)  2095   2096             # Fix up special class initialisation methods and static methods.  2097   2098             if method_is_static:  2099                 fn = staticmethod(fn)  2100   2101             # Remember the real method name and the corresponding methods produced.  2102   2103             if not real_methods.has_key(real_method_name):  2104                 real_methods[real_method_name] = []  2105             real_methods[real_method_name].append((method, fn))  2106   2107             # Add the method to the class's namespace.  2108   2109             namespace[method_name] = fn  2110   2111         # Define superclasses.  2112   2113         bases = self.get_base_classes(global_names)  2114   2115         # Define method dispatchers.  2116   2117         for real_method_name, methods in real_methods.items():  2118             if real_method_name != "<clinit>":  2119                 self.make_method(real_method_name, methods, global_names, namespace)  2120   2121         # Use only the last part of the fully qualified name.  2122   2123         full_class_name = str(self.class_file.this_class.get_python_name())  2124         class_name = full_class_name.split(".")[-1]  2125         cls = new.classobj(class_name, bases, namespace)  2126         global_names[cls.__name__] = cls  2127   2128         return cls, external_names  2129   2130     def get_base_classes(self, global_names):  2131   2132         """  2133         Identify the superclass, then either load it from the given  2134         'global_names' if available, or import the class from its parent module.  2135         Return a tuple containing all base classes (typically a single element  2136         tuple).  2137         """  2138   2139         original_name = str(self.class_file.super_class.get_name())  2140         if original_name in ("java/lang/Object", "java/lang/Exception"):  2141             return (object,)  2142         else:  2143             full_this_class_name = str(self.class_file.this_class.get_python_name())  2144             this_class_name_parts = full_this_class_name.split(".")  2145             this_class_module_name = ".".join(this_class_name_parts[:-1])  2146             full_super_class_name = str(self.class_file.super_class.get_python_name())  2147             super_class_name_parts = full_super_class_name.split(".")  2148             super_class_name = super_class_name_parts[-1]  2149             super_class_module_name = ".".join(super_class_name_parts[:-1])  2150             if super_class_module_name == "":  2151                 obj = global_names[super_class_name]  2152             elif super_class_module_name == this_class_module_name:  2153                 obj = global_names[super_class_name]  2154             else:  2155                 print "Importing", super_class_module_name, super_class_name  2156                 obj = __import__(super_class_module_name, global_names, {}, [])  2157                 for super_class_name_part in super_class_name_parts[1:] or [super_class_name]:  2158                     print "*", obj, super_class_name_part  2159                     obj = getattr(obj, super_class_name_part)  2160             return (obj,)  2161   2162     def make_varnames(self, nlocals, method_is_static=0):  2163   2164         """  2165         A utility method which invents variable names for the given number -  2166         'nlocals' - of local variables in a method. Returns a list of such  2167         variable names.  2168   2169         If the optional 'method_is_static' is set to true, do not use "self" as  2170         the first argument name.  2171         """  2172   2173         if method_is_static:  2174             l = ["cls"]  2175         else:  2176             l = ["self"]  2177         for i in range(1, nlocals):  2178             l.append("_l%s" % i)  2179         return l[:nlocals]  2180   2181 def _map(*args):  2182     print args  2183     return apply(__builtins__.map, args)  2184   2185 def _isinstance(*args):  2186     print args  2187     return apply(__builtins__.isinstance, args)  2188   2189 if __name__ == "__main__":  2190     import sys  2191     import dis  2192     global_names = globals()  2193     #global_names["isinstance"] = _isinstance  2194     #global_names["map"] = _map  2195     for filename in sys.argv[1:]:  2196         f = open(filename, "rb")  2197         c = classfile.ClassFile(f.read())  2198         translator = ClassTranslator(c)  2199         cls, external_names = translator.process(global_names)  2200   2201 # vim: tabstop=4 expandtab shiftwidth=4