def _build_call(state, addr, instruction): call = nodes.FunctionCall() call.function = _build_slot(state, addr, instruction.A) call.arguments.contents = _build_call_arguments(state, addr, instruction) line_marked = [call] if instruction.opcode <= ins.CALL.opcode: if instruction.B == 0: node = nodes.Assignment() node.destinations.contents.append(nodes.MULTRES()) node.expressions.contents.append(call) elif instruction.B == 1: node = call else: from_slot = instruction.A to_slot = instruction.A + instruction.B - 2 node = _build_range_assignment(state, addr, from_slot, to_slot) node.expressions.contents.append(call) else: assert instruction.opcode <= ins.CALLT.opcode node = nodes.Return() node.returns.contents.append(call) line_marked.append(node) return node, line_marked
def _build_class_assignment(addr, slot, class_name): assignment = nodes.Assignment() destination = _build_identifier_name( addr, slot, nodes.Identifier.T_LOCAL, class_name) assignment.destinations.contents.append(destination) return assignment
def _build_table_assignment(state, addr, instruction): assignment = nodes.Assignment() destination = _build_table_element(state, addr, instruction) expression = _build_slot(state, addr, instruction.A) assignment.destinations.contents.append(destination) assignment.expressions.contents.append(expression) return assignment
def _build_global_assignment(state, addr, instruction): assignment = nodes.Assignment() variable = _build_global_variable(state, addr, instruction.CD) expression = _build_slot(state, addr, instruction.A) assignment.destinations.contents.append(variable) assignment.expressions.contents.append(expression) return assignment
def _build_vararg(state, addr, instruction): base = instruction.A last_slot = base + instruction.B - 2 if last_slot < base: node = nodes.Assignment() node.destinations.contents.append(nodes.MULTRES()) node.expressions.contents.append(nodes.Vararg()) else: node = _build_range_assignment(state, addr, base, last_slot) node.expressions.contents.append(nodes.Vararg()) return node
def _build_table_mass_assignment(state, addr, instruction): assignment = nodes.Assignment() base = instruction.A destination = nodes.TableElement() destination.key = nodes.MULTRES() destination.table = _build_slot(state, addr, base - 1) assignment.destinations.contents = [destination] assignment.expressions.contents = [nodes.MULTRES()] return assignment
def _build_range_assignment(state, addr, from_slot, to_slot): assignment = nodes.Assignment() slot = from_slot assert from_slot <= to_slot while slot <= to_slot: destination = _build_slot(state, addr, slot) assignment.destinations.contents.append(destination) slot += 1 return assignment
def _unwarp_logical_expression(start, end, body): slot = _find_expression_slot(body) assert slot is not None true, false, body = _get_terminators(body) expression = _compile_expression([start] + body, end, true, false) dst = copy.deepcopy(slot) assignment = nodes.Assignment() assignment.destinations.contents.append(dst) assignment.expressions.contents.append(expression) start.contents.append(assignment)
def _unwarp_logical_expression(start, end, body): slot = _find_expression_slot(body) assert slot is not None true, false, body = _get_terminators(body) #print("\n\n>>>>> start: " + str(start) + "\n\n\tBODY: " + str(body[0])) #print("\n\nend: " + str(end) + " \n\ntrue: " + str(true) + "\n\nfalse: " + str(false)) #print("\n\ntrue: " + str(true) + "\nfalse: " + str(false) + "\nbody: " + str(body[0])) expression = _compile_expression([start] + body, end, true, false) dst = copy.deepcopy(slot) assignment = nodes.Assignment() assignment.destinations.contents.append(dst) assignment.expressions.contents.append(expression) start.contents.append(assignment)
def _build_call(state, addr, instruction): call = nodes.FunctionCall() call.function = _build_slot(state, addr, instruction.A) call.arguments.contents = _build_call_arguments(state, addr, instruction) call.name = _lookup_variable_name(state, addr, instruction.A) if gconfig.gVerbose: print("_build_call " + call.name) # CALLM Call: A, ..., A+B-2 = A(A+1, ..., A+C+MULTRES) # CALL Call: A, ..., A+B-2 = A(A+1, ..., A+C-1) if instruction.opcode <= ins.CALL.opcode: if instruction.B == 0: node = nodes.Assignment() node.destinations.contents.append(nodes.MULTRES()) node.expressions.contents.append(call) elif instruction.B == 1: node = call # elif call.name and call.name == "class" and instruction.B == 2: # class_name = _lookup_variable_name(state, addr, instruction.A+1) # print("class " + class_name) # assert class_name is not None # node = _build_class_assignment(addr, instruction.A, class_name) # node.expressions.contents.append(call) else: from_slot = instruction.A to_slot = instruction.A + instruction.B - 2 node = _build_range_assignment(state, addr, from_slot, to_slot) node.expressions.contents.append(call) # CALLMT Tailcall: return A(A+1, ..., A+D+MULTRES) # CALLT Tailcall: return A(A+1, ..., A+D-1) else: assert instruction.opcode <= ins.CALLT.opcode node = nodes.Return() node.returns.contents.append(call) return node
def _build_var_assignment(state, addr, instruction): opcode = instruction.opcode assignment = nodes.Assignment() if instruction.A_type == ins.T_DST: destination = _build_slot(state, addr, instruction.A) else: assert instruction.A_type == ins.T_UV destination = _build_upvalue(state, addr, instruction.A) assignment.destinations.contents.append(destination) # Unary assignment operators (A = op D) if opcode == ins.MOV.opcode \ or opcode == ins.NOT.opcode \ or opcode == ins.UNM.opcode \ or (ljd.config.version_config.use_version > 2.0 and opcode == ins.ISTYPE.opcode) \ or (ljd.config.version_config.use_version > 2.0 and opcode == ins.ISNUM.opcode) \ or opcode == ins.LEN.opcode: expression = _build_unary_expression(state, addr, instruction) # Binary assignment operators (A = B op C) elif opcode <= ins.POW.opcode: expression = _build_binary_expression(state, addr, instruction) # Concat assignment type (A = B .. B + 1 .. ... .. C - 1 .. C) elif opcode == ins.CAT.opcode: expression = _build_concat_expression(state, addr, instruction) # Constant assignment operators except KNIL, which is weird anyway elif opcode <= ins.KPRI.opcode: expression = _build_const_expression(state, addr, instruction) elif opcode == ins.UGET.opcode: expression = _build_upvalue(state, addr, instruction.CD) elif opcode == ins.USETV.opcode: expression = _build_slot(state, addr, instruction.CD) elif opcode <= ins.USETP.opcode: expression = _build_const_expression(state, addr, instruction) elif opcode == ins.FNEW.opcode: expression = _build_function(state, instruction.CD, destination.slot + destination.slot_index) elif opcode == ins.TNEW.opcode: expression = nodes.TableConstructor() elif opcode == ins.TDUP.opcode: expression = _build_table_copy(state, instruction.CD) elif opcode == ins.GGET.opcode: expression = _build_global_variable(state, addr, instruction.CD) else: if ljd.config.version_config.use_version > 2.0: assert opcode <= ins.TGETR.opcode expression = _build_table_element(state, addr, instruction) else: assert opcode <= ins.TGETB.opcode expression = _build_table_element(state, addr, instruction) assignment.expressions.contents.append(expression) return assignment