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; }
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; }