/* buildKey: build key from stack data */ char *buildKey( Array *array, Symbol *s ) { int args, i, keylen; char *index, *buffer; /* FIX: should eventually just realloc when size is exceeded */ /* create a buffer */ buffer = (char *)eMalloc( 256 ); buffer[0] = '\0'; /* check arg count */ args = (int)popNumber(); /* there must be at least one index */ if (args == 0) { ePrintf( Runtime, "Array %s[]x expects at least 1 index, not 0" ); } /* build the key backwards, for speed */ keylen = 0; for ( i = 1; i <= args; i++ ) { /* get index */ index = popString(); /* make sure it fits in the buffer */ keylen += strlen( index ); if (keylen >= 256) { ePrintf( Runtime, "Array key exceeds 256 characters" ); } /* append to key */ strcat( buffer, index ); /* ivanixcu: debug need free allocated memory of index! printf("ivanixdebug: freeing (index) (%d)\n", *index ); */ if (*index != '\0' ){ eFree( index ); } if (i < args) { /* add delimiter */ keylen += 1; if (keylen >= 256) { ePrintf( Runtime, "Array key exceeds 256 characters" ); } /* replace with ASCII 34 eventually */ strcat( buffer, "," ); } } /* resize the buffer */ return (char *)eRealloc( buffer, keylen+1 ); }
int NpcScriptInterface::luaActionSayCommand(lua_State* L) { //commandSay(words) std::string msg(popString(L)); ScriptEnviroment* env = getScriptEnv(); Npc* mynpc = env->getNpc(); if(mynpc) if(commands.exeCommand(mynpc, msg)) return 0; }
void basLoadMpeg() { char *fname; int usesound; int ret; usesound=popNumber(); fname=popString(); ret=loadmpeg(fname,usesound); if (ret==-1) ePrintf( Runtime, "SDLengine Error \n"); pushNumber(ret); }
/* setArrayElement: set an item in the array */ void setArrayElement( Symbol *s ) { int offset, type; Array *array; Variant *element; eMemTest( "setArrayElement: symbol", s ); array = getArray( s ); eMemTest( "setArrayElement: array", array ); if (array->isDynamic) { setDynamicValue( array, s ); } else { /* this should be implemented as a seperate routine */ offset = getStaticIndex( array, s ); element = array->data.item+offset; eMemTest( "setArrayElement: array element", element ); /* need to free string? */ if (element->datatype == DATA_STRING) { eFree( element->value.string ); } /* get the tos */ type = getStackType( tos ); switch (type) { case DATA_NUMBER: element->datatype = DATA_NUMBER; element->value.number = popNumber(); break; case DATA_STRING: element->datatype = DATA_STRING; element->value.string = popString(); break; default: ePrintf( Runtime, "setArrayElement: can't store %s %s into Array", datumName[type], s->name ); break; } } }
double callFunction(int nameLength, int argCount) { char *name = popString(nameLength); double *argValues = popArgs(argCount); int first = 0; int last = N_FUNCTIONS-1; while (first <= last) { /* binary search */ int middle = (first+last)/2; int flag = strcmp(name,functionTable[middle].name); if (flag == 0) return functionTable[middle].function(argCount, argValues); if (flag < 0) last = middle-1; else first = middle+1; } diagnoseError("Unknown Function"); return 0; }
std::string LuaInterface::traceback(const std::string& errorMessage, int level) { // gets debug.traceback getGlobal("debug"); getField("traceback"); remove(-2); // remove debug // calls debug.traceback(errorMessage, level) pushString(errorMessage); pushInteger(level); call(2,1); // returns the traceback message return popString(); }
int32_t NpcScriptInterface::luaGetNpcParameter(lua_State* L) { //getNpcParameter(paramKey) std::string paramKey = popString(L); Npc* npc = getScriptEnv()->getNpc(); if (npc) { auto it = npc->m_parameters.find(paramKey); if (it != npc->m_parameters.end()) { LuaScriptInterface::pushString(L, it->second); } else { lua_pushnil(L); } } else { lua_pushnil(L); } return 1; }
CITYHASH_API void GetCityHash64(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) { TCHAR hashString[MAX_STRLEN]; TCHAR hexResult[18]; g_stacktop = stacktop; g_variables = variables; memset(hashString, 0, sizeof(hashString)); memset(hexResult, 0, sizeof(hexResult)); if (!popString(hashString)) { pushString(L"error"); return; } uint64 result = CityHash64((const char*)&hashString[0], wcslen(hashString)*sizeof(TCHAR)); swprintf_s(hexResult, 17, L"%16I64X", result); pushString(hexResult); }
int NpcScriptInterface::luaActionSay(lua_State* L) { //selfSay(words, <optional> delay) int32_t parameters = lua_gettop(L); uint32_t delay = SCHEDULER_MINTICKS; if (parameters > 1) { delay = std::max(delay, popNumber(L)); } std::string msg(popString(L)); ScriptEnviroment* env = getScriptEnv(); Npc* npc = env->getNpc(); if(npc){ npc->doSay(msg, delay); } return 0; }
void GetCityHash64(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) { TCHAR hashString[MAX_STRLEN]; TCHAR hexResult[18] = { _T('\0') }; g_stacktop = stacktop; g_variables = variables; memset(hashString, 0, sizeof(hashString)); memset(hexResult, 0, sizeof(hexResult)); if (!popString(hashString)) { pushString(L"error"); return; } uint64 result = CityHash64((const char*)&hashString[0], wcslen(hashString)*sizeof(TCHAR)); // If the hash happens to work out to less than 16 hash digits it will just // use less of the buffer. swprintf(hexResult, L"%I64X", result); pushString(hexResult); }
int NpcScriptInterface::luaGetNpcParameter(lua_State *L) { //getNpcParameter(paramKey) std::string paramKey = popString(L); ScriptEnviroment* env = getScriptEnv(); Npc* npc = env->getNpc(); if(npc){ Npc::ParametersMap::iterator it = npc->m_parameters.find(paramKey); if(it != npc->m_parameters.end()){ lua_pushstring(L, it->second.c_str()); } else{ lua_pushnil(L); } } else{ lua_pushnil(L); } return 1; }
int LuaInterface::safeCall(int numArgs) { assert(hasIndex(-numArgs-1)); // saves the current stack size for calculating the number of results later int previousStackSize = stackSize(); // pushes error function int errorFuncIndex = previousStackSize - numArgs; pushCFunction(&LuaInterface::luaErrorHandler); insert(errorFuncIndex); // calls the function in protected mode (means errors will be caught) int ret = pcall(numArgs, LUA_MULTRET, errorFuncIndex); remove(errorFuncIndex); // remove error func // if there was an error throw an exception if(ret != 0) throw LuaException(popString()); // returns the number of results return (stackSize() + numArgs + 1) - previousStackSize; }
void calculator(char *string) { char *p = string; char number[32]; int counter = 0; int flagBracket = 0; struct stringStack *stackLabel = intiStringStack(); struct stringStack *stackNumber = intiStringStack(); struct stringStack *stackOpera = intiStringStack(); struct stringStack *stackResult = intiStringStack(); while(*p != '\0') { if(*p >= '0' && *p <= '9') { number[counter++] = *p; } else { if(counter != 0) { number[counter] = '\0'; counter = 0; pushString(stackNumber, number); } if(*p == '(') { flagBracket = 1; pushString(stackLabel, "("); } if(*p == ')') { while(getTopString(stackLabel)[0] != '(') { pushString(stackNumber, popString(stackLabel)); } popString(stackLabel); flagBracket = 0; } if(*p == '*' || *p == '/') { if(getTopString(stackLabel)[0] == '*' || getTopString(stackLabel)[0] == '/') { if(flagBracket == 1) { while(getTopString(stackLabel)[0] != '(') { pushString(stackNumber, popString(stackLabel)); } } else { while((stackLabel->top) > 0) { pushString(stackNumber, popString(stackLabel)); } } } if(*p == '*') { pushString(stackLabel, "*"); } else { pushString(stackLabel, "/"); } } if(*p == '+' || *p == '-') { if(flagBracket == 1) { while(getTopString(stackLabel)[0] != '(') { pushString(stackNumber, popString(stackLabel)); } } else { while((stackLabel->top) > 0) { pushString(stackNumber, popString(stackLabel)); } } if(*p == '+') { pushString(stackLabel, "+"); } else { pushString(stackLabel, "-"); } } } p++; } if(counter != 0) { number[counter] = '\0'; counter = 0; pushString(stackNumber, number); } while((stackLabel->top) > 0) { pushString(stackNumber, popString(stackLabel)); } while((stackNumber->top) > 0) { printf("Member: %s\n", (stackNumber->string)[stackNumber->top]); pushString(stackOpera, popString(stackNumber)); } int left = 0; int right = 0; int result = 0; int flagLeft = 0; int flagRight = 0; int flagResult = 0; while((stackOpera->top) > 0) { if(getTopString(stackOpera)[0] == '*') { right = atoi(popString(stackResult)); left = atoi(popString(stackResult)); result = left * right; // printf("Result: %d\n", result); char tmp[32] = {0}; sprintf(tmp,"%d",result); pushString(stackResult, tmp); } else if(getTopString(stackOpera)[0] == '/') { right = atoi(popString(stackResult)); left = atoi(popString(stackResult)); result = left / right; // printf("Result: %d\n", result); char tmp[32] = {0}; sprintf(tmp,"%d",result); pushString(stackResult, tmp); } else if(getTopString(stackOpera)[0] == '+') { right = atoi(popString(stackResult)); left = atoi(popString(stackResult)); result = left + right; // printf("Result: %d\n", result); char tmp[32] = {0}; sprintf(tmp,"%d",result); pushString(stackResult, tmp); } else if(getTopString(stackOpera)[0] == '-') { right = atoi(popString(stackResult)); left = atoi(popString(stackResult)); result = left - right; // printf("Result: %d\n", result); char tmp[32] = {0}; sprintf(tmp,"%d",result); pushString(stackResult, tmp); } else { pushString(stackResult, getTopString(stackOpera)); } (stackOpera->top)--; } printf("\nResult: %s\n", getTopString(stackResult)); }
//------------------------------------------------------------------------------ // 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; } } }
double *locateVariable(int nameLength) { /* identify variable name */ char *name = popString(nameLength); return locateVariableByName(name); }
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; } } }
CELL * p_pop(CELL * params) { CELL * list; CELL * cell = NULL; ssize_t index; int evalFlag = FALSE; params = getEvalDefault(params, &list); if(symbolCheck && isProtected(symbolCheck->flags)) return(errorProcExt2(ERR_SYMBOL_PROTECTED, stuffSymbol(symbolCheck))); if(!isList(list->type)) { if(list->type == CELL_STRING) return(popString(list, params)); else return(errorProcExt(ERR_LIST_OR_STRING_EXPECTED, list)); } /* leave last element optimization if popping first for queues */ if(params == nilCell) { cell = (CELL *)list->contents; list->contents = (UINT)cell->next; if(cell->next == nilCell) /* check if only one element in list */ list->aux = (UINT)nilCell; /* undo last element optimization */ cell->next = nilCell; return(cell); } else { list->aux = (UINT)nilCell; /* undo last element optimization */ cell = (CELL*)params->next; params = evaluateExpression(params); if(isList(params->type)) { evalFlag = FALSE; params = getIntegerExt((CELL*)params->contents, (UINT*)&index, FALSE); } else { evalFlag = TRUE; getIntegerExt(params, (UINT*)&index, FALSE); params = cell; } } while(isList(list->type)) { cell = list; list = (CELL *)list->contents; if(index < 0) index = convertNegativeOffset(index, list); while(index--) { cell = list; list = list->next; } if(list == nilCell) errorProc(ERR_LIST_INDEX_OUTOF_BOUNDS); if(params == nilCell || !isList(list->type)) break; params = getIntegerExt(params, (UINT*)&index, evalFlag); } if(list == (CELL*)cell->contents) cell->contents = (UINT)list->next; else cell->next = list->next; list->next = nilCell; return(list); }
void eval( Node *node ) { int i, j; Number n1, n2, n3, n4; char *string1; Symbol *s; Node *n; Array *a; /* debugging */ #ifdef __DEBUG_TRACE__ SourceCode *sc; #endif /* init vars */ n1=0; n2=0; n3=0; n4=0; if (node == NULL) { return; } /* test node */ eMemTest( "eval: node is corrupt", node ); eMemTest( "eval: node->left is corrupt", node->left ); eMemTest( "eval: node->right is corrupt", node->right ); /* tracing */ if (node->trace != -1) { runLineId = node->trace; #ifdef __DEBUG_TRACE__ sc = eFindSource( runLineId ); eConsole("%d: %s\n", sc->lineNum, sc->text ); #endif /* sdlBasic_debugging */ if (debug==1){ screendebug(); //////////////////////////////////// } } /* debugging */ #ifdef __DEBUG_TRACE__ eConsole( "Op:%s\n", opcodeName[node->op] ); #endif switch( node->op ) { //case NULL: // break; case OpAdd: eval( node->left ); eval( node->right ); /* add or concat? */ if (getStackType( tos ) == DATA_STRING) { basConcat(); } else { n2 = popNumber(); n1 = popNumber(); pushNumber( n1 + n2 ); } break; case OpAnd: /* short circuit */ eval( node->left ); if (!popNumber()) { pushNumber( (Number)0 ); } else { eval( node->right ); if (popNumber()) { pushNumber( (Number)1 ); } else { pushNumber( (Number)0 ); } } break; case OpArgList: eval( node->left ); eval( node->right ); break; case OpArrayGet: eval( node->left ); /* indices and index */ getArrayElement( node->value.symbol ); break; case OpArrayPtr: pushArray( node->value.symbol ); break; case OpArraySet: eval( node->right ); /* value to store */ eval( node->left ); /* indices and index */ setArrayElement( node->value.symbol ); break; case OpAssign: /* value to be assigned. note the *right* node is used */ eval( node->right ); /* variable to assign to */ setVar( node->value.symbol ); break; case OpBuiltin: case OpBuiltinCall: /* for argcount */ n1 = tos; /* mark start of created objects */ pushCreateStack( 0 ); /* the args */ eval( node->left ); /* builtin symbol */ s = node->value.symbol; if (s == NULL) { ePrintf( Runtime, "builtin pointer is null"); } /* set args */ argCount = (int)(tos - n1); /* call the c function */ (*s->builtin)(); /* destroy created objects */ clearCreateStack(); /* drop result? */ if (node->op == OpBuiltinCall) { dropTos(); } break; case OpCaseSelect: /* top level of a case statement */ /* value to compare */ eval( node->left ); /* resolve into real data */ switch (getStackType( tos )) { case DATA_NUMBER: pushNumber( popNumber() ); break; case DATA_STRING: pushString( popString() ); break; default: ePrintf( Runtime, "OpCaseSelect: can't resolve type %s", datumName[getStackType( tos )] ); } /* get first test */ if (node == NULL) { /* no tests */ break; } else { node = node->right; } /* walk the chain of cases */ while (1) { /* get a test/action pair */ n = node->left; /* perform the tests */ eval( n->left ); /* true? */ if (popNumber()) { /* perform action and leave loop */ eval( n->right ); break; } /* move to next test */ node = node->right; if (node == NULL) { break; } } /* drop the test value from the stack */ dropTos(); break; case OpCaseCmp: case OpCaseRange: case OpCaseElse: /* perform chain of tests until true or end */ while (1) { switch (node->op) { case OpCaseCmp: /* value to compare */ eval(node->left); /* what type of test? */ switch (getStackType( tos-1 )) { case DATA_NUMBER: numberCompare( node->value.iValue, 0 ); break; case DATA_STRING: stringCompare( node->value.iValue, 0 ); break; default: ePrintf( Runtime, "OpCaseCmp: bad data type" ); } break; case OpCaseRange: /* values to compare */ n = node->left; eval( n->left ); eval( n->right ); /* what type of comparison? */ switch (getStackType( tos-2 )) { case DATA_NUMBER: numberRangeCompare(); break; case DATA_STRING: stringRangeCompare(); break; default: ePrintf( Runtime, "OpCaseRange: bad data type" ); break; } break; case OpCaseElse: /* put true on stack */ pushNumber( 1 ); break; default: ePrintf( Runtime, "opcode %s found in Case test chain", opcodeName[node->op] ); } /* was result true? */ if (stack[tos].value.number) { /* leave true flag on stack and exit */ break; } /* move to next test */ node = node->right; if (node == NULL) { /* exit with false flag */ break; } /* drop test result flag */ dropTos(); } break; case OpClassMethod: case OpClassMethodCall: /* the args */ n1 = tos; /* mark start of created objects */ pushCreateStack( 0 ); /* the args */ eval( node->right ); argCount = (int)(tos - n1); me = 0; runMethod( node->left->value.symbol->klass, node->value.string ); /* destroy created objects */ clearCreateStack(); /* drop result? */ if (node->op == OpClassMethodCall) { dropTos(); } break; case OpClose: if (node->left == NULL) { fileCloseAll(); } else { eval( node->left ); i = (int)popNumber(); fileClose( i ); } break; case OpCmp: eval( node->left ); eval( node->right ); switch(getStackType(tos)) { case DATA_NUMBER: numberCompare( node->value.iValue, 1 ); break; case DATA_STRING: stringCompare( node->value.iValue, 1 ); break; default: ePrintf( Runtime, "opCmp: can't handle datatype" ); } break; case OpComma: /* optimized for linked lists */ while (1) { /* exit flag set? */ if (exitForFlag != 0 || exitRoutineFlag != 0 || exitDoFlag != 0 || exitWhileFlag != 0 || continueFlag ) { break; } if (node->left != NULL ) { eval( node->left ); } /* end of list? */ if (node->right == NULL ) { break; /* linked list? */ } else if (node->right->op == OpComma) { node = node->right; /* not a list */ } else { eval( node->right ); break; } } break; case OpConcat: eval( node->left ); eval( node->right ); basConcat(); break; case OpConstGet: s = node->value.symbol; i = s->stackPos; /* this better not be indirected! */ switch (stack[i].datatype) { case DATA_STRING: pushString( stack[i].value.string ); break; case DATA_NUMBER: pushNumber( stack[i].value.number ); break; default: ePrintf( Runtime, "Can't fetch Const type %s", datumName[stack[i].datatype] ); break; } break; case OpConstSet: s = node->value.symbol; eval( node->left ); switch (stack[tos].datatype) { case DATA_STRING: stack[s->stackPos].datatype = DATA_STRING; stack[s->stackPos].value.string = stack[tos].value.string; stack[tos].datatype = DATA_NUMBER; tos--; break; case DATA_NUMBER: stack[s->stackPos].datatype = DATA_NUMBER; stack[s->stackPos].value.number = stack[tos].value.number; tos--; break; default: ePrintf( Runtime, "Can't set Const to %s", datumName[stack[tos].datatype] ); break; } break; case OpDelete: eval( node->left ); runDestructor( (int)popNumber(), OpDelete ); break; case OpDestroy: eval( node->left ); runDestructor( (int)popNumber(), OpDestroy ); break; case OpContinue: continueFlag = 1; break; case OpDiv: eval( node->left ); eval( node->right ); n2 = popNumber(); n1 = popNumber(); if (n2 == 0.0) { ePrintf( Runtime, "Division by zero" ); } pushNumber( n1 / n2 ); break; case OpDo: while (1) { /* test */ eval( node->left ); /*if (!popNumber()){ break; }*/ /* code */ eval( node->right ); //printf("exitDoFlag:%d\n",exitDoFlag); if (exitDoFlag != 0) { exitDoFlag = 0; break; } else if (continueFlag) { continueFlag = 0; } } break; case OpEnd: eShutdown(0); break; case OpErase: if (node->left == NULL) { /* erase entire array */ eraseArray( node->value.symbol ); } else { /* evaluate the indexes */ eval( node->left ); /* erase single element from array */ eraseArrayElement( node->value.symbol ); } break; case OpExitDo: exitDoFlag = 1; break; case OpExitFor: exitForFlag = 1; break; case OpExitRoutine: currentScope=oldScope[oldScopeP--]; exitRoutineFlag = 1; break; case OpExitWhile: exitWhileFlag = 1; break; case OpFloat: pushNumber( node->value.fValue ); break; case OpFor: s = node->value.symbol; eval( node->left ); n2 = popNumber(); n1 = popNumber(); /* initial value */ pushNumber( n3 ); setVar( s ); for( n3=n1; n3 <= n2; n3++ ) { /* set loop variable */ pushNumber( n3 ); setVar( s ); /* run code */ eval( node->right ); /* special exit condition? */ if (exitForFlag) { exitForFlag = 0; break; } else if (continueFlag) { continueFlag = 0; } /* get loop value (in case it changed) */ getVar( s ); n3 = popNumber(); } break; case OpForEach: /* variable to assign */ s = node->value.symbol; /* array to read from */ a = getArray( node->left->value.symbol ); /* iterate through keys */ i = 0; /* put key on stack, or exit */ while (getDynamicKey( a, i )) { /* assign to variable */ setVar( s ); /* run block */ eval( node->right ); /* next */ i += 1; } break; case OpForStep: s = node->value.symbol; eval( node->left ); n3 = popNumber(); /* step */ n2 = popNumber(); /* end */ n1 = popNumber(); /* start */ /* which direction? */ if (n3 > 0) { n2 += ALLOWABLE_ERROR; for( n4=n1; n2 >= n4; n4 += n3 ) { /* set loop variable */ pushNumber( n4 ); setVar( s ); /* run code */ eval( node->right ); /* special exit condition? */ if (exitForFlag) { exitForFlag = 0; break; } else if (continueFlag) { continueFlag = 0; } /* get loop value (in case it changed) */ getVar( s ); n4 = popNumber(); } } else { n2 -= ALLOWABLE_ERROR; for( n4=n1; n2 <= n4; n4 += n3 ) { /* set loop variable */ pushNumber( n4 ); setVar( s ); /* run code */ eval( node->right ); /* special exit condition? */ if (exitForFlag) { exitForFlag = 0; break; } else if (continueFlag) { continueFlag = 0; } /* get loop value (in case it changed) */ getVar( s ); n4 = popNumber(); } } break; case OpFunction: case OpFunctionCall: callFunction( node ); break; case OpInitArray: if (node->left == NULL) { createDynamicArray( node->value.symbol ); } else { eval( node->left ); createStaticArray( node->value.symbol ); } break; case OpInput: if (node->value.iValue == 1) { eval( node->left ); i = (int)popNumber(); string1 = fileLineInput( i ); pushString( string1 ); } else { /* command line */ ePrintf( Runtime, "Input statement is not currently supported" ); } break; case OpInt: pushNumber( node->value.iValue ); break; case OpMethod: case OpMethodCall: /* the index */ eval( node->left ); n1 = popNumber(); /* method name */ string1 = node->value.string; /* mark start of created objects */ pushCreateStack( 0 ); /* args */ n2 = tos; eval( node->right ); argCount = (int)(tos - n2); /* resolve and run method */ resolveMethod( (int)n1, string1 ); /* drop result? */ if (node->op == OpMethodCall) { dropTos(); } /* destroy created objects */ clearCreateStack(); break; case OpMod: eval( node->left ); eval( node->right ); n2 = popNumber(); n1 = popNumber(); //pushNumber( (long)n1 % (long)n2 ); pushNumber( fmod(n1,n2) ); break; case OpMul: eval( node->left ); eval( node->right ); n2 = popNumber(); n1 = popNumber(); pushNumber( n1 * n2 ); break; case OpOpen: /* file name */ eval( node->left ); string1 = popString(); /* mode */ i = node->value.iValue; /* file number */ eval( node->right ); n1 = popNumber(); fileOpen( string1, i, (int)n1 ); free( string1 ); break; case OpOr: /* short circuit */ eval( node->left ); if (popNumber()) { pushNumber( (Number)1 ); } else { eval( node->right ); if (popNumber()) { pushNumber( (Number)1 ); } else { pushNumber( (Number)0 ); } } break; case OpOrBits: eval( node->left ); eval( node->right); i = popNumber(); j = popNumber(); pushNumber( i | j ); break; case OpIDiv: eval( node->left ); eval( node->right ); n2 = popNumber(); n1 = popNumber(); /* check for division by zero */ if (n2 == 0.0) { ePrintf( Runtime, "Division by zero" ); } pushNumber( floor(n1 / n2) ); break; case OpIf: n = node->left; /* test */ eval( n->left ); n1 = popNumber(); if (n1 != 0) { /* true portion */ eval( n->right ); } else { /* false portion */ eval( node->right ); } break; case OpIfTrue: ePrintf( Runtime, "OpIfTrue: internal error" ); break; case OpIn: /* evaluate key */ eval( node->left ); /* look for it in array */ pushNumber( inArray( node->value.symbol ) ); break; case OpInv: ePrintf( Runtime, "Inv is not implemented yet" ); break; case OpNegate: eval( node->left ); n1 = popNumber(); pushNumber( -n1 ); break; case OpNew: case OpNewTmp: /* mark start of created objects */ pushCreateStack( 0 ); /* the args */ n1 = tos; eval( node->left ); argCount = (int)(tos - n1); runMethod( node->value.symbol->klass, "new" ); /* destroy created objects *before* adding new object to stack */ clearCreateStack(); /* add new object to create stack? */ if (node->op == OpNewTmp) { /* track on stack */ copyStackItem( tos ); pushCreateStack( (int)popNumber() ); } break; case OpNoOp: break; case OpNot: eval( node->left ); n1 = popNumber(); pushNumber( !n1 ); break; case OpPower: eval( node->left ); eval( node->right ); n2 = popNumber(); n1 = popNumber(); pushNumber( pow( n1, n2 ) ); break; case OpPrint: if (node->left == NULL) { i = 0; } else { eval( node->left ); i = (int)popNumber(); } node = node->right; /* empty print statement */ if (node == NULL) { if (i==0) { eConsole("\n"); } else { filePrintString( i, "\n" ); } } /* process nodes */ while(node != NULL) { /* data value */ if (node->left != NULL) { eval( node->left ); string1 = popString(); if (i==0) { eConsole("%s", string1 ); } else { filePrintString( i, string1 ); } eFree( string1 ); } /* field delimiter */ switch (node->value.iValue) { case PRINT_TAB: if (i==0) { eConsole("\t"); } else { filePrintString( i, "\t" ); } break; case PRINT_NEWLINE: if (i==0) { eConsole("\n"); } else { filePrintString( i, "\n" ); } break; default: /* no action */ break; } /* link */ node = node->right; } break; case OpReturnValue: eval( node->left ); setReturn(); exitRoutineFlag = 1; break; case OpReturnSetValue: eval( node->left ); setReturn(); break; case OpShl: eval( node->left ); eval( node->right ); n2 = popNumber(); n1 = popNumber(); pushNumber( (long)n1 << (long)n2 ); break; case OpShr: eval( node->left ); eval( node->right ); n2 = popNumber(); n1 = popNumber(); pushNumber( (long)n1 >> (long)n2 ); break; case OpString: pushStringCopy( node->value.string ); break; case OpSub: eval( node->left ); eval( node->right ); n2 = popNumber(); n1 = popNumber(); pushNumber( n1 - n2 ); break; case OpUndefined: ePrintf( Runtime, "Opcode is undefined" ); break; case OpVar: /* check type */ getVar( node->value.symbol ); if (getStackType(tos) == DATA_UNDEFINED) { ePrintf( Runtime, "the value of %s is undefined", node->value.symbol->name ); } break; case OpWhile: while (1) { /* test */ eval( node->left ); if (!popNumber()){ break; } /* code */ eval( node->right ); if (exitWhileFlag != 0) { exitWhileFlag = 0; break; } else if (continueFlag) { continueFlag = 0; } } break; case OpXor: eval( node->left ); eval( node->right ); n2 = popNumber(); n1 = popNumber(); pushNumber( (long)n1 ^ (long)n2 ); break; default: ePrintf( Runtime, "Unknown Opcode: %d", node->op ); } }