Esempio n. 1
0
def write_return():
    # endFrame = LCL
    # retAddr = *(endFrame-5)
    # *ARG = pop(), sets return value to arg[0]
    # SP = ARG+1
    # endFrame -=1, THAT = *(endFrame)
    # endFrame -=1, THIS = *(endFrame)
    # endFrame -=1, ARG = *(endFrame)
    # endFrame -=1, LCL = *(endFrame)
    # goto retAddr

    # ---- implementation ----
    # endFrame = LCL
    output = [at("LCL"), "D=M", at("endFrame"), "M=D"]
    # retAddr = *(endFrame-5)
    output += __write_save_retAddr()
    # *ARG = pop()
    output += (["// *ARG = pop()"] + pop() + ["D=M", "@ARG", "A=M", "M=D"])
    # SP = ARG+1
    output += ["// SP = ARG+1", "@ARG", "D=M+1", "@SP", "M=D"]
    # endFrame -=1, segm_var = *(endFrame)
    output += __write_restore("THAT")
    output += __write_restore("THIS")
    output += __write_restore("ARG")
    output += __write_restore("LCL")
    # goto retAddr
    output += ["// goto retAddr", "@retAddr", "A=M", "0;JMP"]
    return output
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())
Esempio n. 3
0
def write_pop(segment, i, ftitle=None):
    """Pop a value from the stack and store it at position i in segment"""
    # 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",
            at('addr'),
            "M=D"
        ] + pop() + [
            "D=M",
            at('addr'),  # *addr=*SP
            "A=M",
            "M=D"
        ])
    elif segment == "temp":
        return ([
            at(5),  # temp base address is 5
            "D=A",
            at(i),
            "D=D+A",
            at('addr'),
            "M=D"
        ] + pop() + [
            "D=M",
            at('addr'),  # *addr=*SP
            "A=M",
            "M=D"
        ])
    elif segment == "static":
        label = "{0}.{1}".format(ftitle, i)
        return pop() + ["D=M", at(label), "M=D"]
    elif segment == "pointer":
        if int(i) not in [0, 1]:
            raise Exception('Invalid i for pop pointer: ' + str(i))
        target = "THAT" if int(i) else "THIS"
        return [
            "@SP",  # SP--
            "M=M-1",
            "A=M",  # THIS/THAT = *SP
            "D=M",
            at(target),
            "M=D"
        ]
    raise Exception("{0} segment type not implemented yet".format(segment))
Esempio n. 4
0
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
Esempio n. 5
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_goto(label, func):
    return [at(func + '$' + label), "0; JMP"]
def write_if_goto(label, func):
    return pop() + ["D=M", at(func + '$' + label), "D; JNE"]
Esempio n. 8
0
def __write_restore(var):
    """Decrement endframe by 1, then set var to that value"""
    return ([
        "// endFrame-=1, {0} = *(endFrame)".format(var),
        at("endFrame"), "M=M-1"
    ] + ["A=M", "D=M", at(var), "M=D"])
Esempio n. 9
0
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"])