public ByteBuffer GenerateByteCode(Parser parser, IList<Executable> lines, IList<string> spriteSheetOpsStringArgs, IList<int[]> spriteSheetOpsIntArgs) { FunctionDefinition mainFunction = lines .OfType<FunctionDefinition>() .Where<FunctionDefinition>(fd => fd.NameToken.Value == "main") .FirstOrDefault<FunctionDefinition>(); if (mainFunction == null) { throw new Exception(); // should have thrown before if there was no main function. } ByteBuffer userCode = new ByteBuffer(); this.Compile(parser, userCode, lines); ByteBuffer literalsTable = parser.LiteralLookup.BuildByteCode(); ByteBuffer tokenData = this.BuildTokenData(userCode); ByteBuffer fileContent = this.BuildFileContent(parser.GetFilesById()); ByteBuffer switchStatements = this.BuildSwitchStatementTables(parser); ByteBuffer spriteSheetStuff = this.BuildSpriteSheetStuff(spriteSheetOpsStringArgs, spriteSheetOpsIntArgs); ByteBuffer header = new Crayon.ByteBuffer(); header.Concat(literalsTable); header.Concat(tokenData); header.Concat(fileContent); header.Concat(switchStatements); header.Concat(spriteSheetStuff); header.Add(null, OpCode.FINALIZE_INITIALIZATION); ByteBuffer output = new Crayon.ByteBuffer(); output.Add(null, OpCode.USER_CODE_START, header.Size + 1, parser.VariableIds.Size); output.Concat(header); output.Concat(userCode); // artificially inject a function call to main() at the very end after all declarations are done. if (parser.MainFunctionHasArg) { output.Add(null, OpCode.DEF_LIST, 0); // TODO: op code to build a list of the command line args. For now just pass in an empty list. output.Add(null, OpCode.CALL_FUNCTION, (int)FunctionInvocationType.NORMAL_FUNCTION, 1, mainFunction.FunctionID, 0, 0); } else { output.Add(null, OpCode.CALL_FUNCTION, (int)FunctionInvocationType.NORMAL_FUNCTION, 0, mainFunction.FunctionID, 0, 0); } output.Add(null, OpCode.RETURN, 0); return output; }