QString GeneratorForCallGenerator::commonGeneratedString(const QSharedPointer<ElementIdentifier> &calledIdentifier , const QSharedPointer<Identifier> &generatorNameNode , const GeneratorConfigurer &generatorConfigurer , ScopeInfo &scopeInfo) { const auto currentElementId = GeneratorForElementIdentifierNode::neededElementId(calledIdentifier , generatorConfigurer, scopeInfo); const auto currentElementType = TypeQualifier::elementIdentifierType(calledIdentifier , generatorConfigurer, scopeInfo); const auto diagramId = generatorConfigurer.diagramId(); const auto editorManagerInterface = generatorConfigurer.editorManagerInterface(); const auto elementIdInMetamodel = idInMetamodel(editorManagerInterface, currentElementType, diagramId); const auto generationRuleForCurrentElement = editorManagerInterface->generationRule(elementIdInMetamodel); QSharedPointer<Node> generatedTree = TreeGeneratorFromString::generatedTreeFromString(generationRuleForCurrentElement); scopeInfo.currentScope().changeCurrentId(currentElementId); QString resultOfGeneration = ""; if (!generatorNameNode) { resultOfGeneration = CommonGenerator::generatedResult(generatedTree, generatorConfigurer, scopeInfo); } else { QString generatorName = generatorNameNode->name(); scopeInfo.currentScope().changeCurrentGeneratorName(generatorName); resultOfGeneration = CommonGenerator::generatedResult(generatedTree, generatorConfigurer, scopeInfo); } scopeInfo.currentScope().removeLastCurrentId(); return resultOfGeneration; }
qReal::Id GeneratorForElementIdentifierNode::neededElementId( const QSharedPointer<ElementIdentifier> &elementIdentifierNode , const GeneratorConfigurer &generatorConfigurer , ScopeInfo &scopeInfo) { const auto identifierPart = elementIdentifierNode->identifierPart(); const auto optionalTransitionPart = elementIdentifierNode->optionalTransitionPart(); const auto logicalModelInterface = generatorConfigurer.logicalModelInterface(); qReal::Id elementId; if (identifierPart->is<Identifier>()) { elementId = scopeInfo.variablesTable().currentId(qrtext::as<Identifier>(identifierPart)->name()); } else { elementId = scopeInfo.currentScope().currentId(); } if (optionalTransitionPart) { // we have to return transitionEnd or transitionStart for this element if (optionalTransitionPart->is<TransitionEnd>()) { return logicalModelInterface->to(elementId); } else if (optionalTransitionPart->is<TransitionStart>()) { return logicalModelInterface->from(elementId); } else { // TODO: throw exception qDebug() << "ERROR"; return qReal::Id::rootId(); } } else { return elementId; } }
// // Create scope info for an outer scope. // ScopeInfo* ScopeInfo::FromScope(ByteCodeGenerator* byteCodeGenerator, FunctionBody* parent, Scope* scope, ScriptContext *scriptContext) { int count = scope->Count(); // Add argsPlaceHolder which includes same name args and destructuring patterns on parameters AddSlotCount(count, scope->GetFunc()->argsPlaceHolderSlotCount); AddSlotCount(count, scope->GetFunc()->thisScopeSlot != Js::Constants::NoRegister ? 1 : 0); AddSlotCount(count, scope->GetFunc()->newTargetScopeSlot != Js::Constants::NoRegister ? 1 : 0); ScopeInfo* scopeInfo = RecyclerNewPlusZ(scriptContext->GetRecycler(), count * sizeof(SymbolInfo), ScopeInfo, parent, count); scopeInfo->isDynamic = scope->GetIsDynamic(); scopeInfo->isObject = scope->GetIsObject(); scopeInfo->mustInstantiate = scope->GetMustInstantiate(); scopeInfo->isCached = (scope->GetFunc()->GetBodyScope() == scope) && scope->GetFunc()->GetHasCachedScope(); scopeInfo->isGlobalEval = scope->GetScopeType() == ScopeType_GlobalEvalBlock; scopeInfo->canMergeWithBodyScope = scope->GetCanMergeWithBodyScope(); scopeInfo->hasLocalInClosure = scope->GetHasOwnLocalInClosure(); TRACE_BYTECODE(_u("\nSave ScopeInfo: %s parent: %s #symbols: %d %s\n"), scope->GetFunc()->name, parent->GetDisplayName(), count, scopeInfo->isObject ? _u("isObject") : _u("")); MapSymbolData mapSymbolData = { byteCodeGenerator, scope->GetFunc() }; scope->ForEachSymbol([&mapSymbolData, scopeInfo, scope](Symbol * sym) { Assert(scope == sym->GetScope()); scopeInfo->SaveSymbolInfo(sym, &mapSymbolData); }); return scopeInfo; }
// // Save scope info for an outer func which has deferred child. // void ScopeInfo::SaveScopeInfo(ByteCodeGenerator* byteCodeGenerator, FuncInfo* parentFunc, FuncInfo* func) { ParseableFunctionInfo* funcBody = func->byteCodeFunction; Assert((!func->IsGlobalFunction() || byteCodeGenerator->GetFlags() & fscrEvalCode) && (func->HasDeferredChild() || (funcBody->IsReparsed()))); // If we are reparsing a deferred function, we already have correct "parent" info in // funcBody->scopeInfo. parentFunc is the knopProg shell and should not be used in this // case. We should use existing parent if available. FunctionBody * parent = funcBody->GetScopeInfo() ? funcBody->GetScopeInfo()->GetParent() : parentFunc ? parentFunc->byteCodeFunction->GetFunctionBody() : nullptr; ScopeInfo* funcExprScopeInfo = nullptr; Scope* funcExprScope = func->GetFuncExprScope(); if (funcExprScope && funcExprScope->GetMustInstantiate()) { funcExprScopeInfo = FromScope(byteCodeGenerator, parent, funcExprScope, funcBody->GetScriptContext()); } Scope* bodyScope = func->IsGlobalFunction() ? func->GetGlobalEvalBlockScope() : func->GetBodyScope(); ScopeInfo* paramScopeInfo = nullptr; Scope* paramScope = func->GetParamScope(); if (paramScope && bodyScope->GetMustInstantiate()) { paramScopeInfo = FromScope(byteCodeGenerator, parent, paramScope, funcBody->GetScriptContext()); } ScopeInfo* scopeInfo = FromScope(byteCodeGenerator, parent, bodyScope, funcBody->GetScriptContext()); scopeInfo->SetFuncExprScopeInfo(funcExprScopeInfo); scopeInfo->SetParamScopeInfo(paramScopeInfo); funcBody->SetScopeInfo(scopeInfo); }
bool Qualify0(ScopeInfo& nf, const String& type, const String& usings, String& qt) { // Qualify single type based on scoping information const Vector<String>& nd = nf.GetScopes(usings); if(nd.GetCount()) { LTIMING("First test"); qt = nd[0] + type; if(nf.base.Find(qt) >= 0) return true; } if(nf.GetScope() >= 0) { int q = type.ReverseFind(':'); if(q > 0) { LTIMING("Qualifying qualification"); ScopeInfo hnf(nf); hnf.NoBases(); String qn; String qs = type.Mid(0, q - 1); if(IsDigit(*qs)) { qt = type; return true; } if(DoQualify(hnf, qs, usings, qn)) { String tp = type.Mid(q + 1); if(nf.base.Find(qn) >= 0) { qt = qn + "::" + tp; return true; } int scopei = nf.base.Find(qn); if(scopei >= 0) { ScopeInfo nnf(nf.base, scopei); const Vector<String>& bs = nnf.GetBases(); for(int i = 0; i < bs.GetCount(); i++) { qt = bs[i] + tp; if(nf.base.Find(qt) >= 0) return true; } } } if(nf.base.Find(qs) >= 0) { qt = qs; return true; } qt = type; if(nf.base.Find(qt) >= 0) // e.g. std::string return true; qt = type.Mid(q + 1); return true; } else { LTIMING("Bases"); const Vector<String>& bs = nf.GetBases(); for(int i = 0; i < bs.GetCount(); i++) { qt = bs[i] + type; if(nf.base.Find(qt) >= 0) return true; } } } if(type[0] != ':') { LTIMING("Testing scopes"); for(int i = 1; i < nd.GetCount(); i++) { qt = nd[i] + type; if(nf.base.Find(qt) >= 0) return true; } } int q = type.Find(':'); if(q < 0) return false; return Qualify0(nf, type.Mid(q + 1), usings, qt); }