Exemple #1
0
 def test_mov_edi_literal(self):
     writer = CodeWriter()
     writer.mov_edi_literal(1234)
     code = writer.get_code()
     inst = code[len(code) - 5:]
     expected = [0xbf, 0xd2, 0x4, 0, 0]
     for i in range(len(expected)):
         self.assertEqual(inst[i], expected[i])
Exemple #2
0
 def test_mov_edi_literal(self):
     writer = CodeWriter()
     writer.mov_edi_literal(1234)
     code = writer.get_code()
     inst = code[len(code)-5:]
     expected = [0xbf, 0xd2, 0x4, 0, 0]
     for i in range(len(expected)):
         self.assertEqual(inst[i], expected[i])
Exemple #3
0
def main(vmfile):
    vmparser = VMParser(vmfile)
    cw = CodeWriter()

    while True:
        vmparser.advance()
        cw.process_command(vmparser.command)

        if not vmparser.has_more_commands():
            break
 def __init__(self):
     """Inciializa una tabald e simbolos y un ecritor de codigo junto con variables auxiliares"""
     self.symbolTable = SymbolTable()
     self.contWhile = -1
     self.contIf = -1
     self.nombreClase = ""
     self.kindMetodo = ""
     self.nombreMetodo = ""
     self.vmWriter = CodeWriter()
     self.vmWriter.vm = ""
     self.nArgs = 0
def translate(vmfiles, asmfile):
    w = CodeWriter(asmfile)
    
    for fn in vmfiles:
        print 'Parsing %s...'%fn
        p = Parser(fn)
        w.set_filename( os.path.splitext( os.path.split(fn)[-1] )[0] )
    
        # Insert Code Here
            
    print 'Writing %s...'%asmfile
    w.close()
Exemple #6
0
def build_code_writer(dest):
    if is_dest_dir(dest):
        print('we have a dir')
        output_filename = str(dest.split('/')[-1])
        output_filename = os.path.join(dest, output_filename + '.asm')
        print(output_filename)
        code_writer = CodeWriter(output_filename, dest)
    else:
        print('we have a file')
        output_filename = dest[:-3] + '.asm'
        print(output_filename)
        code_writer = CodeWriter(output_filename, dest[:-3])
    return code_writer
def main(argv):
    """
    Main flow of program dealing with extracting files for reading and initializing files to translate into
    """
    if not check_args(argv):
        return

    #  extracting asm file to be processed
    vm_files_path = argv[1]

    #  creating a .asm file to contain vm files translation to hack machine language
    if os.path.isdir(vm_files_path):
        dir_name = os.path.basename(vm_files_path)
        asm_file_name = "{0}/{1}.asm".format(vm_files_path, dir_name)
        code_writer = CodeWriter(asm_file_name)
        for file in os.listdir(vm_files_path):
            if file.endswith(".vm"):
                code_writer.set_file_name(file)
                vm_parser = VMParser('{0}/{1}'.format(vm_files_path, file))
                translate_vm_file(code_writer, vm_parser)
    else:
        asm_file_name = "{0}.asm".format(os.path.splitext(vm_files_path)[0])
        code_writer = CodeWriter(asm_file_name)
        code_writer.set_file_name(vm_files_path)
        vm_parser = VMParser(vm_files_path)
        translate_vm_file(code_writer, vm_parser)
Exemple #8
0
  def main():
    path = Util.getCommandLineArgument(1)
    code_writer = CodeWriter(path.replace('.vm', '') + '.asm')

    if os.path.isdir(path):
      files = FileSet(path, 'vm')

      while files.hasMoreFiles():
        filename = files.nextFile()
        Main.parse(filename, code_writer)
    elif os.path.isfile(path):
      Main.parse(path, code_writer)

    code_writer.Close()
Exemple #9
0
class TestCodeWriter(unittest.TestCase):
    def setUp(self):
        self.filename = './StackArithmetic/SimpleAdd/SimpleAdd.asm'
        self.code_writer = CodeWriter(self.filename)

    def tearDown(self):
        self.code_writer.Close()

    def assertion(self, actual, expected):
        asserted = actual == expected
        if not asserted:
            print 'FAILED: assert {} == {}'.format(actual, expected)
        assert asserted

    def test_constructor_sets_attributes(self):
        assert self.code_writer.output.__class__.__name__ == 'file'

    def test_write_arthmetic(self):
        # self.assertion(self.code_writer.writeArithmetic('add'), '')
        assert '@SP' in self.code_writer.writeArithmetic('add')
Exemple #10
0
def main():
    parser = argparse.ArgumentParser(description='Process some integers.')
    parser.add_argument('path', type=str, help='vm file or folder')

    args = parser.parse_args()
    path = args.path

    if path.endswith(".vm"):  # file
        with CodeWriter(path[:-3] + ".asm") as code_writer:
            translate_file(path, code_writer)
        print "Translated to", path[:-3] + ".asm"
    else:  # directory
        if path.endswith("/"):
            path = path[:-1]
        with CodeWriter(path + ".asm") as code_writer:
            files = glob.glob("%s/*" % path)
            for file in files:
                if file.endswith(".vm"):
                    translate_file(file, code_writer)
        print "Translated to", path + ".asm"
Exemple #11
0
def main():
    vm_filename = sys.argv[1]
    asm_filename = vm_filename.replace('.vm', '.asm')
    vm_file = open(vm_filename, 'r')
    asm_file = open(asm_filename, 'a')

    parser = Parser(vm_file)
    code_writer = CodeWriter(asm_file)

    while parser.has_more_commands():
        parser.advance()
        if parser.command_type() == C_ARITHMETIC:
            code_writer.write_arithmetic(parser.arg1())
        elif parser.command_type() == C_PUSH:
            code_writer.write_push_pop(C_PUSH, parser.arg1(), parser.arg2())
        elif parser.command_type() == C_POP:
            code_writer.write_push_pop(C_POP, parser.arg1(), parser.arg2())

    vm_file.close()
    code_writer.close()
Exemple #12
0
    def translate(self):
        for count, f in enumerate(self.files_to_translate):
            should_bootstrap = True if count == 0 else False

            code_writer = CodeWriter(f.split('.vm')[0].split('/')[-1])
            parser = Parser(f)

            for line in parser.read_lines():
                if should_bootstrap and self.initiate_bootstrap:
                    self.output_string += code_writer.bootstrap(
                        self.contains_sys_vm_file)
                should_bootstrap = False

                command_type = parser.command_type(line)
                arg1 = parser.arg1(line)
                arg2 = parser.arg2(line)
                translated_line = code_writer.generate(command_type, arg1,
                                                       arg2)
                self.output_string += translated_line

        self.__write_out()
def main():
    # Input file Path
    in_file = Path(argv[1])

    # Check if provided argument is
    # a file or a directory
    if (in_file.is_dir()):
        # Argument path to a directory
        out_file = in_file / in_file.with_suffix(".asm")

    elif (in_file.is_file()):
        # Argument is path to a file
        # Output file Path
        out_file = in_file.with_suffix(".asm")

    # Construct a CodeWriter to
    # handle output file
    asm_writer = CodeWriter(out_file)

    if (in_file.is_file()):
        # Translate the single file
        translate_in_file(asm_writer, in_file)

    elif (in_file.is_dir()):
        # Have to loop through every file
        asm_writer.write_bootstrap_code()

        # Loop through each file and translate
        for f in in_file.iterdir():
            # File is .vm file?
            if f.suffix == ".vm":
                print(f"translating {f.name}...")
                asm_writer.set_file_name(f.stem)
                translate_in_file(asm_writer, f)
Exemple #14
0
 def __init__(self, scanner, output_file=None):
     self.scanner = scanner
     self.tokens = scanner.tokens
     self.log = logging.getLogger('parser')
     self.table = SymbolTable()
     if not len(self.log.handlers):
         self.log.setLevel(logging.DEBUG)
         hdlr = logging.FileHandler('/tmp/myapp.log')
         formatter = logging.Formatter(
             '%(asctime)s %(levelname)s %(message)s')
         hdlr.setFormatter(formatter)
         self.log.addHandler(hdlr)
     self.writer = CodeWriter(out_file=output_file)
Exemple #15
0
 def __init__(self, prefix, version, sourceFile, vars=None, events=None, outputdir=None):
     
     if not vars:
         vars = []
     
     if not events:
         events = []
     
     self.variables = vars
     self.events = events
     
     self.prefix = prefix
     self.version = version
     self.source = sourceFile
     
     hfile = headerFileName(prefix) + '.h'
     cfile = headerFileName(prefix) + '.c'
     
     if outputdir:
         hfile = os.path.join(outputdir, hfile)
         cfile = os.path.join(outputdir, cfile)
     
     self.hFile = CodeWriter(hfile)
     self.cFile = CodeWriter(cfile)
Exemple #16
0
def main():
	filename = sys.argv[1].split('.')[0]
	parser = Parser(filename)
	code = CodeWriter(filename)
	while(parser.has_more_commands()):
		parser.advance()

		command_type = parser.command_type()

		if command_type == 'C_ARITHMETIC':
			code.write_arithmetic(parser.arg1())

		elif command_type == 'C_PUSH' or command_type == 'C_POP':
			code.write_push_pop(parser.command(), parser.arg1(), parser.arg2())

		# print(parser.current_command)
	parser.close()
	code.close()
Exemple #17
0
def translate(vmfiles, asmfile):
    w = CodeWriter(asmfile)

    for fn in vmfiles:
        print 'Parsing %s...' % fn
        p = Parser(fn)
        w.set_filename(os.path.splitext(os.path.split(fn)[-1])[0])

        # Insert Code Here

    print 'Writing %s...' % asmfile
    w.close()
Exemple #18
0
   def translate(self):
      code_writer = CodeWriter(self.destination_file)

      # for each source filename
      for source_filename in self.source_filenames:
         parser = Parser(source_filename)
         code_writer.set_filename(source_filename)

         # parse each command
         while parser.has_more_commands():
            # advance to the next command
            parser.advance()

            # parse the command type
            command_type = parser.command_type()
            if command_type == "C_ARITHMETIC":
               code_writer.write_arithemtic(parser.arg1())
            elif command_type in ["C_POP", "C_PUSH"]:
               code_writer.write_push_pop(command_type, parser.arg1(), parser.arg2())
            else:
               raise Error("Not implemented: command type " + command_type)

      # close the output file
      code_writer.close()
def main():
    args = get_args()
    dbc_filepath = args.dbc
    output = args.output
    print_only = args.print_only
    dbc_node_name = args.dbc_node_name

    if not os.path.isfile(dbc_filepath):
        print("Unable to find DBC file: [{}]".format(dbc_filepath))
        return 1  # Return early

    try:
        code_writer = CodeWriter(dbc_filepath, dbc_node_name)
    except InvalidDBCNodeError as err:
        print(ColorString(str(err)).red)
        return 1  # Return early

    if not print_only:
        dbc_filename = os.path.basename(dbc_filepath)
        basename, ext = os.path.splitext(os.path.basename(dbc_filepath))
        output_filename = "{}.h".format(basename)

        if output is None:
            output_filepath = output_filename
        elif os.path.isdir(output) or "." not in os.path.basename(output):
            output_filepath = os.path.join(output, output_filename)
        else:
            output_filepath = output

        message = "Generating code [{}] -> [{}]".format(
            dbc_filename, output_filename)
        if dbc_node_name != GENERATE_ALL_NODE_NAME:
            message += " using node [{}]".format(dbc_node_name)
        print(ColorString(message).green)

        if not os.path.isdir(os.path.dirname(output_filepath)):
            os.makedirs(os.path.dirname(output_filepath))
        with open(output_filepath, "w") as file:
            file.write(str(code_writer))
    else:
        print(code_writer)

    return 0
class TestCodeWriter(unittest.TestCase):
  def setUp(self):
    self.filename = './StackArithmetic/SimpleAdd/SimpleAdd.asm'
    self.code_writer = CodeWriter(self.filename)

  def tearDown(self):
    self.code_writer.Close()

  def assertion(self, actual, expected):
    asserted = actual == expected
    if not asserted:
      print 'FAILED: assert {} == {}'.format(actual, expected)
    assert asserted

  def test_constructor_sets_attributes(self):
    assert self.code_writer.output.__class__.__name__ == 'file'

  def test_write_arthmetic(self):
    # self.assertion(self.code_writer.writeArithmetic('add'), '')
    assert '@SP' in self.code_writer.writeArithmetic('add')
Exemple #21
0
def main():

    # If there is an invalid number of arguments the program stops.
    if len(sys.argv) != 2:
        print("ERROR: Invalid number of arguments. Expected: file_name.vm ")
        exit(1)
    # the VM translator only accepts vm files to be translated into assembly files.
    elif sys.argv[1][-3:] != ".vm":
        print("ERROR: Invalid file type. Expected: vm file")
        exit(1)

    # Get the name of the file to be parsed from the arguments.
    input_file = sys.argv[1]

    # Creates a new parser to parse the file.
    parser = Parser(input_file)
    # Creates the code writer with the input file excluding the .vm part
    code_writer = CodeWriter(input_file[0:-3])

    # Reads the whole file.
    while parser.has_more_commands():
        parser.advance()
        # Gets the command type from the current command.
        command_type = parser.command_type()
        # If the command type is C_ARITHMETIC parses it to get the command and passes it to the code writer to add it to the output file
        if command_type == "C_ARITHMETIC":
            command = parser.arg1()
            code_writer.write_arithmetic(command)
        # If the command type is C_PUSH or C_POP parses it to get the segment and the index and passes it to the code writer to add it to the output file
        elif command_type == "C_PUSH" or command_type == "C_POP":
            segment = parser.arg1()
            index = parser.arg2()
            code_writer.write_push_pop(command_type, segment, index)

    del parser
    code_writer.close()
Exemple #22
0
def main():
    if len(sys.argv) != 2:
        print('<VMTranslator>: Execute script with '
              'one argument only (The path of an existing "vm" file)\n')
        exit()

    vm_file = sys.argv[1]
    parser = VMParser(vm_file)

    asm_file = vm_file.replace('.vm', '.asm')
    code_writer = CodeWriter(asm_file)

    while parser.has_more_commands():
        code_writer.write_command(parser.command)
        parser.advance()
    code_writer.write_end()

    print '<VMTranslator>: Successfully created "{}"\n'.format(asm_file)
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])
Exemple #24
0
from parser import Parser
from code_writer import CodeWriter

# get input file name
try:
	input_folder_name = sys.argv[1].replace('/', '')
except IndexError:
	print('there is no folder argument')
vm_files = filter(lambda f :  f.endswith('.vm'), os.listdir(input_folder_name))
vm_files = deque(vm_files)

for f in ['Main.vm', 'Sys.vm']:
	if f in vm_files:
		vm_files.remove(f)
		vm_files.appendleft(f)
vm_files.appendleft('../BootstrapCode.vm')

shared_data = SharedData(input_folder_name)

io_file = IOFile(shared_data)
parser = Parser(shared_data)
code_writer = CodeWriter(shared_data)

for f in vm_files:
	shared_data.set_input_file_name(f)

	io_file.file_to_array()
	parser.run()
	code_writer.run()
	io_file.array_to_file()
Exemple #25
0
   def translate(self):
      code_writer = CodeWriter(self.destination_file)

      # for each source filename
      for source_filename in self.source_filenames:
         parser = Parser(source_filename)
         code_writer.set_filename(source_filename)

         # parse each command
         while parser.has_more_commands():
            # advance to the next command
            parser.advance()

            # parse the command type
            command_type = parser.command_type()
            if command_type == "C_ARITHMETIC":
               code_writer.write_arithemtic(parser.arg1())
            elif command_type in ["C_POP", "C_PUSH"]:
               code_writer.write_push_pop(command_type, parser.arg1(), parser.arg2())
            elif command_type == "C_LABEL":
               code_writer.write_label(parser.arg1())
            elif command_type == "C_GOTO":
               code_writer.write_goto(parser.arg1())
            elif command_type == "C_IF":
               code_writer.write_if(parser.arg1())
            elif command_type == "C_FUNCTION":
               code_writer.write_function(parser.arg1(), parser.arg2())
            elif command_type == "C_RETURN":
               code_writer.write_return()
            elif command_type == "C_CALL":
               code_writer.write_call(parser.arg1(), parser.arg2())
            else:
               raise Exception("Not implemented: command type " + command_type)


      # close the output file
      code_writer.close()
 def setUp(self):
   self.filename = './StackArithmetic/SimpleAdd/SimpleAdd.asm'
   self.code_writer = CodeWriter(self.filename)
Exemple #27
0
from parser import Parser
from code_writer import CodeWriter

arg_parser = argparse.ArgumentParser(description='Translate vm code into assembly code')
arg_parser.add_argument('path_input', help='The path for vm file *.vm or the directory path which contains *.vm files')
args = arg_parser.parse_args()


path_input = Path(args.path_input)
assert path_input.exists(), "Path not exists."

if path_input.is_dir():	# Translate all vm files in directory
    vmfiles = [f for f in path_input.glob('*.vm')]
    assert vmfiles, "No vm file in this directory."
    out_asm_file = path_input / (path_input.name + '.asm')	# Out asm file name same as directory name
    returned_contents = {}
    for vmfile in vmfiles:
        psr = Parser(vmfile)
        parse_result = psr.parse()
        returned_contents = {**returned_contents, **parse_result}	# Merge returned results to dict returned_contents
else:	# Translate one vm file
    vmfile = path_input
    out_asm_file = path_input.with_suffix('.asm')
    psr = Parser(vmfile)
    returned_contents = psr.parse()

cw = CodeWriter(returned_contents, out_asm_file)
cw.write()
print('Successfully translate to assembly ' + out_asm_file.as_posix())
Exemple #28
0
        elif parser.command_type() == 'C_RETURN':
            code_writer.write_return()

        elif parser.command_type() == 'C_CALL':
            function_name = parser.arg1()
            num_args = int(parser.arg2())
            code_writer.write_call(function_name, num_args)


if __name__ == '__main__':
    input_file = sys.argv[1]

    if path.isfile(input_file):
        src_vm_files = [input_file]
        asm_file = path.splitext(input_file)[0] + ".asm"
    else:
        src_vm_files = glob.glob(path.join(sys.argv[1], '*.vm'))
        asm_file = path.split(input_file.rstrip('/') + ".asm")[1]
        asm_file = path.join(input_file, asm_file)

    code_writer = CodeWriter(asm_file)

    if len(src_vm_files) != 1:
        code_writer.write_init()

    for src_vm_file in src_vm_files:
        parse_and_write(code_writer, src_vm_file)

    code_writer.close()
Exemple #29
0
class LogFile:
    def __init__(self, prefix, version, sourceFile, vars=None, events=None, outputdir=None):
        
        if not vars:
            vars = []
        
        if not events:
            events = []
        
        self.variables = vars
        self.events = events
        
        self.prefix = prefix
        self.version = version
        self.source = sourceFile
        
        hfile = headerFileName(prefix) + '.h'
        cfile = headerFileName(prefix) + '.c'
        
        if outputdir:
            hfile = os.path.join(outputdir, hfile)
            cfile = os.path.join(outputdir, cfile)
        
        self.hFile = CodeWriter(hfile)
        self.cFile = CodeWriter(cfile)
        
    def constructCodeFile(self):
        
        self.cFile.clear()
        
        self.cFile.append(AutogenString(self.source))
        
        #include the header file
        self.cFile.include('"{file}.h"'.format(file=headerFileName(self.prefix)))
        
        self.cFile.appendLine()
        
        #add in the global functions
        self.cFile.startComment()
        self.cFile.appendLine("Global functions")
        self.cFile.finishComment()
        
        self.cFile.appendLine()
        
        self.createResetFunction()
        self.createCopyAllToFunction()
        self.createCopyDataToFunction()
        self.createCopyAllFromFunction()
        self.createCopyDataFromFunction()
        self.getSelectionSizeFunction()
        
        self.cFile.appendLine()
        self.cFile.startComment()
        self.cFile.appendLine("Individual variable functions")
        self.cFile.finishComment()
        
        self.cFile.appendLine()
        
        #add in the functions to add variables
        for v in self.variables:
            self.createAdditionFunction(v)
            self.createDecodeFunction(v)
       
        self.titleByIndexFunction()
        self.unitsByIndexFunction()
        self.valueByIndexFunction()
        
        if len(self.events) > 0:
            self.cFile.appendLine()
            self.cFile.appendLine(comment='Functions to copy *events* to a buffer')
            
            for e in self.events:
                self.addEventCopyFuncs(e)
                
            self.cFile.appendLine(comment='Decode a {pref} event to a string'.format(pref=self.prefix))
            self.eventsToStringFunction()
            
            self.cFile.appendLine()
            self.cFile.appendLine(comment='Functions for formatting individual events to a string')
            for e in self.events:
                self.eventToStringFunc(e)
       
    def constructHeaderFile(self):
        
        self.hFile.clear()
        
        self.hFile.append(AutogenString(self.source))
        
        self.hFile.startIf(headerDefineName(self.prefix),invert=True)
        self.hFile.define(headerDefineName(self.prefix))
        
        self.hFile.appendLine()
        self.hFile.include('"logjam_common.h"', comment='common LogJam routines')
        
        self.hFile.appendLine()
        
        self.hFile.externEntry()
        
        #version information
        self.hFile.appendLine()
        self.hFile.appendLine(comment='{pre} logging version'.format(pre=self.prefix))
        self.hFile.define('LOG_{pref}_VERSION()'.format(pref=self.prefix),value='"{v}"'.format(v=self.version))
        
        vMaj, vMin = self.version.split('.')
        
        self.hFile.define('LOG_{pref}_VERSION_MAJOR'.format(pref=self.prefix),value=vMaj)
        self.hFile.define('LOG_{pref}_VERSION_MINOR'.format(pref=self.prefix),value=vMin)

        self.hFile.appendLine()
        #create global enumeration for the variables
        fn = lambda i,val: "{val} is stored in byte {n}, position {m}".format(val=val,n=int(int(i)/8),m=i%8)
        self.hFile.createEnum('Log{pref}_VariableEnum_t'.format(pref=self.prefix),[v.getEnumString() for v in self.variables],split=8,commentFunc=fn)
        
        self.hFile.appendLine(comment='{n} bytes are required to store all parameter selction bits for {log} logging'.format(n=bitfieldSize(len(self.variables)),log=self.prefix))
        self.hFile.define('LOG_{pref}_SELECTION_BYTES'.format(pref=self.prefix.upper()),value=bitfieldSize(len(self.variables)))
        self.hFile.appendLine()
        
        self.hFile.appendLine(comment="Number of variables defined for the '{pref}' logging structure".format(pref=self.prefix))
        self.hFile.define('LOG_{pref}_VARIABLE_COUNT'.format(pref=self.prefix.upper()), value=len(self.variables))
        self.hFile.appendLine()
        
        self.hFile.appendLine(comment="Struct definition for storing the selection bits of the " + self.prefix + " logging struct")
        self.hFile.appendLine(comment='This is not stored as a native c bitfield to preserve explicit ordering between processors, compilers, etc')
        self.hFile.appendLine('typedef uint8_t {name}[LOG_{pref}_SELECTION_BYTES];'.format(pref=self.prefix.upper(),name=bitfieldStructName(self.prefix)))
        self.hFile.appendLine()
        self.hFile.appendLine(comment="Data struct definition for the " + self.prefix + " logging struct")
        self.createDataStruct()
        
        #total data size
        d_size = sum([v.bytes for v in self.variables])
        self.hFile.appendLine()
        self.hFile.appendLine(comment='{n} bytes are required to store all the data parameters'.format(n=d_size))
        self.hFile.define('LOG_{pref}_DATA_BYTES'.format(pref=self.prefix.upper()),value=d_size)
        
        self.hFile.appendLine()
        
        #events
        if len(self.events) > 0:
            self.hFile.appendLine(comment='Logging event definitions for the {the}'.format(the=self.prefix))
            self.hFile.appendLine(comment='Enumeration starts at 0x80 as *generic* events are 0x00 -> 0x7F')
            self.hFile.createEnum('Log{pref}_EventEnum_t'.format(pref=self.prefix),[e.getEnumString() for e in self.events],start="0x80")
            
        self.hFile.appendLine()
        
        self.hFile.appendLine(comment='Functions to copy various log events to logging buffer')
        self.hFile.appendLine(comment='Each function returns the number of bytes written to the log') 
        self.hFile.appendLine(comment='Pointer is automatically incremented as required')
        #functions for the events
        for e in self.events:
            self.hFile.appendLine('inline uint8_t {func};'.format(func=e.eventPrototype()))
        
        self.hFile.appendLine();
        self.hFile.appendLine(comment='Function to extract an event from a buffer, and format it as a human-readable string')
        self.hFile.appendLine(self.eventsToStringPrototype() + ';')
        
        self.hFile.appendLine()
        self.hFile.appendLine(comment='Functions for turning individual events into strings')
        for e in self.events:
            self.hFile.appendLine(e.toStringPrototype() + ';',comment='Format the {evt} event into a string'.format(evt=e.getEnumString()))
        
        self.hFile.appendLine()
        
        self.hFile.startComment()
        self.hFile.appendLine("Global Functions:")
        self.hFile.finishComment()
        
        self.hFile.appendLine(comment="Reset the bitfield of the logging structure")
        self.hFile.appendLine(self.resetPrototype() + ";")
        
        self.hFile.appendLine(comment='Copy *all* data from the logging structure')
        self.hFile.appendLine(self.copyAllPrototype() + ';')
        
        self.hFile.appendLine(comment="Copy *selected* data from the logging structure")
        self.hFile.appendLine(self.copySelectedPrototype() + ";")
        
        self.hFile.appendLine(comment='Copy all data back out from a buffer')
        self.hFile.appendLine(self.copyAllFromPrototype() + ';')
        
        self.hFile.appendLine(comment='Copy *selected* data back out from a buffer')
        self.hFile.appendLine(self.copyDataFromPrototype() + ';')
        
        self.hFile.appendLine(comment='Get the total size of the selected variables')
        self.hFile.appendLine(self.getSelectionSizePrototype() + ';')
        
        self.hFile.appendLine()
        
        self.hFile.appendLine(comment="Functions for getting variable information based on the index");
        self.hFile.appendLine(self.titleByIndexPrototype()+';')
        self.hFile.appendLine(self.unitsByIndexPrototype()+';')
        self.hFile.appendLine(self.valueByIndexPrototype() + ';')
        
        self.hFile.appendLine()
        
        self.hFile.startComment()
        self.hFile.appendLine("Variable Functions:")
        self.hFile.appendLine("These functions are applied to individual variables within the logging structure")
        self.hFile.finishComment()
        
        #add in the 'addition' functions
        for var in self.variables:
            self.hFile.appendLine()
            self.hFile.appendLine(comment="Functions for the '{name}' variable".format(name=var.name))
            self.hFile.define('Log{prefix}_{name}Title() {title}'.format(
                prefix=self.prefix,
                name=var.name,
                title=var.getTitleString()),
                comment='Title string for {var} variable'.format(var=var.name))
                
            self.hFile.define('Log{prefix}_{name}Units() {units}'.format(
                prefix=self.prefix,
                name=var.name,
                units=var.getUnitsString()),
                comment='Units string for {var} variable'.format(var=var.name))
            self.hFile.appendLine(self.additionPrototype(var) + '; //Add ' + var.name + " to the log struct")
            self.hFile.appendLine(self.decodePrototype(var) + '; //Decode ' + var.name + ' into a printable string')
        
        self.hFile.appendLine()
        self.hFile.externExit()
        
        self.hFile.endIf()
    
    def saveFiles(self):
        
        self.constructHeaderFile()
        self.constructCodeFile()
        
        self.hFile.writeToFile()
        self.cFile.writeToFile() 
        
    def addEventCopyFuncs(self, e):
        #copy TO buffer
        self.cFile.appendLine('inline uint8_t {func}'.format(func=e.eventPrototype()))
        self.cFile.openBrace()
        
        #copy across the event type
        self.cFile.appendLine('*(*ptr++) = {evt};'.format(evt=e.getEnumString()),comment='Copy the event type to the buffer')
        
        if len(e.variables) > 0:
            self.cFile.appendLine()
            for v in e.variables:
                self.copyVarToBuffer(v,struct='',pointer='ptr')
        
        self.cFile.appendLine()
        self.cFile.appendLine('return {n};'.format(n=e.eventSize()),comment='Number of bytes copied')
        
        self.cFile.closeBrace()
        self.cFile.appendLine()
        
    #create the struct of the variables
    def createDataStruct(self):
    
        self.hFile.appendLine('typedef struct {')
        
        self.hFile.tabIn()
        
        for v in self.variables:
            self.hFile.appendLine(comment="Variable '{name}'{units}{scaler} ({n} bytes)".format(
                    name = v.name,
                    units = ", units='{u}'".format(u=v.units) if v.units else '',
                    scaler = ", scaler=1.0/{scaler}".format(scaler=v.scaler) if v.scaler > 1 else '',
                    n = v.bytes))
            
            self.hFile.appendLine(v.dataString())
        
        self.hFile.tabOut()
        
        self.hFile.appendLine('} ' + dataStructName(self.prefix) + ';')
        
    def additionPrototype(self,var):
        return self.createVariableFunction(var,'add',returnType='bool',extra=[('onlyIfNew','bool')])
        
    #create the function for adding a variable to the logging structure
    def createAdditionFunction(self, var):
    
        self.cFile.appendLine(comment='Add variable {name} to the {prefix} logging struct'.format(
                        name=var.name,
                        prefix=self.prefix))
                        
        self.cFile.appendLine(self.additionPrototype(var))
        self.cFile.openBrace()
        self.cFile.appendLine('if (onlyIfNew == true)',comment='Ignore value if it is the same as the value already stored')
        self.cFile.openBrace()
        self.cFile.appendLine('if (data->{var} == {var})'.format(var=var.name))
        self.cFile.tabIn()
        self.cFile.appendLine('return false;')
        self.cFile.tabOut()
        self.cFile.closeBrace()
        self.cFile.appendLine()
        self.cFile.appendLine(var.setBit('selection'),comment='Set the appropriate bit')
        #now actually add the variable in
        self.cFile.appendLine(var.addVariable('data'))
        self.cFile.appendLine()
        self.cFile.appendLine('return true;')
        self.cFile.closeBrace()
        self.cFile.appendLine()
        
    #function for decoding a particular variable into a printable string for writing to a log file
    def decodePrototype(self, var):
        return self.createVariableFunction(var,'decode',blank=True,bits=False,returnType='void',extra=[('*str','char')])
    
    def createDecodeFunction(self, var):
        self.cFile.appendLine(comment='Decode the {name} variable and return a printable string (e.g. for saving to a log file'.format(name=var.name))
        self.cFile.appendLine(comment='Pointer to *str must have enough space allocated!')
        self.cFile.appendLine(self.decodePrototype(var))
        self.cFile.openBrace()
        self.cFile.appendLine('sprintf(str,"{patt}",data->{var});'.format(patt=var.getStringCast(),var=var.name))
        self.cFile.closeBrace()
        self.cFile.appendLine()
        pass
        
    #create a function pointing to a particular variable
    def createVariableFunction(self, var, name, blank=False, extra=None,ptr=False, **params):
        name = var.getFunctionName(name)
        
        if not extra:
            extra = []
        
        if not blank:
            extra = [('{ptr}{name}'.format(ptr='*' if ptr else '',name=var.name),var.format)] + extra
        
        return self.createFunctionPrototype(name,extra=extra,**params)
        
    """
    Create a function type of given NAME
    name - name of the function
    data - Include a pointer to the LogData_t struct?
    bits - Include a pointer to the LogBitfield_t struct?
    inline - Make the function inline?
    returnType - Function return type
    extra - Extra parameters to pass to the function - list of tuples
    """
    def createFunctionPrototype(self, name, data=True, bits=True, inline=False, returnType='void', extra=None):
        
        if not extra:
            extra = []
        
        #pass extra parameters to the function as such
        #params = {'*dest': 'void'} (name, type)
        paramstring = ""
        for pair in extra:
            paramstring += ', '
            paramstring += pair[1]
            paramstring += ' '
            paramstring += pair[0]
            
        return '{inline}{returnType} Log{prefix}_{name}({data}{comma}{bits}{params})'.format(
                    inline='inline ' if inline else '',
                    returnType=returnType,
                    prefix=self.prefix.capitalize(),
                    name=name,
                    comma=', ' if data and bits else '',
                    data=dataStructName(self.prefix) + " *data" if data else "",
                    bits=bitfieldStructName(self.prefix) + " *selection" if bits else "",
                    params=paramstring)
                    
    def resetPrototype(self):
        return self.createFunctionPrototype('ResetSelection',data=False)
                    
    #create a function to reset the logging structure
    def createResetFunction(self):
        
        #add the reset function to the c file
        self.cFile.appendLine(comment='Reset the log data struct (e.g. after writing to memory)')
        self.cFile.appendLine(comment='Only the selection bits need to be reset')
        self.cFile.appendLine(self.resetPrototype())
        self.cFile.openBrace()
        
        self.cFile.appendLine('uint8_t *bf = (uint8_t*) selection;')
        for i in range(bitfieldSize(len(self.variables))):
            self.cFile.appendLine('bf[{n}] = 0; //Clear byte {x} of {y}'.format(n=i,x=i+1,y=bitfieldSize(len(self.variables))))
        
        self.cFile.closeBrace()
        self.cFile.appendLine()
        
    """
    Functions for copying data out of a struct and into a linear buffer
    """
    def copyAllPrototype(self):
        return self.createFunctionPrototype('CopyAllToBuffer',bits=False,extra=[('*dest','void')])
        
    #create a function to copy ALL parameters across, conserving data format
    def createCopyAllToFunction(self):
        
        self.cFile.appendLine(comment="Copy ALL data in the log struct to the provided address")
        self.cFile.appendLine(comment="Data will be copied even if the associated selection bit is cleared")
        
        self.cFile.appendLine(self.copyAllPrototype())
        self.cFile.openBrace()
        
        self.cFile.appendLine('uint8_t *ptr = (uint8_t*) dest; //Pointer for keeping track of data addressing')
        self.cFile.appendLine()
        
        for var in self.variables:
            self.copyVarToBuffer(var)
            self.cFile.appendLine()
        
        self.cFile.closeBrace()
        self.cFile.appendLine()

    def copySelectedPrototype(self):
        return self.createFunctionPrototype('CopyDataToBuffer',extra=[('*dest','void')], returnType='uint16_t')
        
    #create a function that copies across ONLY the bits that are set
    def createCopyDataToFunction(self):
        self.cFile.appendLine(comment="Copy across data whose selection bit is set in the provided bitfield")
        self.cFile.appendLine(comment="Only data selected will be copied (in sequence)")
        self.cFile.appendLine(comment="Ensure a copy of the selection bits is stored for decoding")
        self.cFile.appendLine(self.copySelectedPrototype())
        self.cFile.openBrace()
        self.cFile.appendLine('uint8_t *ptr = (uint8_t*) dest; //Pointer for keeping track of data addressing')
        self.cFile.appendLine('uint8_t *bf = (uint8_t*) selection; //Pointer for keeping track of the bitfield')
        self.cFile.appendLine('uint16_t count = 0; //Variable for keeping track of how many bytes were copied')
        self.cFile.appendLine()
        self.cFile.appendLine(comment='Copy the selection for keeping track of data')
        
        self.copyBitfieldToBuffer(count=True)
        
        self.cFile.appendLine()
        self.cFile.appendLine(comment='Check each variable in the logging struct to see if it should be added')
        
        for var in self.variables:
            self.cFile.appendLine('if ({test})'.format(test=var.getBit('selection')))
            self.cFile.openBrace()
            
            self.copyVarToBuffer(var, count=True)
            self.cFile.closeBrace()
        
        self.cFile.appendLine()
        self.cFile.appendLine('return count; //Return the number of bytes that were actually copied')
        self.cFile.closeBrace()
        self.cFile.appendLine()
        
    def copyBitfieldToBuffer(self, count=False):
        #bitfield is called 'selection' locally
        #size of the bitfield
        bf_size = bitfieldSize(len(self.variables))
        
        for i in range(bf_size):
            self.cFile.appendLine('*(ptr++) = bf[{i}];'.format(i = i))
                
        if count:
            self.cFile.appendLine('count += {size};'.format(size=bf_size))
            
    def copyBitfieldFromBuffer(self, count=False):
        bf_size = bitfieldSize(len(self.variables))
        
        for i in range(bf_size):
            self.cFile.appendLine('bf[{i}] = *(ptr++);'.format(i=i))
            
        if count:
            self.cFile.appendLine('count += {size};'.format(size=bf_size))
        
    def copyVarToBuffer(self, var, struct='data->', pointer='&ptr', count=False):
        self.cFile.appendLine('Copy{sign}{bits}ToBuffer({struct}{name}, {ptr});'.format(
                            sign='I' if var.isSigned() else 'U',
                            bits=var.bytes*8,
                            struct=struct,
                            name=var.name,
                            ptr = pointer),
                            comment= "Copy the '{var}' variable ({n} bytes)".format(var=var.name,n=var.bytes))            
            
        if count:
            self.cFile.appendLine('count += {size};'.format(size=var.bytes))
            
    def copyVarFromBuffer(self, var, struct='data->',pointer='&ptr',count=False):
    
        self.cFile.appendLine('Copy{sign}{bits}FromBuffer({struct}{name}, {ptr});'.format(
                            sign='I' if var.isSigned() else 'U',
                            bits=var.bytes*8,
                            struct=struct,
                            name=var.name,
                            ptr = pointer,
                            ),
                            comment="Copy the '{var}' variable ({n} bytes)".format(var=var.name,n=var.bytes))
                
        if count:
            self.cFile.appendLine('count += {size};'.format(size=var.bytes))
        
    """
    Functions for copying data back out of a buffer
    """
    def copyAllFromPrototype(self):
        return self.createFunctionPrototype(
                            'CopyAllFromBuffer',
                            bits = False,
                            extra = [('*src','void')])
                            
    def createCopyAllFromFunction(self):
        self.cFile.appendLine(comment="Copy across *all* data from a buffer")
        self.cFile.appendLine(comment="Data will be copied even if it is invalid (selection bit is cleared)")
        self.cFile.appendLine(self.copyAllFromPrototype())
        
        self.cFile.openBrace()
        
        self.cFile.appendLine('uint8_t *ptr = (uint8_t*) src; //Pointer for keeping track of data addressing')
        self.cFile.appendLine()
        
        for var in self.variables:
            self.copyVarFromBuffer(var)
            self.cFile.appendLine()
        
        self.cFile.closeBrace()
        self.cFile.appendLine()
        
    def copyDataFromPrototype(self):
        return self.createFunctionPrototype('CopyDataFromBuffer',
                                            returnType='uint16_t',
                                            extra = [('*src','void')])
                                            
    def createCopyDataFromFunction(self):
        self.cFile.appendLine(comment="Copy across *selected* data from a buffer")
        self.cFile.appendLine(self.copyDataFromPrototype())
        self.cFile.openBrace()
        
        self.cFile.appendLine('uint8_t *ptr = (uint8_t*) src; //Pointer for keeping track of data addressing')
        self.cFile.appendLine('uint8_t *bf = (uint8_t*) selection; //Pointer for keeping track of the bitfield')
        self.cFile.appendLine('uint16_t count = 0; //Variable for keeping track of how many bytes were copied')
        self.cFile.appendLine()
        self.cFile.appendLine(comment='Copy the selection bits')
        
        self.copyBitfieldFromBuffer(count=True)
        
        self.cFile.appendLine()
        self.cFile.appendLine(comment='Only copy across variables that have actually been stored in the buffer')
        
        for var in self.variables:
            self.cFile.appendLine('if ({test})'.format(test=var.getBit('selection')))
            self.cFile.openBrace()
            
            self.copyVarFromBuffer(var,count=True)
            
            self.cFile.closeBrace()
            
        self.cFile.appendLine()
        self.cFile.appendLine('return count; //Return the number of bytes that were actually copied')
        
        self.cFile.closeBrace()
        self.cFile.appendLine()
        
        
    #enumerate through all the varibles in the struct, perform 'function' for each
    def createCaseEnumeration(self, vars=None, blankFunction=None, returnFunction=None):
        
        if not vars:
            vars = self.variables
        
        for var in vars:
            self.cFile.addCase(var.getEnumString())
            
            if blankFunction:
                blank = blankFunction(var)
                if not blank.endswith(';'):
                    blank += ';'
                self.cFile.appendLine(blank)
            if returnFunction:
                self.cFile.returnFromCase(returnFunction(var))
            else:
                self.cFile.breakFromCase()

    def titleByIndexPrototype(self):
        return 'char* Log{pref}_GetTitleByIndex(uint8_t index)'.format(pref=self.prefix)
        
    def titleByIndexFunction(self):
        self.cFile.appendLine(comment='Get the title of a variable based on its enumerated value')
        self.cFile.appendLine(self.titleByIndexPrototype())
        self.cFile.openBrace()
        
        self.cFile.startSwitch('index')
        
        #add case labels
        #function to return the index
        fn = lambda var: 'Log{prefix}_{var}Title()'.format(prefix=self.prefix,var=var.name)
        
        self.createCaseEnumeration(returnFunction = fn)
        
        self.cFile.endSwitch()
        
        self.cFile.appendLine(comment='Default return value')
        self.cFile.appendLine('return "";')
        
        self.cFile.closeBrace()
        self.cFile.appendLine()
        
    def unitsByIndexPrototype(self):
        return 'char* Log{pref}_GetUnitsByIndex(uint8_t index)'.format(pref=self.prefix)
        
    def unitsByIndexFunction(self):
        self.cFile.appendLine(comment='Get the units of a variable based on its enumerated value')
        self.cFile.appendLine(self.unitsByIndexPrototype())
        self.cFile.openBrace()
        
        self.cFile.startSwitch('index')
        
        fn = lambda var: 'Log{prefix}_{var}Units()'.format(prefix=self.prefix,var=var.name)
        
        self.createCaseEnumeration(returnFunction = fn)
        
        self.cFile.endSwitch()
        
        self.cFile.appendLine(comment='Default return value')
        self.cFile.appendLine('return "";')
        
        self.cFile.closeBrace()
        self.cFile.appendLine()
         
    def valueByIndexPrototype(self):
        return self.createFunctionPrototype('GetValueByIndex',bits=False,extra=[('index','uint8_t'), ('*str','char')])
        
    def valueByIndexFunction(self):
        self.cFile.appendLine(comment='Get a string-representation of a given variable, based on its enumerated value')
        self.cFile.appendLine(self.valueByIndexPrototype())
        self.cFile.openBrace()
        
        self.cFile.startSwitch('index')
        
        fn = lambda var: 'Log{prefix}_Decode{name}(data,str)'.format(prefix=self.prefix.capitalize(),name=var.name)
        
        self.createCaseEnumeration(blankFunction=fn)
        
        self.cFile.endSwitch()
        
        self.cFile.closeBrace()
        self.cFile.appendLine()
        
    #function to turn an event into a string
    #pass a pointer to where the event data starts
    #pointer will be auto-incremented
    #returns 'true' if an event was extracted, else false
    def eventsToStringPrototype(self):
        return 'bool Log{pref}_EventToString(uint8_t **ptr, char *str)'.format(pref=self.prefix)
        
    def eventsToStringFunction(self):
        self.cFile.startComment()
        self.cFile.appendLine('Extract an event from a buffer, given a pointer to the buffer, and a pointer to where the event will be strung')
        self.cFile.appendLine('Function will auto-increment the pointer as necessary')
        self.cFile.appendLine('Returns true if event was extracted and formatted as string, else returns false')
        self.cFile.finishComment()
        self.cFile.appendLine(self.eventsToStringPrototype())
        self.cFile.openBrace()
        self.cFile.appendLine()
        
        self.cFile.appendLine('#error this needs to be completed')
        self.cFile.startSwitch('TBD')
        
        #function for formatting a given even to a string
        fn = lambda var: 'Log{pref}_EventToString_{name}(ptr,str)'.format(pref=var.prefix,name=var.name)
        
        self.createCaseEnumeration(vars = self.events, blankFunction = fn)
        self.cFile.addCase('default')
        self.cFile.returnFromCase(value='false')
        self.cFile.endSwitch()
        self.cFile.appendLine('return true;',comment='Default return case')
        self.cFile.closeBrace()
        
    #func for formatting an individual func to a string
    def eventToStringFunc(self, evt):
        self.cFile.appendLine(comment='Format a {evt} event into a readable string'.format(evt=evt.name))
        self.cFile.appendLine(comment='Auto-increment the **ptr pointer')
        self.cFile.appendLine(evt.toStringPrototype())
        self.cFile.openBrace()
        
        #define vars for this event
        for v in evt.variables:
            #local var for temp storage of data
            self.cFile.appendLine('{fmt} {name};'.format(fmt=v.format,name=v.name),comment="Temporary storage for '{var}' variable".format(var=v.name))
        
        self.cFile.appendLine()
        
        if len(evt.variables) > 0:
            self.cFile.appendLine(comment='Copy the event variables from the buffer')
        
            for v in evt.variables:
                self.copyVarFromBuffer(v,struct='&',pointer='ptr')

            self.cFile.appendLine()
            
        #compile a list of variables associated with this event
        fmts = " ".join([v.getStringCast() for v in evt.variables])
        vars = ", ".join([v.name for v in evt.variables])
        
        self.cFile.appendLine('sprintf(str,"Event: {evt}{sep}{formats}"{comma}{vars});'.format(
                evt = evt.getEnumString(),
                sep = ' -> ' if len(fmts) > 0 else '',
                formats = fmts,
                comma = ', ' if len(vars) > 0 else '',
                vars = vars))
        
        self.cFile.closeBrace()
        self.cFile.appendLine()
        
    #function to determine the size of the selected data
    def getSelectionSizePrototype(self):
        return self.createFunctionPrototype('GetSelectionSize',data=False,returnType='uint16_t')
        
    def getSelectionSizeFunction(self):
        self.cFile.appendLine(comment='Get the total size of the selected variables')
        self.cFile.appendLine(self.getSelectionSizePrototype())
        self.cFile.openBrace()
        
        self.cFile.appendLine('uint16_t size = 0;')
        self.cFile.appendLine()
        
        for var in self.variables:
            self.cFile.appendLine('if ({test})'.format(test=var.getBit('selection')))
            self.cFile.openBrace()
            self.cFile.appendLine('size += {n};'.format(n=var.bytes))
            self.cFile.closeBrace()
            
        self.cFile.appendLine()
        self.cFile.appendLine('return size;')
        
        self.cFile.closeBrace()
        self.cFile.appendLine()
Exemple #30
0
    def _set_website_snippet_static_javascript_file(self, module):
        """
        Function to set the module hook file
        :param module:
        :return:
        """
        cw = CodeWriter()
        cw.cur_indent = 4 * cw.default_dent

        if module.generate_website_snippet_generic_model:
            lst_model_search = (
                module.generate_website_snippet_generic_model.split(";")
            )
            lst_model_id_search = []
            for s_model in lst_model_search:
                model_id = self.env["ir.model"].search(
                    [("model", "=", s_model)]
                )
                if model_id:
                    lst_model_id_search.append(model_id[0])
                else:
                    _logger.warning(f"Model not existing : {s_model}")
            for model_id in lst_model_id_search:
                for field_id in model_id.field_id:
                    if field_id.name not in MAGIC_FIELDS:
                        cw.emit(f'if (data["{field_id.name}"]) {{')
                        with cw.indent():
                            with cw.indent():
                                cw.emit(
                                    f'self.$(".{field_id.name}_value").text(data["{field_id.name}"]);'
                                )
                            cw.emit("}")
        else:
            cw.emit("var data_json = data;")
            cw.emit('var hello = data_json["hello"];')
            cw.emit(f'self.$(".{module.name}_value").text(hello);')

        code = cw.render()

        content = (
            f"odoo.define('{module.name}.animation', function (require)"
            """ {
    'use strict';

    var sAnimation = require('website.content.snippets.animation');

    sAnimation.registry."""
            f"{module.name}"
            """ = sAnimation.Class.extend({
        """
            f"selector: '.o_{module.name}',"
            """

        start: function () {
            var self = this;
            var def = this._rpc({route: '"""
            f"/{module.name}/helloworld"
            """'}).then(function (data) {

                if (data.error) {
                    return;
                }

                if (_.isEmpty(data)) {
                    return;
                }

"""
            + code
            + """    
            });

            return $.when(this._super.apply(this, arguments), def);
        }
    })
});
        """
        )

        file_path = os.path.join(
            "static", "src", "js", f"website.{module.name}.animation.js"
        )
        self.code_generator_data.write_file_str(file_path, content)
 def setUp(self):
     self.cw = CodeWriter()
def main():
    config = get_config()
    cw = CodeWriter()

    mydoc = minidom.parse(config.file)
    if not mydoc:
        print(f"Error, cannot parse {config.file}")
        sys.exit(1)

    cw.emit("from lxml.builder import E")
    cw.emit("from lxml import etree as ET")
    cw.emit("from code_writer import CodeWriter")
    cw.emit("")
    cw.emit('print(\'<?xml version="1.0" encoding="utf-8"?>\')')
    cw.emit('print("<odoo>")')

    lst_function = []
    comment_for_next_group = None

    for odoo in mydoc.getElementsByTagName("odoo"):
        for ir_view_item in odoo.childNodes:
            if ir_view_item.nodeType == Node.ELEMENT_NODE:
                # Show part of xml
                fct_name = "ma_fonction"
                lst_function.append(fct_name)
                cw.emit(f"def {fct_name}():")
                with cw.indent():
                    cw.emit('"""')
                    for line in transform_string_to_list(
                        ir_view_item.toprettyxml()
                    ):
                        cw.emit(line)
                    cw.emit('"""')
                    # Show comment
                    if comment_for_next_group:
                        cw.emit(
                            "print('<!--"
                            f" {comment_for_next_group.strip()} -->')"
                        )
                        comment_for_next_group = None
                    attributes_root = dict(ir_view_item.attributes.items())

                    lst_out = code_writer_deep_xml(ir_view_item)

                    generate_code = GenerateCode()
                    generate_code.generate_code(lst_out)
                    child_root = generate_code.result

                    code = (
                        "root ="
                        f" E.{ir_view_item.tagName}({str(attributes_root)},"
                        f" {child_root})"
                    )

                    for line in code.split("\n"):
                        cw.emit(line)

                    cw.emit("content = ET.tostring(root, pretty_print=True)")
                    cw.emit()
                    cw.emit("cw = CodeWriter()")
                    cw.emit(
                        'for line in content.decode("utf-8").split("\\n"):'
                    )
                    with cw.indent():
                        cw.emit("with cw.indent():")
                        with cw.indent():
                            cw.emit("cw.emit(line)")
                    cw.emit("print(cw.render())")
                cw.emit(f"{fct_name}()")
            elif ir_view_item.nodeType == Node.COMMENT_NODE:
                comment_for_next_group = ir_view_item.data
            else:
                # print(ir_view_item)
                pass

    cw.emit('print("</odoo>")')

    output = cw.render()
    if config.output:
        with open(config.output, "w") as file:
            file.write(output)
    else:
        print(output)
    def generate(self):
        for file_path, lst_info in self.dct_cb.items():
            cw = CodeWriter()
            lst_header = [b for a in lst_info for b in a[0]]
            # Fix divergence import
            try:
                index_pos = lst_header.index("import odoo.http as http")
                lst_header.pop(index_pos)
                lst_header.append("from odoo import http")
            except:
                pass

            set_header = set(lst_header)
            lst_cb = [a[1] for a in lst_info]
            enable_logger = any([a[3] for a in lst_info])
            lst_inherit_class = list(set([a[2] for a in lst_info]))

            if len(lst_inherit_class) > 1:
                _logger.error(
                    "Cannot support multiple class in the same python file:"
                    f" '{lst_inherit_class}', filepath: '{file_path}'")
                continue
            str_inherit_class = lst_inherit_class[0]

            for line in set_header:
                cw.emit(line)

            if enable_logger:
                cw.emit("import logging")
                cw.emit("_logger = logging.getLogger(__name__)")

            cw.emit(
                "class"
                f" {self._module.name.replace('_', ' ').title().replace(' ', '')}Controller({str_inherit_class}):"
            )

            with cw.indent():
                for cb in lst_cb:
                    cb(self._module, cw)

            out = cw.render()

            l_model = out.split("\n")

            self._code_generator_data.write_file_lst_content(
                file_path, l_model)
Exemple #34
0
except IndexError:
    example_usage('improper arguments')

if '.vm' in input:
    if input in os.listdir():
        vm_files = [input]
    else:
        example_usage('file not found')
else:
    if input in os.getcwd():
        vm_files = get_all_VM_files(os.getcwd())
        if len(vm_files) == 0:
            example_usage('no vm files found')
    else:
        try:
            os.chdir(input)
            vm_files = get_all_VM_files(os.getcwd())
            if len(vm_files) == 0:
                example_usage('no vm files in specified directory')
        except FileNotFoundError:
            example_usage('no such directory')

# create a CodeWriter instance
cw = CodeWriter(vm_files, output, boot)

# perform translation
cw.translate()

# close the output of the CodeWriter
cw.close()
def main():

    # If there is an invalid number of arguments the program stops.
    if len(sys.argv) != 2:
        print("ERROR: Invalid number of arguments. Expected: file_name.vm ")
        exit(1)
    # The VM translator accepts directories or vm files to be translated into assembly files.
    elif not os.path.isdir(sys.argv[1]) and sys.argv[1][-3:] != ".vm":
        print("ERROR: Invalid argument. Expected: directory or vm file")
        exit(1)

    # Get the name of the file to be parsed from the arguments.
    input_file = sys.argv[1]

    if os.path.isdir(input_file):
        # Split the file path
        file_path = input_file.split("/")
        if input_file.endswith("/"):
            # Creates the code writer with the given directory
            code_writer = CodeWriter("{}/{}".format(input_file, file_path[-2]))
            read_directory(input_file, code_writer)
            code_writer.close()
        else:
            # Creates the code writer with the given directory
            code_writer = CodeWriter("{}/{}".format(input_file, file_path[-1]))
            read_directory(input_file, code_writer)
            code_writer.close()
    else:
        # Creates the code writer with the input file excluding the .vm part
        code_writer = CodeWriter(input_file[0:-3])
        read_file(input_file, code_writer)
        code_writer.close()
class TestCodeWriter(TestCase):
    def setUp(self):
        self.cw = CodeWriter()

    def process_commands(self, commands):
        for _ in commands:
            command = VMCommand(_)
            command.parse_command()
            self.cw.process_command(command)

    def test_write_push_constant(self):
        """ test push constant [0-9]* """

        # need to update SP, ie RAM[0]
        asm_command = ['@7', 'D=A', '@SP', 'A=M', 'M=D', '@SP', 'M=M+1']

        commands = ['push constant 7']
        self.process_commands(commands)
        self.assertListEqual(asm_command, self.cw.assm)

    def test_write_two_push_constant(self):
        """ push contant [0-9]* twice in a row"""

        asm_command = ['@7', 'D=A', '@SP', 'A=M', 'M=D', '@SP', 'M=M+1']
        command = VMCommand('push constant 7')
        command.parse_command()
        self.cw.process_command(command)
        self.assertEqual(asm_command, self.cw.assm)

        command = VMCommand('push constant 8')
        command.parse_command()
        self.cw.process_command(command)
        asm_command = ['@8', 'D=A', '@SP', 'A=M', 'M=D', '@SP', 'M=M+1']
        self.assertEqual(asm_command, self.cw.assm)

    def test_write_add_command(self):
        """
        test popping top two items off of stack, adding them, and putting
        the result back on the stack
        """

        # put 7 & 8 on the stack to add
        commands = ['push constant 7', 'push constant 8', 'add']
        self.process_commands(commands);

        assm_command = ['@SP', 'A=M-1', 'D=M', '@SP', 'M=M-1', '@SP', 'A=M-1',
                'M=M+D']

        self.assertListEqual(assm_command, self.cw.assm)


    def test_write_arithmetic_eq(self):
        """ test eq """
        commands = ['push constant 20', 'push constant 20', 'eq']
        self.process_commands(commands)

        assm_command = ['@SP', 'A=M-1', 'D=M', '@SP', 'M=M-1', '@SP', 'A=M-1',
                'D=M-D', '@SP', 'M=M-1', '@L%s' % 0, 'D;JEQ', '@L%s' % 1,
                '(L%s)' % 1, '@SP', 'A=M', 'M=0', '@L%s' % 2, '0;JMP', '(L%s)' %
                0, '@SP', 'A=M', 'M=-1', '@L%s' % 2, '0;JMP', '(L%s)' % 2,
                '@SP', 'M=M+1']

        self.assertListEqual(assm_command, self.cw.assm)

    def test_neg(self):
        """ test taking negative of top item on stack """
        commands = ['push constant 10']
        self.process_commands(commands)

        command = VMCommand('neg')
        command.parse_command()
        self.cw.process_command(command)
        assm_command = ['@SP', 'A=M-1', 'MD=-M']
        self.assertListEqual(assm_command, self.cw.assm)


    def test_pop_to_diff_stack(self):
        """ test popping to segment. 0 arg2 """
        # push ten onto global stack
        commands=['push constant 10', 
               'pop local 0' ]
        self.process_commands(commands)

        # pop it off and it goes into local

        assm_command = ['@LCL', 'D=M', '@0', 'D=A+D', '@R5', 'M=D', '@SP',
                'A=M-1', 'D=M', '@R5', 'A=M', 'M=D', '@SP', 'M=M-1']

        self.assertListEqual(assm_command, self.cw.assm)

    def test_pop_non0_to_diff_stack(self):
        """ test pushing to segment. non 0 arg2 """
        # push ten onto global stack
        commands = ['push constant 10',
                    'pop local 8']
        self.process_commands(commands)

        assm_command = ['@LCL', 'D=M', '@8', 'D=A+D', '@R5', 'M=D', '@SP',
                'A=M-1', 'D=M', '@R5', 'A=M', 'M=D', '@SP', 'M=M-1']

        self.assertListEqual(assm_command, self.cw.assm)

    def test_pop_from_segment(self):
        """ test pushing from segment onto """
        prep_commands=['push constant 12',
                       'pop local 1',
                       'push constant 21']
        for _ in prep_commands:
            command = VMCommand(_)
            command.parse_command()

        command = VMCommand('push local 1')
        command.parse_command()
        self.cw.process_command(command)

        assm_command = ['@LCL', 'D=M', '@1', 'A=A+D', 'D=M', '@SP', 'A=M',
                'M=D', '@SP', 'M=M+1']

        self.assertListEqual(assm_command, self.cw.assm)

    def test_pop_from_temp(self):
        """ test popping from TMP segment """
        prep_commands = ['push constant 510']
        for _ in prep_commands:
            command = VMCommand(_)
            command.parse_command()
            self.cw.process_command(command)

        command = VMCommand('pop temp 6')
        command.parse_command()
        self.cw.process_command(command)

        assm_command = ['@SP', 'A=M-1', 'D=M', '@11', 'M=D', '@SP', 'M=M-1']

        self.assertListEqual(assm_command, self.cw.assm)

    def test_push_from_temp(self):
        """ test pushing from TMP segment """
        prep_commands = ['push constant 510',
                         'pop temp 6',
                         'push constant 415']

        for _ in prep_commands:
            command = VMCommand(_)
            command.parse_command()
            self.cw.process_command(command)

        command = VMCommand('push temp 6')
        command.parse_command()
        self.cw.process_command(command)

        assm_command = ['@11', 'D=M', '@SP', 'A=M', 'M=D', '@SP', 'M=M+1']
        self.assertListEqual(assm_command, self.cw.assm)

    def test_push_from_segment(self):
        """ test pushing from segment onto global stack """
        commands = ['push constant 510',
                         'pop local 6',
                         'push local 6']
        self.process_commands(commands)

        assm_command = ['@LCL', 'D=M', '@6', 'A=A+D', 'D=M', '@SP', 'A=M',
            'M=D', '@SP', 'M=M+1']
        self.assertListEqual(assm_command, self.cw.assm)

    def test_pop_from_pointer(self):
        """ test popping to pointer """
        commands = ['push constant 3040', 'pop pointer 0']
        self.process_commands(commands)

        assm_command = ['@SP', 'A=M-1', 'D=M', '@3', 'M=D', '@SP', 'M=M-1']
        self.assertListEqual(assm_command, self.cw.assm)

    def test_push_from_pointer(self):
        """ test pushing to pointer """
        commands = ['push constant 3040', 'pop pointer 0', 'push pointer 0']
        self.process_commands(commands)

        assm_command = ['@3', 'D=M', '@SP', 'A=M', 'M=D', '@SP', 'M=M+1']
        self.assertListEqual(assm_command, self.cw.assm)
Exemple #37
0
def main():
    argument = sys.argv[1]
    if argument.endswith('.vm'):
        asm_filename = argument.replace('.vm', '.asm')
        asm_file = open(asm_filename, 'a')
        code_writer = CodeWriter(asm_file)
        open_vm_file(argument, code_writer)
        code_writer.close()
    else:
        if argument.endswith('/'):
            argument = argument[0:-1]
        foldername = os.path.basename(argument)
        asm_file = open('%s/%s.asm' % (argument, foldername), 'a')
        code_writer = CodeWriter(asm_file)
        code_writer.write_comment('write init')
        code_writer.write_init()
        files = glob.glob('%s/*.vm' % argument)
        for file in files:
            open_vm_file(file, code_writer)
        code_writer.close()
class jackVisitor(jackGrammarVisitor):
    """Clase que hereda del visitor para ir escribiendo en lenguaje de maquina virtual"""

    def __init__(self):
        """Inciializa una tabald e simbolos y un ecritor de codigo junto con variables auxiliares"""
        self.symbolTable = SymbolTable()
        self.contWhile = -1
        self.contIf = -1
        self.nombreClase = ""
        self.kindMetodo = ""
        self.nombreMetodo = ""
        self.vmWriter = CodeWriter()
        self.vmWriter.vm = ""
        self.nArgs = 0

    def visitClasses(self, ctx):
        """Obtiene y guarda el nombre de la clase actualmente compilada"""
        self.nombreClase = ctx.children[1].children[0].getText()
        return self.visitChildren(ctx)

    def visitClassVarDec(self, ctx):
        """Guarda en la tabla de simbolos cada uno de los fields  variables taticas declaradas """
        kind = ctx.children[0].getText()
        tipo = ctx.children[1].children[0].getText()
        i = 2
        while ctx.children[i].getText() != ';': 
            name = ctx.children[i].getText()  
            if name == ',':
                pass
            else:
                self.symbolTable.define(name, tipo, kind)
            i +=1
        return self.visitChildren(ctx)

    def visitTypes(self, ctx):
        return self.visitChildren(ctx)

    def visitSubroutineDec(self, ctx):
        """Inicializa en la tabla de simbolos una subrotina, y en caso de se un metodo agrega this como parametro"""
        self.kindMetodo = ctx.children[0].getText()
        self.nombreMetodo = ctx.children[2].children[0].getText()
        self.symbolTable.startSubroutine()
        if self.kindMetodo == 'method':
            self.symbolTable.define('this', self.nombreMetodo, 'argument')
        return self.visitChildren(ctx)

    def visitParameterList(self, ctx):
        """Agrega a la tabla de simbolos de la subroutina cada uno de los parametros """
        if ctx.getChildCount() > 0:
            tipo = ctx.children[0].children[0].getText()
            nombre = ctx.children[1].children[0].getText()
            self.symbolTable.define(nombre, tipo, 'argument')
            i = 2
            while i < len(ctx.children)-1  and ctx.children[i].getText() != ')':
                tipo = ctx.children[i+1].getText()
                nombre = ctx.children[i+2].getText()
                self.symbolTable.define(nombre, tipo, 'argument')
                i+=3
        return self.visitChildren(ctx)

    def visitSubroutineBody(self, ctx):
        """Despues de contar las variables locales escribe la funcion en 
        maquina virtual y dependiendo del tipo de funcion hace los llamados, push y pop correspondientes"""
        i = 1
        while ctx.children[i].children[0].getText() == "var":
            self.visit(ctx.children[i])
            i += 1
        funcion = self.nombreClase +'.'+ self.nombreMetodo
        numLcl = self.symbolTable.varCount('local')
        self.vmWriter.writeFunction(funcion, numLcl)
        if self.kindMetodo == 'constructor':
            numFields = self.symbolTable.varCount('field')
            self.vmWriter.writePush('constant', numFields)
            self.vmWriter.writeCall('Memory.alloc', 1)
            self.vmWriter.writePop('pointer', 0)
        elif self.kindMetodo == 'method':
            self.vmWriter.writePush('argument', 0)
            self.vmWriter.writePop('pointer', 0)
        while i < ctx.getChildCount():
            self.visit(ctx.children[i])
            i += 1

    def visitVarDec(self, ctx):
        """Inicializa en la tabla de simbolos todas las variables locales de la subrutina para poder escribir la función"""
        tipo = ctx.children[1].children[0].getText()
        nombre = ctx.children[2].getText()
        self.symbolTable.define(nombre, tipo, 'local')
        i = 3
        while ctx.children[i].getText() != ';':
            nombre = ctx.children[i].getText()
            if nombre == ',':
                pass
            else:
                self.symbolTable.define(nombre, tipo, 'local')
            i += 1
        return self.visitChildren(ctx)

    """Llamados en los que no es necesario  escribir codigo de VM"""
    def visitClassName(self, ctx):
        return self.visitChildren(ctx)

    def visitSubroutineName(self, ctx):
        return self.visitChildren(ctx)

    def visitVarName(self, ctx):
        return self.visitChildren(ctx)

    def visitStatements(self, ctx):
        return self.visitChildren(ctx)

    def visitStatement(self, ctx):
        return self.visitChildren(ctx)

    def visitLetStatement(self, ctx): 
        """Realiza los push y pop necesarios para guardar un valor y asignarle una posiicon en memoria"""
        nombre = ctx.children[1].getText()
        tipo = self.symbolTable.kindOf(nombre)
        index = self.symbolTable.indexOf(nombre)
        if tipo  == None:
            tipo = self.symbolTable.kindOf(nombre)
            index = self.symbolTable.indexOf(nombre)
        if ctx.children[2].getText() == '[':
            self.visit(ctx.children[3])
            self.vmWriter.writePush(tipo,index)
            self.vmWriter.writeArithmetic('add')
            self.visit(ctx.children[6]) 
            self.vmWriter.writePop('temp', 0)           
            self.vmWriter.writePop('pointer', 1)
            self.vmWriter.writePush('temp', 0)
            self.vmWriter.writePop('that', 0)
        else:
            self.visit(ctx.children[3])
            self.vmWriter.writePop(tipo,index)

    def visitIfStatement(self, ctx):
        """Escribe los labels necesarios para manejar el flujo del programa de a cuerdo a lo indicado por la expresión"""
        self.contIf += 1
        cont = self.contIf
        self.visit(ctx.children[2])
        self.vmWriter.writeIf('IF_TRUE' + str(cont))
        self.vmWriter.writeGoto('IF_FALSE' + str(cont))
        self.vmWriter.writeLabel('IF_TRUE' + str(cont))
        self.visit(ctx.children[5])
        if ctx.getChildCount() > 7 :
            if str(ctx.children[7]) == 'else':
                self.vmWriter.writeGoto('IF_END' + str(cont))
                self.vmWriter.writeLabel('IF_FALSE' + str(cont))
                self.visit(ctx.children[9])
                self.vmWriter.writeLabel('IF_END' + str(cont))
        else:
            self.vmWriter.writeLabel('IF_FALSE' + str(cont))

    def visitWhileStatement(self, ctx):
        """Similar al if, escribe labels para que el flujo del programa se repita hasta que una condicion no se cumpla"""
        self.contWhile += 1 
        contW = self.contWhile
        self.vmWriter.writeLabel('WHILE_EXP' + str(contW))
        self.visit(ctx.children[2])
        self.vmWriter.writeArithmetic('not')
        self.vmWriter.writeIf('WHILE_END' + str(contW))
        self.visit(ctx.children[5])
        self.vmWriter.writeGoto('WHILE_EXP' + str(contW))
        self.vmWriter.writeLabel('WHILE_END' + str(contW))

    def visitDoStatement(self, ctx):
        """Hago el llamado y posteriormente vuelvo a la función de donde hice el llamado"""
        self.visitChildren(ctx)
        self.vmWriter.writePop('temp', 0)

    def visitReturnStatement(self, ctx):
        """Obtengo valor de retorno, si no hay, el valor de retorno es 0"""
        if ctx.children[1].getText() != ';':
            self.visit(ctx.children[1])
        else:
            self.vmWriter.writePush('constant', 0)
        self.vmWriter.writeReturn()

    def visitExpression(self, ctx):
        """Separo al expresion por partes para irla compilando"""
        self.visit(ctx.children[0])
        i = 2
        while i < ctx.getChildCount():
            self.visit(ctx.children[i])
            self.visit(ctx.children[i-1])
            i +=2

    def visitTerm(self, ctx):
        """Determino el tipo de termino,si es un tipo de dato o un valor de un arreglo, dependiendo de esto obtengo 
        su valor si está en la tabla de simbolos o lo busco en un arreglo o busco el siguiente etrmino con el que opera y lo guardo en memoria"""
        term = ctx.children[0].getText()
        if ctx.getChildCount() == 1:
            if term.isdigit():
                self.vmWriter.writePush('constant', term)
            elif term.startswith('"'):
                term = term.strip('"')
                tam = len(term)
                self.vmWriter.writePush('constant', tam)
                self.vmWriter.writeCall('String.new', 1)
                for char in term:
                    self.vmWriter.writePush('constant', ord(char))
                    self.vmWriter.writeCall('String.appendChar', 2)
            elif term in ['true', 'false', 'null', 'this']:
                self.visitChildren(ctx)
            elif term in self.symbolTable.subrutina.keys():
                tipo = self.symbolTable.kindOf(term)
                index = self.symbolTable.indexOf(term)
                self.vmWriter.writePush(tipo,index)
            elif term in self.symbolTable.clase.keys():
                tipo = self.symbolTable.kindOf(term)
                index = self.symbolTable.indexOf(term)
                self.vmWriter.writePush(tipo,index)
            else:
                self.visitChildren(ctx) 
        else:
            var = ctx.children[0].getText()
            if ctx.children[1].getText() == '[':
                index = self.symbolTable.indexOf(var)
                segment = self.symbolTable.kindOf(var)
                self.visit(ctx.children[2])
                self.vmWriter.writePush(segment, index)
                self.vmWriter.writeArithmetic('add')
                self.vmWriter.writePop('pointer', '1')
                self.vmWriter.writePush('that', '0')
            elif term == '(':
                self.visitChildren(ctx)
            elif term  == '-':
                self.visit(ctx.children[1])
                self.visit(ctx.children[0])
            elif term  == '~':
                self.visit(ctx.children[1])
                self.visit(ctx.children[0])

    def visitSubroutineCall(self, ctx):
        """Ubica la subrutina de acuerdo a la clase en la que se encuentre y escribe en VM el respectivo llamado con su paso de parametros"""
        nombre = ctx.children[0].children[0].getText()
        funcion = nombre
        args = 0
        if ctx.children[1].getText() == '.':    
            nombreSubrutina = ctx.children[2].children[0].getText()
            tipo = self.symbolTable.typeOf(nombre)
            if tipo != None:
                kind = self.symbolTable.kindOf(nombre)
                index = self.symbolTable.indexOf(nombre)
                self.vmWriter.writePush(kind, index)
                funcion = tipo + '.' + nombreSubrutina
                args += 1
            else: 
                funcion = nombre + '.' + nombreSubrutina
        elif ctx.children[1].getText() == '(':
            funcion =  self.nombreClase + '.' + nombre
            args += 1
            self.vmWriter.writePush('pointer', 0)
        self.visitChildren(ctx)
        args = args +self.nArgs
        self.vmWriter.writeCall(funcion, args)

    def visitExpressionList(self, ctx):
        """Evalua cada expresion indivudualmente"""
        self.nArgs = 0
        if ctx.getChildCount() > 0:
            self.nArgs = 1
            self.visit(ctx.children[0])
            i = 2
            while i < ctx.getChildCount():
                self.visit(ctx.children[i])
                self.visit(ctx.children[i-1])
                self.nArgs += 1
                i += 2

    def visitOp(self, ctx):
        """Genera el comando de VM respectivo dependiendo del operador"""
        op = ctx.children[0].getText()
        if op == "+":
            self.vmWriter.writeArithmetic('add')
        elif op == "-":
            self.vmWriter.writeArithmetic('sub')
        elif op == "*":
            self.vmWriter.writeArithmetic('call Math.multiply 2')
        elif op == "/":
            self.vmWriter.writeArithmetic('call Math.divide 2')
        elif op == "&":
            self.vmWriter.writeArithmetic('and')
        elif op == "|":
            self.vmWriter.writeArithmetic('or')
        elif op == ">":
            self.vmWriter.writeArithmetic('gt')
        elif op == "<":
            self.vmWriter.writeArithmetic('lt')
        elif op == "=":
            self.vmWriter.writeArithmetic('eq')
        return self.visitChildren(ctx)

    def visitUnaryop(self, ctx):
        """Determina el comando de VM para cada operaodr unario"""
        op = ctx.children[0].getText()
        if op == "~":
            self.vmWriter.writeArithmetic('not')
        elif op == "-":
            self.vmWriter.writeArithmetic('neg')

    def visitKeywordconstant(self, ctx):
        """Escribe el comando de VM para poder hacer uso de una palabra reservada espcifica"""
        keyword = ctx.children[0].getText()
        if keyword == 'this':
            self.vmWriter.writePush('pointer', 0)
        elif keyword in ['false','null']:
            self.vmWriter.writePush('constant', 0)
        elif keyword == 'true':
            self.vmWriter.writePush('constant', 0)
            self.vmWriter.writeArithmetic('not')
        return self.visitChildren(ctx)

    def crearArchivo(self,path):
        """Abre el archivo .vm donde se escribirán lso comandos de máquina virtual"""
        filewrite = path.split('.jack') #Reemplazo el .jack con .xml si lo tiene 
        filewritef = filewrite[0]+'.vm'  #Sino le agrego el .
        codigoVM = self.vmWriter.vm
        archivo = filewritef
        try:
            file = open(archivo,'w')  #Abro el file en modo escribir
        except FileNotFoundError:
            print('ERROR:No hay directorio existente para escribir')   
            exit(1) 
        file.write(codigoVM)
Exemple #39
0
class VMTranslator:
    def __init__(self, src: str):
        self.asm_file, self.vm_files = self._parse_files(src)
        print("Translate to %s." % self.asm_file)
        self.code_writer = CodeWriter(self.asm_file)

    def translates(self):
        for vm_file in self.vm_files:
            self._translate(vm_file)

    def _parse_files(self, file_path: str) -> (str, list):
        if not os.path.exists(file_path):
            raise IOError("No such file or directory.")

        if os.path.isfile(file_path) and file_path.endswith(VM_EXT):
            asm_file = file_path.replace(VM_EXT, ASM_EXT)
            vm_files = [file_path]

        elif os.path.isdir(file_path):
            dir_path = file_path[:-1] if file_path[-1] == "/" else file_path
            asm_file = dir_path + "/" + os.path.basename(dir_path) + ASM_EXT
            vm_files = self._find_all_files_with_ext(dir_path, "vm")
        else:
            raise IOError("No such file or directory.")

        return asm_file, vm_files

    def _find_all_files_with_ext(self, dir_path: str, ext: str) -> list:
        ext_files = []
        suffix = os.extsep + ext.lower()
        for cur_dir, _, files in os.walk(dir_path):
            for file in files:
                if file.lower().endswith(suffix):
                    ext_files.append(os.path.join(cur_dir, file))
        return ext_files

    def _translate(self, vm_file: str):
        parser = Parser(vm_file)
        self.code_writer.set_filename(vm_file)
        self.code_writer.write("// ----------  %s ----------" %
                               self.code_writer.current_vm_file)

        while parser.next_line():
            self.code_writer.write("// " + parser.command_line())

            if parser.command_type() == "C_ARITHMETIC":
                self.code_writer.write_arithmetic(parser.argn(0))
            elif parser.command_type() == "C_PUSH":
                self.code_writer.write_push(parser.argn(1), parser.argn(2))
            elif parser.command_type() == "C_POP":
                self.code_writer.write_pop(parser.argn(1), parser.argn(2))
            elif parser.command_type() == "C_LABEL":
                self.code_writer.write_label(parser.argn(1))
            elif parser.command_type() == "C_GOTO":
                self.code_writer.write_goto(parser.argn(1))
            elif parser.command_type() == "C_IF_GOTO":
                self.code_writer.write_if_goto(parser.argn(1))
            elif parser.command_type() == "C_FUNCTION":
                self.code_writer.write_function(parser.argn(1),
                                                int(parser.argn(2)))
            elif parser.command_type() == "C_CALL":
                self.code_writer.write_call(parser.argn(1),
                                            int(parser.argn(2)))
            elif parser.command_type() == "C_RETURN":
                self.code_writer.write_return()

            self.code_writer.write("")  # empty line
        self.code_writer.write("// ------------------------------\n")
Exemple #40
0
    "pointer": MemorySegType.M_POINTER,
    "temp": MemorySegType.M_TEMP
}

if __name__ == "__main__":

    if len(sys.argv) != 2:
        print(f"Usage: {sys.argv[0]} <{sys.argv[1]}>")

    files = []
    if sys.argv[1].endswith('.vm'):
        files.append(sys.argv[1])
    elif os.path.isdir(sys.argv[1]):
        files.extend(glob.glob("*.vm"))

    cw = CodeWriter(sys.argv[1].strip(".vm") + ".asm")

    print(f"Creating {sys.argv[1].strip('.vm') + '.asm'} ...")

    for f in files:
        p = Parser(f)
        cw.file_name = f
        while p.advance():
            if p.command_type == CommandType.C_ARITHMETIC:
                cw.write_arithmetic(p.arg1())
            elif p.command_type == CommandType.C_PUSH:
                cw.write_push_pop(CommandType.C_PUSH, segment_map[p.arg1()],
                                  p.arg2())
            elif p.command_type == CommandType.C_POP:
                cw.write_push_pop(CommandType.C_POP, segment_map[p.arg1()],
                                  p.arg2())
    def generate_python_init_file(self, cg_module):
        for component, lst_module in self._dct_import_dir.items():
            init_path = os.path.join(component, "__init__.py")
            if not component:
                lst_module = [a for a in self._dct_import_dir.keys() if a]

            lst_module.sort()

            cw = CodeWriter()

            if cg_module.license == "AGPL-3":
                cw.emit("# License AGPL-3.0 or later"
                        " (https://www.gnu.org/licenses/agpl)")
                cw.emit()
            elif cg_module.license == "LGPL-3":
                cw.emit("# License LGPL-3.0 or later"
                        " (https://www.gnu.org/licenses/lgpl)")
                cw.emit()
            else:
                _logger.warning(f"License {cg_module.license} not supported.")

            if component:
                for module in lst_module:
                    cw.emit(f"from . import {module}")
            elif lst_module:
                cw.emit(f"from . import {', '.join(lst_module)}")
            for extra_import in self._dct_extra_module_init_path.get(
                    component, []):
                cw.emit(extra_import)
            self.write_file_str(init_path, cw.render())
Exemple #42
0
 def __init__(self, src: str):
     self.asm_file, self.vm_files = self._parse_files(src)
     print("Translate to %s." % self.asm_file)
     self.code_writer = CodeWriter(self.asm_file)
Exemple #43
0
from os import listdir
from parser import Parser
from code_writer import CodeWriter

# TODO: make this command line arguments
FILENAME='StaticsTest'
BASE = '/Users/plum/Desktop/codes/nand2tetris/projects/08/FunctionCalls/StaticsTest/'
READ_ADDRESS = '{0}'.format(BASE)
WRITE_ADDRESS = '{0}{1}.asm'.format(BASE, FILENAME)

if __name__ == '__main__':
    c = CodeWriter(WRITE_ADDRESS)

    files = [f for f in listdir(READ_ADDRESS) if f.find('.vm') != -1]
    sys_init = files.index('Sys.vm')
    rest = [f for f in files if files.index(f) != sys_init]
    c.write_init()
    for filename in [files[sys_init]] + rest: #  order matters
        # only parse .vm files
        if filename.find('.vm') != -1:
            c.set_filename(filename)
            p = Parser(BASE + filename)
            while p.has_more_lines():
                p.advance()
                command = p.command_type()
                arg_1 = p.arg_1()
                arg_2 = p.arg_2()
                if command in ['C_PUSH', 'C_POP']:
                    c.write_push_pop(command, arg_1, arg_2)

                if command == 'C_ARITHMETIC':
Exemple #44
0
import os
import sys
from parser import Parser
from code_writer import CodeWriter

vm_file = sys.argv[1]

writer = CodeWriter(vm_file + '.asm')

path = ''
if os.path.isdir(vm_file):
    path = vm_file
    vm_files = os.listdir(vm_file)
else:
    vm_files = [vm_file]

for vm_file in vm_files:
    print 'parsing:', vm_file
    with open(os.path.join(path, vm_file)) as f:
        writer.set_filename(vm_file.split('.')[0])
        parser = Parser(f, writer)
        for instr in parser.parse():
            print instr