void Interpreter::divDoubles() { double right = popDouble(); double left = popDouble(); //cout << "Dividing " << left << " " << right << endl; pushDouble(left / right); }
static char cmdRoll( tPSStackItem **topStack, void* /*dummy*/, const char* /*path*/ ) { char error = FALSE; int jj = (int)floor( popDouble( topStack, &error ) + 0.5f ); int nn = (int)floor( popDouble( topStack, &error ) + 0.5f ); tPSStackItem **stackItems = (tPSStackItem**)malloc( sizeof( tPSStackItem* ) * nn ); int xx; if( nn <= 0 ) { free( stackItems ); return FALSE; } for( xx = 0; xx < nn; ++xx ) stackItems[ xx ] = pop( topStack ); if( !error || !stackItems[ nn - 1 ] ) { free( stackItems ); return FALSE; } jj %= nn; while( jj < 0 ) jj += nn; for( xx = nn + jj - 1; xx >= jj; --xx ) push( topStack, stackItems[ xx % nn ] ); free( stackItems ); return TRUE; }
static char cmdMin( tPSStackItem **topStack, void* /*dummy*/, const char* /*path*/ ) { char error = FALSE; double bb = popDouble( topStack, &error ); double aa = popDouble( topStack, &error ); if( error ) return FALSE; pushDouble( topStack, aa < bb ? aa : bb ); return TRUE; }
void Interpreter::loadFunParamsInCtx(uint16_t id) { BytecodeFunction* fun = ((BytecodeFunction*)_code->functionById(id)); uint16_t n = fun->parametersNumber(); FunctionContext* ctx = this->topContext(); //cout << "loading params: " << n << endl; //cout << "stack size " << _stack.size() << endl; for (uint16_t i = 0; i < n; ++i) { VarType type = fun->parameterType(i); switch (type) { case VT_INT: ctx->storeInt(ctx->getId(), i, popInt()); //cout << "int loaded from bc" << endl; break; case VT_DOUBLE: ctx->storeDouble(ctx->getId(), i, popDouble()); //cout << "double loaded from bc" << endl; break; default: //cout << "loading STRIG or INVALID from bc" << endl; assert(false); break; } } }
double calculatePostfix(const char expression[]) { DoubleStack *stack = createDoubleStack(); char c = EOF; int i = 0; while (true) { c = expression[i]; ++i; if (c == '\0') break; switch (c) { case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '0': { pushDouble(stack, c - '0'); break; } case '+': { pushDouble(stack, popDouble(stack) + popDouble(stack)); break; } case '-': { double operand2 = popDouble(stack); pushDouble(stack, popDouble(stack) - operand2); break; } case '*': { pushDouble(stack, popDouble(stack) * popDouble(stack)); break; } case '/': { double operand2 = popDouble(stack); if (operand2 == 0) break; pushDouble(stack, popDouble(stack) / operand2); break; } } } double result = popDouble(stack); deleteDoubleStack(stack); return result; }
void OSCServerThread::run() { oscpkt::UdpSocket server; server.bindTo(this->port); if (!server.isOk()) { std::cerr << "Error opening OSC server at " << port << std::endl; return; } std::cout << "Started OSC Server at " << port << std::endl; oscpkt::PacketReader reader; oscpkt::PacketWriter writer; while (server.isOk() && !mustQuit) { if (server.receiveNextPacket(30)) { reader.init(server.packetData(), server.packetSize()); oscpkt::Message *msg; while (reader.isOk() && (msg = reader.popMessage()) != 0) { QVariantList message; message.append(QString::fromStdString( msg->addressPattern())); auto args = msg->arg(); while (!args.isOkNoMoreArgs()) { if (args.isInt32()) { int32_t i; args = args.popInt32(i); message.append(i); } else if (args.isInt64()) { int64_t i; args = args.popInt64(i); message.append( static_cast<qlonglong>(i)); } else if (args.isFloat()) { float f; args = args.popFloat(f); message.append(f); } else if (args.isDouble()) { double d; args = args.popDouble(d); message.append(d); } else if (args.isStr()) { std::string s; args = args.popStr(s); message.append( QString::fromStdString(s)); } } emit messageIn(message); } } } }
//0x8e d2i int op_d2i( unsigned char **opCode, StackFrame *stack, SimpleConstantPool *p ) { double value1 = popDouble(stack); int result = 0; result = (int)value1; #if SIMPLE_JVM_DEBUG printf("d2i: %d <-- %f\n", result, value1); #endif pushInt(stack, result); *opCode = *opCode + 1; return 0; }
tdble GfFormCalcFunc( void *cmd, void *parmHandle, const char *path ) { tdble result; char error = FALSE; tPSCommand *command = (tPSCommand *)cmd; tPSStackItem *item = NULL; pushDouble( &item, 0.0f ); item->varList = parmHandle; execCommands( &item, command, path ); result = (tdble)popDouble( &item, &error ); while( item != NULL && !error ) popFree( &item ); return result; }
static double get_double_parameter(StackFrame *stack, SimpleConstantPool *p) { double value = 0.0f; if (is_ref_entry(stack)) { int index = popInt(stack); value = get_double_from_constant_pool(p, index); #if SIMPLE_JVM_DEBUG printf("index %d\n", index); printf("get value from constant pool = %f\n", value); #endif } else { value = popDouble(stack); #if SIMPLE_JVM_DEBUG printf("get value from stack = %f\n", value); #endif } return value; }
void StackMachine::run() { while (true) { Instruction current_instruction = currentBytecode().getInsn(current_location_++); char const * v = 0; switch (current_instruction) { case BC_DLOAD: push(currentBytecode().getDouble(current_location_)); current_location_ += sizeof(double); break; case BC_DLOAD0: push(0.0); break; case BC_DLOAD1: push(1.0); break; case BC_ILOAD: push(currentBytecode().getInt64(current_location_)); current_location_ += sizeof(vm_int_t); break; case BC_ILOAD0: push(vm_int_t(0L)); break; case BC_ILOAD1: push(vm_int_t(1L)); break; case BC_SLOAD: push(code_->constantById(getCurrent2BytesAndShiftLocation()).c_str()); break; case BC_SLOAD0: push(__EMPTY_STRING); break; case BC_DADD: PUSH_BINARY_RESULT(double, std::plus<double>()); break; case BC_DSUB: PUSH_BINARY_RESULT(double, std::minus<double>()); break; case BC_DMUL: PUSH_BINARY_RESULT(double, std::multiplies<double>()); break; case BC_DDIV: PUSH_BINARY_RESULT(double, std::divides<double>()); break; case BC_IADD: PUSH_BINARY_RESULT(vm_int_t, std::plus<vm_int_t>()); break; case BC_ISUB: PUSH_BINARY_RESULT(vm_int_t, std::minus<vm_int_t>()); break; case BC_IMUL: PUSH_BINARY_RESULT(vm_int_t, std::multiplies<vm_int_t>()); break; case BC_IDIV: PUSH_BINARY_RESULT(vm_int_t, std::divides<vm_int_t>()); break; case BC_IMOD: PUSH_BINARY_RESULT(vm_int_t, std::modulus<vm_int_t>()); break; case BC_IAOR: PUSH_BINARY_RESULT(vm_int_t, std::bit_or<vm_int_t>()); break; case BC_IAAND: PUSH_BINARY_RESULT(vm_int_t, std::bit_and<vm_int_t>()); break; case BC_IAXOR: PUSH_BINARY_RESULT(vm_int_t, std::bit_xor<vm_int_t>()); break; case BC_DCMP: PUSH_BINARY_RESULT_(double, vm_int_t, cmp<double>); break; case BC_ICMP: PUSH_BINARY_RESULT(vm_int_t, cmp<vm_int_t>); break; case BC_DNEG: push(-popDouble()); break; case BC_INEG: push(-popInt()); break; case BC_IPRINT: os_ << popInt(); os_.flush(); break; case BC_DPRINT: os_ << popDouble(); os_.flush(); break; case BC_SPRINT: v = popString(); os_ << (v == 0 ? "" : v); os_.flush(); break; case BC_I2D: push((double) popInt()); break; case BC_S2I: v = popString(); try { push((vm_int_t) v); } catch (std::exception & e) { throwError("S2I conversion error: " + string(v)); } break; case BC_D2I: push((vm_int_t) popDouble()); break; case BC_POP: pop(); break; case BC_LOADDVAR0: loadLocalVar<double>(0); break; case BC_LOADDVAR1: loadLocalVar<double>(1); break; case BC_LOADDVAR2: loadLocalVar<double>(2); break; case BC_LOADDVAR3: loadLocalVar<double>(3); break; case BC_LOADDVAR: loadLocalVar<double>(getCurrent2BytesAndShiftLocation()); break; case BC_LOADIVAR0: loadLocalVar<vm_int_t>(0); break; case BC_LOADIVAR1: loadLocalVar<vm_int_t>(1); break; case BC_LOADIVAR2: loadLocalVar<vm_int_t>(2); break; case BC_LOADIVAR3: loadLocalVar<vm_int_t>(3); break; case BC_LOADIVAR: loadLocalVar<vm_int_t>(getCurrent2BytesAndShiftLocation()); break; case BC_LOADSVAR0: loadLocalVar<vm_str_t>(0); break; case BC_LOADSVAR1: loadLocalVar<vm_str_t>(1); break; case BC_LOADSVAR2: loadLocalVar<vm_str_t>(2); break; case BC_LOADSVAR3: loadLocalVar<vm_str_t>(3); break; case BC_LOADSVAR: loadLocalVar<vm_str_t>(getCurrent2BytesAndShiftLocation()); break; case BC_STOREDVAR0: storeLocalVar<double>(0); break; case BC_STOREDVAR1: storeLocalVar<double>(1); break; case BC_STOREDVAR2: storeLocalVar<double>(2); break; case BC_STOREDVAR3: storeLocalVar<double>(3); break; case BC_STOREDVAR: storeLocalVar<double>(getCurrent2BytesAndShiftLocation()); break; case BC_STOREIVAR0: storeLocalVar<vm_int_t>(0); break; case BC_STOREIVAR1: storeLocalVar<vm_int_t>(1); break; case BC_STOREIVAR2: storeLocalVar<vm_int_t>(2); break; case BC_STOREIVAR3: storeLocalVar<vm_int_t>(3); break; case BC_STOREIVAR: storeLocalVar<vm_int_t>(getCurrent2BytesAndShiftLocation()); break; case BC_STORESVAR0: storeLocalVar<vm_str_t>(0); break; case BC_STORESVAR1: storeLocalVar<vm_str_t>(1); break; case BC_STORESVAR2: storeLocalVar<vm_str_t>(2); break; case BC_STORESVAR3: storeLocalVar<vm_str_t>(3); break; case BC_STORESVAR: storeLocalVar<vm_str_t>(getCurrent2BytesAndShiftLocation()); break; case BC_LOADCTXDVAR: processLoadContextVar<double>(); break; case BC_LOADCTXIVAR: processLoadContextVar<vm_int_t>(); break; case BC_LOADCTXSVAR: processLoadContextVar<vm_str_t>(); break; case BC_STORECTXDVAR: processStoreContextVar<double>(); break; case BC_STORECTXIVAR: processStoreContextVar<vm_int_t>(); break; case BC_STORECTXSVAR: processStoreContextVar<vm_str_t>(); break; case BC_JA: current_location_ = calculateTransitionAndShiftLocation(); continue; case BC_IFICMPE: case BC_IFICMPNE: case BC_IFICMPL: case BC_IFICMPLE: case BC_IFICMPG: case BC_IFICMPGE: { index_t transition = calculateTransitionAndShiftLocation(); vm_int_t a = popInt(); vm_int_t b = popInt(); if (ifSatisfied(current_instruction, cmp(a, b))) { current_location_= transition; continue; } break; } case BC_CALL: processCall(getCurrent2BytesAndShiftLocation()); break; case BC_CALLNATIVE: processNativeCall(getCurrent2BytesAndShiftLocation()); continue; case BC_RETURN: if (processReturn()) { return; } continue; default: throwError("unsupported insn=" + string(bytecodeName(current_instruction))); return; } } }
v8::Handle<v8::Value> QV8Worker::deserialize(const char *&data, QV8Engine *engine) { quint32 header = popUint32(data); Type type = headertype(header); switch (type) { case WorkerUndefined: return v8::Undefined(); case WorkerNull: return v8::Null(); case WorkerTrue: return v8::True(); case WorkerFalse: return v8::False(); case WorkerString: { quint32 size = headersize(header); v8::Local<v8::String> string = v8::String::New((uint16_t*)data, size - 1); data += ALIGN(size * sizeof(uint16_t)); return string; } case WorkerFunction: Q_ASSERT(!"Unreachable"); break; case WorkerArray: { quint32 size = headersize(header); v8::Local<v8::Array> array = v8::Array::New(size); for (quint32 ii = 0; ii < size; ++ii) { array->Set(ii, deserialize(data, engine)); } return array; } case WorkerObject: { quint32 size = headersize(header); v8::Local<v8::Object> o = v8::Object::New(); for (quint32 ii = 0; ii < size; ++ii) { v8::Handle<v8::Value> name = deserialize(data, engine); v8::Handle<v8::Value> value = deserialize(data, engine); o->Set(name, value); } return o; } case WorkerInt32: return v8::Integer::New((qint32)popUint32(data)); case WorkerUint32: return v8::Integer::NewFromUnsigned(popUint32(data)); case WorkerNumber: return v8::Number::New(popDouble(data)); case WorkerDate: return v8::Date::New(popDouble(data)); case WorkerRegexp: { quint32 flags = headersize(header); quint32 length = popUint32(data); v8::Local<v8::String> source = v8::String::New((uint16_t*)data, length - 1); data += ALIGN(length * sizeof(uint16_t)); return v8::RegExp::New(source, (v8::RegExp::Flags)flags); } case WorkerListModel: { void *ptr = popPtr(data); QDeclarativeListModelWorkerAgent *agent = (QDeclarativeListModelWorkerAgent *)ptr; v8::Handle<v8::Value> rv = engine->newQObject(agent); if (rv->IsObject()) { QDeclarativeListModelWorkerAgent::VariantRef ref(agent); QVariant var = qVariantFromValue(ref); rv->ToObject()->SetHiddenValue(v8::String::New("qml::ref"), engine->fromVariant(var)); } agent->release(); agent->setV8Engine(engine); return rv; } } Q_ASSERT(!"Unreachable"); return v8::Undefined(); }
void Interpreter::dMul() { double d1 = popDouble(); double d2 = popDouble(); pushDouble(d1*d2); }
void Interpreter::addDoubles() { pushDouble(popDouble() + popDouble()); }
void Interpreter::subDoubles() { double top = popDouble(); double down = popDouble(); pushDouble(top - down); }
//------------------------------------------------------------------------------ // An adaptation of a function of the same name in the original Babuino code. //------------------------------------------------------------------------------ void Babuino::code_exec() { //Serial.println("code_exec()"); if (!_storage.getReadyToRead()) { // TO DO: What now? How do I report an error? } while (_states.getRunRequest() == RUNNING) { _storage.readByte(_regs.pc, _regs.opCode); _regs.pc++; switch (_regs.opCode) { case OP_CONFIG: withConfig(); break; case OP_MATH: withMath(); break; case OP_BYTE: case OP_INT8: case OP_SPAN: { //Serial.println("int8 "); uint8_t value; _regs.pc = _storage.readByte(_regs.pc, value); pushUint8(_stack, value); } break; case OP_SHORT: case OP_UINT16: { //Serial.print("int16: "); uint16_t value; _regs.pc = _storage.read<uint16_t>(_regs.pc, value); //Serial.println(value); pushUint16(_stack, value); } break; case OP_GLOBAL: { //Serial.print("global: "); STACKPTR value; _regs.pc = _storage.read<STACKPTR>(_regs.pc, value); //Serial.println(value); pushStackPtr(_stack, value); //_stack.push(_stack.getBottom() - value); } break; case OP_INT32: case OP_UINT32: { //Serial.print("int32 "); uint32_t value; _regs.pc = _storage.read<uint32_t>(_regs.pc, value); #ifdef SUPPORT_32BIT pushUint32(_stack, value); #else pushUint16(_stack, (value >> 16) & 0xFFFF); // High 16 bits pushUint16(_stack, value & 0xFFFF); // Low 16 bits #endif } break; #ifdef SUPPORT_FLOAT case OP_FLOAT: { //Serial.print("float "); float value; _regs.pc = _storage.read<float>(_regs.pc, value); pushFloat(_stack, value); } break; #endif #ifdef SUPPORT_DOUBLE case OP_DOUBLE: { //Serial.print("double "); double value; _regs.pc = _storage.read<double>(_regs.pc, value); pushDouble(_stack, value); } break; #endif case OP_BOOL: { //Serial.print("bool "); bool value; _regs.pc = _storage.read<bool>(_regs.pc, value); pushUint8(_stack, (uint8_t)value); } break; case OP_CPTR: { //Serial.print("cptr "); PROGPTR value; _regs.pc = _storage.read<PROGPTR>(_regs.pc, value); pushProgPtr(_stack, value); } break; #ifdef SUPPORT_STRING case OP_STRING: { //Serial.print("string: \""); // ***KLUDGE WARNING*** // Borrowing unused (hopefully) stack space as a buffer! // (To avoid having to allocate another buffer. uint8_t* psz = (uint8_t*)getTopAddress(_stack); uint8_t nextChar; int16_t i = -1; do { i++; _regs.pc = _storage.readByte(_regs.pc, nextChar); psz[i] = nextChar; } while (nextChar); //Serial.print((char *)psz); //Serial.print("\" "); // Logically this is wrong because I'm apparently // pushing a string to a location that it already // occupies. However, the stack implementation // pushes strings onto a separate stack, then // pushes the location onto the main stack. So // the string doesn't get copied over itself, and // is already copied before the first characters are // overwritten by pushing the said location onto the // main stack. //STACKSTATE state; //getStackState(_stack, &state); //Serial.print("[("); Serial.print(state.top); Serial.print(","); Serial.print(state.stringTop);Serial.print(") -> ("); pushString(_stack, psz); //getStackState(_stack, &state); //Serial.print(state.top); Serial.print(","); Serial.print(state.stringTop);Serial.println(")]"); } break; case OP_ASCII: { uint8_t* psz; topString(_stack, &psz); uint8_t ascii = psz[0]; popString(_stack); pushUint8(_stack, ascii); } break; case OP_STRLEN: { uint8_t* psz; topString(_stack, &psz); uint8_t len = strlen((char*)psz); popString(_stack); pushUint8(_stack, len); } break; #endif case OP_BEEP: //Serial.println("---beep---"); beep(); break; case OP_LEDON: //Serial.println("---LED on---"); userLed(true); // set the correct bit break; case OP_LEDOFF: //Serial.println("---LED off---"); userLed(false); break; case OP_WITHINT8: case OP_WITHUINT8: case OP_WITHINT16: case OP_WITHUINT16: case OP_WITHBOOL: case OP_WITHPTR: #ifdef SUPPORT_32BIT case OP_WITHINT32: case OP_WITHUINT32: #endif #ifdef SUPPORT_FLOAT case OP_WITHFLOAT: #endif #ifdef SUPPORT_DOUBLE case OP_WITHDOUBLE: #endif #ifdef SUPPORT_STRING case OP_WITHSTRING: #endif _regs.withCode = _regs.opCode; break; case OP_LOCAL: { //Serial.print("local: local frame ("); //Serial.print(_regs.localFrame); //Serial.print(") - "); STACKPTR varOffset; _regs.pc = _storage.read<uint16_t>(_regs.pc, (uint16_t&)varOffset); pushStackPtr(_stack, (STACKPTR)_regs.localFrame.top + varOffset); //Serial.print(varOffset); //Serial.print(" = global "); //Serial.println(_regs.localFrame + varOffset); } break; case OP_PARAM: { //Serial.print("param: "); STACKPTR varOffset; _regs.pc = _storage.read<uint16_t>(_regs.pc, (uint16_t&)varOffset); // We have an index into the parameters, which were put on // the stack in reverse order before the function call. // Calculate the absolute stack offset using the local // stack frame offset. // Also, the total size of the arguments was pushed last, // so we need to step past that too. // TODO: Check against the total argument size. pushStackPtr(_stack, getArgsLocation() - sizeof(uint8_t) // Number of args - varOffset // Offset to the required param ); } break; case OP_BLOCK: { //Serial.print("block "); descendBlock(); // Shift the flag to the next block bit //char psz[10]; //utoa(_regs.blockDepthMask, psz, 2); //Serial.println(psz); uint16_t blockLength; // Push address of next instruction (following the block // length data) pushProgPtr(_stack, (PROGPTR)_regs.pc + sizeof(uint16_t)); _storage.read<uint16_t>(_regs.pc, blockLength); // Step past the block (tests there will bring execution back) _regs.pc.increment(blockLength); } break; case OP_EOB: //Serial.println("--eob--"); setBlockExecuted(); // Set the bit to indicate that this block has executed break; case OP_DO: { //Serial.println("---do---"); // OP_DO is like OP_BLOCK except that execution falls through to // the top of the block of code unconditionally rather than jump // to the end where some condition is tested. // Need to: // - Push the address that the following OP_BLOCK would push // - Step past the: // - The OP_BLOCK code (uint8_t) // - The block size (uint16_t) // After going through the code block it should jump back to // the beginning of the OP_BLOCK and loop as usual. descendBlock(); // Shift the flag to the next block bit (normally done by OP_BLOCK) PROGPTR startOfBlock = (PROGPTR)_regs.pc + sizeof(uint8_t) +sizeof(uint16_t); pushProgPtr(_stack, startOfBlock); _regs.pc.set(startOfBlock); } break; case OP_WHILE: { //Serial.print("while "); bool condition; PROGPTR blockAddr; popUint8(_stack, (uint8_t*)&condition); //Serial.println(condition ? "true" : "false"); //_stack.pop(blockAddr); if (condition) // if true then go to the block start address { topProgPtr(_stack, &blockAddr); _regs.pc = blockAddr; } else { popProgPtr(_stack, &blockAddr); // Throw it away ascendBlock(); // Finished with this block now } } break; case OP_REPEAT: { //Serial.print("repeat "); PROGPTR blockAddr; uint16_t max; popProgPtr(_stack, &blockAddr); popUint16(_stack, &max); uint16_t repcount; if (!hasBlockExecuted()) // First time around? { repcount = 1; pushUint16(_stack, repcount); // point to the counter we just pushed STACKPTR slot = getTop(_stack); // Save outer loop's repcount pointer pushStackPtr(_stack, _regs.repcountLocation); // Set it to ours _regs.repcountLocation = slot; } else { getUint16(_stack, _regs.repcountLocation, &repcount); // Get counter value repcount++; } //Serial.println(repcount); if (repcount <= max) { setUint16(_stack, _regs.repcountLocation, repcount); pushUint16(_stack, max); pushProgPtr(_stack, blockAddr); _regs.pc = blockAddr; } else { // Restore the outer loop's repcount pointer popStackPtr(_stack, &_regs.repcountLocation); popUint16(_stack, &repcount); // Dispose of counter ascendBlock(); // Finished with this block now } } break; case OP_REPCOUNT: { uint16_t repcount; getUint16(_stack, _regs.repcountLocation, &repcount); pushUint16(_stack, repcount); } break; case OP_FOR: { //Serial.println("for "); // The counter variable has already been set to the from // value, so the from value isn't on the stack. PROGPTR blockAddr; int16_t step, to, from; STACKPTR counterOff; int16_t counterVal; popProgPtr(_stack, &blockAddr); popUint16(_stack, (uint16_t*)&step); popUint16(_stack, (uint16_t*)&to); popUint16(_stack, (uint16_t*)&from); popStackPtr(_stack, &counterOff); getUint16(_stack, counterOff, (uint16_t*)&counterVal); //Serial.print(counterVal); //Serial.print(" "); //Serial.print(to); //Serial.print(" "); //Serial.println(step); bool keepGoing; // See if this is the first time around if (!hasBlockExecuted()) { counterVal = from; keepGoing = true; } else { // If step > 0 then assume from < to otherwise assume from > to keepGoing = (step > 0) ? (counterVal < to) : (counterVal > to); counterVal += step; } if (keepGoing) { setUint16(_stack, counterOff, (uint16_t)counterVal); _regs.pc = blockAddr; // reiterate pushStackPtr(_stack, counterOff); // Var offset pushUint16(_stack, (uint16_t)from); // to pushUint16(_stack, (uint16_t)to); // to pushUint16(_stack, (uint16_t)step); // step pushProgPtr(_stack, blockAddr); } else { ascendBlock(); } } break; case OP_IF: { //Serial.print("if "); // If it's the first time through then check the // condition if (!hasBlockExecuted()) { PROGPTR blockAddr; bool condition; popProgPtr(_stack, &blockAddr); // Block initial address popUint8(_stack, (uint8_t*)&condition); // argument to test //Serial.println(condition ? "true" : "false"); if (condition) { _regs.pc = blockAddr; } else { ascendBlock(); } } else { ascendBlock(); } } break; // IFELSE starts with address of THEN and ELSE lists (and // CONDITIONAL) on the stack. CONDITIONAL is tested and // appropriate list is run. case OP_IFELSE: { //Serial.print("ifelse "); PROGPTR elseBlock; popProgPtr(_stack, &elseBlock); // ELSE block start // Note that descendBlock() will have been called twice // the first time around (once for each block). ascendBlock(); // Remove the else block... // ...and use the then block flag for both purposes if (!hasBlockExecuted()) { PROGPTR thenBlock; bool condition; popProgPtr(_stack, &thenBlock); // THEN block start popUint8(_stack, (uint8_t*)&condition); // argument to test if (condition) { //Serial.println("(then)"); _regs.pc = thenBlock; // The ELSE address will get pushed again when // execution falls into the ELSE block after // exiting the THEN block. // Another else block will be descended into // as well, and ascended away again above. // The eob code will be encountered at the end // of the then block, and that will set the // executed flag. } else { //Serial.println("(else)"); _regs.pc = elseBlock; // the "ELSE" list pushProgPtr(_stack, (PROGPTR)0); // Push fake ELSE to balance // Borrow the then block flag and set it now as // executed since it won't actually be set // otherwise. setBlockExecuted(); // Descend the else block now, as // this also won't be done in the block's code. descendBlock(); } } else { //popProgPtr(_stack, &elseBlock); // dispose of unrequired address ascendBlock(); // ie. the then block } } break; case OP_PUSH: { //Serial.print("push "); uint8_t amount; popUint8(_stack, &amount); pushn(_stack, (STACKPTR)amount); } break; case OP_POP: { //Serial.print("pop "); uint8_t amount; popUint8(_stack, &amount); popn(_stack, (STACKPTR)amount); } break; case OP_CHKPOINT: getStackState(_stack, &_regs.checkPoint); break; case OP_ROLLBACK: setStackState(_stack, &_regs.checkPoint); break; case OP_CALL: { //Serial.println("call"); PROGPTR procAddr; popProgPtr(_stack, &procAddr); // Get the function location // Save the args location used by the calling function, and // set it to what was the stack top before it was pushed. /* _regs.argsLoc = _stack.push(_regs.argsLoc); //Serial.print("args location: "); //Serial.println(_regs.argsLoc); */ pushProgPtr(_stack, (PROGPTR)_regs.pc); // Save the current code location for the return _regs.pc.set(procAddr); // Now jump to the function } break; case OP_BEGIN: //Serial.println("begin"); pushRegisters(); // Save state of the caller _regs.blockDepthMask = 0; _regs.blocksExecuted = 0; getStackState(_stack, &_regs.localFrame); // = getTop(_stack); //Serial.println(_regs.localFrame); break; case OP_RETURN: { //Serial.print("return "); //Unwind the stack to the beginning of the local frame setStackState(_stack, &_regs.localFrame); popRegisters(); PROGPTR returnAddr; popProgPtr(_stack, &returnAddr); // Get the return address //_stack.pop(_regs.argsLoc); // Restore the param location for the calling function _regs.pc.set(returnAddr); } break; case OP_EXIT: reset(); //Serial.println("---exit---"); break; case OP_LOOP: { //Serial.println("---loop---"); PROGPTR blockAddr; topProgPtr(_stack, &blockAddr); _regs.pc.set(blockAddr); } break; case OP_WAIT: { //Serial.println("---wait---"); uint16_t tenths; popUint16(_stack, &tenths); delay(100 * tenths); } break; case OP_TIMER: //Serial.print("timer "); pushUint16(_stack, _timerCount); // TODO: implement timer!! break; case OP_RESETT: //Serial.println("---resett---"); _timerCount = 0; break; case OP_RANDOM: //Serial.print("random "); pushUint16(_stack, (uint16_t)random(0, 32767)); break; case OP_RANDOMXY: { //Serial.print("randomxy "); int16_t x; int16_t y; popUint16(_stack, (uint16_t*)&y); popUint16(_stack, (uint16_t*)&x); pushUint16(_stack, (uint16_t)random(x, y)); } break; case OP_MOTORS: { //Serial.print("motors "); uint8_t selected; popUint8(_stack, &selected); _selectedMotors = (Motors::Selected)selected; } break; case OP_THISWAY: //Serial.print("---thisway---"); _motors.setDirection(_selectedMotors, MotorBase::THIS_WAY); break; case OP_THATWAY: //Serial.print("---thatway---"); _motors.setDirection(_selectedMotors, MotorBase::THAT_WAY); break; case OP_RD: //Serial.print("---rd---"); _motors.reverseDirection(_selectedMotors); break; case OP_SETPOWER: { //Serial.print("setpower "); uint8_t power; popUint8(_stack, &power); if (power > 7) power = 7; _motors.setPower(_selectedMotors, power); } break; case OP_BRAKE: //Serial.println("---brake---"); _motors.setBrake(_selectedMotors, MotorBase::BRAKE_ON); break; case OP_ON: //Serial.println("---on---"); _motors.on(_selectedMotors); break; case OP_ONFOR: { //Serial.print("onfor"); uint16_t tenths; popUint16(_stack, &tenths); _motors.on(_selectedMotors); delay(100 * tenths); _motors.off(_selectedMotors); } break; case OP_OFF: //Serial.println("---off---"); _motors.off(_selectedMotors); break; case OP_SENSOR1: case OP_SENSOR2: case OP_SENSOR3: case OP_SENSOR4: case OP_SENSOR5: case OP_SENSOR6: case OP_SENSOR7: case OP_SENSOR8: //Serial.print("sensor "); //Serial.print(_regs.opCode - OP_SENSOR1); //Serial.print(" "); pushUint16(_stack, (uint16_t)readAnalog(_regs.opCode - OP_SENSOR1)); break; case OP_AIN: { //Serial.print("ain "); uint8_t input; popUint8(_stack, &input); pushUint16(_stack, (uint16_t)readAnalog(input)); } break; case OP_AOUT: { //Serial.print("aout "); uint8_t output; uint8_t value; popUint8(_stack, &output); popUint8(_stack, &value); writeAnalog(output, value); } break; case OP_SWITCH1: case OP_SWITCH2: case OP_SWITCH3: case OP_SWITCH4: case OP_SWITCH5: case OP_SWITCH6: case OP_SWITCH7: case OP_SWITCH8: { //Serial.print("switch "); //Serial.print(_regs.opCode - OP_SWITCH1); //Serial.print(" "); int16_t val = readAnalog(_regs.opCode - OP_SWITCH1); if (val < 0) pushUint8(_stack, (uint8_t)false); else pushUint8(_stack, (uint8_t)!!(val >> 7)); } break; case OP_NOT: break; case OP_AND: break; case OP_OR: break; case OP_XOR: break; case OP_DIN: { //Serial.print("din "); uint8_t input; popUint8(_stack, &input); pushUint8(_stack, (uint8_t)readDigital(input)); } break; case OP_DOUT: { //Serial.print("dout "); uint8_t output; bool value; popUint8(_stack, &output); popUint8(_stack, (uint8_t*)&value); writeDigital(output, value); } break; case OP_BTOS: { int8_t value; popUint8(_stack, (uint8_t*)&value); pushUint16(_stack,(uint16_t)value); } break; case OP_UBTOS: { uint8_t value; popUint8(_stack, &value); pushUint16(_stack,(uint16_t)value); } break; case OP_STOB: // and OP_USTOB { //Serial.print("stob: "); uint16_t value; popUint16(_stack, (uint16_t*)&value); //Serial.println(value); pushUint8(_stack, (uint8_t)value); } break; #ifdef SUPPORT_32BIT case OP_BTOI: { int8_t value; popUint8(_stack, (uint8_t*)&value); pushUint32(_stack,(uint32_t)value); } break; case OP_UBTOI: { uint8_t value; popUint8(_stack, &value); pushUint32(_stack,(uint32_t)value); } break; case OP_STOI: { int16_t value; popUint16(_stack, (uint16_t*)&value); pushUint32(_stack,(uint32_t)value); } break; case OP_USTOI: { uint16_t value; popUint16(_stack, &value); pushUint32(_stack,(uint32_t)value); } break; case OP_ITOB: // and OP_UITOB { int32_t value; popUint32(_stack, (uint32_t*)&value); pushUint8(_stack, (uint8_t)value); } break; case OP_ITOS: //and OP_UITOS { int32_t value; popUint32(_stack, (uint32_t*)&value); pushUint16(_stack, (uint16_t)value); } break; #endif #ifdef SUPPORT_FLOAT case OP_BTOF: { int8_t value; popUint8(_stack, (uint8_t*)&value); pushFloat(_stack, (float)value); } break; case OP_UBTOF: { uint8_t value; popUint8(_stack, &value); pushFloat(_stack, (float)value); } break; case OP_STOF: { int16_t value; popUint16(_stack, (uint16_t*)&value); pushFloat(_stack, (float)value); } break; case OP_USTOF: { uint16_t value; popUint16(_stack, &value); pushFloat(_stack, (float)value); } break; case OP_FTOB: { float value; popFloat(_stack, &value); pushUint8(_stack, (uint8_t)value); } break; case OP_FTOS: { float value; popFloat(_stack, &value); pushUint16(_stack, (uint16_t)value); } break; #endif #ifdef SUPPORT_DOUBLE case OP_BTOD: { int8_t value; popUint8(_stack, (uint8_t*)&value); pushDouble(_stack, (double)value); } break; case OP_UBTOD: { uint8_t value; popUint8(_stack, &value); pushDouble(_stack, (double)value); } break; case OP_STOD: { int16_t value; popUint16(_stack, (uint16_t*)&value); pushDouble(_stack, (double)value); } break; case OP_USTOD: { uint16_t value; popUint8(_stack, (uint8_t*)&value); pushDouble(_stack, (double)value); } break; case OP_DTOB: { double value; popDouble(_stack, &value); pushUint8(_stack, (uint8_t)value); } break; case OP_DTOS: { double value; popDouble(_stack, &value); pushUint16(_stack, (uint16_t)value); } break; #endif #if defined(SUPPORT_DOUBLE) && defined(SUPPORT_32BIT) case OP_ITOD: { int32_t value; popUint32(_stack, (uint32_t*)&value); pushDouble(_stack, (double)value); } break; case OP_UITOD: { uint32_t value; popUint32(_stack, &value); pushDouble(_stack, (double)value); } break; case OP_DTOI: { double value; popDouble(_stack, &value); pushUint32(_stack, (uint32_t)value); } break; #endif #if defined(SUPPORT_DOUBLE) && defined(SUPPORT_FLOAT) case OP_FTOD: { float value; popFloat(_stack, &value); pushDouble(_stack, (double)value); } break; case OP_DTOF: { double value; popDouble(_stack, &value); pushFloat(_stack, (float)value); } break; #endif #if defined(SUPPORT_FLOAT) && defined(SUPPORT_32BIT) case OP_ITOF: { int32_t value; popUint32(_stack, (uint32_t*)&value); pushFloat(_stack, (float)value); } break; case OP_UITOF: { uint32_t value; popUint32(_stack, &value); pushFloat(_stack, (float)value); } break; case OP_FTOI: { float value; popFloat(_stack, &value); pushUint32(_stack, (uint32_t)value); } break; #endif case OP_I2CSTART: i2cStart(); break; case OP_I2CSTOP: i2cStop(); break; case OP_I2CTXRX: { uint16_t i2cAddr; uint16_t txBuffOffset; uint8_t txBuffLen; uint16_t rxBuffOffset; uint8_t rxBuffLen; uint16_t timeout; popUint16(_stack, &i2cAddr); popUint16(_stack, &txBuffOffset); popUint8(_stack, &txBuffLen); popUint16(_stack, &rxBuffOffset); popUint8(_stack, &rxBuffLen); popUint16(_stack, &timeout); i2cTxRx(i2cAddr, (uint8_t*)getStackAddress(_stack, txBuffOffset), txBuffLen, (uint8_t*)getStackAddress(_stack, rxBuffOffset), rxBuffLen, timeout); } break; case OP_I2CRX: { uint16_t addr; uint16_t rxBuffOffset; uint8_t rxBuffLen; uint16_t timeout; popUint16(_stack, &addr); popUint16(_stack, &rxBuffOffset); popUint8(_stack, &rxBuffLen); popUint16(_stack, &timeout); i2cRx(addr, (uint8_t*)getStackAddress(_stack, rxBuffOffset), rxBuffLen, timeout); } break; #ifdef SUPPORT_32BIT case OP_I2CERR: { //Serial.println("---i2cerr---"); uint32_t errors = i2cErrors(); pushUint32(_stack, errors); } break; #endif case OP_WAITUNTIL: case OP_RECORD: case OP_RECALL: case OP_RESETDP: case OP_SETDP: case OP_ERASE: case OP_SETSVH: case OP_SVR: case OP_SVL: // TODO!!! break; default: // All of the type specific codes are dealt with here if (!withCurrentType()) { //beep(); // Just an indication for now. Serial.print("unrecognised opcode: "); Serial.println(_regs.opCode); } break; } } }