def binary_comp(comp): return concat( decr_sp(), load_stack_top_into_d(), decr_sp(), ['@SP', 'A=M', 'D=M-D'], if_else( comparator=comp, true_block=['@SP', 'A=M', 'M=-1'], # recall: in HW -1 represents true, 0 false false_block=['@SP', 'A=M', 'M=0']), incr_sp())
def func_call(func_label, nargs): return_address = get_func_end_label(func_label) return concat( # push dummy value onto stack to allocate space for return value when nargs = 0 load_constant_into_d(0), push_d_onto_stack(), incr_sp(), push_stack_frame(return_address), set_segment_to_sp('ARG'), concat(load_constant_into_d(5), ['@ARG', 'M=M-D']), concat(load_constant_into_d(int(nargs) + 1), ['@ARG', 'M=M-D']), set_segment_to_sp('LCL'), goto(func_label), label(return_address), )
def unary_op(op): return concat(decr_sp(), ['@SP', 'A=M', f'M={op}M'], incr_sp())
def binary_op(op): return concat(decr_sp(), load_stack_top_into_d(), decr_sp(), ['@SP', 'A=M', f'M=M{op}D'], incr_sp())
def push_return_address(return_address): return concat(load_constant_into_d(return_address), push_d_onto_stack(), incr_sp())
def push_segment_pointer(segment): return concat([f'@{segment}', 'D=M'], push_d_onto_stack(), incr_sp())
def push_static(_, index): varname = get_static_varname(index) return concat([f'@{varname}', 'D=M'], push_d_onto_stack(), incr_sp())
def push_temp(_, index): addr = get_temp_addr(index) return concat([f'@{addr}', 'D=M'], push_d_onto_stack(), incr_sp())
def push_pointer(_, val): segment = get_pointer_segment(val) return concat([f'@{segment}', 'D=M'], push_d_onto_stack(), incr_sp())
def push_heap(segment, index): return concat(load_heap_val_into_d(segment, index), push_d_onto_stack(), incr_sp())
def push_constant(_, c): return concat(load_constant_into_d(c), push_d_onto_stack(), incr_sp())