javaclass

bytecode.py

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