def to_s(self): """ this method is used to print the output of the executable in a readable/ tokenized format. sample usage: >>> from boa.compiler import Compiler >>> module = Compiler.load('./boa/tests/src/LambdaTest.py').default >>> module.write() >>> module.to_s() 12 3 LOAD_CONST 9 [data] 4 STORE_FAST j [data] 22 11 LOAD_FAST j [data] 17 CALL_FUNCTION Main.<locals>.q_1 \ [<boa.code.pytoken.PyToken object at 0x10cb53c50>] [data] 22 20 STORE_FAST m [data] 24 27 243 b'\x03\x00' [data] 3 30 LOAD_FAST m [data] 35 NOP [data] 36 241 [data] 37 242 [data] 38 RETURN_VALUE [data] 20 49 243 b'\x03\x00' [data] 3 52 LOAD_FAST x [data] 57 LOAD_CONST 1 [data] 58 BINARY_ADD [data] 59 NOP [data] 60 241 [data] 61 242 [data] 62 RETURN_VALUE [data] """ # Initialize if needed if self.all_vm_tokens is None: self.link_methods() lineno = 0 pstart = True for i, (key, value) in enumerate(self.all_vm_tokens.items()): if value.pytoken: pt = value.pytoken do_print_line_no = False to_label = None from_label = ' ' if pt.line_no != lineno: print("\n") lineno = pt.line_no do_print_line_no = True if pt.args and type(pt.args) is Label: addr = value.addr if value.data is not None: plus_addr = int.from_bytes(value.data, 'little', signed=True) target_addr = addr + plus_addr to_label = 'to %s [ %s ]' % (target_addr, pt.args) else: to_label = 'from << %s ' % pt.args # to_label = 'to %s ' % pt.args elif pt.jump_label: from_label = ' >> ' to_label = 'from [%s]' % pt.jump_label ds = '' if value.data is not None: try: ds = int.from_bytes(value.data, 'little', signed=True) except Exception as e: pass if type(ds) is not int and len(ds) < 1: try: ds = value.data.decode('utf-8') except Exception as e: pass if pt.py_op == pyop.CALL_FUNCTION: if to_label is None: old = "" else: old = to_label param_string = "(" for param in pt.func_params: param_string += str(param.args) + ", " param_string = param_string.rstrip(", ") + ")" to_label = '%s %s %s' % (pt.func_name, param_string, old) lno = "{:<10}".format( pt.line_no if do_print_line_no or pstart else '') addr = "{:<5}".format(key) op = "{:<20}".format(str(pt.py_op)) # If this is a number, it is likely a custom python opcode, get the name if str(pt.py_op).isnumeric(): opname = pyop.to_name(int(str(pt.py_op))) if opname is not None: op = "{:<20}".format(opname) arg = "{:<50}".format( to_label if to_label is not None else pt.arg_s) data = "[data] {:<20}".format(ds) print("%s%s%s%s%s%s" % (lno, from_label, addr, op, arg, data)) pstart = False
def to_s_bak(self): """ this method is used to print the output of the executable in a readable/ tokenized format. sample usage: >>> from boa.compiler import Compiler >>> module = Compiler.load('./boa/tests/src/LambdaTest.py').default >>> module.write() >>> module.to_s() 12 3 LOAD_CONST 9 [data] 4 STORE_FAST j [data] 22 11 LOAD_FAST j [data] 17 CALL_FUNCTION Main.<locals>.q_1 \ [<boa.code.pytoken.PyToken object at 0x10cb53c50>] [data] 22 20 STORE_FAST m [data] 24 27 243 b'\x03\x00' [data] 3 30 LOAD_FAST m [data] 35 NOP [data] 36 241 [data] 37 242 [data] 38 RETURN_VALUE [data] 20 49 243 b'\x03\x00' [data] 3 52 LOAD_FAST x [data] 57 LOAD_CONST 1 [data] 58 BINARY_ADD [data] 59 NOP [data] 60 241 [data] 61 242 [data] 62 RETURN_VALUE [data] """ # Initialize if needed if self.all_vm_tokens is None: self.link_methods() lineno = 0 pstart = True global_lineno = None for i, (key, value) in enumerate(self.all_vm_tokens.items()): if value.pytoken: pt = value.pytoken do_print_line_no = False to_label = None from_label = ' ' if pt.method_lineno + pt.lineno != global_lineno: print("\n") lineno = pt.lineno global_lineno = pt.lineno + pt.method_lineno do_print_line_no = True ds = '' if value.data is not None: try: ds = int.from_bytes(value.data, 'little', signed=True) except Exception as e: pass if type(ds) is not int and len(ds) < 1: try: ds = value.data.decode('utf-8') except Exception as e: pass lno = "{:<10}".format( pt.method_lineno + pt.lineno if do_print_line_no or pstart else '') addr = "{:<5}".format(key) op = "{:<20}".format(pt.instruction.name) # If this is a number, it is likely a custom python opcode, get the name if str(pt.pyop).isnumeric(): opname = pyop.to_name(int(str(pt.pyop))).replace( 'HAVE_ARGUMENT', 'STORE_NAME').replace('YIELD_VALUE', 'REVERSE') if opname is not None: op = "{:<20}".format(opname) arg = "{:<50}".format(pt.arg_str) data = "[data] {:<20}".format(ds) print("%s%s%s%s%s%s" % (lno, from_label, addr, op, arg, data)) pstart = False