Ejemplo n.º 1
0
void Interpreter::divDoubles() {
	double right = popDouble();
	double left = popDouble();

	//cout << "Dividing " << left << " " << right << endl;
    pushDouble(left / right);
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
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;
        }
    }
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 8
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;
}
Ejemplo n.º 9
0
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;
}
Ejemplo n.º 10
0
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;
        }
    }
}
Ejemplo n.º 11
0
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();
}
Ejemplo n.º 12
0
void Interpreter::dMul() {
    double d1 = popDouble();
    double d2 = popDouble();

    pushDouble(d1*d2);
}
Ejemplo n.º 13
0
void Interpreter::addDoubles() {
	pushDouble(popDouble() + popDouble());
}
Ejemplo n.º 14
0
void Interpreter::subDoubles() {
	double top = popDouble();
	double down = popDouble();

	pushDouble(top - down);
}
Ejemplo n.º 15
0
//------------------------------------------------------------------------------
// 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;

		}
	}
}