void CustomGUIReader::setCustomProps(const std::string &classType, cocos2d::Ref *widget, const rapidjson::Value &customOptions) { if (_setPropsFunc != 0) { rapidjson::StringBuffer buffer; rapidjson::Writer<rapidjson::StringBuffer> writer(buffer); customOptions.Accept(writer); auto stack = LuaEngine::getInstance()->getLuaStack(); stack->pushString(classType.c_str(), classType.size()); stack->pushObject(widget, "cc.Ref"); stack->pushString(buffer.GetString(), buffer.Size()); stack->executeFunctionByHandler(_setPropsFunc, 3); } }
void DBCCArmatureNode::registerMovementEventHandler(cocos2d::LUA_FUNCTION func) { unregisterMovementEventHandler(); _movementEventHandler = func; auto dispatcher = getCCEventDispatcher(); auto f = [this](cocos2d::EventCustom *event) { auto eventData = (dragonBones::EventData*)(event->getUserData()); auto type = (int) eventData->getType(); auto movementId = eventData->animationState->name; auto lastState = eventData->armature->getAnimation()->getLastAnimationState(); auto stack = cocos2d::LuaEngine::getInstance()->getLuaStack(); stack->pushObject(this, "db.DBCCArmatureNode"); stack->pushInt(type); stack->pushString(movementId.c_str(), movementId.size()); stack->pushBoolean(lastState == eventData->animationState); stack->executeFunctionByHandler(_movementEventHandler, 4); }; dispatcher->addCustomEventListener(dragonBones::EventData::COMPLETE, f); dispatcher->addCustomEventListener(dragonBones::EventData::LOOP_COMPLETE, f); }
int CCLuaEngine::pushCCLuaValue(const CCLuaValue& value) { const CCLuaValueType type = value.getType(); if (type == CCLuaValueTypeInt) { return pushInt(value.intValue()); } else if (type == CCLuaValueTypeFloat) { return pushFloat(value.floatValue()); } else if (type == CCLuaValueTypeBoolean) { return pushBoolean(value.booleanValue()); } else if (type == CCLuaValueTypeString) { return pushString(value.stringValue().c_str()); } else if (type == CCLuaValueTypeDict) { pushCCLuaValueDict(value.dictValue()); } else if (type == CCLuaValueTypeArray) { pushCCLuaValueArray(value.arrayValue()); } else if (type == CCLuaValueTypeCCObject) { pushCCObject(value.ccobjectValue(), value.getCCObjectTypename().c_str()); } return lua_gettop(m_state); }
void autoMatchResponse(const boids::MatchResponse& response) { auto stack = cocos2d::LuaEngine::getInstance()->getLuaStack(); stack->pushInt(response.ret_value()); stack->pushString(response.ret_info().c_str()); if (response.ret_value() == boids::MatchResponse_Value_Success) { cocos2d::log("autoMatch success. ip: %s, port: %d", response.game_server_ip().c_str(), response.game_server_port()); if (NetworkAdapter::getInstance()->init(response.game_server_ip(), response.game_server_port())) { processGameInit(response.game_init_data(), stack); stack->executeFunctionByHandler(autoMatchCallback, 3); } else { cocos2d::log("[ERROR] udp init failed !"); } } else { cocos2d::log("autoMatch error: %d %s", response.ret_value(), response.ret_info().c_str()); stack->executeFunctionByHandler(autoMatchCallback, 2); } }
MojErr MojService::SubscriptionKey::init(const MojChar* sender) { MojErr err = pushString(sender); MojErrCheck(err); return MojErrNone; }
int LuaBinder::luaDatabaseEscapeBlob(lua_State* L) { // Database.escapeBlob(blob) uint32_t length = getNumber<uint32_t>(L, 2); pushString(L, Database::getInstance()->escapeBlob(getString(L, 1).c_str(), length)); return 1; }
void LuaStack::pushLuaValue(const LuaValue& value) { const LuaValueType type = value.getType(); if (type == LuaValueTypeInt) { return pushInt(value.intValue()); } else if (type == LuaValueTypeFloat) { return pushFloat(value.floatValue()); } else if (type == LuaValueTypeBoolean) { return pushBoolean(value.booleanValue()); } else if (type == LuaValueTypeString) { return pushString(value.stringValue().c_str()); } else if (type == LuaValueTypeDict) { pushLuaValueDict(value.dictValue()); } else if (type == LuaValueTypeArray) { pushLuaValueArray(value.arrayValue()); } else if (type == LuaValueTypeObject) { pushObject(value.ccobjectValue(), value.getObjectTypename().c_str()); } }
void Stack::pushVariable(const Variable &var) { switch (var.getType()) { case kTypeNil: pushNil(); break; case kTypeBoolean: pushBoolean(var.getBool()); break; case kTypeNumber: pushFloat(var.getFloat()); break; case kTypeString: pushString(var.getString()); break; case kTypeTable: pushTable(var.getTable()); break; case kTypeFunction: pushFunction(var.getFunction()); break; case kTypeUserType: pushRawUserType(var.getRawUserType(), var.getExactType()); break; default: warning("Pushing a varible of type \"%s\" not supported", var.getExactType().c_str()); break; } }
void GameNetDelegate::dispatchEvent(std::string event) { auto stack = LuaEngine::getInstance()->getLuaStack(); stack->pushString(event.c_str()); auto it = m_callBacks.find("netStatus"); stack->executeFunctionByHandler(it->second, 1); stack->clean(); }
int LuaStack::loadChunksFromZIP(const char *zipFilePath) { pushString(zipFilePath); luaLoadChunksFromZIP(_state); int ret = lua_toboolean(_state, -1); lua_pop(_state, 1); return ret; }
void LuaInterface::throwError(const std::string& message) { if(isInCppCallback()) { pushString(message); error(); } else throw stdext::exception(message); }
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); }
MojErr MojService::SubscriptionKey::init(const MojServiceMessage* msg) { MojAssert(msg); MojErr err = push((MojInt64) msg->token()); MojErrCheck(err); err = pushString(msg->senderAddress()); MojErrCheck(err); return MojErrNone; }
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); }
void GameNetDelegate::onMessageReceived(const char *data, unsigned short size) { CCLOG("onMessageReceived, size is %d %d", size, size - sizeof(CMD_Head)); CMD_Command Command = ((CMD_Head *)data)->CommandInfo; auto stack = LuaEngine::getInstance()->getLuaStack(); stack->pushInt(Command.wMainCmdID); stack->pushInt(Command.wSubCmdID); stack->pushString(data + sizeof(CMD_Head), size - sizeof(CMD_Head)); auto it = m_callBacks.find("onReceived"); stack->executeFunctionByHandler(it->second, 3); stack->clean(); }
/** * Used for Lua callbacks and extended functionality. * @param data the object * @param type tolua type of the object * @param the method name * @return true if the corresponding table key was found and it is a function */ bool Interpreter::pushMethod(void *data, const std::string& type, const std::string& name) { pushUserType(data, type); if (lua_gettop(luastate) == 0) return false; pushString(name); lua_gettable(luastate, -2); if (lua_gettop(luastate) >= 2 && (lua_isuserdata(luastate, -2) || lua_istable(luastate, -2))) lua_remove(luastate, -2); if (lua_isfunction(luastate, -1)) return true; lua_pop(luastate, 1); return false; }
int CCLuaEngine::executeNotificationEvent(CCNotificationCenter* pNotificationCenter, const char* pszName) { int ret = 0; do { int nScriptHandler = pNotificationCenter->getScriptHandler(); CC_BREAK_IF(0 == nScriptHandler); cleanStack(); pushString(pszName); ret = executeFunctionByHandler(nScriptHandler, 1); } while (0); return ret; }
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(); }
void InAppPurchaseDelegate::onPurchaseFailed( const char* desc ) { if(m_ScriptHandler) { auto stack = LuaEngine::getInstance()->getLuaStack(); auto state = stack->getLuaState(); if(state) { stack->pushInt(IAP_EVENT_PURCHASE_FAILED); stack->pushString(desc); stack->executeFunctionByHandler(m_ScriptHandler,2); } } }
int NpcScriptInterface::luaNpcGetParameter(lua_State* L) { // npc:getParameter(key) const std::string& key = getString(L, 2); Npc* npc = getUserdata<Npc>(L, 1); if (npc) { auto it = npc->parameters.find(key); if (it != npc->parameters.end()) { pushString(L, it->second); } else { lua_pushnil(L); } } else { lua_pushnil(L); } return 1; }
static JSValueRef getChildren(JSContextRef ctx, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) { KJS::JSLock lock(false); if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileNodeClass())) return JSValueMakeUndefined(ctx); ProfileNode* profileNode = static_cast<ProfileNode*>(JSObjectGetPrivate(thisObject)); const Vector<RefPtr<ProfileNode> >& children = profileNode->children(); JSObjectRef global = JSContextGetGlobalObject(ctx); JSRetainPtr<JSStringRef> arrayString(Adopt, JSStringCreateWithUTF8CString("Array")); JSValueRef arrayProperty = JSObjectGetProperty(ctx, global, arrayString.get(), exception); if (exception && *exception) return JSValueMakeUndefined(ctx); JSObjectRef arrayConstructor = JSValueToObject(ctx, arrayProperty, exception); if (exception && *exception) return JSValueMakeUndefined(ctx); JSObjectRef result = JSObjectCallAsConstructor(ctx, arrayConstructor, 0, 0, exception); if (exception && *exception) return JSValueMakeUndefined(ctx); JSRetainPtr<JSStringRef> pushString(Adopt, JSStringCreateWithUTF8CString("push")); JSValueRef pushProperty = JSObjectGetProperty(ctx, result, pushString.get(), exception); if (exception && *exception) return JSValueMakeUndefined(ctx); JSObjectRef pushFunction = JSValueToObject(ctx, pushProperty, exception); if (exception && *exception) return JSValueMakeUndefined(ctx); for (Vector<RefPtr<ProfileNode> >::const_iterator it = children.begin(); it != children.end(); ++it) { JSValueRef arg0 = toRef(toJS(toJS(ctx), (*it).get() )); JSObjectCallAsFunction(ctx, pushFunction, result, 1, &arg0, exception); if (exception && *exception) return JSValueMakeUndefined(ctx); } return result; }
void InAppPurchaseDelegate::onPurchaseFinish(void* content) { if(m_ScriptHandler) { auto stack = LuaEngine::getInstance()->getLuaStack(); auto state = stack->getLuaState(); if(state) { const char* str = (const char*)content; stack->pushInt(IAP_EVENT_PURCHASE_FINISH); if (str != NULL ) { stack->pushString(str); }else stack->pushNil(); stack->executeFunctionByHandler(m_ScriptHandler,2); } } }
void LuaInterface::createLuaState() { // creates lua state L = luaL_newstate(); if(!L) g_logger.fatal("Unable to create lua state"); // load lua standard libraries luaL_openlibs(L); // load bit32 lib for bitwise operations luaopen_bit32(L); // creates weak table newTable(); newTable(); pushString("v"); setField("__mode"); setMetatable(); m_weakTableRef = ref(); // installs script loader getGlobal("package"); getField("loaders"); pushCFunction(&LuaInterface::luaScriptLoader); rawSeti(5); pop(2); // replace dofile pushCFunction(&LuaInterface::lua_dofile); setGlobal("dofile"); // dofiles pushCFunction(&LuaInterface::lua_dofiles); setGlobal("dofiles"); // replace loadfile pushCFunction(&LuaInterface::lua_loadfile); setGlobal("loadfile"); }
void DBCCArmatureNode::registerFrameEventHandler(cocos2d::LUA_FUNCTION func) { unregisterFrameEventHandler(); _frameEventHandler = func; auto dispatcher = getCCEventDispatcher(); auto f = [this](cocos2d::EventCustom *event) { auto eventData = (dragonBones::EventData*)(event->getUserData()); auto type = (int) eventData->getType(); auto movementId = eventData->animationState->name; auto frameLabel = eventData->frameLabel; auto stack = cocos2d::LuaEngine::getInstance()->getLuaStack(); stack->pushObject(this, "db.DBCCArmatureNode"); stack->pushInt(type); stack->pushString(movementId.c_str(), movementId.size()); stack->pushString(frameLabel.c_str(), frameLabel.size()); stack->executeFunctionByHandler(_frameEventHandler, 4); }; dispatcher->addCustomEventListener(dragonBones::EventData::ANIMATION_FRAME_EVENT, f); }
Object* getObject(Value* value, VM* vm){ Object* object = NULL; switch(value->type){ case VALUE_TYPE_NULL: break; case VALUE_TYPE_NUM: object = pushInt(vm, parseNum(value->data, 10)); break; case VALUE_TYPE_STRING: object = pushString(vm, parseString(value->data)); break; case VALUE_TYPE_OP: break; case VALUE_TYPE_VAR: break; } return object; }
bool Babuino::withInt32() { STACKPTR location, index; int32_t rhs, lhs; switch (_regs.opCode) { case OP_ASHIFT: case OP_LSHIFT: { int8_t shift; popUint8(_stack, (uint8_t*)&shift); popUint32(_stack, (uint32_t*)&lhs); if (shift >= 0) pushUint32(_stack, (uint32_t)(lhs << shift)); else pushUint32(_stack, (uint32_t)(lhs >> -shift)); return true; } case OP_SET: //Serial.println("---set---"); popStackPtr(_stack, &location); popUint32(_stack, (uint32_t*)&rhs); setUint32(_stack, location, (uint32_t)rhs); return true; case OP_GET: //Serial.println("---get---"); popStackPtr(_stack, &location); getUint32(_stack, location, (uint32_t*)&rhs); pushUint32(_stack, (uint32_t)rhs); return true; case OP_ASET: //Serial.println("---aset---"); popStackPtr(_stack, &location); popStackPtr(_stack, &index); popUint32(_stack, (uint32_t*)&rhs); setUint32(_stack, location + index * sizeof(int32_t), (uint32_t)rhs); return true; case OP_AGET: //Serial.println("---aget---"); popStackPtr(_stack, &location); popStackPtr(_stack, &index); getUint32(_stack, location + index * sizeof(int32_t), (uint32_t*)&rhs); pushUint32(_stack, (uint32_t)rhs); return true; case OP_OUTPUT: { //Serial.print("output "); popUint32(_stack, (uint32_t*)&rhs); // The return value // point to where the arguments size is on the stack. location = getArgsLocation(); uint8_t argsSize; getUint8(_stack, location - sizeof(uint8_t), &argsSize); // Get size of args. // If the size > 0 then step over the size location too. // Otherwise keep pointing to the same place because the return // value should overwrite where the arguments size would be. if (argsSize > 0) argsSize += sizeof(uint8_t); setUint32(_stack, location - (STACKPTR)argsSize - sizeof(int32_t), (uint32_t)rhs); } return true; case OP_SEND: { //Serial.println("---send---"); popUint32(_stack, (uint32_t*)&rhs); uint8_t buf[sizeof(int32_t)]; hton(rhs, buf); //_defaultStream->write(nbuf, sizeof(int32_t)); // Replaced for debugging _defaultStream->print(rhs); } return true; case OP_SENDN: { //Serial.println("---sendn---"); uint8_t items; uint8_t port; STACKPTR bufLoc; popUint8(_stack, &items); popUint8(_stack, &port); popStackPtr(_stack, &bufLoc); int32_t* buf = (int32_t*)getStackAddress(_stack, bufLoc); uint8_t nbuf[sizeof(int32_t)]; for (int i = 0; i < items; i++) { rhs = *buf; hton(rhs, nbuf); //_defaultStream->write(nbuf, sizeof(int32_t)); // Replaced for debugging _defaultStream->print(rhs); buf++; } } return true; #ifdef SUPPORT_STRING case OP_TOSTR: { //Serial.println("---tostr---"); popUint32(_stack, (uint32_t*)&rhs); // ***KLUDGE WARNING*** // Borrowing unused (hopefully) stack space as a buffer! // just to avoid having to allocate another buffer. char* psz = (char *)getTopAddress(_stack); itoa((int) rhs, psz, 10); // 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. pushString(_stack, (uint8_t*)psz); } return true; #endif case OP_FOREACH: { //Serial.print("foreach "); PROGPTR blockAddr; popProgPtr(_stack, &blockAddr); // Block address popStackPtr(_stack, &location); // Iterator variable location (Variable contains a 'pointer') uint8_t itemsRemaining; popUint8(_stack, &itemsRemaining); // Number of items remaining // If we've gone through the block then we need to pop the // previous list item off the stack if (hasBlockExecuted()) { uint32_t tmpUint32; popUint32(_stack, &tmpUint32); } if (itemsRemaining > 0) // Any items remaining { // Set the value of the variable to the location on the // stack of the next list item (ie the top) setStackPtr(_stack, location, getTop(_stack) - sizeof(int32_t)); _regs.pc = blockAddr; // Point to the top of the block for the next iteration itemsRemaining--; // Decrement the number of items remaining pushUint8(_stack, itemsRemaining); // Save number of items remaining for next time pushStackPtr(_stack, location); // Save iterator variable location for next time pushProgPtr(_stack, blockAddr); // Save block address for next time } else { ascendBlock(); // Leaving. Pop the block. } } return true; } popUint32(_stack, (uint32_t*)&rhs); switch (_regs.opCode) { case OP_BITNOT: pushUint32(_stack, (uint32_t)~rhs); return true; case OP_ABS: pushUint32(_stack, (uint32_t)abs(rhs)); return true; case OP_NEG: pushUint32(_stack, (uint32_t)-rhs); return true; } popUint32(_stack, (uint32_t*)&lhs); switch (_regs.opCode) { case OP_ADD: pushUint32(_stack, (uint32_t)(lhs + rhs)); return true; case OP_SUB: pushUint32(_stack, (uint32_t)(lhs - rhs)); return true; case OP_MUL: pushUint32(_stack, (uint32_t)(lhs * rhs)); return true; case OP_DIV: pushUint32(_stack, (uint32_t)(lhs / rhs)); return true; case OP_MOD: pushUint32(_stack, (uint32_t)(lhs % rhs)); return true; case OP_EQ: pushUint8(_stack, (uint8_t)(lhs == rhs)); return true; case OP_GT: pushUint8(_stack, (uint8_t)(lhs > rhs)); return true; case OP_LT: pushUint8(_stack, (uint8_t)(lhs < rhs)); return true; case OP_LE: pushUint8(_stack, (uint8_t)(lhs <= rhs)); return true; case OP_GE: pushUint8(_stack, (uint8_t)(lhs >= rhs)); return true; case OP_NE: pushUint8(_stack, (uint8_t)(lhs != rhs)); return true; case OP_BITAND: pushUint32(_stack, (uint32_t)(lhs & rhs)); return true; case OP_BITOR: pushUint32(_stack, (uint32_t)(lhs | rhs)); return true; case OP_BITXOR: pushUint32(_stack, (uint32_t)(lhs ^ rhs)); return true; case OP_MIN: pushUint32(_stack, (uint32_t)min(lhs, rhs)); return true; case OP_MAX: pushUint32(_stack, (uint32_t)max(lhs, rhs)); return true; } return false; }
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)); }
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 ); } }
void CILuaState::setMetaTableIndex(void) { pushString("__index"); pushValue(-2); setTable(-3); }
void Operators::doOperator(Context *context, OperatorType oper) { Token token1, token2, token3; stutskFloat f1, f2; stutskInteger i1, i2; string s1, s2; switch (oper) { case OP_ASSIG: token1 = stack_back_safe(); stutskStack.pop_back(); // Variable token2 = stack_back_safe(); stutskStack.pop_back(); // Value setVariable(token1, token2); break; case OP_ASSIG_REF: token1 = stack_back_safe(); stutskStack.pop_back(); // Variable token2 = stack_back_safe(); stutskStack.pop_back(); // Value setVariable(token1, token2, true); break; case OP_FUNC: token1 = stack_back_safe(); stutskStack.pop_back(); // Name token2 = stack_back_safe(); stutskStack.pop_back(); // Codeblock recurseVariables(token2); if (token2.tokenType != T_CODEBLOCK) { throw StutskException(ET_ERROR, "Token is not a codeblock"); } else { OperatorType dummy; string functionName = *giveString(token1); if (readOperator(functionName, dummy)) throw StutskException(ET_ERROR, "Cannot override an operator"); if (functionName.substr(0,10) == "__builtin_") throw StutskException(ET_ERROR, "Cannot override an internal function"); userFunctions[functionName] = *token2.asTokenList; } break; case OP_UNSET: token1 = stack_back_safe(); stutskStack.pop_back(); if (token1.tokenType == T_VARIABLE) { struct Token::_un_TokenData::_un_VariableData *var = & token1.data.asVariable; TokenMap::iterator iter = var->context->variables.find(var->name); if (iter != var->context->variables.end()) var->context->variables.erase(iter); } else { UserFunctionsMap::iterator iter = userFunctions.find(*giveString(token1)); if (iter != userFunctions.end()) userFunctions.erase(iter); } break; case OP_DEREF: token1 = stack_back_safe(); stutskStack.pop_back(); if (token1.tokenType != T_VARIABLE) { throw StutskException(ET_ERROR, "Token is not a variable"); } else { recurseVariables(token1, true); stutskStack.push_back(copy_token(token1)); } break; case OP_PLUSPLUS: token1 = stack_back_safe(); stutskStack.pop_back(); // Name if (token1.tokenType == T_VARIABLE) { switch (giveGCD(token1, f1, i1, s1)) { case NT_INVALID: case NT_STRING: throw StutskException(ET_ERROR, "Variable is not a numeric type"); case NT_INTEGER: token2.tokenType = T_INTEGER; token2.data.asInteger = i1 + 1; setVariable(token1, token2); break; case NT_FLOAT: token2.tokenType = T_FLOAT; token2.data.asFloat = f1 + 1.; setVariable(token1, token2); break; } } else { switch (giveGCD(token1, f1, i1, s1)) { case NT_INVALID: case NT_STRING: throw StutskException(ET_ERROR, "Token is not a numeric type"); case NT_INTEGER: pushInteger(++i1); break; case NT_FLOAT: pushFloat(++f1); break; } } break; case OP_MINMIN: token1 = stack_back_safe(); stutskStack.pop_back(); // Name if (token1.tokenType == T_VARIABLE) { switch (giveGCD(token1, f1, i1, s1)) { case NT_INVALID: case NT_STRING: throw StutskException(ET_ERROR, "Variable is not a numeric type"); case NT_INTEGER: token2.tokenType = T_INTEGER; token2.data.asInteger = i1 - 1; setVariable(token1, token2); break; case NT_FLOAT: token2.tokenType = T_FLOAT; token2.data.asFloat = f1 - 1.; setVariable(token1, token2); break; } } else { switch (giveGCD(token1, f1, i1, s1)) { case NT_INVALID: case NT_STRING: throw StutskException(ET_ERROR, "Token is not a numeric type"); case NT_INTEGER: pushInteger(--i1); break; case NT_FLOAT: pushFloat(--f1); break; } } break; case OP_PLUS: token1 = stack_back_safe(); stutskStack.pop_back(); token2 = stack_back_safe(); stutskStack.pop_back(); switch (giveGCD(token1, f1, i1, s1)) { case NT_STRING: case NT_INVALID: throw StutskException(ET_ERROR, "Token is not a numeric type"); case NT_INTEGER: switch (giveGCD(token2, f2, i2, s1)) { case NT_STRING: case NT_INVALID: throw StutskException(ET_ERROR, "Token is not a numeric type"); case NT_INTEGER: i1 += i2; pushInteger(i1); break; case NT_FLOAT: f2 += i1; pushFloat(f2); break; } break; case NT_FLOAT: f1 += giveFloat(token2); pushFloat(f1); break; } break; case OP_MINUS: token1 = stack_back_safe(); stutskStack.pop_back(); token2 = stack_back_safe(); stutskStack.pop_back(); switch (giveGCD(token1, f1, i1, s1)) { case NT_STRING: case NT_INVALID: throw StutskException(ET_ERROR, "Token is not a numeric type"); case NT_INTEGER: switch (giveGCD(token2, f2, i2, s1)) { case NT_STRING: case NT_INVALID: throw StutskException(ET_ERROR, "Token is not a numeric type"); case NT_INTEGER: i2 -= i1; pushInteger(i2); break; case NT_FLOAT: f2 -= i1; pushFloat(f2); break; } break; case NT_FLOAT: f2 = giveFloat(token2) - f1; pushFloat(f2); break; } break; case OP_MULTIP: token1 = stack_back_safe(); stutskStack.pop_back(); token2 = stack_back_safe(); stutskStack.pop_back(); switch (giveGCD(token1, f1, i1, s1)) { case NT_STRING: case NT_INVALID: throw StutskException(ET_ERROR, "Token is not a numeric type"); case NT_INTEGER: switch (giveGCD(token2, f2, i2, s1)) { case NT_STRING: case NT_INVALID: throw StutskException(ET_ERROR, "Token is not a numeric type"); case NT_INTEGER: i1 *= i2; pushInteger(i1); break; case NT_FLOAT: f2 *= i1; pushFloat(f2); break; } break; case NT_FLOAT: f1 *= giveFloat(token2); pushFloat(f1); break; } break; case OP_DIV: token1 = stack_back_safe(); stutskStack.pop_back(); token2 = stack_back_safe(); stutskStack.pop_back(); switch (giveGCD(token1, f1, i1, s1)) { case NT_STRING: case NT_INVALID: throw StutskException(ET_ERROR, "Token is not a numeric type"); case NT_INTEGER: if (i1 == 0) throw StutskException(ET_ERROR, "Division by zero"); switch (giveGCD(token2, f2, i2, s1)) { case NT_STRING: case NT_INVALID: throw StutskException(ET_ERROR, "Token is not a numeric type"); case NT_INTEGER: f1 = (stutskFloat)i2 / (stutskFloat)i1; pushFloat(f1); break; case NT_FLOAT: f2 /= (stutskFloat)i1; pushFloat(f2); break; } break; case NT_FLOAT: if (f1 == 0.) throw StutskException(ET_ERROR, "Division by zero"); f2 = giveFloat(token2) / f1; pushFloat(f2); break; } break; case OP_DIVINT: token1 = stack_back_safe(); stutskStack.pop_back(); token2 = stack_back_safe(); stutskStack.pop_back(); switch (giveGCD(token1, f1, i1, s1)) { case NT_STRING: case NT_INVALID: throw StutskException(ET_ERROR, "Token is not a numeric type"); case NT_INTEGER: switch (giveGCD(token2, f2, i2, s1)) { case NT_STRING: case NT_INVALID: throw StutskException(ET_ERROR, "Token is not a numeric type"); case NT_INTEGER: i1 = (stutskInteger)i2 / i1; pushInteger(i1); break; case NT_FLOAT: i2 = (stutskInteger)f2 / i1; pushInteger(i2); break; } break; case NT_FLOAT: i2 = giveInteger(token2) / (stutskInteger)f1; pushInteger(i2); break; } break; case OP_MOD: token1 = stack_back_safe(); stutskStack.pop_back(); token2 = stack_back_safe(); stutskStack.pop_back(); switch (giveGCD(token1, f1, i1, s1)) { case NT_STRING: case NT_INVALID: throw StutskException(ET_ERROR, "Token is not a numeric type"); case NT_INTEGER: switch (giveGCD(token2, f2, i2, s1)) { case NT_STRING: case NT_INVALID: throw StutskException(ET_ERROR, "Token is not a numeric type"); case NT_INTEGER: i1 = (stutskInteger)i2 % i1; pushInteger(i1); break; case NT_FLOAT: i2 = (stutskInteger)f2 % i1; pushInteger(i2); break; } break; case NT_FLOAT: i2 = giveInteger(token2) % (stutskInteger)f1; pushInteger(i2); break; } break; case OP_LESSTHAN: token1 = stack_back_safe(); stutskStack.pop_back(); token2 = stack_back_safe(); stutskStack.pop_back(); pushBool(tokenNumericCompare(token1, token2) == CN_SMALLER); break; case OP_MORETHAN: token1 = stack_back_safe(); stutskStack.pop_back(); token2 = stack_back_safe(); stutskStack.pop_back(); pushBool(tokenNumericCompare(token1, token2) == CN_LARGER); break; case OP_LESSTHAN_EQ: token1 = stack_back_safe(); stutskStack.pop_back(); token2 = stack_back_safe(); stutskStack.pop_back(); pushBool(tokenNumericCompare(token1, token2) != CN_LARGER); break; case OP_MORETHAN_EQ: token1 = stack_back_safe(); stutskStack.pop_back(); token2 = stack_back_safe(); stutskStack.pop_back(); pushBool(tokenNumericCompare(token1, token2) != CN_SMALLER); break; case OP_EQ: token1 = stack_back_safe(); stutskStack.pop_back(); token2 = stack_back_safe(); stutskStack.pop_back(); pushBool(tokenEqual(token1, token2)); break; case OP_SAME: token1 = stack_back_safe(); stutskStack.pop_back(); token2 = stack_back_safe(); stutskStack.pop_back(); pushBool(tokenSame(token1, token2)); break; case OP_NOTEQ: token1 = stack_back_safe(); stutskStack.pop_back(); token2 = stack_back_safe(); stutskStack.pop_back(); pushBool(!tokenEqual(token1, token2)); break; case OP_GLOBAL: token1 = stack_back_safe(); stutskStack.pop_back(); // Variable if (token1.tokenType != T_VARIABLE) { throw StutskException(ET_ERROR, "Token is not a variable"); } else { context->variableScopeMap[token1.data.asVariable.name] = VS_GLOBAL; } break; case OP_AUTO: token1 = stack_back_safe(); stutskStack.pop_back(); // Variable if (token1.tokenType != T_VARIABLE) { throw StutskException(ET_ERROR, "Token is not a variable"); } else { context->variableScopeMap[token1.data.asVariable.name] = VS_AUTO; } break; case OP_STATIC: token1 = stack_back_safe(); stutskStack.pop_back(); // Variable if (token1.tokenType != T_VARIABLE) { throw StutskException(ET_ERROR, "Token is not a variable"); } else { context->variableScopeMap[token1.data.asVariable.name] = VS_STATIC; } break; case OP_FOREVER: token1 = stack_back_safe(); stutskStack.pop_back(); // Codeblock recurseVariables(token1); if (token1.tokenType != T_CODEBLOCK) { throw StutskException(ET_ERROR, "Token is not a codeblock"); } else { while (true) { context->run(*token1.asTokenList, "forever"); if (exitVar == OP_CONTINUE) exitVar = OP_INVALID; if (exitVar != OP_INVALID) break; } if (exitVar == OP_BREAK) exitVar = OP_INVALID; } break; case OP_FOREACH: token1 = stack_back_safe(); stutskStack.pop_back(); // Codeblock token2 = stack_back_safe(); stutskStack.pop_back(); // Codeblock recurseVariables(token1); if (token1.tokenType != T_CODEBLOCK) throw StutskException(ET_ERROR, "Token is not a codeblock"); recurseVariables(token2); if (token2.tokenType == T_ARRAY) { for (TokenList::const_iterator it = token2.asTokenList->begin(); it != token2.asTokenList->end(); ++it) { stutskStack.push_back(*it); stringstream ss; ss << "foreach [" << std::distance(token2.asTokenList->cbegin(), it) << "]"; context->run(*token1.asTokenList, ss.str()); if (exitVar == OP_CONTINUE) exitVar = OP_INVALID; if (exitVar != OP_INVALID) break; } } else if (token2.tokenType == T_DICTIONARY) { for (TokenMap::const_iterator it = token2.asDictionary->begin(); it != token2.asDictionary->end(); ++it) { stutskStack.push_back(it->second); StringPtr f = pushString(); *f = it->first; stringstream ss; ss << "foreach [" << it->first << "]"; context->run(*token1.asTokenList, ss.str()); if (exitVar == OP_CONTINUE) exitVar = OP_INVALID; if (exitVar != OP_INVALID) break; } } else { StringPtr s1_ptr = giveString(token2); for (int i = 0; i < (signed)s1_ptr->length(); i++) { *pushString() = (*s1_ptr)[i]; stringstream ss; ss << "foreach [" << i << "]"; context->run(*token1.asTokenList, ss.str()); if (exitVar == OP_CONTINUE) exitVar = OP_INVALID; if (exitVar != OP_INVALID) break; } } if (exitVar == OP_BREAK) exitVar = OP_INVALID; break; case OP_REPEAT: token1 = stack_back_safe(); stutskStack.pop_back(); // Codeblock token2 = stack_back_safe(); stutskStack.pop_back(); // Codeblock i1 = giveInteger(token2); recurseVariables(token1); if (token1.tokenType != T_CODEBLOCK) { throw StutskException(ET_ERROR, "Token is not a codeblock"); } else { while (i1 > 0) { stringstream ss; ss << "repeat [" << i1 << "]"; context->run(*token1.asTokenList, ss.str()); if (exitVar == OP_CONTINUE) exitVar = OP_INVALID; if (exitVar != OP_INVALID) break; i1--; } if (exitVar == OP_BREAK) exitVar = OP_INVALID; } break; case OP_TRY: token1 = stack_back_safe(); stutskStack.pop_back(); // Codeblock token2 = stack_back_safe(); stutskStack.pop_back(); // Codeblock recurseVariables(token1); recurseVariables(token2); if ((token2.tokenType != T_CODEBLOCK) || (token2.tokenType != T_CODEBLOCK)) { throw StutskException(ET_ERROR, "Token is not a codeblock"); } else { try { context->run(*token2.asTokenList, "try"); } catch (StutskException &e) { *pushString() = e.getMessage(); pushInteger(e.getLineNumber()); *pushString() = e.getFileName(); context->run(*token1.asTokenList, "try"); } catch (std::exception &e) { *pushString() = e.what(); pushInteger(errorToken.lineNum); *pushString() = ParseContext::get_by_id(errorToken.context_id).FileName; context->run(*token1.asTokenList, "try"); } } break; case OP_POWER: token1 = stack_back_safe(); stutskStack.pop_back(); // Codeblock token2 = stack_back_safe(); stutskStack.pop_back(); // Codeblock f1 = pow(giveFloat(token2), giveFloat(token1)); pushFloat(f1); break; case OP_THROW: token1 = stack_back_safe(); stutskStack.pop_back(); // Error name throw StutskException(ET_CUSTOM, *giveString(token1)); break; case OP_NOT: token1 = stack_back_safe(); stutskStack.pop_back(); pushBool(!giveBool(token1)); break; case OP_AND: token1 = stack_back_safe(); stutskStack.pop_back(); token2 = stack_back_safe(); stutskStack.pop_back(); pushBool(giveBool(token1) && giveBool(token2)); break; case OP_OR: token1 = stack_back_safe(); stutskStack.pop_back(); token2 = stack_back_safe(); stutskStack.pop_back(); pushBool(giveBool(token1) || giveBool(token2)); break; case OP_IF: token2 = stack_back_safe(); stutskStack.pop_back(); // Codeblock token1 = stack_back_safe(); stutskStack.pop_back(); // Codeblock recurseVariables(token2); if (token2.tokenType != T_CODEBLOCK) { throw StutskException(ET_ERROR, "Token is not a codeblock"); } else { if (giveBool(token1)) { context->run(*token2.asTokenList, "if"); } } break; case OP_IFELSE: token2 = stack_back_safe(); stutskStack.pop_back(); // Codeblock token3 = stack_back_safe(); stutskStack.pop_back(); // Codeblock token1 = stack_back_safe(); stutskStack.pop_back(); // Codeblock recurseVariables(token2); recurseVariables(token3); if ((token2.tokenType != T_CODEBLOCK) || (token3.tokenType != T_CODEBLOCK)) { throw StutskException(ET_ERROR, "Token is not a codeblock"); } else { if (giveBool(token1)) { context->run(*token3.asTokenList, "ifelse"); } else { context->run(*token2.asTokenList, "ifelse"); } } break; case OP_TERNARY: token2 = stack_back_safe(); stutskStack.pop_back(); // Codeblock token3 = stack_back_safe(); stutskStack.pop_back(); // Codeblock token1 = stack_back_safe(); stutskStack.pop_back(); // Codeblock stutskStack.push_back((giveBool(token1) ? token3 : token2)); break; case OP_CONCAT: token1 = stack_back_safe(); stutskStack.pop_back(); // Codeblock token2 = stack_back_safe(); stutskStack.pop_back(); // Codeblock // Be careful NOT to recurse variable here because we wouldn't want // to overwrite the saved value. if (token2.tokenType == T_STRING) // Performance optimization { token2.asString->append(*giveString(token1)); stutskStack.push_back(token2); } else // Should be fast enough ... *pushString() = *giveString(token2) + *giveString(token1); break; case OP_SWITCH: token2 = stack_back_safe(); stutskStack.pop_back(); // Codeblock token1 = stack_back_safe(); stutskStack.pop_back(); // Codeblock recurseVariables(token2); if (token2.tokenType != T_ARRAY) throw StutskException(ET_ERROR, "Token is not an array"); else { for (TokenList::iterator it = token2.asTokenList->begin(); it != token2.asTokenList->end(); ++it) { token3 = *it; recurseVariables(token3); if (token3.tokenType != T_ARRAY) throw StutskException(ET_ERROR, "Token is not an array"); else { if (token3.asTokenList->size() != 2) throw StutskException(ET_ERROR, "Array of wrong length"); if ((*token3.asTokenList)[1].tokenType != T_CODEBLOCK) throw StutskException(ET_ERROR, "Token is not a codeblock"); if (tokenEqual(token1, (*token3.asTokenList)[0])) { context->run(*(*token3.asTokenList)[1].asTokenList, "switch"); break; } } } } break; case OP_BREAK: case OP_CONTINUE: case OP_HALT: case OP_EXIT: exitVar = oper; break; case OP_ARRAY: token1 = stack_back_safe(); stutskStack.pop_back(); // Codeblock token2 = stack_back_safe(); stutskStack.pop_back(); // Codeblock recurseVariables(token1); if (token2.tokenType == T_VARIABLE) { if (token1.tokenType == T_ARRAY) { for (TokenList::iterator it = token1.asTokenList->begin(); it != token1.asTokenList->end(); ++it) token2.index.push_back(giveInteger(*it)); } else token2.index.push_back(giveInteger(token1)); stutskStack.push_back(token2); } else if (token2.tokenType == T_ARRAY) { if (token1.tokenType == T_ARRAY) { for (TokenList::iterator it = token1.asTokenList->begin(); it != token1.asTokenList->end(); ++it) { i1 = giveInteger(*it); if (i1 < 0) throw StutskException(ET_ERROR, "Array index underflow"); if ((signed)token2.asTokenList->size() >= i1 + 1) { token2 = (*token2.asTokenList)[i1]; } else throw StutskException(ET_ERROR, "Array index overflow"); } stutskStack.push_back(token2); } else { i1 = giveInteger(token1); if (i1 < 0) throw StutskException(ET_ERROR, "Array index underflow"); if ((signed)token2.asTokenList->size() >= i1 + 1) { stutskStack.push_back((*token2.asTokenList)[i1]); } else throw StutskException(ET_ERROR, "Array index overflow"); } } else { i1 = giveInteger(token1); StringPtr s1_ptr = giveString(token2); if (i1 < 0) throw StutskException(ET_ERROR, "String index underflow"); if ((signed)s1_ptr->length() >= i1 + 1) { *pushString() = (*s1_ptr)[i1]; } else throw StutskException(ET_ERROR, "String index overflow"); } } }