char *test_pop_push() { int i; for (i = 0; i < NUMS; i++) { Stack_push(stack, tests[i]); mu_assert(Stack_peek(stack) == tests[i], "wrong value"); } mu_assert(Stack_count(stack) == NUMS, "wrong count"); StackNode *v = NULL; for (v = stack->top; v != NULL; v = v->prev) { debug("Val: %s", (char *)v->data); } for (i = NUMS -1; i >= 0; i--) { char *val = Stack_pop(stack); mu_assert(val == tests[i], "wrong value"); } mu_assert(Stack_count(stack) == 0, "wrong count after poping"); return NULL; }
char *test_push_pop() { int i = 0; for(i = 0; i < NUM_TESTS; i++) { Stack_push(stack, tests[i]); mu_assert(Stack_peek(stack) == tests[i], "Wrong next value."); } mu_assert(Stack_count(stack) == NUM_TESTS, "Wrong count on push."); for(i = NUM_TESTS - 1; i >= 0; i--) { char *val = Stack_pop(stack); mu_assert(val == tests[i], "Wrong value on pop."); } mu_assert(Stack_count(stack) == 0, "Wrong count after pop."); return NULL; }
void IoCoroutine_rawPrint(IoCoroutine *self) { Coro *coro = DATA(self)->cid; if (coro) { printf("Coroutine_%p with cid %p ioStackSize %i\n", (void *)self, (void *)coro, (int)Stack_count(DATA(self)->ioStack)); } }
void Stack_print(STATE, Stack* stack) { printf("---STACK (%i)---\n", Stack_count(stack)); int i = 0; STACK_FOREACH(stack, node) { if(node) { printf("\n%i. ", i); Value_print(state, (VALUE)node->value); } i++; } printf("\n"); }
char *test_push_pop(void) { int i = 0; for (i = 0; i < NUM_TESTS; i++) { Stack_push(stack, tests[i]); mu_assert(Stack_peek(stack) == tests[i], "Wrong next value."); } mu_assert(Stack_count(stack) == NUM_TESTS, "Wrong count on push."); STACK_FOREACH(stack, cur) { debug("VAL: %s", (char *)cur->value); }
void Stack_do_on_(const Stack *self, StackDoOnCallback *callback, void *target) { Stack *stack = Stack_newCopyWithNullMarks(self); int i; for(i = 0; i < Stack_count(stack) - 1; i ++) { void *v = Stack_at_(stack, i); if (v) (*callback)(target, v); } Stack_free(stack); }
VALUE VM_run(STATE) { Debugger_load_current_file(state); int *ip = CURR_FRAME->fn->code; while(1) { switch(*ip) { case NOOP: break; case SETLINE: { // debugging ip++; Debugger_setline(state, *ip); break; } case PUSH: { Debugger_evaluate(state); ip++; debugi("PUSH %i", *ip); VALUE value = LITERAL(*ip); Stack_push(STACK, value); break; } case PUSHTRUE: { Debugger_evaluate(state); debugi("PUSHTRUE"); Stack_push(STACK, TrueObject); break; } case PUSHFALSE: { Debugger_evaluate(state); debugi("PUSHFALSE"); Stack_push(STACK, FalseObject); break; } case PUSHNIL: { Debugger_evaluate(state); debugi("PUSHNIL"); Stack_push(STACK, NilObject); break; } case JMP: { Debugger_evaluate(state); ip++; int jump = *ip; debugi("JMP %i", jump); while(jump--) ip++; break; } case JIF: { Debugger_evaluate(state); ip++; int jump = *ip; debugi("JIF %i", jump); VALUE value = Stack_pop(STACK); if (value == FalseObject || value == NilObject) { while(jump--) ip++; } break; } case JIT: { Debugger_evaluate(state); ip++; int jump = *ip; debugi("JIT %i", jump); VALUE value = Stack_pop(STACK); if (value != FalseObject && value != NilObject) { while(jump--) ip++; } break; } case GOTO: { Debugger_evaluate(state); ip++; int jump = *ip - 2; debugi("GOTO %i", jump); ip = CURR_FRAME->fn->code; while(jump--) ip++; break; } case GETSLOT: { Debugger_evaluate(state); ip++; debugi("GETSLOT %i", *ip); VALUE receiver = Stack_pop(STACK); VALUE slot = LITERAL(*ip); check(receiver->type != NilType, "Tried to get a slot from nil."); check(slot->type == StringType, "Slot name must be a String."); VALUE value = Value_get(receiver, VAL2STR(slot)); check(value, "Undefined slot %s on object type %i.", VAL2STR(slot), receiver->type); Stack_push(STACK, value); break; } case SETSLOT: { Debugger_evaluate(state); ip++; debugi("SETSLOT %i", *ip); VALUE value = Stack_pop(STACK); VALUE receiver = Stack_pop(STACK); VALUE slot = LITERAL(*ip); check(receiver->type != NilType, "Tried to set a slot on nil."); check(slot->type == StringType, "Slot name must be a String."); Value_set(state, receiver, VAL2STR(slot), value); Stack_push(STACK, value); // push the rhs back to the stack break; } case DEFN: { Debugger_evaluate(state); ip++; debugi("DEFN %i", *ip); VALUE fn_name = LITERAL(*ip); bstring state_fn = bfromcstr(VAL2STR(fn_name)); VALUE closure = Closure_new(state, STATE_FN(state_fn), CURR_FRAME); bdestroy(state_fn); Stack_push(STACK, closure); break; } case MAKEVEC: { Debugger_evaluate(state); ip++; debugi("MAKEVEC %i", *ip); int count = *ip; DArray *array = DArray_create(sizeof(VALUE), count || 1); while(count--) { VALUE elem = Stack_pop(STACK); check(elem, "Stack underflow."); GC_protect(elem); DArray_push(array, elem); } VALUE vector = Vector_new(state, array); Stack_push(STACK, vector); Vector_each(vector, ^ void (VALUE element) { GC_unprotect(element); }); break; } case SEND: { Debugger_evaluate(state); ip++; int op1 = *ip; ip++; int op2 = *ip; debugi("SEND %i %i", op1, op2); VALUE name = LITERAL(op1); int argcount = op2; DArray *locals = DArray_create(sizeof(VALUE), argcount+1); while(argcount--) { DArray_push(locals, Stack_pop(STACK)); } VALUE receiver = Stack_pop(STACK); // Special chicken-egg case. We cannot define "apply" as a native method // on Closure, since that triggers the creation of a new closure ad // infinitum, so we have to handle this special function here. if(receiver->type == ClosureType && strcmp(VAL2STR(name), "apply") == 0) { state->ret = ip; // save where we want to return ip = Function_call(state, VAL2FN(receiver), CURR_FRAME->self, locals, VAL2STR(name)); break; } VALUE closure = Value_get(receiver, VAL2STR(name)); check(closure, "Undefined slot %s on object type %i.", VAL2STR(name), receiver->type); if (closure->type != ClosureType && closure != NilObject) { // GETSLOT Stack_push(STACK, closure); DArray_destroy(locals); break; } #ifdef OPTIMIZE_SEND if(op2 == 1 && strcmp(VAL2STR(name), "[]") == 0) { // getslot VALUE key = (VALUE)DArray_at(locals, 0); Stack_push(STACK, Value_get(receiver, VAL2STR(key))); DArray_destroy(locals); break; } if(op2 == 2 && strcmp(VAL2STR(name), "[]=") == 0) { // setslot VALUE key = (VALUE)DArray_at(locals, 0); VALUE value = (VALUE)DArray_at(locals, 1); Value_set(receiver, VAL2STR(key), value); Stack_push(STACK, value); DArray_destroy(locals); break; } #endif state->ret = ip; // save where we want to return ip = Function_call(state, VAL2FN(closure), receiver, locals, VAL2STR(name)); break; } case PUSHLOBBY: { Debugger_evaluate(state); debugi("PUSHLOBBY"); Stack_push(STACK, state->lobby); break; } case PUSHSELF: { Debugger_evaluate(state); debugi("PUSHSELF"); Stack_push(STACK, CURR_FRAME->self); break; } case PUSHLOCAL: { Debugger_evaluate(state); ip++; Stack_push(STACK, LOCAL(*ip)); debugi("PUSHLOCAL %i", *ip); break; } case PUSHLOCALDEPTH: { Debugger_evaluate(state); ip++; int depth = *ip; ip++; Stack_push(STACK, DEEPLOCAL(depth, *ip)); debugi("PUSHLOCALDEPTH %i %i", depth, *ip); break; } case SETLOCAL: { Debugger_evaluate(state); ip++; debugi("SETLOCAL %i", *ip); LOCALSET(*ip, Stack_peek(STACK)); break; } case SETLOCALDEPTH: { Debugger_evaluate(state); ip++; int depth = *ip; ip++; debugi("SETLOCAL %i %i", depth, *ip); DEEPLOCALSET(depth, *ip, Stack_peek(STACK)); break; } case POP: { Debugger_evaluate(state); ip++; int count = *ip; debugi("POP %i", count); check(Stack_count(STACK) >= count, "Stack underflow."); while(count--) Stack_pop(STACK); break; } case RET: { Debugger_evaluate(state); debugi("RET"); CallFrame *old_frame = Stack_pop(FRAMES); ip = old_frame->ret; CallFrame_destroy(old_frame); check(Stack_count(STACK) > 0, "Stack underflow."); if (ip == NULL) return Stack_pop(STACK); // if there's nowhere to return, exit break; } case DUMP: { Debugger_evaluate(state); debugi("DUMP"); Stack_print(state, STACK); DArray *literals = CURR_FRAME->fn->literals; printf("--LITERALS (%i)--\n", DArray_count(literals)); Value_print_all(state, literals); DArray *locals = CURR_FRAME->locals; printf("--LOCALS (%i)--\n", DArray_count(locals)); Value_print_all(state, locals); break; } }
int IoCoroutine_rawIoStackSize(IoCoroutine *self) { return Stack_count(DATA(self)->ioStack); }