diff --git a/.notes/for-loop.txt b/.notes/for-loop.txt new file mode 100644 index 0000000..fb57c20 --- /dev/null +++ b/.notes/for-loop.txt @@ -0,0 +1,23 @@ + + +```toy +for (var name in array) { + // +} +``` + + +pushStack name +pushStack array +pushStack counter //tracks the index for each loop + +OPCODE iterable: + pushScope + declare name = array.next() if next is not null else jump to end + + (user code) + + popScope + jump to beginning + +popStack counter, array, name \ No newline at end of file diff --git a/repl/bytecode_inspector.c b/repl/bytecode_inspector.c index b7d71c5..a3d8589 100644 --- a/repl/bytecode_inspector.c +++ b/repl/bytecode_inspector.c @@ -195,9 +195,24 @@ int inspect_instruction(unsigned char* bytecode, unsigned int pc, unsigned int j return 4; case TOY_OPCODE_ELIMINATE: - printf(MARKER "ELIMINATE\n", MARKER_VALUE(pc, unsigned char)); + printf(MARKER "ELIMINATE %u\n", MARKER_VALUE(pc, unsigned char), (unsigned int)bytecode[pc + 1]); return 4; + case TOY_OPCODE_ITERATE: + printf(MARKER TOY_CC_DEBUG "ITERATE on [-2] based on type, with [-1] as counter, then delegate to: JUMP %s%s (%s%d) (GOTO %u)\n" TOY_CC_RESET, MARKER_VALUE(pc, unsigned char), + bytecode[pc + 1] == TOY_OP_PARAM_JUMP_ABSOLUTE ? "absolute" : "relative", + bytecode[pc + 2] == TOY_OP_PARAM_JUMP_ALWAYS ? "" : + bytecode[pc + 2] == TOY_OP_PARAM_JUMP_IF_TRUE ? " if true" : + bytecode[pc + 2] == TOY_OP_PARAM_JUMP_IF_FALSE ? " if false" : + bytecode[pc + 2] == TOY_OP_PARAM_JUMP_IF_NULL ? " if null" : + "if " + , + (*(int*)(bytecode + pc + 4)) > 0 ? "+" : "", //show a + sign when positive + (*(int*)(bytecode + pc + 4)), + (*(int*)(bytecode + pc + 4)) + pc + 8 + ); + return 8; + case TOY_OPCODE_ADD: printf(MARKER "ADD %s\n", MARKER_VALUE(pc, unsigned char), bytecode[pc + 1] == TOY_OPCODE_ASSIGN ? "and ASSIGN" : ""); return 4; @@ -262,18 +277,22 @@ int inspect_instruction(unsigned char* bytecode, unsigned int pc, unsigned int j printf(MARKER TOY_CC_DEBUG "JUMP %s%s (%s%d) (GOTO %u)\n" TOY_CC_RESET, MARKER_VALUE(pc, unsigned char), bytecode[pc + 1] == TOY_OP_PARAM_JUMP_ABSOLUTE ? "absolute" : "relative", bytecode[pc + 2] == TOY_OP_PARAM_JUMP_ALWAYS ? "" : - bytecode[pc + 2] == TOY_OP_PARAM_JUMP_IF_TRUE ? " if true" : " if false", - bytecode[pc + 4] > 0 ? "+" : "", //show a + sign when positive - bytecode[pc + 4], - bytecode[pc + 4] + pc + 8 - ); + bytecode[pc + 2] == TOY_OP_PARAM_JUMP_IF_TRUE ? " if true" : + bytecode[pc + 2] == TOY_OP_PARAM_JUMP_IF_FALSE ? " if false" : + bytecode[pc + 2] == TOY_OP_PARAM_JUMP_IF_NULL ? " if null" : + "if " + , + (*(int*)(bytecode + pc + 4)) > 0 ? "+" : "", //show a + sign when positive + (*(int*)(bytecode + pc + 4)), + (*(int*)(bytecode + pc + 4)) + pc + 8 + ); return 8; case TOY_OPCODE_ESCAPE: printf(MARKER TOY_CC_DEBUG "ESCAPE relative %s%d (GOTO %u) and pop %d\n" TOY_CC_RESET, MARKER_VALUE(pc, unsigned char), - bytecode[pc + 4] > 0 ? "+" : "", //show a + sign when positive - bytecode[pc + 4], - bytecode[pc + 4] + pc + 12, + (*(int*)(bytecode + pc + 4)) > 0 ? "+" : "", //show a + sign when positive + (*(int*)(bytecode + pc + 4)), + (*(int*)(bytecode + pc + 4)) + pc + 12, bytecode[pc + 8] ); return 12; diff --git a/scripts/hello_world.toy b/scripts/hello_world.toy index d572290..4258f7f 100644 --- a/scripts/hello_world.toy +++ b/scripts/hello_world.toy @@ -1,12 +1,10 @@ +var array = ["foo", "bar"]; -fn a(x) { - print x; +for (var i in array) { + print i; + break; } -fn b() { - return 42; -} - -a(b(), b()); \ No newline at end of file +print "done"; \ No newline at end of file diff --git a/source/toy_compiler.c b/source/toy_compiler.c index 66e67a3..c43382c 100644 --- a/source/toy_compiler.c +++ b/source/toy_compiler.c @@ -226,6 +226,7 @@ static unsigned int writeBytecodeFromAst(Toy_Bytecode** mb, Toy_Ast* ast); //for static void writeBytecodeBody(Toy_Bytecode* mb, Toy_Ast* ast); static unsigned char* collateBytecodeBody(Toy_Bytecode* mb); static unsigned int writeInstructionAssign(Toy_Bytecode** mb, Toy_AstVarAssign ast, bool chainedAssignment); //forward declare for chaining of var declarations +static unsigned int writeInstructionAccess(Toy_Bytecode** mb, Toy_AstVarAccess ast); static unsigned int writeInstructionFnInvoke(Toy_Bytecode** mb, Toy_AstFnInvoke ast, bool chainedInvoke); static unsigned int writeInstructionValue(Toy_Bytecode** mb, Toy_AstValue ast) { @@ -456,7 +457,7 @@ static unsigned int writeInstructionBinaryShortCircuit(Toy_Bytecode** mb, Toy_As //if the lhs value isn't needed, pop it EMIT_BYTE(mb, code,TOY_OPCODE_ELIMINATE); - EMIT_BYTE(mb, code, 0); + EMIT_BYTE(mb, code, 1); EMIT_BYTE(mb, code, 0); EMIT_BYTE(mb, code, 0); @@ -719,12 +720,71 @@ static unsigned int writeInstructionWhileThen(Toy_Bytecode** mb, Toy_AstWhileThe } static unsigned int writeInstructionForThen(Toy_Bytecode** mb, Toy_AstForThen ast) { - //URGENT: WIP - (void)mb; - (void)ast; + //check the operands + if (ast.condBranch->type != TOY_AST_ITERABLE || ast.condBranch->iterable.left->type != TOY_AST_VAR_DECLARE || ast.condBranch->iterable.right->type != TOY_AST_VAR_ACCESS) { + fprintf(stderr, TOY_CC_ERROR "COMPILER ERROR: Invalid conditional found in a 'for' loop\n" TOY_CC_RESET); + (*mb)->panic = true; + return 0; + } - (*mb)->panic = true; - return 1; + //set up the iterable, and the counter + writeInstructionAccess(mb, ast.condBranch->iterable.right->varAccess); + + EMIT_BYTE(mb, code, TOY_OPCODE_READ); + EMIT_BYTE(mb, code, TOY_VALUE_INTEGER); + EMIT_BYTE(mb, code, 0); + EMIT_BYTE(mb, code, 0); + + EMIT_INT(mb, code, 0); //start from zero + + unsigned int beginAddr = CURRENT_ADDRESS(mb, code); + + //access [-1] from [-2], incrementing [-1] afterwards + //then delegate to JUMP + EMIT_BYTE(mb, code, TOY_OPCODE_ITERATE); + EMIT_BYTE(mb, code, TOY_OP_PARAM_JUMP_RELATIVE); + EMIT_BYTE(mb, code, TOY_OP_PARAM_JUMP_IF_NULL); + EMIT_BYTE(mb, code, 0); + + unsigned int thenParamAddr = SKIP_INT(mb, code); //parameter to be written later + + //push scope (built-into the keyword) + EMIT_BYTE(mb, code, TOY_OPCODE_SCOPE_PUSH); + EMIT_BYTE(mb, code, 0); + EMIT_BYTE(mb, code, 0); + EMIT_BYTE(mb, code, 0); + (*mb)->currentScopeDepth++; + + //delcare the iterator with the given string + EMIT_BYTE(mb, code, TOY_OPCODE_DECLARE); + EMIT_BYTE(mb, code, ast.condBranch->iterable.left->varDeclare.valueType); + EMIT_BYTE(mb, code, ast.condBranch->iterable.left->varDeclare.name->info.length); //quick optimisation to skip a 'strlen()' call + EMIT_BYTE(mb, code, ast.condBranch->iterable.left->varDeclare.constant); //check for constness + + emitString(mb, ast.condBranch->iterable.left->varDeclare.name); + + //write the body + writeBytecodeFromAst(mb, ast.thenBranch); + + //pop scope after each iteration + EMIT_BYTE(mb, code, TOY_OPCODE_SCOPE_POP); + EMIT_BYTE(mb, code, 0); + EMIT_BYTE(mb, code, 0); + EMIT_BYTE(mb, code, 0); + (*mb)->currentScopeDepth--; + + //jump to begin to repeat the conditional test + EMIT_BYTE(mb, code, TOY_OPCODE_JUMP); + EMIT_BYTE(mb, code, TOY_OP_PARAM_JUMP_RELATIVE); + EMIT_BYTE(mb, code, TOY_OP_PARAM_JUMP_ALWAYS); + EMIT_BYTE(mb, code, 0); + + EMIT_INT(mb, code, beginAddr - (CURRENT_ADDRESS(mb, code) + 4)); //this sets a negative value + + //end of the loop, overwrite the parameter + OVERWRITE_INT(mb, code, thenParamAddr, CURRENT_ADDRESS(mb, code) - (thenParamAddr + 4)); + + return 0; } static unsigned int writeInstructionBreak(Toy_Bytecode** mb, Toy_AstBreak ast) { @@ -1163,7 +1223,7 @@ static unsigned int writeInstructionStackPop(Toy_Bytecode** mb, Toy_AstStackPop //dead simple EMIT_BYTE(mb, code,TOY_OPCODE_ELIMINATE); - EMIT_BYTE(mb, code, 0); + EMIT_BYTE(mb, code, 1); EMIT_BYTE(mb, code, 0); EMIT_BYTE(mb, code, 0); diff --git a/source/toy_opcodes.h b/source/toy_opcodes.h index 8aedbd4..0154365 100644 --- a/source/toy_opcodes.h +++ b/source/toy_opcodes.h @@ -12,9 +12,9 @@ typedef enum Toy_OpcodeType { TOY_OPCODE_ACCESS, TOY_OPCODE_INVOKE, //for calling functions TOY_OPCODE_ATTRIBUTE, //for accessing parts of compounds - TOY_OPCODE_ITERABLE, //for operating on all members of a compound TOY_OPCODE_DUPLICATE, //duplicate the top of the stack TOY_OPCODE_ELIMINATE, //remove the top of the stack + TOY_OPCODE_ITERATE, //for operating on all members of a compound //arithmetic instructions TOY_OPCODE_ADD, @@ -67,5 +67,6 @@ typedef enum Toy_OpParamJumpConditional { TOY_OP_PARAM_JUMP_ALWAYS = 0, TOY_OP_PARAM_JUMP_IF_TRUE = 1, TOY_OP_PARAM_JUMP_IF_FALSE = 2, + TOY_OP_PARAM_JUMP_IF_NULL = 3, } Toy_OpParamJumpConditional; diff --git a/source/toy_parser.c b/source/toy_parser.c index 9b8dcb8..793aea6 100644 --- a/source/toy_parser.c +++ b/source/toy_parser.c @@ -122,7 +122,6 @@ static Toy_AstFlag aggregate(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_ static Toy_AstFlag unaryPostfix(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle); static Toy_AstFlag invoke(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle); static Toy_AstFlag attribute(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle); -static Toy_AstFlag iterable(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle); //precedence definitions static ParsingTuple parsingRulesetTable[] = { @@ -157,7 +156,7 @@ static ParsingTuple parsingRulesetTable[] = { {PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_FUNCTION, {PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_IF, {PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_IMPORT, - {PREC_CALL,NULL,iterable},// TOY_TOKEN_KEYWORD_IN, + {PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_IN, {PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_OF, {PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_PASS, {PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_PRINT, @@ -761,19 +760,6 @@ static Toy_AstFlag attribute(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_ } } -static Toy_AstFlag iterable(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle) { - //infix must advance - advance(parser); - - Toy_Ast* expr = NULL; - parsePrecedence(bucketHandle, parser, &expr, PREC_CALL); - Toy_private_emitAstIterable(bucketHandle, rootHandle, expr); - - //TODO: check for var declare without assignment - - return TOY_AST_FLAG_NONE; -} - //grammar rules static void parsePrecedence(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle, ParsingPrecedence precRule) { //'step over' the token to parse @@ -785,7 +771,7 @@ static void parsePrecedence(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_A if (prefix == NULL) { //make a nice error message if (Toy_private_findKeywordByType(parser->previous.type)) { - printError(parser, parser->previous, "Found reserved keyword instead"); + printError(parser, parser->previous, "Expected expression, found reserved keyword instead"); } else { printError(parser, parser->previous, "Expected expression"); @@ -906,20 +892,52 @@ static void makeWhileStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast } static void makeForStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle) { + Toy_Ast* declBranch = NULL; Toy_Ast* condBranch = NULL; Toy_Ast* thenBranch = NULL; //for (condBranch) consume(parser, TOY_TOKEN_OPERATOR_PAREN_LEFT, "Expected '(' after 'for' keyword"); - makeExpr(bucketHandle, parser, &condBranch); - consume(parser, TOY_TOKEN_OPERATOR_PAREN_RIGHT, "Expected ')' after 'for' condition"); + consume(parser, TOY_TOKEN_KEYWORD_VAR, "Expected 'var' in 'for' conditional"); - //TODO: check for an iterable node + //WARN: duped from var declare + consume(parser, TOY_TOKEN_NAME, "Expected variable name after 'var' keyword"); + + if (parser->previous.length > 255) { + printError(parser, parser->previous, "Can't have a variable name longer than 255 characters"); + Toy_private_emitAstError(bucketHandle, rootHandle); + return; + } + + Toy_Token nameToken = parser->previous; + + //read the type specifier if present + Toy_ValueType varType = TOY_VALUE_ANY; + bool constant = false; + + if (match(parser, TOY_TOKEN_OPERATOR_COLON)) { + varType = readType(parser); + if (match(parser, TOY_TOKEN_KEYWORD_CONST)) { + constant = true; + } + } + + //build the name string & emit a var declare + Toy_String* nameStr = Toy_toStringLength(bucketHandle, nameToken.lexeme, nameToken.length); + Toy_private_emitAstVariableDeclaration(bucketHandle, &declBranch, nameStr, varType, constant, NULL); + + //continue to the 'in' keyword + consume(parser, TOY_TOKEN_KEYWORD_IN, "Expected 'in' inside 'for' condition"); + parsePrecedence(bucketHandle, parser, &condBranch, PREC_CALL); + + consume(parser, TOY_TOKEN_OPERATOR_PAREN_RIGHT, "Expected ')' after 'for' condition"); //{ thenBranch } makeDeclarationStmt(bucketHandle, parser, &thenBranch, true); - Toy_private_emitAstForThen(bucketHandle, rootHandle, condBranch, thenBranch); + //finalize everything + Toy_private_emitAstIterable(bucketHandle, &declBranch, condBranch); + Toy_private_emitAstForThen(bucketHandle, rootHandle, declBranch, thenBranch); } static void makeBreakStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle) { @@ -1125,7 +1143,7 @@ static void makeStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** ro return; } - //TODO: import + //import? //print else if (match(parser, TOY_TOKEN_KEYWORD_PRINT)) { diff --git a/source/toy_vm.c b/source/toy_vm.c index e606926..f529fc8 100644 --- a/source/toy_vm.c +++ b/source/toy_vm.c @@ -33,6 +33,9 @@ static inline void fixAlignment(Toy_VM* vm) { vm->programCounter = (vm->programCounter + 3) & ~3; } +//forward declarations for delegations +static void processJump(Toy_VM* vm); + //instruction handlers static void processRead(Toy_VM* vm) { Toy_ValueType type = READ_BYTE(vm); @@ -470,9 +473,51 @@ static void processDuplicate(Toy_VM* vm) { } static void processEliminate(Toy_VM* vm) { - //discard the stack top - Toy_Value value = Toy_popStack(&vm->stack); - Toy_freeValue(value); + //discard the stack top, X times + unsigned int x = (unsigned int)READ_BYTE(vm); + for (unsigned int i = 0; i < x; i++) { + Toy_Value value = Toy_popStack(&vm->stack); + Toy_freeValue(value); + } +} + +static void processIterate(Toy_VM* vm) { + //ITERATE on [-2] based on type, with [-1] as counter + //then delegate to processJump + + Toy_Value counter = Toy_popStack(&vm->stack); + Toy_Value compound = Toy_popStack(&vm->stack); + + if (!TOY_VALUE_IS_INTEGER(counter)) { + fprintf(stderr, TOY_CC_ERROR "ERROR: Unknown counter type '%s' found in for loop, exiting\n" TOY_CC_RESET, Toy_getValueTypeAsCString(counter.type)); + exit(-1); + } + + if (TOY_VALUE_IS_ARRAY(compound)) { + Toy_Array* array = TOY_VALUE_AS_ARRAY(compound); + unsigned int index = (unsigned int)TOY_VALUE_AS_INTEGER(counter); + + //check out-of-bounds + if (index >= array->count) { + Toy_freeValue(counter); + Toy_freeValue(compound); + Toy_pushStack(&vm->stack, TOY_VALUE_FROM_NULL()); //force a jump + processJump(vm); + return; + } + + //get the desired element + Toy_Value value = Toy_copyValue(&vm->memoryBucket, array->data[index]); + + //push everything back onto the stack (iterating the counter) + Toy_pushStack(&vm->stack, compound); + Toy_pushStack(&vm->stack, TOY_VALUE_FROM_INTEGER(index + 1)); + Toy_pushStack(&vm->stack, value); + } + else { + fprintf(stderr, TOY_CC_ERROR "ERROR: Unknown iterable type '%s' found in for loop, exiting\n" TOY_CC_RESET, Toy_getValueTypeAsCString(compound.type)); + exit(-1); + } } static void processArithmetic(Toy_VM* vm, Toy_OpcodeType opcode) { @@ -682,6 +727,17 @@ static void processJump(Toy_VM* vm) { Toy_freeValue(value); return; } + + case TOY_OP_PARAM_JUMP_IF_NULL: { + Toy_Value value = Toy_popStack(&vm->stack); + if (TOY_VALUE_IS_NULL(value)) { + Toy_freeValue(value); + break; + } + + Toy_freeValue(value); + return; + } } //do the jump @@ -997,6 +1053,10 @@ static unsigned int process(Toy_VM* vm) { processEliminate(vm); break; + case TOY_OPCODE_ITERATE: + processIterate(vm); + break; + //arithmetic instructions case TOY_OPCODE_ADD: case TOY_OPCODE_SUBTRACT: @@ -1060,7 +1120,6 @@ static unsigned int process(Toy_VM* vm) { processIndex(vm); break; - case TOY_OPCODE_ITERABLE: //tmp case TOY_OPCODE_UNUSED: case TOY_OPCODE_PASS: case TOY_OPCODE_ERROR: diff --git a/tests/scripts/test_keyword_for_break_continue.toy b/tests/scripts/test_keyword_for_break_continue.toy deleted file mode 100644 index e69de29..0000000 diff --git a/tests/scripts/test_keyword_for_iteration.toy b/tests/scripts/test_keyword_for_iteration.toy new file mode 100644 index 0000000..1010ae9 --- /dev/null +++ b/tests/scripts/test_keyword_for_iteration.toy @@ -0,0 +1,5 @@ +//TODO: empty test script + +//TODO: test iteration on arrays, tables, closures + +//TODO: test break, continue \ No newline at end of file diff --git a/tests/units/test_compiler.c b/tests/units/test_compiler.c index abb7be5..e7eb203 100644 --- a/tests/units/test_compiler.c +++ b/tests/units/test_compiler.c @@ -139,7 +139,7 @@ int test_compiler_expressions(Toy_Bucket** bucketHandle) { *((unsigned char*)(buffer + 27)) != 0 || *((unsigned char*)(buffer + 28)) != TOY_OPCODE_ELIMINATE || - *((unsigned char*)(buffer + 29)) != 0 || + *((unsigned char*)(buffer + 29)) != 1 || *((unsigned char*)(buffer + 30)) != 0 || *((unsigned char*)(buffer + 31)) != 0 || @@ -197,7 +197,7 @@ int test_compiler_expressions(Toy_Bucket** bucketHandle) { *((unsigned char*)(buffer + 27)) != 0 || *((unsigned char*)(buffer + 28)) != TOY_OPCODE_ELIMINATE || - *((unsigned char*)(buffer + 29)) != 0 || + *((unsigned char*)(buffer + 29)) != 1 || *((unsigned char*)(buffer + 30)) != 0 || *((unsigned char*)(buffer + 31)) != 0 || @@ -257,7 +257,7 @@ int test_compiler_expressions(Toy_Bucket** bucketHandle) { *(int*)(buffer + 28) != 42 || *((unsigned char*)(buffer + 32)) != TOY_OPCODE_ELIMINATE || - *((unsigned char*)(buffer + 33)) != 0 || + *((unsigned char*)(buffer + 33)) != 1 || *((unsigned char*)(buffer + 34)) != 0 || *((unsigned char*)(buffer + 35)) != 0 || @@ -317,7 +317,7 @@ int test_compiler_expressions(Toy_Bucket** bucketHandle) { *(float*)(buffer + 28) != 3.1415f || *((unsigned char*)(buffer + 32)) != TOY_OPCODE_ELIMINATE || - *((unsigned char*)(buffer + 33)) != 0 || + *((unsigned char*)(buffer + 33)) != 1 || *((unsigned char*)(buffer + 34)) != 0 || *((unsigned char*)(buffer + 35)) != 0 || @@ -389,7 +389,7 @@ int test_compiler_expressions(Toy_Bucket** bucketHandle) { *(unsigned int*)(code + 4) != 0 || //the jump index *((unsigned char*)(code + 8)) != TOY_OPCODE_ELIMINATE || - *((unsigned char*)(code + 9)) != 0 || + *((unsigned char*)(code + 9)) != 1 || *((unsigned char*)(code + 10)) != 0 || *((unsigned char*)(code + 11)) != 0 || @@ -499,7 +499,7 @@ int test_compiler_binary(Toy_Bucket** bucketHandle) { *((unsigned char*)(buffer + 43)) != 0 || *((unsigned char*)(buffer + 44)) != TOY_OPCODE_ELIMINATE || - *((unsigned char*)(buffer + 45)) != 0 || + *((unsigned char*)(buffer + 45)) != 1 || *((unsigned char*)(buffer + 46)) != 0 || *((unsigned char*)(buffer + 47)) != 0 || @@ -569,7 +569,7 @@ int test_compiler_binary(Toy_Bucket** bucketHandle) { *((unsigned char*)(buffer + 43)) != 0 || *((unsigned char*)(buffer + 44)) != TOY_OPCODE_ELIMINATE || - *((unsigned char*)(buffer + 45)) != 0 || + *((unsigned char*)(buffer + 45)) != 1 || *((unsigned char*)(buffer + 46)) != 0 || *((unsigned char*)(buffer + 47)) != 0 || @@ -639,7 +639,7 @@ int test_compiler_binary(Toy_Bucket** bucketHandle) { *((unsigned char*)(buffer + 43)) != 0 || *((unsigned char*)(buffer + 44)) != TOY_OPCODE_ELIMINATE || - *((unsigned char*)(buffer + 45)) != 0 || + *((unsigned char*)(buffer + 45)) != 1 || *((unsigned char*)(buffer + 46)) != 0 || *((unsigned char*)(buffer + 47)) != 0 || @@ -735,7 +735,7 @@ int test_compiler_binary(Toy_Bucket** bucketHandle) { *((unsigned char*)(buffer + 67)) != 0 || *((unsigned char*)(buffer + 68)) != TOY_OPCODE_ELIMINATE || - *((unsigned char*)(buffer + 69)) != 0 || + *((unsigned char*)(buffer + 69)) != 1 || *((unsigned char*)(buffer + 70)) != 0 || *((unsigned char*)(buffer + 71)) != 0 ||