Exemplo n.º 1
0
	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);
        }
	}
Exemplo n.º 2
0
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);
}
Exemplo n.º 3
0
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);
}
Exemplo n.º 4
0
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);
	}
}
Exemplo n.º 5
0
MojErr MojService::SubscriptionKey::init(const MojChar* sender)
{
	MojErr err = pushString(sender);
	MojErrCheck(err);

	return MojErrNone;
}
Exemplo n.º 6
0
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;
}
Exemplo n.º 7
0
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());
    }
}
Exemplo n.º 8
0
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;
	}
}
Exemplo n.º 9
0
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();
}
Exemplo n.º 10
0
int LuaStack::loadChunksFromZIP(const char *zipFilePath)
{
    pushString(zipFilePath);
    luaLoadChunksFromZIP(_state);
    int ret = lua_toboolean(_state, -1);
    lua_pop(_state, 1);
    return ret;
}
Exemplo n.º 11
0
void LuaInterface::throwError(const std::string& message)
{
    if(isInCppCallback()) {
        pushString(message);
        error();
    } else
        throw stdext::exception(message);
}
Exemplo n.º 12
0
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);
}
Exemplo n.º 13
0
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;
}
Exemplo n.º 14
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);
}
Exemplo n.º 15
0
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();
}
Exemplo n.º 16
0
	/**
	 * 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;
	}
Exemplo n.º 17
0
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;
}
Exemplo n.º 18
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();
}
Exemplo n.º 19
0
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);
		}
	}
}
Exemplo n.º 20
0
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;
}
Exemplo n.º 21
0
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;
}
Exemplo n.º 22
0
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);
		}
	}
}
Exemplo n.º 23
0
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");
}
Exemplo n.º 24
0
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);
}
Exemplo n.º 25
0
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;
}
Exemplo n.º 26
0
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;
}
Exemplo n.º 27
0
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));
}
Exemplo n.º 28
0
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 );

    }
}
Exemplo n.º 29
0
void CILuaState::setMetaTableIndex(void)
{
    pushString("__index");
    pushValue(-2);
    setTable(-3);
}
Exemplo n.º 30
0
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");
		}
	}
}