ICCItem *fnForLoop (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnForLoop // // Evaluates an expression for a given number of iterations // Iterates from "from" to "to" inclusive. // // (for var from to exp) { CCodeChain *pCC = pCtx->pCC; ICCItem *pArgs; ICCItem *pResult; ICCItem *pVar; ICCItem *pBody; ICCItem *pLocalSymbols; ICCItem *pOldSymbols; ICCItem *pError; int i, iFrom, iTo, iVarOffset; // Evaluate the arguments and validate them pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("qiiu")); if (pArgs->IsError()) return pArgs; pVar = pArgs->GetElement(0); iFrom = pArgs->GetElement(1)->GetIntegerValue(); iTo = pArgs->GetElement(2)->GetIntegerValue(); pBody = pArgs->GetElement(3); // Setup the locals. We start by creating a local symbol table pLocalSymbols = pCC->CreateSymbolTable(); if (pLocalSymbols->IsError()) { pArgs->Discard(pCC); return pLocalSymbols; } // Associate the enumaration variable pError = pLocalSymbols->AddEntry(pCC, pVar, pCC->CreateNil()); if (pError->IsError()) { pArgs->Discard(pCC); return pError; } pError->Discard(pCC); // Setup the context if (pCtx->pLocalSymbols) pLocalSymbols->SetParent(pCtx->pLocalSymbols); else pLocalSymbols->SetParent(pCtx->pLexicalSymbols); pOldSymbols = pCtx->pLocalSymbols; pCtx->pLocalSymbols = pLocalSymbols; // Start with a default result pResult = pCC->CreateNil(); // Get the offset of the variable so we don't have to // search for it all the time iVarOffset = pLocalSymbols->FindOffset(pCC, pVar); // Loop over all elements of the list for (i = iFrom; i <= iTo; i++) { ICCItem *pItem = pCC->CreateInteger(i); // Clean up the previous result pResult->Discard(pCC); // Set the element pLocalSymbols->AddByOffset(pCC, iVarOffset, pItem); pItem->Discard(pCC); // Eval pResult = pCC->Eval(pCtx, pBody); if (pResult->IsError()) break; } // Clean up pCtx->pLocalSymbols = pOldSymbols; pLocalSymbols->Discard(pCC); // Done pArgs->Discard(pCC); return pResult; }
ICCItem *fnFilter (CEvalContext *pCtx, ICCItem *pArgs, DWORD dwData) // fnFilter // // Filters a list based on a boolean expression. // // (filter list var exp) -> list { int i; CCodeChain *pCC = pCtx->pCC; if (pArgs->GetElement(0)->IsNil()) return pCC->CreateNil(); // Args ICCItem *pSource = pArgs->GetElement(0); ICCItem *pVar = pArgs->GetElement(1); ICCItem *pBody = pArgs->GetElement(2); // Create a destination list ICCItem *pResult = pCC->CreateLinkedList(); if (pResult->IsError()) return pResult; CCLinkedList *pList = (CCLinkedList *)pResult; // Setup the locals. We start by creating a local symbol table ICCItem *pLocalSymbols = pCC->CreateSymbolTable(); if (pLocalSymbols->IsError()) { pResult->Discard(pCC); return pLocalSymbols; } // Associate the enumaration variable ICCItem *pError = pLocalSymbols->AddEntry(pCC, pVar, pCC->CreateNil()); if (pError->IsError()) { pLocalSymbols->Discard(pCC); pResult->Discard(pCC); return pError; } pError->Discard(pCC); // Setup the context if (pCtx->pLocalSymbols) pLocalSymbols->SetParent(pCtx->pLocalSymbols); else pLocalSymbols->SetParent(pCtx->pLexicalSymbols); ICCItem *pOldSymbols = pCtx->pLocalSymbols; pCtx->pLocalSymbols = pLocalSymbols; // Get the offset of the variable so we don't have to // search for it all the time int iVarOffset = pLocalSymbols->FindOffset(pCC, pVar); // Loop over all elements of the list for (i = 0; i < pSource->GetCount(); i++) { ICCItem *pItem = pSource->GetElement(i); // Set the element pLocalSymbols->AddByOffset(pCC, iVarOffset, pItem); // Eval ICCItem *pSelect = pCC->Eval(pCtx, pBody); if (pSelect->IsError()) { pResult->Discard(pCC); pResult = pSelect; break; } // If the evaluation is not Nil, then we include the // item in the result if (!pSelect->IsNil()) pList->Append(pCC, pItem, NULL); pSelect->Discard(pCC); } // Clean up pCtx->pLocalSymbols = pOldSymbols; pLocalSymbols->Discard(pCC); // Done if (pResult->GetCount() > 0) return pResult; else { pResult->Discard(pCC); return pCC->CreateNil(); } }
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 *fnEnum (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnEnum // // Enumerates the elements of a list // // (enum list item-var exp) // (enumwhile list condition item-var exp) { CCodeChain *pCC = pCtx->pCC; ICCItem *pArgs; ICCItem *pResult; ICCItem *pVar; ICCItem *pBody; ICCItem *pList; ICCItem *pCondition; ICCItem *pLocalSymbols; ICCItem *pOldSymbols; ICCItem *pError; int i, iVarOffset; // Evaluate the arguments and validate them if (dwData == FN_ENUM_WHILE) { pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("vuqu")); if (pArgs->IsError()) return pArgs; pList = pArgs->GetElement(0); pCondition = pArgs->GetElement(1); pVar = pArgs->GetElement(2); pBody = pArgs->GetElement(3); } else { pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("vqu")); if (pArgs->IsError()) return pArgs; pList = pArgs->GetElement(0); pCondition = NULL; pVar = pArgs->GetElement(1); pBody = pArgs->GetElement(2); } // Setup the locals. We start by creating a local symbol table pLocalSymbols = pCC->CreateSymbolTable(); if (pLocalSymbols->IsError()) { pArgs->Discard(pCC); return pLocalSymbols; } // Associate the enumaration variable pError = pLocalSymbols->AddEntry(pCC, pVar, pCC->CreateNil()); if (pError->IsError()) { pArgs->Discard(pCC); return pError; } pError->Discard(pCC); // Setup the context if (pCtx->pLocalSymbols) pLocalSymbols->SetParent(pCtx->pLocalSymbols); else pLocalSymbols->SetParent(pCtx->pLexicalSymbols); pOldSymbols = pCtx->pLocalSymbols; pCtx->pLocalSymbols = pLocalSymbols; // Start with a default result pResult = pCC->CreateNil(); // Get the offset of the variable so we don't have to // search for it all the time iVarOffset = pLocalSymbols->FindOffset(pCC, pVar); // Loop over all elements of the list for (i = 0; i < pList->GetCount(); i++) { // Check the condition if (pCondition) { ICCItem *pEval; // Evaluate the condition pEval = pCC->Eval(pCtx, pCondition); if (pEval->IsError()) { pResult->Discard(pCC); pResult = pEval; break; } // If the condition is Nil, then we're done if (pEval->IsNil()) { pEval->Discard(pCC); break; } } ICCItem *pItem = pList->GetElement(i); // Clean up the previous result pResult->Discard(pCC); // Set the element pLocalSymbols->AddByOffset(pCC, iVarOffset, pItem); // Eval pResult = pCC->Eval(pCtx, pBody); if (pResult->IsError()) break; } // Clean up pCtx->pLocalSymbols = pOldSymbols; pLocalSymbols->Discard(pCC); // Done pArgs->Discard(pCC); return pResult; }
ICCItem *fnPageMap (CEvalContext *pEvalCtx, ICCItem *pArgs, DWORD dwData) // fnPageMap // // (pageMap address|pageID enumMethod ['excludeNil] var exp) -> filtered list { CCodeChain *pCC = pEvalCtx->pCC; // Args ICCItem *pAddress = pArgs->GetElement(0); ICCItem *pMethod = pArgs->GetElement(1); bool bExcludeNil; int iOptionalArg = 2; if (pArgs->GetCount() > 4) bExcludeNil = strEquals(pArgs->GetElement(iOptionalArg++)->GetStringValue(), CONSTLIT("excludeNil")); else bExcludeNil = false; ICCItem *pVar = pArgs->GetElement(iOptionalArg++); ICCItem *pBody = pArgs->GetElement(iOptionalArg++); // Open the page IPage *pPage; CString sError; if (g_PM.OpenPage(pAddress->GetStringValue(), &pPage, &sError) != NOERROR) return pCC->CreateError(sError, NULL); // Prepare the method SPageEnumCtx EnumCtx; if (pPage->EnumReset(*pCC, pMethod, EnumCtx, &sError)) { g_PM.ClosePage(pPage); return pCC->CreateError(sError, NULL); } // Create a destination list ICCItem *pResult = pCC->CreateLinkedList(); if (pResult->IsError()) { g_PM.ClosePage(pPage); return pResult; } CCLinkedList *pList = (CCLinkedList *)pResult; // Setup the locals. We start by creating a local symbol table ICCItem *pLocalSymbols = pCC->CreateSymbolTable(); if (pLocalSymbols->IsError()) { pResult->Discard(pCC); g_PM.ClosePage(pPage); return pLocalSymbols; } // Associate the enumaration variable ICCItem *pError = pLocalSymbols->AddEntry(pCC, pVar, pCC->CreateNil()); if (pError->IsError()) { pLocalSymbols->Discard(pCC); pResult->Discard(pCC); g_PM.ClosePage(pPage); return pError; } pError->Discard(pCC); // Setup the context if (pEvalCtx->pLocalSymbols) pLocalSymbols->SetParent(pEvalCtx->pLocalSymbols); else pLocalSymbols->SetParent(pEvalCtx->pLexicalSymbols); ICCItem *pOldSymbols = pEvalCtx->pLocalSymbols; pEvalCtx->pLocalSymbols = pLocalSymbols; // Get the offset of the variable so we don't have to // search for it all the time int iVarOffset = pLocalSymbols->FindOffset(pCC, pVar); // Enumerate the page while (pPage->EnumHasMore(EnumCtx)) { ICCItem *pItem = pPage->EnumGetNext(*pCC, EnumCtx); if (pItem->IsError()) { pResult->Discard(pCC); pResult = pItem; break; } // Set the element pLocalSymbols->AddByOffset(pCC, iVarOffset, pItem); // Eval ICCItem *pMapped = pCC->Eval(pEvalCtx, pBody); if (pMapped->IsError()) { pItem->Discard(pCC); pResult->Discard(pCC); pResult = pMapped; break; } // If the evaluation is not Nil, then we include the // item in the result if (!bExcludeNil || !pMapped->IsNil()) pList->Append(*pCC, pMapped); pItem->Discard(pCC); pMapped->Discard(pCC); } // Clean up pEvalCtx->pLocalSymbols = pOldSymbols; pLocalSymbols->Discard(pCC); g_PM.ClosePage(pPage); // Done if (pResult->GetCount() > 0) return pResult; else { pResult->Discard(pCC); return pCC->CreateNil(); } }