예제 #1
0
ICCItem *fnSet (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData)

//	fnSet
//
//	Bind an identifier to some value
//
//	(set var exp)
//	(setq var exp)

	{
	CCodeChain *pCC = pCtx->pCC;
	ICCItem *pArgs;
	ICCItem *pVar;
	ICCItem *pValue;
	int iFrame, iOffset;
	ICCItem *pSymTable;

	//	Evaluate the arguments and validate them

	if (dwData == FN_SET_SET)
		pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("sv"));
	else
		pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("qv"));
	if (pArgs->IsError())
		return pArgs;

	//	First is the variable; next is the value

	pVar = pArgs->GetElement(0);
	pValue = pArgs->GetElement(1);

	//	Figure out which symbol table to start with

	if (pCtx->pLocalSymbols)
		pSymTable = pCtx->pLocalSymbols;
	else
		pSymTable = pCtx->pLexicalSymbols;

	//	If this variable has already been bound, then use a short-cut

	if (pVar->GetBinding(&iFrame, &iOffset))
		{
		while (iFrame > 0)
			{
			pSymTable = pSymTable->GetParent();
			iFrame--;
			}

		pSymTable->AddByOffset(pCC, iOffset, pValue);
		}
	else
		{
		ICCItem *pError;

		pError = pSymTable->AddEntry(pCC, pVar, pValue);

		//	Check for error

		if (pError->IsError())
			{
			pArgs->Discard(pCC);
			return pError;
			}

		pError->Discard(pCC);
		}

	//	Keep a reference to the value, so we can return it

	pValue->Reference();

	//	Done with these

	pArgs->Discard(pCC);

	//	Done

	return pValue;
	}
예제 #2
0
파일: CodeChain.cpp 프로젝트: bmer/Alchemy
ICCItem *CCodeChain::Lookup (CEvalContext *pCtx, ICCItem *pItem)

//	Lookup
//
//	Returns the binding for this item

	{
	ICCItem *pBinding = NULL;
	BOOL bFound;
	ICCItem *pStart;
	int iFrame, iOffset;

	//	Start somewhere

	if (pCtx->pLocalSymbols)
		pStart = pCtx->pLocalSymbols;
	else
		pStart = pCtx->pLexicalSymbols;

	//	If this item already has been resolved, do a quick lookup

	if (pItem->GetBinding(&iFrame, &iOffset))
		{
		while (iFrame > 0)
			{
			pStart = pStart->GetParent();
			iFrame--;
			}

		pBinding = pStart->LookupByOffset(this, iOffset);
		bFound = TRUE;
		}

	//	Otherwise, do a lookup

	else
		{
		bFound = FALSE;
		iFrame = 0;

		while (!bFound && pStart)
			{
			pBinding = pStart->SimpleLookup(this, pItem, &bFound, &iOffset);
			if (!bFound)
				{
				pBinding->Discard(this);
				pBinding = NULL;
				pStart = pStart->GetParent();
				iFrame++;
				}
			}

		//	If we found it and this is a local frame,
		//	set the resolution info

		if (bFound && pStart->IsLocalFrame())
			pItem->SetBinding(iFrame, iOffset);
		}

	//	If there is no binding, return an error

	if (!bFound)
		{
		ASSERT(pBinding == NULL);
		//pBinding->Discard(this);
		pBinding = CreateError(LITERAL("No binding for symbol"), pItem);
		}

	return pBinding;
	}