def main():
    '''Main entry point for the script.'''

    # For each .vm file, create a parser object
    filetrue = os.path.isfile(sys.argv[1])
    dirtrue = os.path.isdir(sys.argv[1])
    vmfiles = []

    # Rename directory as a ".asm" file for later use
    finame = os.path.basename(os.path.normpath(sys.argv[1])) + ".asm"

    # Get file path with .asm file appended
    dirname = os.path.join(sys.argv[1], finame)

    # Create list of files to convert and add to asm file
    if dirtrue:

        cw = CodeWriter(dirname)
        fi = os.listdir(sys.argv[1])

        for names in fi:

            if names.endswith(".vm"):
                vmfiles.append(sys.argv[1] + names)

    elif filetrue:

        di = sys.argv[1]

        if di.endswith(".vm"):

            vmfiles.append(di)
            tr = vmfiles[0]
            trs = tr.replace("vm", "asm")
            cw = CodeWriter(trs)

        else:
            print "invalid filetype: only input .vm files"

    else:
        print "usage: 'python <file.vm> or <dirname/>'"

    out = cw.constructor()
    cw.writeInit(out)

    with out as outfile:

        for files in vmfiles:

            # Create new instance of class Parser()
            p = cw.setFileName(files)

            with p.constructor() as infile:

                for line in infile:

                    if p.commandType(line) == "comments":

                        pass

                    elif p.commandType(line) == "C_ARITHMETIC":

                        cw.writeArithmetic(outfile, p.args(line)[0])

                    elif p.commandType(line) == "C_IF":

                        # Handle if-goto command
                        cw.writeIf(outfile, p.args(line)[1])

                    elif p.commandType(line) == "C_GOTO":

                        # Handle goto command
                        cw.writeGoto(outfile, p.args(line)[1])

                    elif p.commandType(line) == "C_RETURN":

                        # Return function result
                        cw.writeReturn(outfile)

                    elif p.commandType(line) == "C_LABEL":

                        # Set label address
                        cw.writeLabel(outfile, p.args(line)[1])

                    elif p.commandType(line) == "C_CALL":

                        # Handle function calls
                        cw.writeCall(outfile, p.args(line)[1], p.args(line)[2])

                    elif p.commandType(line) == "C_FUNCTION":

                        cw.writeFunction(outfile,
                                         p.args(line)[1],
                                         p.args(line)[2])

                    elif p.commandType(line) == "C_PUSH" or "C_POP":

                        cw.writePushPop(outfile, p.commandType(line),
                                        p.args(line)[1],
                                        p.args(line)[2])
Example #2
0
def main(path):
    """Entry point for the vm translator."""
    vm_files_paths = get_vm_files(path)

    if not os.path.exists(path):
        print("invalid file path")
        sys.exit(1)

    if os.path.isdir(path):
        dirname = os.path.dirname(path)
        name = os.path.basename(dirname)
        path = f"{dirname}/{name}"
        isdir = True
    else:
        path = os.path.splitext(path)[0]
        isdir = False

    # Create single code write module
    code_writer = CodeWriter(f"{path}.asm")

    if isdir:
        code_writer.writeInit()

    for vm_file_path in vm_files_paths:
        filestream = open(vm_file_path, "r")
        parser = Parser(filestream)
        filestream.close()

        # write to assembly file
        code_writer.setFileName(os.path.basename(vm_file_path))

        while parser.hasMoreCommands():
            parser.advance()
            command_type = parser.commandType()

            if (command_type == CommandType.C_PUSH or
                    command_type == CommandType.C_POP):
                segment = parser.arg1()
                index = parser.arg2()
                code_writer.writePushPop(
                    command_type,
                    segment,
                    int(index)
                )
            elif command_type == CommandType.C_ARITHMETIC:
                command = parser.arg1()
                code_writer.writeArithmetic(command)
            elif command_type == CommandType.C_LABEL:
                label = parser.arg1()
                code_writer.writeLabel(label)
            elif command_type == CommandType.C_GOTO:
                label = parser.arg1()
                code_writer.writeGoto(label)
            elif command_type == CommandType.C_IF:
                label = parser.arg1()
                code_writer.writeIf(label)
            elif command_type == CommandType.C_FUNCTION:
                label = parser.arg1()
                number_of_locals = int(parser.arg2())
                code_writer.writeFunction(label, number_of_locals)
            elif command_type == CommandType.C_RETURN:
                code_writer.writeReturn()
            elif command_type == CommandType.C_CALL:
                functioname = parser.arg1()
                number_of_args = int(parser.arg2())
                code_writer.writeCall(functioname, number_of_args)

        print(code_writer.filestream.get_global_counter())
    code_writer.close()