示例#1
0
void BIF_IsObject(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount)
// IsObject(obj) is currently equivalent to (obj && obj=""), but much more intuitive.
{
	int i;
	for (i = 0; i < aParamCount && TokenToObject(*aParam[i]); ++i);
	aResultToken.value_int64 = (__int64)(i == aParamCount); // TRUE if all are objects.
}
示例#2
0
void BIF_ObjCreate(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount)
{
	IObject *obj = NULL;

	if (aParamCount == 1) // L33: POTENTIALLY UNSAFE - Cast IObject address to object reference.
	{
		if (obj = TokenToObject(*aParam[0]))
		{	// Allow &obj == Object(obj), but AddRef() for equivalence with ComObjActive(comobj).
			obj->AddRef();
			aResultToken.value_int64 = (__int64)obj;
			return; // symbol is already SYM_INTEGER.
		}
		obj = (IObject *)TokenToInt64(*aParam[0]);
		if (obj < (IObject *)1024) // Prevent some obvious errors.
			obj = NULL;
		else
			obj->AddRef();
	}
	else
		obj = Object::Create(aParam, aParamCount);

	if (obj)
	{
		aResultToken.symbol = SYM_OBJECT;
		aResultToken.object = obj;
		// DO NOT ADDREF: after we return, the only reference will be in aResultToken.
	}
	else
	{
		aResultToken.symbol = SYM_STRING;
		aResultToken.marker = _T("");
	}
}
ResultType BIF_ObjMethod(int aID, ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount)
{
	aResultToken.symbol = SYM_STRING;
	aResultToken.marker = _T("");

	Object *obj = dynamic_cast<Object*>(TokenToObject(*aParam[0]));
	if (!obj)
		return OK; // Return "".
	return obj->CallBuiltin(aID, aResultToken, aParam + 1, aParamCount - 1);
}
void BIF_ObjInvoke(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount)
{
    int invoke_type;
    IObject *obj;
    ExprTokenType *obj_param;

	// Since ObjGet/ObjSet/ObjCall are not publicly accessible as functions, Func::mName
	// (passed via aResultToken.marker) contains the actual flag rather than a name.
	invoke_type = (int)(INT_PTR)aResultToken.marker;

	// Set default return value; ONLY AFTER THE ABOVE.
	aResultToken.symbol = SYM_STRING;
	aResultToken.marker = _T("");
    
    obj_param = *aParam; // aParam[0].  Load-time validation has ensured at least one parameter was specified.
	++aParam;
	--aParamCount;
    
    if (obj = TokenToObject(*obj_param))
	{
		bool param_is_var = obj_param->symbol == SYM_VAR;
		if (param_is_var)
			// Since the variable may be cleared as a side-effect of the invocation, call AddRef to ensure the object does not expire prematurely.
			// This is not necessary for SYM_OBJECT since that reference is already counted and cannot be released before we return.  Each object
			// could take care not to delete itself prematurely, but it seems more proper, more reliable and more maintainable to handle it here.
			obj->AddRef();
        obj->Invoke(aResultToken, *obj_param, invoke_type, aParam, aParamCount);
		if (param_is_var)
			obj->Release();
	}
	// Invoke meta-functions of g_MetaObject.
	else if (INVOKE_NOT_HANDLED == g_MetaObject.Invoke(aResultToken, *obj_param, invoke_type | IF_META, aParam, aParamCount)
		// If above did not handle it, check for attempts to access .base of non-object value (g_MetaObject itself).
		// CALL is unsupported (for simplicity); SET is supported only in "multi-dimensional" mode: "".base[x]:=y
		&& invoke_type != IT_CALL && (invoke_type == IT_SET ? aParamCount > 2 : aParamCount)
		&& !_tcsicmp(TokenToString(*aParam[0]), _T("base")))
	{
		if (aParamCount > 1)	// "".base[x] or similar
		{
			// Re-invoke g_MetaObject without meta flag or "base" param.
			ExprTokenType base_token;
			base_token.symbol = SYM_OBJECT;
			base_token.object = &g_MetaObject;
			g_MetaObject.Invoke(aResultToken, base_token, invoke_type, aParam + 1, aParamCount - 1);
		}
		else					// "".base
		{
			// Return a reference to g_MetaObject.  No need to AddRef as g_MetaObject ignores it.
			aResultToken.symbol = SYM_OBJECT;
			aResultToken.object = &g_MetaObject;
		}
	}
}
示例#5
0
void BIF_ObjNew(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount)
{
	aResultToken.symbol = SYM_STRING;
	aResultToken.marker = _T("");

	ExprTokenType *class_token = aParam[0]; // Save this to be restored later.

	IObject *class_object = TokenToObject(*class_token);
	if (!class_object)
		return;

	Object *new_object = Object::Create(NULL, 0);
	if (!new_object)
		return;

	new_object->SetBase(class_object);

	ExprTokenType name_token, this_token;
	name_token.symbol = SYM_STRING;
	name_token.marker = Object::sMetaFuncName[4]; // __New
	this_token.symbol = SYM_OBJECT;
	this_token.object = new_object;
	aParam[0] = &name_token;
	if (class_object->Invoke(aResultToken, this_token, IT_CALL | IF_METAOBJ, aParam, aParamCount) != EARLY_RETURN)
	{
		// Although it isn't likely to happen, if __New points at a built-in function or if mBase
		// (or an ancestor) is not an Object (i.e. it's a ComObject), aResultToken can be set even when
		// the result is not EARLY_RETURN.  So make sure to clean up any result we're not going to use.
		if (aResultToken.symbol == SYM_OBJECT)
			aResultToken.object->Release();
		if (aResultToken.mem_to_free)
		{
			// This can be done by our caller, but is done here for maintainability; i.e. because
			// some callers might expect mem_to_free to be NULL when the result isn't a string.
			free(aResultToken.mem_to_free);
			aResultToken.mem_to_free = NULL;
		}
		// Either it wasn't handled (i.e. neither this class nor any of its super-classes define __New()),
		// or there was no explicit "return", so just return the new object.
		aResultToken.symbol = SYM_OBJECT;
		aResultToken.object = new_object;
	}
	else
		new_object->Release();
	aParam[0] = class_token;
}
示例#6
0
void BIF_ObjNew(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount)
{
	aResultToken.symbol = SYM_STRING;
	aResultToken.marker = _T("");

	ExprTokenType *class_token = aParam[0]; // Save this to be restored later.

	IObject *class_object = TokenToObject(*class_token);
	if (!class_object)
		return;

	Object *new_object = Object::Create(NULL, 0);
	if (!new_object)
		return;

	new_object->SetBase(class_object);

	ExprTokenType name_token, this_token;
	this_token.symbol = SYM_OBJECT;
	this_token.object = new_object;
	name_token.symbol = SYM_STRING;
	aParam[0] = &name_token;

	ResultType result;
	LPTSTR buf = aResultToken.buf; // In case Invoke overwrites it via the union.

	// __Init was added so that instance variables can be initialized in the correct order
	// (beginning at the root class and ending at class_object) before __New is called.
	// It shouldn't be explicitly defined by the user, but auto-generated in DefineClassVars().
	name_token.marker = _T("__Init");
	result = class_object->Invoke(aResultToken, this_token, IT_CALL | IF_METAOBJ, aParam, 1);
	if (result != INVOKE_NOT_HANDLED)
	{
		// See similar section below for comments.
		if (aResultToken.symbol == SYM_OBJECT)
			aResultToken.object->Release();
		if (aResultToken.mem_to_free)
		{
			free(aResultToken.mem_to_free);
			aResultToken.mem_to_free = NULL;
		}
		// Reset to defaults for __New, invoked below.
		aResultToken.symbol = SYM_STRING;
		aResultToken.marker = _T("");
		aResultToken.buf = buf;
		if (result == FAIL)
		{
			aParam[0] = class_token; // Restore it to original caller-supplied value.
			return;
		}
	}
	
	// __New may be defined by the script for custom initialization code.
	name_token.marker = Object::sMetaFuncName[4]; // __New
	if (class_object->Invoke(aResultToken, this_token, IT_CALL | IF_METAOBJ, aParam, aParamCount) != EARLY_RETURN)
	{
		// Although it isn't likely to happen, if __New points at a built-in function or if mBase
		// (or an ancestor) is not an Object (i.e. it's a ComObject), aResultToken can be set even when
		// the result is not EARLY_RETURN.  So make sure to clean up any result we're not going to use.
		if (aResultToken.symbol == SYM_OBJECT)
			aResultToken.object->Release();
		if (aResultToken.mem_to_free)
		{
			// This can be done by our caller, but is done here for maintainability; i.e. because
			// some callers might expect mem_to_free to be NULL when the result isn't a string.
			free(aResultToken.mem_to_free);
			aResultToken.mem_to_free = NULL;
		}
		// Either it wasn't handled (i.e. neither this class nor any of its super-classes define __New()),
		// or there was no explicit "return", so just return the new object.
		aResultToken.symbol = SYM_OBJECT;
		aResultToken.object = new_object;
	}
	else
		new_object->Release();
	aParam[0] = class_token;
}