def _second_pass(input_fname, symbol_table, output_fname): """Go through each line of assembly code and generate machine code. Arguments input_fname (string) - Name of the input file containing assembly code. symbol_table (SymbolTable) - Symbol table. output_fname (string) - Output file name of a file to write machine code to. """ # Variable symbols start at RAM address 16. ram_address = 16 fout = open(output_fname, "w") parser = Parser(input_fname) while parser.has_more_commands(): parser.advance() if parser.command_type() == Parser.A_COMMAND: symbol = parser.symbol() try: # If the symbol is a decimal number convert it to a binary string. fout.write("0" + Code.to_binary(int(symbol)) + "\n") except ValueError: # The symbol isn't a decimal number thus it must either be in the symbol table or it needs to be # assigned a value. if not symbol_table.contains(symbol): symbol_table.add_entry(symbol, ram_address) ram_address += 1 fout.write("0" + Code.to_binary(symbol_table.get_address(symbol)) + "\n") elif parser.command_type() == Parser.C_COMMAND: fout.write("111" + Code.comp(parser.comp()) + Code.dest(parser.dest()) + Code.jmp(parser.jmp()) + "\n") # Ignore L_COMMAND, they have been looked at in the first pass. fout.close()
def comp(self): """ Returns the comp menomonic in the current C_COMMAND (28 possibilities) Should be called only when commandType() is C_COMMAND return string """ if '=' in self.current_command: c = self.current_command.split('=')[1] elif ';' in self.current_command: c = self.current_command.split(';')[0] code = Code() self.current_comp, self.current_a = code.comp(c)
def assemble(asm_file): parser = Parser(asm_file) fp_out = open("{}.hack".format(asm_file), "w") while (parser.hasMoreCommands()): parser.advance() if parser.commandType() == Parser.L_CMD: continue; if parser.commandType() == Parser.A_CMD: out_line = "0{:015b}".format(int(parser.symbol())) else: comp = Code.comp(parser.comp()) dest = Code.dest(parser.dest()) jump = Code.jump(parser.jump()) out_line = "111%s%s%s" % (comp, dest, jump) fp_out.write("{}\n".format(out_line))
def jump(self): """ Returns the jump mnemonic in the current C_COMMAND (8 possibilities) Should be called only when commandType() is C_COMMAND returns string """ # equal: 000 jump if ';' in self.current_command: j = self.current_command.split(';')[1] elif '=' in self.current_command: j='null' else: j = None code = Code() self.current_jump = code.jump(j)
def dest(self): """ returns the dest mnemonic in the current C_COMMAND (8 possibilities). Should be called only when AssmCommandType() is C_COMMAND returns string """ # semicolon: 000 dest if '=' in self.current_command: d = self.current_command.split('=')[0] else: d='null' code = Code() self.current_dest = code.dest(d)
def main(): filename = os.path.join(os.getcwd(), Util.getCommandLineArg(1)) parser = Parser(filename) hack_filename = filename.replace('asm', 'hack') hack_file = open(hack_filename, 'w') ann_filename = filename.replace('asm', 'ann') ann_file = open(ann_filename, 'w') while parser.has_more_commands(): parser.advance() machine_command = '' if parser.command_type() is 'A_COMMAND': machine_command = '{0:016b}\n'.format(int(parser.symbol())) hack_file.write(machine_command) elif parser.command_type() is 'C_COMMAND': dest = Code.dest(parser.dest()) comp = Code.comp(parser.comp()) jump = Code.jump(parser.jump()) machine_command = '111{0}{1}{2}\n'.format(comp, dest, jump) hack_file.write(machine_command) # elif parser.command_type() is 'L_COMMAND': # parser.symbol() assembly = parser.original_command().strip() mc = machine_command.strip() annotated_machine = '{} {} {} {}'.format(mc[0:4], mc[4:8], mc[8:12], mc[12:16]) annotated_command = '{:<39} // {:<11} {}\n'.format(assembly, parser.command, annotated_machine) ann_file.write(annotated_command) hack_file.close() ann_file.close()
def _GenerateCreateCallbackArguments(self, function_scope, callback): """Generate all functions to create Value parameters for a callback. E.g for function "Bar", generate Bar::Results::Create E.g for event "Baz", generate Baz::Create function_scope: the function scope path, e.g. Foo::Bar for the function Foo::Bar::Baz(). May be None if there is no function scope. callback: the Function object we are creating callback arguments for. """ c = Code() params = callback.params c.Concat(self._GeneratePropertyFunctions(function_scope, params)) (c.Sblock('scoped_ptr<base::ListValue> %(function_scope)s' 'Create(%(declaration_list)s) {').Append( 'scoped_ptr<base::ListValue> create_results(' 'new base::ListValue());')) declaration_list = [] for param in params: declaration_list.append( cpp_util.GetParameterDeclaration( param, self._type_helper.GetCppType(param.type_))) c.Append('create_results->Append(%s);' % self._CreateValueFromType(param.type_, param.unix_name)) c.Append('return create_results.Pass();') c.Eblock('}') c.Substitute({ 'function_scope': ('%s::' % function_scope) if function_scope else '', 'declaration_list': ', '.join(declaration_list), 'param_names': ', '.join(param.unix_name for param in params) }) return c
def _GeneratePropertyStructures(self, props): """Generate the structures required by a property such as OBJECT classes and enums. """ c = Code() for prop in props: if prop.type_ == PropertyType.OBJECT: c.Concat(self._GenerateType(prop)) c.Append() elif prop.type_ == PropertyType.CHOICES: c.Concat(self._GenerateEnumDeclaration( self._cpp_type_generator.GetChoicesEnumType(prop), prop, [choice.type_.name for choice in prop.choices.values()])) c.Concat(self._GeneratePropertyStructures(prop.choices.values())) elif prop.type_ == PropertyType.ENUM: enum_name = self._cpp_type_generator.GetType(prop) c.Concat(self._GenerateEnumDeclaration( enum_name, prop, prop.enum_values)) c.Append('static scoped_ptr<Value> CreateEnumValue(%s %s);' % (enum_name, prop.unix_name)) return c
def _parse_c_instruction(self, instruction): # Maybe split instruction into 3 parts. # Use a Code class code = Code() parsed = "" if (len(instruction) == 1): # Handle ALU instruction mnemonics = instruction[0].split("=") parsed += code.comp(mnemonics[1]) parsed += code.dest(mnemonics[0]) parsed += "000" else: parsed += code.comp(instruction[0]) parsed += "000" parsed += code.jump(instruction[1]) return parsed
def _GenerateChoiceTypeToValue(self, cpp_namespace, type_): """Generates a function that serializes a choice-representing type into a base::Value. """ c = Code() c.Sblock('scoped_ptr<base::Value> %s::ToValue() const {' % cpp_namespace) c.Append('scoped_ptr<base::Value> result;') for choice in type_.choices: choice_var = 'as_%s' % choice.unix_name (c.Sblock('if (%s) {' % choice_var).Append( 'DCHECK(!result) << "Cannot set multiple choices for %s";' % type_.unix_name).Append( 'result.reset(%s);' % self._CreateValueFromType( choice, '*%s' % choice_var)).Eblock('}')) (c.Append('DCHECK(result) << "Must set at least one choice for %s";' % type_.unix_name).Append('return result.Pass();').Eblock('}')) return c
def Generate(self): """Generates a Code object with the schema for the entire namespace. """ c = Code() (c.Append(LICENSE) .Append() .Append('/** @fileoverview Externs generated from namespace: %s */' % self._namespace.name) .Append()) c.Cblock(self._GenerateNamespaceObject()) for js_type in self._namespace.types.values(): c.Cblock(self._GenerateType(js_type)) for function in self._namespace.functions.values(): c.Cblock(self._GenerateFunction(function)) for event in self._namespace.events.values(): c.Cblock(self._GenerateEvent(event)) return c
def _GenerateType(self, cpp_namespace, type_): """Generates the function definitions for a type. """ classname = cpp_util.Classname(type_.name) c = Code() if type_.functions: # Types with functions are not instantiable in C++ because they are # handled in pure Javascript and hence have no properties or # additionalProperties. if type_.properties: raise NotImplementedError('\n'.join(model.GetModelHierarchy(type_)) + '\nCannot generate both functions and properties on a type') for function in type_.functions.values(): (c.Concat( self._GenerateFunction( cpp_namespace + '::' + cpp_util.Classname(function.name), function)) .Append() ) elif type_.type_ == PropertyType.OBJECT: (c.Concat(self._GeneratePropertyFunctions( cpp_namespace, type_.properties.values())) .Sblock('%(namespace)s::%(classname)s()') .Concat(self._GenerateInitializersAndBody(type_)) .Eblock('%(namespace)s::~%(classname)s() {}') .Append() ) if type_.from_json: (c.Concat(self._GenerateTypePopulate(cpp_namespace, type_)) .Append() ) if type_.from_client: (c.Concat(self._GenerateTypeToValue(cpp_namespace, type_)) .Append() ) c.Substitute({'classname': classname, 'namespace': cpp_namespace}) return c
def setUp(self): self.aars_space = AARS_Space(range(2), np.diag([1] * 2), get_uniform_mutation_matrix(2, .01)) # mu is zero so that there is only 3 potential codes available # and so the code is forced to handle mutants with a fixation # probability of zero. self.trna_space = TRNA_Space(range(2), np.diag([1] * 2), np.diag([1] * 2), get_uniform_mutation_matrix(2, .01)) pchem_vals = [.30, .70] self.site_types = Ring_Site_Types(.05, zip(range(2), pchem_vals), zip(range(2), pchem_vals), [1] * 2) message_mutation_matrix = get_uniform_mutation_matrix(2, .01) #print message_mutation_matrix.shape #print np.matrix([[.5, .5], [.5, .5]]).shape self.code = Code([1], [1], self.trna_space, self.aars_space) rng = Random() rng.seed(42) self.evolver = Evolver(self.code, self.site_types, message_mutation_matrix, 100, rng)
def _GenerateInitializersAndBody(self, type_): items = [] for prop in type_.properties.values(): if prop.optional: continue t = prop.type_ if t == PropertyType.INTEGER: items.append('%s(0)' % prop.unix_name) elif t == PropertyType.DOUBLE: items.append('%s(0.0)' % prop.unix_name) elif t == PropertyType.BOOLEAN: items.append('%s(false)' % prop.unix_name) elif t == PropertyType.BINARY: items.append('%s(NULL)' % prop.unix_name) elif (t == PropertyType.ADDITIONAL_PROPERTIES or t == PropertyType.ANY or t == PropertyType.ARRAY or t == PropertyType.CHOICES or t == PropertyType.ENUM or t == PropertyType.OBJECT or t == PropertyType.REF or t == PropertyType.STRING): # TODO(miket): It would be nice to initialize CHOICES and ENUM, but we # don't presently have the semantics to indicate which one of a set # should be the default. continue else: sys.exit("Unhandled PropertyType: %s" % t) if items: s = ': %s' % (', '.join(items)) else: s = '' s = s + ' {}' return Code().Append(s)
def get_possible_codes(self): if self._possible_codes is None: num_aarss = self._aars_mutation_matrix.shape[0] num_trnas = self._trna_mutation_matrix.shape[0] encodable_trnas = len(self._initial_code.trnas) encodable_aarss = len(self._initial_code.aarss) aarss_prod = list(product(range(num_aarss), repeat=encodable_aarss)) trnas_prod = list(product(range(num_trnas), repeat=encodable_trnas)) self._possible_codes = [ Code(trnas, aarss, self._initial_code._trna_space, self._initial_code._aars_space) for trnas in trnas_prod for aarss in aarss_prod ] potential_codes = (num_trnas**encodable_trnas) * (num_aarss** encodable_aarss) assert len(self._possible_codes) == potential_codes, \ "An incorrect number of potential codes was generated {} {}.".format(potential_codes, len(self._possible_codes)) return self._possible_codes
def eval(self, code, *args): """Evaluate a JavaScript expression on the Mongo server. Useful if you need to touch a lot of data lightly; in such a scenario the network transfer of the data could be a bottleneck. The `code` argument must be a JavaScript function. Additional positional arguments will be passed to that function when it is run on the server. Raises TypeError if `code` is not an instance of (str, unicode, `Code`). Raises OperationFailure if the eval fails. Returns the result of the evaluation. :Parameters: - `code`: string representation of JavaScript code to be evaluated - `args` (optional): additional positional arguments are passed to the `code` being evaluated """ if not isinstance(code, Code): code = Code(code) command = SON([("$eval", code), ("args", list(args))]) result = self._command(command) return result.get("retval", None)
def _GenerateInitializersAndBody(self, type_): items = [] for prop in type_.properties.values(): if prop.optional: continue t = prop.type_ if t.property_type == PropertyType.INTEGER: items.append('%s(0)' % prop.unix_name) elif t.property_type == PropertyType.DOUBLE: items.append('%s(0.0)' % prop.unix_name) elif t.property_type == PropertyType.BOOLEAN: items.append('%s(false)' % prop.unix_name) elif (t.property_type == PropertyType.ANY or t.property_type == PropertyType.ARRAY or t.property_type == PropertyType.BINARY or # mapped to std::string t.property_type == PropertyType.CHOICES or t.property_type == PropertyType.ENUM or t.property_type == PropertyType.OBJECT or t.property_type == PropertyType.FUNCTION or t.property_type == PropertyType.REF or t.property_type == PropertyType.STRING): # TODO(miket): It would be nice to initialize CHOICES and ENUM, but we # don't presently have the semantics to indicate which one of a set # should be the default. continue else: raise TypeError(t) if items: s = ': %s' % (', '.join(items)) else: s = '' s = s + ' {}' return Code().Append(s)
def _GenerateEnumToString(self, cpp_namespace, type_): """Generates ToString() which gets the string representation of an enum. """ c = Code() classname = cpp_util.Classname(schema_util.StripNamespace(type_.name)) if cpp_namespace is not None: c.Append('// static') maybe_namespace = '' if cpp_namespace is None else '%s::' % cpp_namespace c.Sblock('std::string %sToString(%s enum_param) {' % (maybe_namespace, classname)) c.Sblock('switch (enum_param) {') for enum_value in self._type_helper.FollowRef(type_).enum_values: (c.Append( 'case %s: ' % self._type_helper.GetEnumValue(type_, enum_value)).Append( ' return "%s";' % enum_value.name)) (c.Append( 'case %s:' % self._type_helper.GetEnumNoneValue(type_)).Append(' return "";'). Eblock('}').Append('NOTREACHED();').Append('return "";').Eblock('}')) return c
def _GenerateParamsCheck(self, function, var): """Generates a check for the correct number of arguments when creating Params. """ c = Code() num_required = 0 for param in function.params: if not param.optional: num_required += 1 if num_required == len(function.params): c.Append('if (%(var)s.GetSize() != %(total)d)') elif not num_required: c.Append('if (%(var)s.GetSize() > %(total)d)') else: c.Append('if (%(var)s.GetSize() < %(required)d' ' || %(var)s.GetSize() > %(total)d)') c.Append(' return scoped_ptr<Params>();') c.Substitute({ 'var': var, 'required': num_required, 'total': len(function.params), }) return c
def Generate(self): """Generates a Code object for features. """ c = Code() (c.Append(cpp_util.CHROMIUM_LICENSE).Append().Append( cpp_util.GENERATED_FEATURE_MESSAGE % self._source_file).Append()) ifndef_name = cpp_util.GenerateIfndefName(self._source_file_filename, self._class_name) (c.Append('#ifndef %s' % ifndef_name).Append('#define %s' % ifndef_name).Append()) (c.Append('#include <map>').Append( '#include <string>').Append().Concat( cpp_util.OpenNamespace(self._namespace)).Append()) (c.Append('class %s {' % self._class_name).Append(' public:').Sblock().Concat( self._GeneratePublicBody()).Eblock().Append(' private:'). Sblock().Concat( self._GeneratePrivateBody()).Eblock('};').Append().Cblock( cpp_util.CloseNamespace(self._namespace))) (c.Append('#endif // %s' % ifndef_name).Append()) return c
def _GenerateFields(self, props): """Generates the field declarations when declaring a type. """ c = Code() # Generate the enums needed for any fields with "choices" for prop in props: if prop.type_ == PropertyType.CHOICES: enum_name = self._cpp_type_generator.GetChoicesEnumType(prop) c.Append('%s %s_type;' % (enum_name, prop.unix_name)) c.Append() for prop in self._cpp_type_generator.ExpandParams(props): if prop.description: c.Comment(prop.description) (c.Append('%s %s;' % ( self._cpp_type_generator.GetCompiledType(prop, wrap_optional=True), prop.unix_name)) .Append() ) return c
def _GenerateCreateCallbackArguments(self, function, generate_to_json=False): """Generates functions for passing paramaters to a callback. """ c = Code() params = function.params c.Concat(self._GeneratePropertyStructures(params)) param_lists = self._cpp_type_generator.GetAllPossibleParameterLists(params) for param_list in param_lists: declaration_list = [] for param in param_list: if param.description: c.Comment(param.description) declaration_list.append('const %s' % cpp_util.GetParameterDeclaration( param, self._cpp_type_generator.GetCompiledType(param))) c.Append('scoped_ptr<base::ListValue> Create(%s);' % ', '.join(declaration_list)) if generate_to_json: c.Append('std::string ToJson(%s);' % ', '.join(declaration_list)) return c
def _GenerateChoiceTypeToValue(self, cpp_namespace, type_): """Generates a function that serializes a choice-representing type into a base::Value. """ c = Code() c.Sblock('std::unique_ptr<base::Value> %s::ToValue() const {' % cpp_namespace) c.Append('std::unique_ptr<base::Value> result;') for choice in type_.choices: choice_var = 'as_%s' % choice.unix_name # Enums cannot be wrapped with scoped_ptr, but the XXX_NONE enum value # is equal to 0. (c.Sblock('if (%s) {' % choice_var) .Append('DCHECK(!result) << "Cannot set multiple choices for %s";' % type_.unix_name).Cblock(self._CreateValueFromType( 'result = %s;', choice.name, choice, choice_var, True)) .Eblock('}')) (c.Append('DCHECK(result) << "Must set at least one choice for %s";' % type_.unix_name).Append('return result;').Eblock('}')) return c
def _GenerateTypePopulateProperty(self, prop, src, dst): """Generate the code to populate a single property in a type. src: DictionaryValue* dst: Type* """ c = Code() value_var = prop.unix_name + '_value' c.Append('Value* %(value_var)s = NULL;') if prop.optional: (c.Sblock( 'if (%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s)) {' ).Concat( self._GeneratePopulatePropertyFromValue( prop, value_var, dst, 'false')).Eblock('}')) else: (c.Append( 'if (!%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s))' ).Append(' return false;').Concat( self._GeneratePopulatePropertyFromValue( prop, value_var, dst, 'false'))) c.Append() c.Substitute({'value_var': value_var, 'key': prop.name, 'src': src}) return c
def _GenerateFunction(self, cpp_namespace, function): """Generates the definitions for function structs. """ c = Code() # Params::Populate function if function.params: c.Concat( self._GeneratePropertyFunctions(cpp_namespace + '::Params', function.params)) (c.Append('%(cpp_namespace)s::Params::Params() {}').Append( '%(cpp_namespace)s::Params::~Params() {}').Append().Concat( self._GenerateFunctionParamsCreate(cpp_namespace, function)).Append()) # Result::Create function if function.callback: c.Concat( self._GenerateFunctionResultCreate(cpp_namespace, function)) c.Substitute({'cpp_namespace': cpp_namespace}) return c
def _GenerateEnumFromString(self, cpp_namespace, type_): """Generates FromClassNameString() which gets an enum from its string representation. """ c = Code() classname = cpp_util.Classname(schema_util.StripNamespace(type_.name)) if cpp_namespace is not None: c.Append('// static') maybe_namespace = '' if cpp_namespace is None else '%s::' % cpp_namespace c.Sblock('%s%s %sParse%s(const std::string& enum_string) {' % (maybe_namespace, classname, maybe_namespace, classname)) for _, enum_value in enumerate( self._type_helper.FollowRef(type_).enum_values): # This is broken up into all ifs with no else ifs because we get # "fatal error C1061: compiler limit : blocks nested too deeply" # on Windows. (c.Append('if (enum_string == "%s")' % enum_value.name).Append( ' return %s;' % self._type_helper.GetEnumValue(type_, enum_value))) (c.Append('return %s;' % self._type_helper.GetEnumNoneValue(type_)).Eblock('}')) return c
def __init__(self, win): Code.__init__(self, win) self.__line_to_addr = None self.__addr_to_line = None
def testAppend(self): c = Code() c.Append('line') self.assertEquals('line', c.Render())
def _GenerateType(self, cpp_namespace, type_): """Generates the function definitions for a type. """ classname = cpp_util.Classname(schema_util.StripNamespace(type_.name)) c = Code() if type_.functions: # Wrap functions within types in the type's namespace. (c.Append('namespace %s {' % classname) .Append()) for function in type_.functions.values(): c.Cblock(self._GenerateFunction(function)) c.Append('} // namespace %s' % classname) elif type_.property_type == PropertyType.ARRAY: c.Cblock(self._GenerateType(cpp_namespace, type_.item_type)) elif type_.property_type in (PropertyType.CHOICES, PropertyType.OBJECT): if cpp_namespace is None: classname_in_namespace = classname else: classname_in_namespace = '%s::%s' % (cpp_namespace, classname) if type_.property_type == PropertyType.OBJECT: c.Cblock(self._GeneratePropertyFunctions(classname_in_namespace, type_.properties.values())) else: c.Cblock(self._GenerateTypes(classname_in_namespace, type_.choices)) (c.Append('%s::%s()' % (classname_in_namespace, classname)) .Cblock(self._GenerateInitializersAndBody(type_)) .Append('%s::~%s() {}' % (classname_in_namespace, classname)) .Append() ) if type_.origin.from_json: c.Cblock(self._GenerateTypePopulate(classname_in_namespace, type_)) if cpp_namespace is None: # only generate for top-level types c.Cblock(self._GenerateTypeFromValue(classname_in_namespace, type_)) if type_.origin.from_client: c.Cblock(self._GenerateTypeToValue(classname_in_namespace, type_)) elif type_.property_type == PropertyType.ENUM: (c.Cblock(self._GenerateEnumToString(cpp_namespace, type_)) .Cblock(self._GenerateEnumFromString(cpp_namespace, type_)) ) return c
def _GenerateFunctionParamsCreate(self, function): """Generate function to create an instance of Params. The generated function takes a base::ListValue of arguments. E.g for function "Bar", generate Bar::Params::Create() """ c = Code() (c.Append('// static') .Sblock('scoped_ptr<Params> Params::Create(%s) {' % self._GenerateParams( ['const base::ListValue& args'])) ) if self._generate_error_messages: c.Append('DCHECK(error);') (c.Concat(self._GenerateParamsCheck(function, 'args')) .Append('scoped_ptr<Params> params(new Params());') ) for param in function.params: c.Concat(self._InitializePropertyToDefault(param, 'params')) for i, param in enumerate(function.params): # Any failure will cause this function to return. If any argument is # incorrect or missing, those following it are not processed. Note that # for optional arguments, we allow missing arguments and proceed because # there may be other arguments following it. failure_value = 'scoped_ptr<Params>()' c.Append() value_var = param.unix_name + '_value' (c.Append('const base::Value* %(value_var)s = NULL;') .Append('if (args.Get(%(i)s, &%(value_var)s) &&') .Sblock(' !%(value_var)s->IsType(base::Value::TYPE_NULL)) {') .Concat(self._GeneratePopulatePropertyFromValue( param, value_var, 'params', failure_value)) .Eblock('}') ) if not param.optional: (c.Sblock('else {') .Concat(self._GenerateError('"\'%%(key)s\' is required"')) .Append('return %s;' % failure_value) .Eblock('}')) c.Substitute({'value_var': value_var, 'i': i, 'key': param.name}) (c.Append() .Append('return params.Pass();') .Eblock('}') .Append() ) return c
if re.search('.*\.asm',in_file) == None: print('incorrect file name!') sys.exit(0) #If user passed in option to allow extra functionality if len(sys.argv) == 3: temp_op=sys.argv[2] if '-x' in temp_op: extended_op=True #Strips .asm of the end and adds .hack temp_out=re.search('(.*)(\.asm)',in_file) out_file+=temp_out.group(1)+'.hack' par = Parser(in_file,extended_op) code = Code() symT = SymbolTable() #------------------------------------------------------------------------------ # Main #------------------------------------------------------------------------------ #Builds the symbol table while par.hasMoreCommands(): par.advance() cType = par.commandType() #if the command type is a label if re.search('L_COMMAND',cType) is not None: temp_L = re.search('(.*)(;)(.*)',par.symbol()) symT.addEntry(temp_L.group(1),int(temp_L.group(3)),False)
def testSubstituteErrors(self): # No unnamed placeholders allowed when substitute is run c = Code() c.Append('%s %s') self.assertRaises(TypeError, c.Substitute, ('var1', 'one')) c = Code() c.Append('%s %(var1)s') self.assertRaises(TypeError, c.Substitute, {'var1': 'one'}) c = Code() c.Append('%s %(var1)s') self.assertRaises(TypeError, c.Substitute, {'var1': 'one'}) c = Code() c.Append('%(var1)s') self.assertRaises(KeyError, c.Substitute, {'clearlynotvar1': 'one'})
class Mysha: def __init__(self, x, y, left, kind): global game game = Base.game self.x = x self.y = y self.jx = 0 self.jy = 0 self.frame = 0 self.left = left self.jump = False self.ground = True self.dead = False self.rest = 0 self.fy = 0 self.coins = 0 self.code = None self.kind = kind self.executing = 0 self.command = None self.command_x = 0 def move(self): self.frame += 1 if self.frame & 3 == 0: dx = -4 if self.left else +4 if self.check(-20 if self.left else 20, 0) not in wall: self.x += dx def turn(self): self.left = not self.left tx = self.x // 32 dx = self.x - tx * 32 if self.check(-dx - 1, 0) in wall: self.x = tx * 32 + 20 elif self.check(32 - dx, 0) == wall: self.x = tx * 32 + 12 def input(self, k): if self.jy == 0: self.jx = 0 if k.right: if not self.rest: if self.left: self.turn() else: self.move() if self.jy == 0: self.jx = 3 if k.left: if not self.rest: if self.left: self.move() else: self.turn() if self.jy == 0: self.jx = -3 if k.up and not self.jump: if not self.rest and self.check(0, 1) in wall: if self.jx: self.jy = 8 else: self.jy = 12 def tick(self): if self.rest: self.rest -= 1 if self.jy > 0: if self.check(-32 if self.left else 32, 0) not in wall: self.x += self.jx self.y -= self.jy self.jy -= 1 self.jump = True self.ground = False if self.jy == 0: gravity = 1 + self.fy for i in range(gravity): ty = self.y // 32 if self.y - ty * 32 != 31: self.y += 1 if self.fy < 8: self.fy += 1 else: if self.check(0, 1) not in wall: if self.ground: tx = self.x // 32 if self.left: self.x -= 8 else: self.x += 8 self.ground = False self.y += 1 else: grab = False if self.left: if self.check(-32, 8) in wall and\ self.check(-32, 0) not in wall: grab = True else: if self.check(32, 8) in wall and\ self.check(32, 0) not in wall: grab = True if grab: self.y = ty * 32 + 31 tx = self.x // 32 if self.left: self.x = tx * 32 - 1 else: self.x = tx * 32 + 32 else: self.y += 1 else: if self.fy > 0: ty = self.y // 32 if self.y - ty * 32 < 16: self.y = ty * 32 - 1 self.fy = 0 self.ground = True if self.jump: self.jump = False self.rest = 15 c = self.check(0, 0) if c == "X": self.dead = True al_play_sample(game.ohnosound, 1, 0, 1, ALLEGRO_PLAYMODE_ONCE, byref(ALLEGRO_SAMPLE_ID())) elif c == "*": self.coins += 1 self.put(0, 0, " ") al_play_sample(game.yaysound, 1, 0, 1, ALLEGRO_PLAYMODE_ONCE, byref(ALLEGRO_SAMPLE_ID())) elif c == "W": game.coins_collected += self.coins if self.coins > 0: al_play_sample(game.welldone, 1, 0, 1, ALLEGRO_PLAYMODE_ONCE, byref(ALLEGRO_SAMPLE_ID())) self.coins = 0 def check(self, x, y): tx = (self.x + x) // 32 ty = (self.y + y) // 32 return game.level[1 + ty][1 + tx] def put(self, x, y, c): tx = (self.x + x) // 32 ty = (self.y + y) // 32 row = game.level[1 + ty] game.level[1 + ty] = row[:1 + tx] + c + row[1 + tx + 1:] def follow_commands(self, keys): if not self.code: self.code = Code() self.code.code = game.code.code[:] if (game.ticks - self.executing > 2 and not self.command) or\ game.ticks - self.executing > 120: self.command = self.code.execute(self) if self.command in game.sounds: al_play_sample(game.sounds[self.command], 1, 0, 1, ALLEGRO_PLAYMODE_ONCE, byref(ALLEGRO_SAMPLE_ID())) self.executing = game.ticks if self.command == "move": self.command_x = self.x elif self.command == "hop": self.command_x = self.x elif self.command == "jump": keys.up = 1 elif self.command == "turn": self.left = not self.left if self.command == "move": if self.command_x // 32 != self.x // 32: self.command = "" if self.left: keys.left = 1 else: keys.right = 1 elif self.command == "hop": tx = self.x // 32 if self.left: keys.left = 1 else: keys.right = 1 if not self.left and self.x - tx * 32 >= 28: keys.up = 1 self.command = "wait" if self.left and self.x - tx * 32 <= 3: keys.up = 1 self.command = "wait" elif self.command == "wait": tx = self.x // 32 if self.ground and not self.rest: if not self.left and self.command_x // 32 + 2 == self.x // 32: self.command = "center" if self.left and self.command_x // 32 - 2 == self.x // 32: self.command = "center" elif self.command == "jump": if game.ticks > self.executing and self.ground and not self.rest: self.command = "" elif self.command == "turn": if game.ticks - self.executing > 30: self.command = "" elif self.command == "center": if self.left: keys.left = 1 else: keys.right = 1 tx = self.x // 32 if self.x - tx * 32 >= 12 and self.x - tx * 32 <= 20: self.command = "" else: self.command = ""
def follow_commands(self, keys): if not self.code: self.code = Code() self.code.code = game.code.code[:] if (game.ticks - self.executing > 2 and not self.command) or\ game.ticks - self.executing > 120: self.command = self.code.execute(self) if self.command in game.sounds: al_play_sample(game.sounds[self.command], 1, 0, 1, ALLEGRO_PLAYMODE_ONCE, byref(ALLEGRO_SAMPLE_ID())) self.executing = game.ticks if self.command == "move": self.command_x = self.x elif self.command == "hop": self.command_x = self.x elif self.command == "jump": keys.up = 1 elif self.command == "turn": self.left = not self.left if self.command == "move": if self.command_x // 32 != self.x // 32: self.command = "" if self.left: keys.left = 1 else: keys.right = 1 elif self.command == "hop": tx = self.x // 32 if self.left: keys.left = 1 else: keys.right = 1 if not self.left and self.x - tx * 32 >= 28: keys.up = 1 self.command = "wait" if self.left and self.x - tx * 32 <= 3: keys.up = 1 self.command = "wait" elif self.command == "wait": tx = self.x // 32 if self.ground and not self.rest: if not self.left and self.command_x // 32 + 2 == self.x // 32: self.command = "center" if self.left and self.command_x // 32 - 2 == self.x // 32: self.command = "center" elif self.command == "jump": if game.ticks > self.executing and self.ground and not self.rest: self.command = "" elif self.command == "turn": if game.ticks - self.executing > 30: self.command = "" elif self.command == "center": if self.left: keys.left = 1 else: keys.right = 1 tx = self.x // 32 if self.x - tx * 32 >= 12 and self.x - tx * 32 <= 20: self.command = "" else: self.command = ""
class Assembler: def __init__(self,input_file): print("initializing assembler to work on " + input_file) self.input_file = input_file self.code = Code() self.parser = Parser(self.input_file) #to implement this, I am going to go with a straight #prodcedural implementation. the above functions are the #API that is probably needed for the other chapters. #Anyway, the parser requires a file for input, and the #advance and has_more_commands are just basic #iterator functions #The quickest way to solve this is just implement #a counter when the file is initialized. def symbol_less_assembly(self): #letst iterate! while(self.parser.has_more_commands()): cmd = self.parser.get_current_command() if(self.parser.commands.A_COMMAND==self.parser.command_type()): print "A: " + self.parser.symbol() #the magic symbol is from here: http://stackoverflow.com/questions/1002116/can-bin-be-overloaded-like-oct-and-hex-in-python-2-6 self.parser.output.write("0" + '{0:015b}'.format(int(self.parser.symbol()))+"\n") elif(self.parser.commands.C_COMMAND==self.parser.command_type()): print "C: d=" + str(self.parser.dest()) + " c=" + str(self.parser.comp()) + " j=" + str(self.parser.jump()) #code emission. should be set to the output_file in the end. self.parser.output.write("111" + self.code.comp(self.parser.comp()) + self.code.dest(self.parser.dest()) + self.code.jump(self.parser.jump())+"\n") elif(self.parser.commands.L_COMMAND==self.parser.command_type()): print "L: " + self.parser.symbol() self.parser.advance() def two_pass_assembly(self): symbol_table = SymbolTable() rom_address = 0 print("starting first pass") while(self.parser.has_more_commands()): cmd = self.parser.get_current_command() if(self.parser.commands.L_COMMAND==self.parser.command_type()): print "L: " + self.parser.symbol() symbol_table.add_entry(self.parser.symbol(),rom_address) else: rom_address += 1 self.parser.advance() self.parser.reset() #the second pass is the same as the first without the print statements, #and without handling (Xxx) syntax print("starting second pass") while(self.parser.has_more_commands()): cmd = self.parser.get_current_command() if(self.parser.commands.A_COMMAND==self.parser.command_type()): sym = self.parser.symbol() if(sym.isdigit()): val = sym else: if(symbol_table.contains(sym)): val = symbol_table.get_address(sym) else: symbol_table.add_entry(sym, rom_address) rom_address += 1 val = rom_address self.parser.output.write("0" + '{0:015b}'.format(int(val))+"\n") elif(self.parser.commands.C_COMMAND==self.parser.command_type()): self.parser.output.write("111" + self.code.comp(self.parser.comp()) + self.code.dest(self.parser.dest()) + self.code.jump(self.parser.jump()) +"\n") self.parser.advance()
def test_xhh_type(self): assert Code.xhh_type('X7F') == '1111111' assert Code.xhh_type('X1D') == '0011101'
def testComment(self): long_comment = ('This comment is eighty nine characters in longness, ' 'that is, to use another word, length') c = Code() c.Comment(long_comment) self.assertEquals( '// This comment is eighty nine characters ' 'in longness, that is, to use another\n' '// word, length', c.Render()) c = Code() c.Sblock('sblock') c.Comment(long_comment) c.Eblock('eblock') c.Comment(long_comment) self.assertEquals( 'sblock\n' ' // This comment is eighty nine characters ' 'in longness, that is, to use\n' ' // another word, length\n' 'eblock\n' '// This comment is eighty nine characters in ' 'longness, that is, to use another\n' '// word, length', c.Render()) long_word = 'x' * 100 c = Code() c.Comment(long_word) self.assertEquals('// ' + 'x' * 77 + '\n' '// ' + 'x' * 23, c.Render())
def __init__(self,input_file): print("initializing assembler to work on " + input_file) self.input_file = input_file self.code = Code() self.parser = Parser(self.input_file)
def test_sum(): c = Code() assert c.sum(1,2) == 3
def main(): filename = os.path.join(os.getcwd(), Util.getCommandLineArg(1)) first_parser = Parser(filename) second_parser = Parser(filename) symbol_table = SymbolTable() hack_filename = filename.replace('asm', 'hack') hack_file = open(hack_filename, 'w') ann_filename = filename.replace('asm', 'ann') ann_file = open(ann_filename, 'w') rom_address = 0 ram_address = 16 assembly = '' while first_parser.has_more_commands(): first_parser.advance() if first_parser.command_type() is 'A_COMMAND' or first_parser.command_type() is 'C_COMMAND': rom_address += 1 elif first_parser.command_type() is 'L_COMMAND': symbol_table.add_entry(first_parser.symbol(), rom_address, 'LAB') while second_parser.has_more_commands(): second_parser.advance() machine_command = '' if second_parser.command_type() is 'A_COMMAND': if second_parser.symbol()[0].isdigit(): binary = second_parser.symbol() else: if symbol_table.contains(second_parser.symbol()): binary = symbol_table.get_address(second_parser.symbol()) else: binary = ram_address symbol_table.add_entry(second_parser.symbol(), ram_address, 'VAR') ram_address += 1 machine_command = '{0:016b}\n'.format(int(binary)) hack_file.write(machine_command) elif second_parser.command_type() is 'C_COMMAND': dest = Code.dest(second_parser.dest()) comp = Code.comp(second_parser.comp()) jump = Code.jump(second_parser.jump()) machine_command = '111{0}{1}{2}\n'.format(comp, dest, jump) hack_file.write(machine_command) assembly = second_parser.original_command().strip() mc = machine_command.strip() annotated_machine = '{} {} {} {}'.format(mc[0:4], mc[4:8], mc[8:12], mc[12:16]) symbolless_command = '' if second_parser.command_type() is 'L_COMMAND': symbolless_command = symbol_table.get_address(second_parser.symbol()) elif second_parser.command_type() is 'A_COMMAND' and not second_parser.symbol().isdigit(): symbolless_command = '@{}'.format(symbol_table.get_address(second_parser.symbol())) else: symbolless_command = second_parser.command annotated_command = '{:<39} {} {:<11} {}\n'.format(assembly, '//' if second_parser.command_type() else '', symbolless_command, annotated_machine) ann_file.write(annotated_command) ann_file.write('\n// Symbol Table:\n') for symbol, address in symbol_table.symbol_table.items(): ann_file.write('// {}: {:<30} -> {}\n'.format(address[1], symbol, address[0])) hack_file.close() ann_file.close()
line_address += 1 parser.seek_head() var_address = 16 while parser.has_more_commands(): parser.advance() if parser.command_type() == 'L_COMMAND': continue elif parser.command_type() == 'A_COMMAND': symbol = parser.symbol() if symbol.isdigit(): address = int(symbol) elif symbol_table.contains(symbol): address = symbol_table.get_address(symbol) else: address = var_address symbol_table.add_entry(symbol, address) var_address += 1 machine_code = address elif parser.command_type() == 'C_COMMAND': comp = Code.comp(parser.comp()) dest = Code.dest(parser.dest()) jump = Code.jump(parser.jump()) machine_code = 0b111 << 13 | comp << 6 | dest << 3 | jump machine_code_str = "{0:016b}".format(machine_code) hack_file.write(machine_code_str + '\n')
def test_comp_without_XHH_instructions(self): assert Code.comp('D+1') == '0011111' assert Code.comp('D&M') == '1000000'
def _GeneratePopulateVariableFromValue(self, type_, src_var, dst_var, failure_value, is_ptr=False): """Generates code to populate a variable |dst_var| of type |type_| from a Value* at |src_var|. The Value* is assumed to be non-NULL. In the generated code, if |dst_var| fails to be populated then Populate will return |failure_value|. """ c = Code() underlying_type = self._type_helper.FollowRef(type_) if underlying_type.property_type.is_fundamental: if is_ptr: (c.Append('%(cpp_type)s temp;') .Sblock('if (!%s) {' % cpp_util.GetAsFundamentalValue( self._type_helper.FollowRef(type_), src_var, '&temp')) .Concat(self._GenerateError( '"\'%%(key)s\': expected ' + '%s, got " + %s' % ( type_.name, self._util_cc_helper.GetValueTypeString( '%%(src_var)s', True))))) c.Append('%(dst_var)s.reset();') if not self._generate_error_messages: c.Append('return %(failure_value)s;') (c.Eblock('}') .Append('else') .Append(' %(dst_var)s.reset(new %(cpp_type)s(temp));') ) else: (c.Sblock('if (!%s) {' % cpp_util.GetAsFundamentalValue( self._type_helper.FollowRef(type_), src_var, '&%s' % dst_var)) .Concat(self._GenerateError( '"\'%%(key)s\': expected ' + '%s, got " + %s' % ( type_.name, self._util_cc_helper.GetValueTypeString( '%%(src_var)s', True)))) .Append('return %(failure_value)s;') .Eblock('}') ) elif underlying_type.property_type == PropertyType.OBJECT: if is_ptr: (c.Append('const base::DictionaryValue* dictionary = NULL;') .Sblock('if (!%(src_var)s->GetAsDictionary(&dictionary)) {') .Concat(self._GenerateError( '"\'%%(key)s\': expected dictionary, got " + ' + self._util_cc_helper.GetValueTypeString('%%(src_var)s', True)))) # If an optional property fails to populate, the population can still # succeed with a warning. If no error messages are generated, this # warning is not set and we fail out instead. if not self._generate_error_messages: c.Append('return %(failure_value)s;') (c.Eblock('}') .Sblock('else {') .Append('scoped_ptr<%(cpp_type)s> temp(new %(cpp_type)s());') .Append('if (!%%(cpp_type)s::Populate(%s)) {' % self._GenerateArgs( ('*dictionary', 'temp.get()'))) .Append(' return %(failure_value)s;') ) (c.Append('}') .Append('else') .Append(' %(dst_var)s = temp.Pass();') .Eblock('}') ) else: (c.Append('const base::DictionaryValue* dictionary = NULL;') .Sblock('if (!%(src_var)s->GetAsDictionary(&dictionary)) {') .Concat(self._GenerateError( '"\'%%(key)s\': expected dictionary, got " + ' + self._util_cc_helper.GetValueTypeString('%%(src_var)s', True))) .Append('return %(failure_value)s;') .Eblock('}') .Append('if (!%%(cpp_type)s::Populate(%s)) {' % self._GenerateArgs( ('*dictionary', '&%(dst_var)s'))) .Append(' return %(failure_value)s;') .Append('}') ) elif underlying_type.property_type == PropertyType.FUNCTION: if is_ptr: c.Append('%(dst_var)s.reset(new base::DictionaryValue());') elif underlying_type.property_type == PropertyType.ANY: c.Append('%(dst_var)s.reset(%(src_var)s->DeepCopy());') elif underlying_type.property_type == PropertyType.ARRAY: # util_cc_helper deals with optional and required arrays (c.Append('const base::ListValue* list = NULL;') .Sblock('if (!%(src_var)s->GetAsList(&list)) {') .Concat(self._GenerateError( '"\'%%(key)s\': expected list, got " + ' + self._util_cc_helper.GetValueTypeString('%%(src_var)s', True))) ) if is_ptr and self._generate_error_messages: c.Append('%(dst_var)s.reset();') else: c.Append('return %(failure_value)s;') c.Eblock('}') c.Sblock('else {') item_type = self._type_helper.FollowRef(underlying_type.item_type) if item_type.property_type == PropertyType.ENUM: c.Concat(self._GenerateListValueToEnumArrayConversion( item_type, 'list', dst_var, failure_value, is_ptr=is_ptr)) else: c.Sblock('if (!%s(%s)) {' % ( self._util_cc_helper.PopulateArrayFromListFunction(is_ptr), self._GenerateArgs(('*list', '&%(dst_var)s')))) c.Concat(self._GenerateError( '"unable to populate array \'%%(parent_key)s\'"')) if is_ptr and self._generate_error_messages: c.Append('%(dst_var)s.reset();') else: c.Append('return %(failure_value)s;') c.Eblock('}') c.Eblock('}') elif underlying_type.property_type == PropertyType.CHOICES: if is_ptr: (c.Append('scoped_ptr<%(cpp_type)s> temp(new %(cpp_type)s());') .Append('if (!%%(cpp_type)s::Populate(%s))' % self._GenerateArgs( ('*%(src_var)s', 'temp.get()'))) .Append(' return %(failure_value)s;') .Append('%(dst_var)s = temp.Pass();') ) else: (c.Append('if (!%%(cpp_type)s::Populate(%s))' % self._GenerateArgs( ('*%(src_var)s', '&%(dst_var)s'))) .Append(' return %(failure_value)s;')) elif underlying_type.property_type == PropertyType.ENUM: c.Concat(self._GenerateStringToEnumConversion(underlying_type, src_var, dst_var, failure_value)) elif underlying_type.property_type == PropertyType.BINARY: (c.Append('const base::BinaryValue* binary_value = NULL;') .Sblock('if (!%(src_var)s->IsType(base::Value::TYPE_BINARY)) {') .Concat(self._GenerateError( '"\'%%(key)s\': expected binary, got " + ' + self._util_cc_helper.GetValueTypeString('%%(src_var)s', True))) ) if not self._generate_error_messages: c.Append('return %(failure_value)s;') (c.Eblock('}') .Sblock('else {') .Append(' binary_value =') .Append(' static_cast<const base::BinaryValue*>(%(src_var)s);') ) if is_ptr: (c.Append('%(dst_var)s.reset(new std::vector<char>(') .Append(' binary_value->GetBuffer(),') .Append(' binary_value->GetBuffer() + binary_value->GetSize()));') ) else: (c.Append('%(dst_var)s.assign(') .Append(' binary_value->GetBuffer(),') .Append(' binary_value->GetBuffer() + binary_value->GetSize());') ) c.Eblock('}') else: raise NotImplementedError(type_) if c.IsEmpty(): return c return Code().Sblock('{').Concat(c.Substitute({ 'cpp_type': self._type_helper.GetCppType(type_), 'src_var': src_var, 'dst_var': dst_var, 'failure_value': failure_value, 'key': type_.name, 'parent_key': type_.parent.name, })).Eblock('}')
def produceCode(data): code = Code(data["name"]) music = len(data["notes"]) > 1 if music: code.defineVariable("music_index") code.defineVariable("note_index") code.includeDependency("macro/sound.asm") code.includeDependency("data/constants.inc") code.includeDependency("data/sound_constants.inc") functionName = "Play%s" % data["name"] code.exportFunction(functionName) code.append("%s:" % functionName) code.indent() if music: checkNoteIndex(code) code.append("LDA #%00000011; square 1 and 2") code.append("STA APU_CTRL") code.append("; DClm vol") code.append("LDA #%10000111 ; duty cycle 50%, deaktivert lengdeteller") code.append(" ; deaktivert envelope - generator, fullt volum (15)") code.append("STA $4000") code.append("STA $4004") if not music: for tone in data["notes"][0]["tones"]: code.append("SET_SQUARE_NOTE %s, %s, %s" % (tone[0], tone[1], tone[2])) else: code.append("LDA music_index") i = 0 code.indent() for note in data["notes"]: code.append("SKIP_IF_NOT %d" % i) for tone in note["tones"]: code.append("SET_SQUARE_NOTE %s, %s, %s" % (tone[0], tone[1], tone[2])) code.append("LDA #%s" % note["length"]) code.append("JMP @end_set_note") code.append(":", -1) i += 1 code.unindent() code.append("LDA #0") code.append("STA music_index") code.append("RTS") code.append(setNoteIndex) code.append("RTS") return str(code)
def __init__(self, number): self.length = number self._secret_code = Code.generate_secret_code(self.length) self.game_over = False
def test_comp_with_XHH_instructions(self): # print '\n{} == \n{}'.format(Code.comp('D&A'), Code.comp('X00')) assert Code.comp('X7F') == '1111111' assert Code.comp('X3A') == '0111010' assert Code.comp('D&A') == Code.comp('X00')
def testConcat(self): b = Code() (b.Sblock('2').Append('2').Eblock('2')) c = Code() (c.Sblock('1').Concat(b).Append('1').Eblock('1')) self.assertEquals('1\n' ' 2\n' ' 2\n' ' 2\n' ' 1\n' '1', c.Render()) d = Code() a = Code() a.Concat(d) self.assertEquals('', a.Render()) a.Concat(c) self.assertEquals('1\n' ' 2\n' ' 2\n' ' 2\n' ' 1\n' '1', a.Render())
for i in range(len(codecool_bp.mentors)): print(' ', codecool_bp.mentors[i].full_name) input() print('\nStudents:') for i in range(len(codecool_bp.students)): print(' ', codecool_bp.students[i].full_name) input() print("\nMentors arrive at school. They welcome students with a cheery smile\n") input() codecool_bp.mentors[1].check_energy_level(codecool_bp.students) input() codecool_bp.mentors[0].check_mood(codecool_bp.students) input() codecool_bp.students[3].use_EKI(codecool_bp.EKI_list[7]) input() code = Code(215, "Fakkin' Hard Shit") code.get_worked_on(codecool_bp.students[1]) input() codecool_bp.students[3].use_EKI(codecool_bp.EKI_list[10]) input() creepy = Management("Creepy", "Guy", 0, "male", 0, True) creepy.creeping(codecool_bp.mentors, codecool_bp.students) input() coffeemachine = CoffeeMachine(70, 0, True, True) coffeemachine.make_coffee() input() coffeemachine.get_filled_water() input() coffeemachine.make_coffee() boda = Management("Boda", "Józsi", 0, "male", 0, True) boda.change_life(codecool_bp.mentors, codecool_bp.students)
def testIsEmpty(self): c = Code() self.assertTrue(c.IsEmpty()) c.Append('asdf') self.assertFalse(c.IsEmpty())
def __init__(self, win): Code.__init__(self, win)
def Write(self): """Writes the output.""" header_file = self._out_base_filename + '.h' cc_file = self._out_base_filename + '.cc' include_file_root = self._out_root GEN_DIR_PREFIX = 'gen/' if include_file_root.startswith(GEN_DIR_PREFIX): include_file_root = include_file_root[len(GEN_DIR_PREFIX):] header_file_path = '%s/%s' % (include_file_root, header_file) cc_file_path = '%s/%s' % (include_file_root, cc_file) substitutions = ({ 'header_file_path': header_file_path, 'header_guard': (header_file_path.replace('/', '_').replace('.', '_').upper()), 'method_name': self._method_name, 'source_files': str(self._source_files), 'year': str(datetime.now().year) }) if not os.path.exists(self._out_root): os.makedirs(self._out_root) # Write the .h file. with open(os.path.join(self._out_root, header_file), 'w') as f: header_file = Code() header_file.Append(HEADER_FILE_TEMPLATE) header_file.Substitute(substitutions) f.write(header_file.Render().strip()) # Write the .cc file. with open(os.path.join(self._out_root, cc_file), 'w') as f: cc_file = Code() cc_file.Append(CC_FILE_BEGIN) cc_file.Substitute(substitutions) cc_file.Concat(self.Render()) cc_end = Code() cc_end.Append(CC_FILE_END) cc_end.Substitute(substitutions) cc_file.Concat(cc_end) f.write(cc_file.Render().strip())
def assemble(self): # # first pass - build the symbol table for labels # parser = Parser(self.source_filename) symbol_table = SymbolTable() # the current instruction instruction = 0 # parse each command while parser.hasMoreCommands(): # advance to the next command parser.advance() # parse the command type and look for symbols command_type = parser.commandType() if command_type == "L": # look for an instruction label symbol symbol = parser.symbol() if symbol not in symbol_table: symbol_table.addEntry(symbol, instruction) else: # increment the instruction count if this was not a label if command_type != "L": instruction += 1 # # second pass - build the symbol table for variables # parser = Parser(self.source_filename) # the memory location for the next variable variable_address = 16 # parse each command while parser.hasMoreCommands(): # advance to the next command parser.advance() # parse the command type and look for symbols command_type = parser.commandType() if command_type == "A": # look for a variable value symbol symbol = parser.symbol() if symbol[0] not in map(str, range(0, 10)): # the symbol is not a number; that is, it is actually a symbol if symbol not in symbol_table: symbol_table.addEntry(symbol, variable_address) variable_address += 1 # # third pass - generate assembly # parser = Parser(self.source_filename) code = Code() # parse all commands while parser.hasMoreCommands(): # advance to the next command parser.advance() command_type = parser.commandType() if command_type == "A": # a command symbol = parser.symbol() if symbol in symbol_table: symbol = symbol_table.getAddress(symbol) symbol_binary = code.decimalToBinary(symbol) self.destination_file.write("0" + symbol_binary + "\n") elif command_type == "C": # c command comp = code.comp(parser.comp()) dest = code.dest(parser.dest()) jump = code.jump(parser.jump()) self.destination_file.write("111" + comp + dest + jump + "\n") elif command_type == "L": # label - do nothing in this stage pass else: # unknown command raise Exception("ERROR: Unknown command type encountered") # close the output file self.destination_file.close()