def __write_cmp(jump_type):
    """Pop 2 items off the stack, compare them, push the result back on"""
    # pop an item off the stack
    # D = M
    # pop another item off the stack
    # D = D - M
    # @TRUE_0
    # D; JEQ
    # (FALSE_0)
    #   D = 0
    #   @END_0
    #   0; jump_type
    # (TRUE_0)
    #   D = 1
    # (END_0)
    #   push()
    if jump_type not in ['EQ', 'GT', 'LT', 'GE', 'LE', 'NE']:
        raise Exception("Unexpected Jump Type: {0}".format(jump_type))
    true_label = unique("TRUE")
    false_label = unique("FALSE")
    end_label = unique("END")
    return (pop() +
            ['D=M'] +
            pop() +
            ['D=M-D',
             at(true_label),
             'D;J{0}'.format(jump_type),
             '({0})'.format(false_label),
             'D=0',
             at(end_label),
             '0;JMP',
             '({0})'.format(true_label),
             'D=-1',  # -1 == 11111...11 in 2's complement
             '({0})'.format(end_label)] +
            push())
Beispiel #2
0
def write_push(segment, i, ftitle=None):
    """Push value i from a segment onto the stack"""
    # local, argument, this, and that are implemented the same way
    standard_segs = {
        "local": "LCL",
        "argument": "ARG",
        "this": "THIS",
        "that": "THAT",
    }
    if segment in standard_segs:
        segname = standard_segs[segment]
        return ([
            at(segname),  # addr=segname+i
            "D=M",
            at(i),
            "D=D+A",
            "A=D",
            "D=M"
        ] + push())
    elif segment == "temp":
        return ([
            at(5),  # temp base address is 5
            "D=A",
            at(i),
            "D=D+A",
            "A=D",
            "D=M"
        ] + push())
    elif segment == "static":
        label = "{0}.{1}".format(ftitle, i)
        return [at(label), "D=M"] + push()
    elif segment == "pointer":
        if int(i) not in [0, 1]:
            raise Exception('Invalid i for push pointer: ' + str(i))
        target = "THAT" if int(i) else "THIS"
        return [
            at(target),  # *SP = THIS/THAT
            "D=M",
            "@SP",
            "A=M",
            "M=D",
            "@SP",  # SP++
            "M=M+1"
        ]
    elif segment == "constant":
        return [at(i), "D=A"] + push()
    raise Exception("{0} segment type not implemented yet".format(segment))
def write_call(func_name, num_args, curr_func, num_calls):
    return_label = "{0}$ret.{1}".format(curr_func, num_calls)
    # push returnLabel
    output = [at(return_label), "D=A"] + push()
    # push LCL
    output += [at("LCL"), "D=M"] + push()
    # push ARG
    output += [at("ARG"), "D=M"] + push()
    # push THIS
    output += [at("THIS"), "D=M"] + push()
    # push THAT
    output += [at("THAT"), "D=M"] + push()
    # ARG=SP-5-nArgs
    output += [at("SP"), "D=M-1"]
    for i in range(3 + int(num_args)):
        output.append("D=D-1")
    output += [at("ARG"), "M=D-1"]
    # LCL=SP
    output += [at("SP"), "D=M", at("LCL"), "M=D"]
    # goto functionName
    output += [at(func_name), "0;JMP"]
    # (returnLabel)
    output.append("({0})".format(return_label))
    return output
def __write_bitwise(op):
    """Pop 2 items off the stack, do a bitwise operation, push result back on
       this is only used for operations which do not need a jump"""
    if op not in ['|', '&', '+', '-']:
        raise Exception("Unexpected Bitwise Operation: {0}".format(op))
    return pop() + ['D=M'] + pop() + ['D=M{0}D'.format(op)] + push()
def write_not():
    """Pop 1 item off the stack, negate it, push the result back on"""
    return pop() + ['D=!M'] + push()
def __write_save_retAddr():
    """Saves the return address in a local variable. """
    return (["// retAddr = *(endFrame - 5)",
             at("endFrame"), "D=M"] + push() + [at(5), "D=A", "// push"] +
            push() + ["// write_sub"] + write_sub() + ["// pop"] + pop() +
            ["A=M", "D=M", at("retAddr"), "M=D"])
def write_function(func_name, num_vars):
    output = ["({0})".format(func_name)]
    for i in range(int(num_vars)):
        output += ["D=0"] + push()
    return output