123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721 |
- #include "BeefySysLib/util/AllocDebug.h"
- #include "BfDefBuilder.h"
- #include "BeefySysLib/util/Hash.h"
- #include "BfParser.h"
- #include "BfResolvePass.h"
- #include "BeefySysLib/util/PerfTimer.h"
- #include "BeefySysLib/util/BeefPerf.h"
- #include "BfUtil.h"
- USING_NS_BF;
- static void HashNode(HashContext& ctx, BfAstNode* astNode)
- {
- // Add a separator marker so two nodes hashed back-to-back won't mix
- uint8 marker = 0;
- ctx.Mixin(&marker, 1);
- if (astNode == NULL)
- return;
- ctx.Mixin(astNode->GetSourceData()->mSrc + astNode->GetSrcStart(), astNode->GetSrcLength());
- }
- static void HashNode(HashContext& ctx, BfAstNode* astNode, BfAstNode* endNode)
- {
- // Add a separator marker so two nodes hashed back-to-back won't mix
- uint8 marker = 0;
- ctx.Mixin(&marker, 1);
- if (endNode == NULL)
- {
- HashNode(ctx, astNode);
- return;
- }
- ctx.Mixin(astNode->GetSourceData()->mSrc + astNode->GetSrcStart(), endNode->GetSrcStart() - astNode->GetSrcStart());
- }
- static Val128 HashNode(BfAstNode* astNode)
- {
- if (astNode == NULL)
- return Val128();
- return Hash128(astNode->GetSourceData()->mSrc + astNode->GetSrcStart(), astNode->GetSrcLength());
- }
- static Val128 HashNode(BfAstNode* astNode, BfAstNode* endNode)
- {
- if (endNode == NULL)
- return HashNode(astNode);
- return Hash128(astNode->GetSourceData()->mSrc + astNode->GetSrcStart(), endNode->GetSrcStart() - astNode->GetSrcStart());
- }
- static Val128 HashString(const StringImpl& str, const Val128& seed = Val128())
- {
- return Hash128(str.c_str(), (int)str.length(), seed);
- }
- BfDefBuilder::BfDefBuilder(BfSystem* bfSystem)
- {
- mPassInstance = NULL;
- mSystem = bfSystem;
- mCurTypeDef = NULL;
- mCurDeclaringTypeDef = NULL;
- mCurActualTypeDef = NULL;
- mFullRefresh = false;
- mIsComptime = false;
- mResolvePassData = NULL;
- mCurSource = NULL;
- mFullHashCtx = NULL;
- mSignatureHashCtx = NULL;
- mNamespaceBlockDepth = 0;
- }
- BfDefBuilder::~BfDefBuilder()
- {
- for (auto& usingNamespace : mNamespaceSearch)
- mSystem->ReleaseAtomComposite(usingNamespace);
- }
- void BfDefBuilder::Process(BfPassInstance* passInstance, BfSource* bfSource, bool fullRefresh)
- {
- BF_ASSERT((mSystem->mCurSystemLockThreadId == 0) || (mSystem->mCurSystemLockThreadId == BfpThread_GetCurrentId()));
- String fileName;
- BfParser* parser = bfSource->ToParser();
- if (parser != NULL)
- fileName = parser->mFileName;
- BP_ZONE_F("BfDefBuilder::Process %s", fileName.c_str());
- BfLogSys(parser->mSystem, "DefBuilder::Process parser %p\n", parser);
- if (mResolvePassData == NULL)
- mSystem->mNeedsTypesHandledByCompiler = true;
- mPassInstance = passInstance;
- bool isAutocomplete = false;
- if ((mResolvePassData != NULL) && (mResolvePassData->mAutoComplete != NULL))
- {
- mCurSource = bfSource;
- Visit(bfSource->mRootNode);
- mCurSource = NULL;
- mPassInstance = NULL;
- return;
- }
- mFullRefresh = fullRefresh;
- if (bfSource->mPrevRevision != NULL)
- {
- for (auto typeDef : bfSource->mPrevRevision->mTypeDefs)
- {
- BF_ASSERT((typeDef->mDefState >= BfTypeDef::DefState_New) && (typeDef->mDefState < BfTypeDef::DefState_Deleted));
- typeDef->mDefState = BfTypeDef::DefState_AwaitingNewVersion;
- }
- }
- {
- BP_ZONE("RootNode");
- if (bfSource->mRootNode != NULL)
- {
- mCurSource = bfSource;
- Visit(bfSource->mRootNode);
- mCurSource = NULL;
- }
- }
- if (bfSource->mPrevRevision != NULL)
- {
- for (auto typeDef : bfSource->mPrevRevision->mTypeDefs)
- {
- if (!typeDef->mIsCombinedPartial)
- {
- if (typeDef->mDefState == BfTypeDef::DefState_AwaitingNewVersion)
- {
- BfLogSys(parser->mSystem, "DefBuilder::Process deleting typeDef %p\n", typeDef);
- typeDef->mName->mAtomUpdateIdx = ++mSystem->mAtomUpdateIdx;
- typeDef->mDefState = BfTypeDef::DefState_Deleted;
- mSystem->mTypeMapVersion++;
- }
- }
- }
- }
- mPassInstance = NULL;
- }
- void BfDefBuilder::Visit(BfIdentifierNode* identifier)
- {
- if (mResolvePassData != NULL)
- mResolvePassData->mExteriorAutocompleteCheckNodes.push_back(identifier);
- }
- // We need to be aware of the startNode because the reducer adds specifiers like 'static' and 'public' AFTER the method has
- // already been handled, so we need to ignore that space while determining if we're "inside" this method or not during
- // autocompletion
- bool BfDefBuilder::WantsNode(BfAstNode* wholeNode, BfAstNode* startNode, int addLen)
- {
- if ((mResolvePassData == NULL) || (!mResolvePassData->mHasCursorIdx))
- return true;
- auto parser = wholeNode->GetParser();
- if (parser->mCursorIdx == -1)
- return true;
- // We need to get all nodes when we get fixits because the cursor could be either before or after fields with
- // warnings, but still on the correct line
- //if (mResolvePassData->mResolveType == BfResolveType_GetFixits)
- //return true;
- addLen++;
- if ((parser->mCursorIdx >= wholeNode->GetSrcStart()) && (parser->mCursorIdx < wholeNode->GetSrcEnd() + addLen))
- {
- if ((startNode == NULL) || (parser->mCursorIdx >= startNode->GetSrcStart()))
- return true;
- }
- return false;
- }
- static int sGenericParamIdx = 0;
- void BfDefBuilder::ParseGenericParams(BfGenericParamsDeclaration* genericParamsDecl, BfGenericConstraintsDeclaration* genericConstraints, Array<BfGenericParamDef*>& genericParams, Array<BfExternalConstraintDef>* externConstraintDefs, int outerGenericSize, bool isInGeneric)
- {
- if (genericParamsDecl != NULL)
- {
- int startIdx = (int)genericParams.size();
- for (int genericParamIdx = 0; genericParamIdx < (int)genericParamsDecl->mGenericParams.size(); genericParamIdx++)
- {
- BfIdentifierNode* genericParamNode = genericParamsDecl->mGenericParams[genericParamIdx];
- String name = genericParamNode->ToString();
- for (int checkParamsIdx = startIdx; checkParamsIdx < (int)genericParams.size(); checkParamsIdx++)
- {
- if (genericParams[checkParamsIdx]->mName == name)
- {
- Fail("Duplicate generic param name", genericParamNode);
- }
- }
- auto checkTypeDef = mCurTypeDef;
- while (checkTypeDef != NULL)
- {
- if (&genericParams != &checkTypeDef->mGenericParamDefs)
- {
- for (int checkParamsIdx = 0; checkParamsIdx < (int)checkTypeDef->mGenericParamDefs.size(); checkParamsIdx++)
- {
- if (checkTypeDef->mGenericParamDefs[checkParamsIdx]->mName == name)
- {
- mPassInstance->Warn(0, "Generic param name has same name as generic param from outer type", genericParamNode);
- }
- }
- }
- checkTypeDef = checkTypeDef->mOuterType;
- }
- auto genericParamDef = new BfGenericParamDef();
- genericParamDef->mName = name;
- genericParamDef->mNameNodes.Add(genericParamNode);
- genericParamDef->mGenericParamFlags = BfGenericParamFlag_None;
- genericParams.push_back(genericParamDef);
- }
- }
- if (genericConstraints == NULL)
- return;
- for (BfAstNode* genericConstraintNode : genericConstraints->mGenericConstraints)
- {
- auto genericConstraint = BfNodeDynCast<BfGenericConstraint>(genericConstraintNode);
- if (genericConstraint == NULL)
- continue;
- if (genericConstraint->mTypeRef == NULL)
- continue;
- BfIdentifierNode* nameNode = NULL;
- BfGenericParamDef* genericParamDef = NULL;
- if (auto namedTypeRef = BfNodeDynCast<BfNamedTypeReference>(genericConstraint->mTypeRef))
- {
- nameNode = namedTypeRef->mNameNode;
- String findName = nameNode->ToString();
- for (int genericParamIdx = outerGenericSize; genericParamIdx < (int)genericParams.size(); genericParamIdx++)
- {
- auto checkGenericParam = genericParams[genericParamIdx];
- if (checkGenericParam->mName == findName)
- genericParamDef = checkGenericParam;
- }
- }
- BfConstraintDef* constraintDef = genericParamDef;
- if (genericParamDef == NULL)
- {
- if (externConstraintDefs == NULL)
- {
- Fail("Cannot find generic parameter in constraint", genericConstraint->mTypeRef);
- if (genericParams.IsEmpty())
- continue;
- genericParamDef = genericParams[0];
- constraintDef = genericParamDef;
- }
- else
- {
- if (!isInGeneric)
- Fail("Constraints cannot be specified for non-generics", genericConstraint);
- externConstraintDefs->Add(BfExternalConstraintDef());
- BfExternalConstraintDef* externConstraintDef = &externConstraintDefs->back();
- externConstraintDef->mTypeRef = genericConstraint->mTypeRef;
- constraintDef = externConstraintDef;
- }
- }
- if (genericParamDef != NULL)
- genericParamDef->mNameNodes.Add(nameNode);
- for (BfAstNode* constraintNode : genericConstraint->mConstraintTypes)
- {
- String name;
- if ((constraintNode->IsA<BfNamedTypeReference>()) || (constraintNode->IsA<BfTokenNode>()))
- {
- name = constraintNode->ToString();
- }
- else if (auto tokenPairNode = BfNodeDynCast<BfTokenPairNode>(constraintNode))
- {
- name = tokenPairNode->mLeft->ToString() + tokenPairNode->mRight->ToString();
- }
- if (!name.empty())
- {
- if ((name == "class") || (name == "struct") || (name == "struct*") || (name == "const") || (name == "var") || (name == "concrete") || (name == "interface") || (name == "enum"))
- {
- int prevFlags = constraintDef->mGenericParamFlags &
- (BfGenericParamFlag_Class | BfGenericParamFlag_Struct | BfGenericParamFlag_StructPtr | BfGenericParamFlag_Interface | BfGenericParamFlag_Enum);
- if (prevFlags != 0)
- {
- String prevFlagName;
- if (prevFlags & BfGenericParamFlag_Class)
- prevFlagName = "class";
- else if (prevFlags & BfGenericParamFlag_Struct)
- prevFlagName = "struct";
- else if (prevFlags & BfGenericParamFlag_StructPtr)
- prevFlagName = "struct*";
- else if (prevFlags & BfGenericParamFlag_Enum)
- prevFlagName = "enum";
- else // interface
- prevFlagName = "interface";
- if (prevFlagName == name)
- Fail(StrFormat("Cannot specify '%s' twice", prevFlagName.c_str()), constraintNode);
- else
- Fail(StrFormat("Cannot specify both '%s' and '%s'", prevFlagName.c_str(), name.c_str()), constraintNode);
- return;
- }
- if (name == "class")
- constraintDef->mGenericParamFlags = (BfGenericParamFlags)(constraintDef->mGenericParamFlags | BfGenericParamFlag_Class);
- else if (name == "struct")
- constraintDef->mGenericParamFlags = (BfGenericParamFlags)(constraintDef->mGenericParamFlags | BfGenericParamFlag_Struct);
- else if (name == "struct*")
- constraintDef->mGenericParamFlags = (BfGenericParamFlags)(constraintDef->mGenericParamFlags | BfGenericParamFlag_StructPtr);
- else if (name == "const")
- constraintDef->mGenericParamFlags = (BfGenericParamFlags)(constraintDef->mGenericParamFlags | BfGenericParamFlag_Const);
- else if (name == "concrete")
- constraintDef->mGenericParamFlags = (BfGenericParamFlags)(constraintDef->mGenericParamFlags | BfGenericParamFlag_Concrete);
- else if (name == "interface")
- constraintDef->mGenericParamFlags = (BfGenericParamFlags)(constraintDef->mGenericParamFlags | BfGenericParamFlag_Interface);
- else if (name == "enum")
- constraintDef->mGenericParamFlags = (BfGenericParamFlags)(constraintDef->mGenericParamFlags | BfGenericParamFlag_Enum);
- else //if (name == "var")
- constraintDef->mGenericParamFlags = (BfGenericParamFlags)(constraintDef->mGenericParamFlags | BfGenericParamFlag_Var);
- continue;
- }
- else if (name == "new")
- {
- constraintDef->mGenericParamFlags = (BfGenericParamFlags)(constraintDef->mGenericParamFlags | BfGenericParamFlag_New);
- continue;
- }
- else if (name == "delete")
- {
- constraintDef->mGenericParamFlags = (BfGenericParamFlags)(constraintDef->mGenericParamFlags | BfGenericParamFlag_Delete);
- continue;
- }
- }
- if (auto genericOpConstraint = BfNodeDynCast<BfGenericOperatorConstraint>(constraintNode))
- {
- // Ok
- }
- else
- {
- auto constraintType = BfNodeDynCast<BfTypeReference>(constraintNode);
- if (constraintType == NULL)
- {
- Fail("Invalid constraint", constraintNode);
- return;
- }
- }
- constraintDef->mConstraints.Add(constraintNode);
- }
- }
- }
- BfProtection BfDefBuilder::GetProtection(BfAstNode* protectionNode)
- {
- if (auto tokenPair = BfNodeDynCast<BfTokenPairNode>(protectionNode))
- {
- return BfProtection_ProtectedInternal;
- }
- else if (auto protectionToken = BfNodeDynCast<BfTokenNode>(protectionNode))
- {
- if (protectionToken->GetToken() == BfToken_Public)
- return BfProtection_Public;
- if (protectionToken->GetToken() == BfToken_Protected)
- return BfProtection_Protected;
- if (protectionToken->GetToken() == BfToken_Internal)
- return BfProtection_Internal;
- return BfProtection_Private;
- }
- if (mCurTypeDef->mTypeCode == BfTypeCode_Interface)
- return BfProtection_Public;
- else
- return BfProtection_Private;
- }
- void BfDefBuilder::Visit(BfConstructorDeclaration* ctorDeclaration)
- {
- if (!WantsNode(ctorDeclaration, NULL))
- return;
- Visit((BfMethodDeclaration*)ctorDeclaration);
- }
- BfMethodDef* BfDefBuilder::CreateMethodDef(BfMethodDeclaration* methodDeclaration, BfMethodDef* outerMethodDef)
- {
- BfMethodDef* methodDef;
- if (auto operatorDecl = BfNodeDynCast<BfOperatorDeclaration>(methodDeclaration))
- {
- auto operatorDef = new BfOperatorDef();
- operatorDef->mOperatorDeclaration = operatorDecl;
- operatorDef->mIsOperator = true;
- methodDef = operatorDef;
- }
- else
- methodDef = new BfMethodDef();
- BF_ASSERT(mCurDeclaringTypeDef != NULL);
- methodDef->mDeclaringType = mCurDeclaringTypeDef;
- methodDef->mMethodDeclaration = methodDeclaration;
- methodDef->mExplicitInterface = methodDeclaration->mExplicitInterface;
- methodDef->mReturnTypeRef = methodDeclaration->mReturnType;
- methodDef->mProtection = GetProtection(methodDeclaration->mProtectionSpecifier);
- methodDef->mIsReadOnly = methodDeclaration->mReadOnlySpecifier != NULL;
- methodDef->mIsStatic = methodDeclaration->mStaticSpecifier != NULL;
- methodDef->mIsVirtual = methodDeclaration->mVirtualSpecifier != NULL;
- methodDef->mIsPartial = methodDeclaration->mPartialSpecifier != NULL;
- methodDef->mIsNew = methodDeclaration->mNewSpecifier != NULL;
- methodDef->mIsMutating = methodDeclaration->mMutSpecifier != NULL;
- methodDef->mIsExtern = methodDeclaration->mExternSpecifier != NULL;
- methodDef->mBody = methodDeclaration->mBody;
- if ((methodDeclaration->mThisToken != NULL) && (!methodDeclaration->mParams.IsEmpty()))
- {
- methodDef->mMethodType = BfMethodType_Extension;
- if (!methodDef->mIsStatic)
- {
- methodDef->mIsStatic = true;
- Fail("Extension methods must be declared 'static'", methodDef->GetRefNode());
- }
- }
- HashContext signatureHashCtx;
- HashNode(signatureHashCtx, methodDeclaration, methodDef->mBody);
- //methodDef->mSignatureHash = signatureHashCtx.Finish128();
- if (mSignatureHashCtx != NULL)
- HashNode(*mSignatureHashCtx, methodDeclaration, methodDef->mBody);
- HashContext fullHash;
- HashNode(fullHash, methodDeclaration);
- methodDef->mFullHash = fullHash.Finish128();
- if (methodDeclaration->mVirtualSpecifier != NULL)
- {
- methodDef->mIsOverride = methodDeclaration->mVirtualSpecifier->GetToken() == BfToken_Override;
- methodDef->mIsAbstract = methodDeclaration->mVirtualSpecifier->GetToken() == BfToken_Abstract;
- if (methodDef->mIsOverride)
- mCurTypeDef->mHasOverrideMethods = true;
- if (methodDeclaration->mVirtualSpecifier->GetToken() == BfToken_Concrete)
- {
- methodDef->mIsConcrete = true;
- methodDef->mIsVirtual = false;
- }
- if (methodDef->mIsAbstract)
- {
- if (methodDeclaration->mBody != NULL)
- Fail("Abstract method cannot declare a body", methodDeclaration);
- }
- }
- else
- {
- methodDef->mIsOverride = false;
- methodDef->mIsAbstract = false;
- }
- if (mCurTypeDef->mTypeCode == BfTypeCode_Interface)
- {
- if ((!methodDef->mIsConcrete) && (!methodDef->mIsStatic) && (!methodDef->mGenericParams.empty()) && (methodDef->mProtection == BfProtection_Public))
- methodDef->mIsVirtual = true;
- }
- bool isAutoCtor = false;
- if (auto autoCtorDeclaration = BfNodeDynCast<BfAutoConstructorDeclaration>(methodDeclaration))
- {
- methodDef->mProtection = BfProtection_Public;
- isAutoCtor = true;
- }
- if (auto ctorDeclaration = BfNodeDynCast<BfConstructorDeclaration>(methodDeclaration))
- {
- methodDef->mIsMutating = true;
- if (methodDeclaration->mOpenParen != NULL)
- {
- methodDef->mMethodType = BfMethodType_Ctor;
- if (methodDef->mIsStatic)
- methodDef->mName = "__BfStaticCtor";
- else
- methodDef->mName = "__BfCtor";
- }
- else
- {
- methodDef->mMethodType = BfMethodType_Init;
- methodDef->mName = "__BfInit";
- }
- }
- else if (methodDeclaration->IsA<BfDestructorDeclaration>())
- {
- methodDef->mMethodType = BfMethodType_Dtor;
- if (methodDef->mIsStatic)
- methodDef->mName = "__BfStaticDtor";
- else
- {
- methodDef->mName = "~this";
- if (!methodDef->mIsVirtual)
- {
- methodDef->mIsVirtual = true;
- methodDef->mIsOverride = true;
- }
- }
- }
- else if (auto operatorDecl = BfNodeDynCast<BfOperatorDeclaration>(methodDeclaration))
- {
- methodDef->mMethodType = BfMethodType_Operator;
- /*if (propertyDecl->mStaticSpecifier == NULL)
- {
- Fail("Operators must be declared as static", methodDeclaration);
- }*/
- String declError;
- if (methodDef->mProtection != BfProtection_Public)
- {
- declError = "'public'";
- methodDef->mProtection = BfProtection_Public; // Fix it
- }
- if (operatorDecl->mAssignOp != BfAssignmentOp_None)
- {
- if (methodDef->mIsStatic)
- {
- Fail("Assignment operator must not be declared 'static'", operatorDecl->mStaticSpecifier);
- }
- }
- else
- {
- if (!methodDef->mIsStatic)
- {
- if ((operatorDecl->mUnaryOp != BfUnaryOp_Increment) && (operatorDecl->mUnaryOp != BfUnaryOp_Decrement))
- {
- if (!declError.empty())
- declError += " and ";
- declError += "'static'";
- methodDef->mIsStatic = true; // Fix it
- }
- }
- }
- if (!declError.empty())
- {
- Fail(StrFormat("Operator must be declared %s", declError.c_str()), operatorDecl->mOperatorToken);
- }
- }
- else if ((mCurTypeDef->mIsDelegate) || (mCurTypeDef->mIsFunction))
- {
- methodDef->mName = "Invoke";
- methodDef->mMethodType = BfMethodType_Normal;
- methodDef->mProtection = BfProtection_Public;
- methodDef->mIsStatic = mCurTypeDef->mIsFunction;
- auto attributes = mCurTypeDef->mTypeDeclaration->mAttributes;
- while (attributes != NULL)
- {
- if (attributes->mAttributeTypeRef != NULL)
- {
- auto typeRefName = attributes->mAttributeTypeRef->ToCleanAttributeString();
- if (typeRefName == "StdCall")
- methodDef->mCallingConvention = BfCallingConvention_Stdcall;
- }
- attributes = attributes->mNextAttribute;
- }
- }
- else if (methodDeclaration->mMixinSpecifier != NULL)
- {
- if (methodDeclaration->mNameNode != NULL)
- methodDef->SetName(methodDeclaration->mNameNode);
- methodDef->mMethodType = BfMethodType_Mixin;
- }
- else
- {
- if (methodDeclaration->mNameNode != NULL)
- methodDef->SetName(methodDeclaration->mNameNode);
- methodDef->mMethodType = BfMethodType_Normal;
- if ((methodDeclaration->mThisToken != NULL) && (!methodDeclaration->mParams.IsEmpty()))
- {
- methodDef->mMethodType = BfMethodType_Extension;
- mCurTypeDef->mHasExtensionMethods = true;
- }
- }
- if (outerMethodDef != NULL)
- {
- for (auto genericParam : outerMethodDef->mGenericParams)
- {
- auto* copiedGenericParamDef = new BfGenericParamDef();
- *copiedGenericParamDef = *genericParam;
- methodDef->mGenericParams.Add(copiedGenericParamDef);
- }
- }
- int outerGenericSize = 0;
- if (outerMethodDef != NULL)
- outerGenericSize = (int)outerMethodDef->mGenericParams.size();
- if ((methodDef->mMethodType == BfMethodType_Normal) ||
- (methodDef->mMethodType == BfMethodType_Operator) ||
- (methodDef->mMethodType == BfMethodType_Mixin) ||
- (methodDef->mMethodType == BfMethodType_Extension) ||
- (methodDef->mMethodType == BfMethodType_Ctor))
- {
- bool isGeneric = (methodDeclaration->mGenericParams != NULL) || (!mCurTypeDef->mGenericParamDefs.IsEmpty());
- ParseGenericParams(methodDeclaration->mGenericParams, methodDeclaration->mGenericConstraintsDeclaration, methodDef->mGenericParams, &methodDef->mExternalConstraints, outerGenericSize, isGeneric);
- }
- else
- {
- if (methodDeclaration->mGenericParams != NULL)
- Fail("Generic parameters are only allowed on normal methods", methodDeclaration->mGenericParams);
- if (methodDeclaration->mGenericConstraintsDeclaration != NULL)
- Fail("Generic constraints are only allowed on normal methods", methodDeclaration->mGenericConstraintsDeclaration);
- }
- bool didDefaultsError = false;
- bool hadParams = false;
- bool hasDefault = false;
- for (int paramIdx = 0; paramIdx < (int)methodDeclaration->mParams.size(); paramIdx++)
- {
- BfParameterDeclaration* paramDecl = methodDeclaration->mParams[paramIdx];
- auto paramDef = new BfParameterDef();
- paramDef->mParamDeclaration = paramDecl;
- if (paramDecl->mNameNode != NULL)
- paramDef->SetName(paramDecl->mNameNode);
- paramDef->mTypeRef = paramDecl->mTypeRef;
- paramDef->mMethodGenericParamIdx = mSystem->GetGenericParamIdx(methodDef->mGenericParams, paramDef->mTypeRef);
- if (paramDecl->mModToken == NULL)
- paramDef->mParamKind = BfParamKind_Normal;
- else if (paramDecl->mModToken->mToken == BfToken_Params)
- paramDef->mParamKind = BfParamKind_Params;
- else if ((paramDecl->mModToken->mToken == BfToken_ReadOnly) && (isAutoCtor))
- {
- // Readonly specifier
- }
- else
- {
- Fail(StrFormat("Invalid use of '%s' specifier", BfTokenToString(paramDecl->mModToken->mToken)), paramDecl->mModToken);
- }
- if ((mCurTypeDef->mIsFunction) && (paramIdx == 0) && (paramDef->mName == "this"))
- {
- paramDef->mParamKind = BfParamKind_ExplicitThis;
- methodDef->mIsStatic = false;
- }
- if (auto dotTypeRef = BfNodeDynCast<BfDotTypeReference>(paramDef->mTypeRef))
- {
- if (dotTypeRef->mDotToken->mToken == BfToken_DotDotDot)
- {
- if (paramIdx == (int)methodDeclaration->mParams.size() - 1)
- paramDef->mParamKind = BfParamKind_VarArgs;
- else
- Fail("Varargs specifier must be the last parameter", paramDecl);
- }
- }
- if (paramDef->mParamDeclaration != NULL)
- {
- if (paramDef->mParamKind == BfParamKind_Params)
- {
- hadParams = true;
- }
- else if (hadParams)
- {
- methodDef->mParams[paramIdx - 1]->mParamKind = BfParamKind_Normal;
- hadParams = false;
- Fail("Params parameter must be the last parameter", methodDef->mParams[paramIdx - 1]->mParamDeclaration);
- }
- if (paramDef->mParamDeclaration->mInitializer != NULL)
- hasDefault = true;
- else if ((hasDefault) && (paramDef->mParamKind != BfParamKind_Params))
- {
- if (!didDefaultsError)
- Fail("Optional parameters must appear after all required parameters", methodDef->mParams[paramIdx - 1]->mParamDeclaration);
- didDefaultsError = true;
- }
- }
- methodDef->mParams.push_back(paramDef);
- }
- if ((mCurTypeDef->mIsFunction) && (!methodDef->mParams.IsEmpty()) && (methodDef->mParams[0]->mName == "this"))
- {
- methodDef->mIsStatic = false;
- methodDef->mHasExplicitThis = true;
- methodDef->mParams[0]->mParamKind = BfParamKind_ExplicitThis;
- if (auto refTypeRef = BfNodeDynCast<BfRefTypeRef>(methodDef->mParams[0]->mTypeRef))
- {
- if (refTypeRef->mRefToken->mToken != BfToken_Mut)
- {
- Fail("Only 'mut' is allowed here", refTypeRef->mRefToken);
- }
- methodDef->mIsMutating = true;
- }
- }
- if (isAutoCtor)
- {
- for (auto paramDef : methodDef->mParams)
- {
- auto fieldDef = new BfFieldDef();
- fieldDef->mFieldDeclaration = paramDef->mParamDeclaration;
- fieldDef->mName = paramDef->mName;
- while (fieldDef->mName.StartsWith("@"))
- {
- fieldDef->mNamePrefixCount++;
- fieldDef->mName.Remove(0);
- }
- fieldDef->mTypeRef = paramDef->mTypeRef;
- fieldDef->mProtection = BfProtection_Public;
- BF_ASSERT(mCurDeclaringTypeDef != NULL);
- fieldDef->mDeclaringType = mCurDeclaringTypeDef;
- fieldDef->mIdx = mCurTypeDef->mFields.mSize;
- if ((paramDef->mParamDeclaration->mModToken != NULL) &&
- (paramDef->mParamDeclaration->mModToken->mToken == BfToken_ReadOnly))
- fieldDef->mIsReadOnly = true;
- mCurTypeDef->mFields.Add(fieldDef);
- }
- }
- ParseAttributes(methodDeclaration->mAttributes, methodDef);
- return methodDef;
- }
- BfError* BfDefBuilder::Fail(const StringImpl& errorStr, BfAstNode* refNode)
- {
- auto error = mPassInstance->Fail(errorStr, refNode);
- if (error != NULL)
- error->mProject = mCurSource->mProject;
- return error;
- }
- void BfDefBuilder::Visit(BfMethodDeclaration* methodDeclaration)
- {
- if (mCurTypeDef == NULL)
- {
- return;
- }
- int addLen = 0;
- if ((methodDeclaration->mNameNode == NULL) && (methodDeclaration->mBody == NULL))
- addLen = 1;
- mSystem->CheckLockYield();
- bool wantsBody = true;
- BfAstNode* startNode = methodDeclaration->mReturnType;
- if (startNode == NULL)
- startNode = methodDeclaration->mMixinSpecifier;
- if (startNode == NULL)
- {
- if (auto ctorDecl = BfNodeDynCast<BfConstructorDeclaration>(methodDeclaration))
- startNode = ctorDecl->mThisToken;
- else if (auto ctorDecl = BfNodeDynCast<BfDestructorDeclaration>(methodDeclaration))
- startNode = ctorDecl->mTildeToken;
- }
- if (startNode == NULL)
- startNode = methodDeclaration->mOpenParen;
- if (!WantsNode(methodDeclaration, startNode, addLen))
- {
- if (!WantsNode(methodDeclaration, NULL, addLen))
- return;
- wantsBody = false;
- }
- auto methodDef = CreateMethodDef(methodDeclaration);
- methodDef->mWantsBody = wantsBody;
- if (methodDef->mMethodType == BfMethodType_Operator)
- mCurTypeDef->mOperators.push_back((BfOperatorDef*)methodDef);
- mCurTypeDef->mMethods.push_back(methodDef);
- if (methodDef->mCommutableKind == BfCommutableKind_Forward)
- {
- auto revMethodDef = CreateMethodDef(methodDeclaration);
- revMethodDef->mWantsBody = wantsBody;
- if (revMethodDef->mMethodType == BfMethodType_Operator)
- mCurTypeDef->mOperators.push_back((BfOperatorDef*)revMethodDef);
- if (revMethodDef->mParams.size() >= 2)
- {
- BF_SWAP(revMethodDef->mParams[0], revMethodDef->mParams[1]);
- }
- revMethodDef->mCommutableKind = BfCommutableKind_Reverse;
- mCurTypeDef->mMethods.push_back(revMethodDef);
- }
- }
- void BfDefBuilder::ParseAttributes(BfAttributeDirective* attributes, BfMethodDef* methodDef, bool checkReturnType)
- {
- if (checkReturnType)
- {
- if (auto inlineTypeRef = BfNodeDynCast<BfInlineTypeReference>(methodDef->mReturnTypeRef))
- ParseAttributes(inlineTypeRef->mTypeDeclaration->mAttributes, methodDef, false);
- }
- while (attributes != NULL)
- {
- if (attributes->mAttributeTypeRef != NULL)
- {
- auto typeRefName = attributes->mAttributeTypeRef->ToCleanAttributeString();
- if (typeRefName == "CLink")
- methodDef->mCLink = true;
- else if (typeRefName == "StdCall")
- methodDef->mCallingConvention = BfCallingConvention_Stdcall;
- else if (typeRefName == "Inline")
- {
- if (methodDef->mIsExtern)
- Fail("Extern methods cannot be inline", attributes->mAttributeTypeRef);
- else
- methodDef->mAlwaysInline = true;
- }
- else if (typeRefName == "AllowAppend")
- {
- methodDef->mAppendKind = BfAllowAppendKind_Yes;
- methodDef->mIsNoSplat = true;
- if (!attributes->mArguments.IsEmpty())
- {
- if (auto assignExpr = BfNodeDynCast<BfAssignmentExpression>(attributes->mArguments[0]))
- {
- if ((assignExpr->mLeft != NULL) && (assignExpr->mRight != NULL) &&
- (assignExpr->mLeft->Equals("ZeroGap")))
- {
- if (assignExpr->mRight->Equals("true"))
- methodDef->mAppendKind = BfAllowAppendKind_ZeroGap;
- else if (assignExpr->mRight->Equals("false"))
- methodDef->mAppendKind = BfAllowAppendKind_Yes;
- else
- Fail("Can only use 'true' or 'false' for 'ZeroGap'", assignExpr->mRight);
- }
- }
- }
- }
- else if (typeRefName == "Checked")
- methodDef->mCheckedKind = BfCheckedKind_Checked;
- else if (typeRefName == "Unchecked")
- methodDef->mCheckedKind = BfCheckedKind_Unchecked;
- else if (typeRefName == "Export")
- {
- mCurTypeDef->mIsAlwaysInclude = true;
- methodDef->mImportKind = BfImportKind_Export;
- }
- else if (typeRefName == "Import")
- {
- methodDef ->mImportKind = BfImportKind_Import_Unknown;
- if (!attributes->mArguments.IsEmpty())
- {
- if (auto literalExpr = BfNodeDynCast<BfLiteralExpression>(attributes->mArguments[0]))
- {
- if (literalExpr->mValue.mTypeCode == BfTypeCode_CharPtr)
- {
- String filePath = *literalExpr->mValue.mString;
- methodDef->mImportKind = BfMethodDef::GetImportKindFromPath(filePath);
- }
- }
- }
- }
- else if (typeRefName == "NoReturn")
- methodDef->mIsNoReturn = true;
- else if (typeRefName == "SkipCall")
- methodDef->mIsSkipCall = true;
- else if (typeRefName == "Comptime")
- {
- methodDef->mHasComptime = true;
- }
- else if (typeRefName == "NoShow")
- {
- methodDef->mShow = BfShow_Hide;
- if (!attributes->mArguments.IsEmpty())
- {
- if (auto literalExpr = BfNodeDynCast<BfLiteralExpression>(attributes->mArguments[0]))
- {
- if (literalExpr->mValue.mBool)
- methodDef->mShow = BfShow_HideIndirect;
- }
- }
- }
- else if (typeRefName == "NoDiscard")
- methodDef->mIsNoDiscard = true;
- else if (typeRefName == "NoSplat")
- methodDef->mIsNoSplat = true;
- else if (typeRefName == "Commutable")
- {
- if (methodDef->mParams.size() != 2)
- {
- Fail("Commutable attributes can only be applied to methods with two arguments", attributes->mAttributeTypeRef);
- }
- else
- {
- if (methodDef->mIsOperator)
- methodDef->mCommutableKind = BfCommutableKind_Operator;
- else
- methodDef->mCommutableKind = BfCommutableKind_Forward;
- }
- }
- else if (typeRefName == "OnCompile")
- {
- mCurTypeDef->mHasCEOnCompile = true;
- }
- }
- attributes = attributes->mNextAttribute;
- }
- }
- void BfDefBuilder::ParseAttributes(BfAttributeDirective* attributes, BfTypeDef* typeDef)
- {
- while (attributes != NULL)
- {
- if (attributes->mAttributeTypeRef != NULL)
- {
- auto typeRefName = attributes->mAttributeTypeRef->ToCleanAttributeString();
- if (typeRefName == "AlwaysInclude")
- typeDef->mIsAlwaysInclude = true;
- else if (typeRefName == "NoDiscard")
- typeDef->mIsNoDiscard = true;
- else if (typeRefName == "NoShow")
- {
- typeDef->mShow = BfShow_Hide;
- if (!attributes->mArguments.IsEmpty())
- {
- if (auto literalExpr = BfNodeDynCast<BfLiteralExpression>(attributes->mArguments[0]))
- {
- if (literalExpr->mValue.mBool)
- typeDef->mShow = BfShow_HideIndirect;
- }
- }
- }
- }
- attributes = attributes->mNextAttribute;
- }
- }
- void BfDefBuilder::Visit(BfPropertyDeclaration* propertyDeclaration)
- {
- int addLen = 0;
- if (propertyDeclaration->mTypeRef == NULL)
- addLen = 1;
- bool wantsBody = true;
- if (!WantsNode(propertyDeclaration, propertyDeclaration->mTypeRef, addLen))
- {
- if (!WantsNode(propertyDeclaration, NULL, addLen))
- return;
- // The cursor is inside some exterior specifiers, don't process body
- wantsBody = false;
- }
- if ((propertyDeclaration->mConstSpecifier != NULL) && (propertyDeclaration->mConstSpecifier->mToken == BfToken_Const))
- {
- Fail("Const properties are not allowed", propertyDeclaration->mConstSpecifier);
- }
- if (mSignatureHashCtx != NULL)
- HashNode(*mSignatureHashCtx, propertyDeclaration, propertyDeclaration->mDefinitionBlock);
- BfPropertyDef* propertyDef = new BfPropertyDef();
- mCurTypeDef->mProperties.push_back(propertyDef);
- propertyDef->mProtection = GetProtection(propertyDeclaration->mProtectionSpecifier);
- propertyDef->mIdx = (int)mCurTypeDef->mProperties.size() - 1;
- propertyDef->mIsConst = false;
- propertyDef->mIsProperty = true;
- if (auto usingSpecifier = BfNodeDynCast<BfUsingSpecifierNode>(propertyDeclaration->mConstSpecifier))
- {
- if (usingSpecifier->mProtection != NULL)
- propertyDef->mUsingProtection = GetProtection(usingSpecifier->mProtection);
- else
- propertyDef->mUsingProtection = propertyDef->mProtection;
- }
- propertyDef->mIsStatic = propertyDeclaration->mStaticSpecifier != NULL;
- propertyDef->mIsReadOnly = propertyDeclaration->mReadOnlySpecifier != NULL;
- if (propertyDeclaration->mNameNode != NULL)
- propertyDef->SetName(propertyDeclaration->mNameNode);
- else if (propertyDeclaration->IsA<BfIndexerDeclaration>())
- {
- propertyDef->mName = "[]";
- }
- propertyDef->mTypeRef = propertyDeclaration->mTypeRef;
- propertyDef->mFieldDeclaration = propertyDeclaration;
- BF_ASSERT(mCurDeclaringTypeDef != NULL);
- propertyDef->mDeclaringType = mCurDeclaringTypeDef;
- if (auto varType = BfNodeDynCast<BfLetTypeReference>(propertyDef->mTypeRef))
- propertyDef->mIsReadOnly = true;
- //HashNode(*mSignatureHashCtx, propertyDeclaration, propertyDeclaration->mDefinitionBlock);
- //mCurTypeDef->mSignatureHash = HashNode(propertyDeclaration, propertyDeclaration->mDefinitionBlock, mCurTypeDef->mSignatureHash);
- if (propertyDeclaration->mDefinitionBlock == NULL) // To differentiate between autocompleting partial property if it transitions to a field
- {
- //mCurTypeDef->mSignatureHash = HashString("nullprop", mCurTypeDef->mSignatureHash);
- if (mSignatureHashCtx != NULL)
- mSignatureHashCtx->MixinStr("nullprop");
- }
- auto indexerDeclaration = BfNodeDynCast<BfIndexerDeclaration>(propertyDeclaration);
- bool isAbstract = false;
- if (propertyDeclaration->mVirtualSpecifier != NULL)
- isAbstract = propertyDeclaration->mVirtualSpecifier->GetToken() == BfToken_Abstract;
- bool needsAutoProperty = mCurTypeDef->HasAutoProperty(propertyDeclaration);
- if (needsAutoProperty)
- {
- BfFieldDef* fieldDef = new BfFieldDef();
- BF_ASSERT(mCurDeclaringTypeDef != NULL);
- fieldDef->mDeclaringType = mCurDeclaringTypeDef;
- fieldDef->mFieldDeclaration = propertyDeclaration;
- fieldDef->mProtection = BfProtection_Hidden;
- fieldDef->mIsStatic = propertyDef->mIsStatic;
- fieldDef->mTypeRef = propertyDef->mTypeRef;
- if (auto refTypeRef = BfNodeDynCast<BfRefTypeRef>(fieldDef->mTypeRef))
- fieldDef->mTypeRef = refTypeRef->mElementType;
- fieldDef->mName = mCurTypeDef->GetAutoPropertyName(propertyDeclaration);
- fieldDef->mIdx = (int)mCurTypeDef->mFields.size();
- mCurTypeDef->mFields.push_back(fieldDef);
- mCurTypeDef->mSignatureHash = HashString(fieldDef->mName, mCurTypeDef->mSignatureHash + fieldDef->mNamePrefixCount);
- }
- else
- {
- if (propertyDeclaration->mInitializer != NULL)
- {
- if (mCurTypeDef->mTypeCode == BfTypeCode_Interface)
- Fail("Interface properties cannot have initializers", propertyDeclaration->mInitializer);
- else
- Fail("Properties with method bodies cannot have initializers", propertyDeclaration->mInitializer);
- }
- if (propertyDeclaration->mFieldDtor != NULL)
- {
- if (mCurTypeDef->mTypeCode == BfTypeCode_Interface)
- Fail("Interface properties cannot have field destructors", propertyDeclaration->mFieldDtor);
- else
- Fail("Properties with method bodies cannot have field destructors", propertyDeclaration->mFieldDtor);
- }
- }
- for (auto methodDeclaration : propertyDeclaration->mMethods)
- {
- if (mSignatureHashCtx != NULL)
- {
- HashNode(*mSignatureHashCtx, methodDeclaration->mAttributes);
- HashNode(*mSignatureHashCtx, methodDeclaration->mProtectionSpecifier);
- HashNode(*mSignatureHashCtx, methodDeclaration->mNameNode);
- HashNode(*mSignatureHashCtx, methodDeclaration->mMutSpecifier);
- }
- if (!wantsBody)
- continue;
- if (!WantsNode(methodDeclaration))
- continue;
- auto methodDef = new BfMethodDef();
- mCurTypeDef->mMethods.push_back(methodDef);
- BF_ASSERT(mCurDeclaringTypeDef != NULL);
- methodDef->mDeclaringType = mCurDeclaringTypeDef;
- methodDef->mMethodDeclaration = methodDeclaration;
- methodDef->mProtection = propertyDef->mProtection;
- methodDef->mWantsBody = (methodDeclaration->mBody != NULL) && (WantsNode(methodDeclaration->mBody));
- if (methodDeclaration->mProtectionSpecifier != NULL)
- {
- BfProtection newProtection = GetProtection(methodDeclaration->mProtectionSpecifier);
- if (newProtection > methodDef->mProtection)
- Fail(StrFormat("the accessibility modifier of the 'get' accessor must be more restrictive than the property or indexer '%s'", propertyDef->mName.c_str()),
- methodDeclaration->mProtectionSpecifier);
- methodDef->mProtection = newProtection;
- }
- methodDef->mIsMutating = methodDeclaration->mMutSpecifier != NULL;
- methodDef->mIsAbstract = isAbstract;
- methodDef->mIsStatic = propertyDef->mIsStatic;
- methodDef->mIsVirtual = propertyDeclaration->mVirtualSpecifier != NULL;
- methodDef->mIsExtern = propertyDeclaration->mExternSpecifier != NULL;
- methodDef->mMethodDeclaration = methodDeclaration;
- methodDef->mExplicitInterface = propertyDeclaration->mExplicitInterface;
- HashContext propHashCtx;
- HashNode(propHashCtx, methodDeclaration->mNameNode);
- HashNode(propHashCtx, methodDeclaration->mAttributes);
- HashNode(propHashCtx, methodDeclaration->mProtectionSpecifier);
- HashNode(propHashCtx, methodDeclaration->mMutSpecifier);
- HashNode(propHashCtx, propertyDeclaration, propertyDeclaration->mDefinitionBlock);
- //methodDef->mSignatureHash = propHashCtx.Finish128();
- methodDef->mFullHash = HashNode(propertyDeclaration);
- if (propertyDeclaration->mVirtualSpecifier != NULL)
- methodDef->mIsOverride = propertyDeclaration->mVirtualSpecifier->GetToken() == BfToken_Override;
- else
- methodDef->mIsOverride = false;
- methodDef->mIsNew = propertyDeclaration->mNewSpecifier != NULL;
- if (indexerDeclaration != NULL)
- {
- for (int paramIdx = 0; paramIdx < (int)indexerDeclaration->mParams.size(); paramIdx++)
- {
- auto paramDef = new BfParameterDef();
- BfParameterDeclaration* paramDecl = indexerDeclaration->mParams[paramIdx];
- paramDef->mParamDeclaration = paramDecl;
- paramDef->SetName(paramDecl->mNameNode);
- paramDef->mTypeRef = paramDecl->mTypeRef;
- paramDef->mMethodGenericParamIdx = mSystem->GetGenericParamIdx(methodDef->mGenericParams, paramDef->mTypeRef);
- if (paramDecl->mModToken == NULL)
- paramDef->mParamKind = BfParamKind_Normal;
- else if (paramDecl->mModToken->mToken == BfToken_Params)
- paramDef->mParamKind = BfParamKind_Params;
- methodDef->mParams.push_back(paramDef);
- }
- }
- String methodName;
- if (auto propExprBody = BfNodeDynCast<BfPropertyBodyExpression>(propertyDeclaration->mDefinitionBlock))
- {
- methodName = "get";
- ParseAttributes(propertyDeclaration->mAttributes, methodDef);
- if (propExprBody->mMutSpecifier != NULL)
- methodDef->mIsMutating = true;
- if (mSignatureHashCtx != NULL)
- HashNode(*mSignatureHashCtx, propExprBody->mMutSpecifier);
- }
- else if ((methodDeclaration != NULL) && (methodDeclaration->mNameNode != NULL))
- methodName = methodDeclaration->mNameNode->ToString();
- if (methodName == "get")
- {
- methodDef->mName = "get__";
- if (propertyDeclaration->mNameNode != NULL)
- methodDef->mName += propertyDeclaration->mNameNode->ToString();
- methodDef->mReturnTypeRef = propertyDeclaration->mTypeRef;
- methodDef->mMethodType = BfMethodType_PropertyGetter;
- if (propertyDeclaration->mReadOnlySpecifier != NULL)
- methodDef->mIsReadOnly = true;
- propertyDef->mMethods.Add(methodDef);
- }
- else if (methodName == "set")
- {
- methodDef->mName = "set__";
- if (propertyDeclaration->mNameNode != NULL)
- methodDef->mName += propertyDeclaration->mNameNode->ToString();
- methodDef->mMethodType = BfMethodType_PropertySetter;
- if (BfNodeDynCast<BfTokenNode>(methodDeclaration->mBody) != NULL)
- methodDef->mIsMutating = true; // Don't require "set mut;", just "set;"
- auto paramDef = new BfParameterDef();
- paramDef->mName = "value";
- paramDef->mTypeRef = propertyDeclaration->mTypeRef;
- if (auto refTypeRef = BfNodeDynCast<BfRefTypeRef>(propertyDeclaration->mTypeRef))
- {
- if (methodDeclaration->mSetRefSpecifier == NULL)
- paramDef->mTypeRef = refTypeRef->mElementType;
- }
- else
- {
- if (methodDeclaration->mSetRefSpecifier != NULL)
- Fail("Property setter 'ref' can only be used with a 'ref' property type", methodDeclaration->mSetRefSpecifier);
- }
- methodDef->mParams.Insert(0, paramDef);
- propertyDef->mMethods.Add(methodDef);
- }
- else
- {
- // Parse had an error, leave this block as an unnamed method
- }
- methodDef->mBody = methodDeclaration->mBody;
- ParseAttributes(methodDeclaration->mAttributes, methodDef);
- }
- }
- void BfDefBuilder::Visit(BfFieldDeclaration* fieldDeclaration)
- {
- mSystem->CheckLockYield();
- int endingAdd = 1;// Add '1' for autocompletion of 'new' initializer
- if (!WantsNode(fieldDeclaration, NULL, endingAdd))
- {
- return;
- }
- // This check is a bit of a hack to determine the difference between a "MemberType mMember" and a proper case entry of "mMember(TupleType)"
- bool isEnumEntryDecl = fieldDeclaration->IsA<BfEnumEntryDeclaration>();
- auto fieldDef = new BfFieldDef();
- mCurTypeDef->mFields.push_back(fieldDef);
- fieldDef->mFieldDeclaration = fieldDeclaration;
- BF_ASSERT(mCurDeclaringTypeDef != NULL);
- fieldDef->mDeclaringType = mCurDeclaringTypeDef;
- if (fieldDeclaration->mNameNode != NULL)
- fieldDef->SetName(fieldDeclaration->mNameNode);
- fieldDef->mProtection = GetProtection(fieldDeclaration->mProtectionSpecifier);
- if (isEnumEntryDecl)
- fieldDef->mProtection = BfProtection_Public;
- fieldDef->mIsReadOnly = fieldDeclaration->mReadOnlySpecifier != NULL;
- fieldDef->mIsInline = (fieldDeclaration->mReadOnlySpecifier != NULL) && (fieldDeclaration->mReadOnlySpecifier->GetToken() == BfToken_Inline);
- fieldDef->mIsExtern = (fieldDeclaration->mExternSpecifier != NULL) && (fieldDeclaration->mExternSpecifier->mToken == BfToken_Extern);
- fieldDef->mIsAppend = (fieldDeclaration->mExternSpecifier != NULL) && (fieldDeclaration->mExternSpecifier->mToken == BfToken_Append);
- auto constSpecifierToken = BfNodeDynCast<BfTokenNode>(fieldDeclaration->mConstSpecifier);
- fieldDef->mIsConst = ((constSpecifierToken != NULL) && (constSpecifierToken->mToken == BfToken_Const)) || (isEnumEntryDecl);
- if (auto usingSpecifier = BfNodeDynCast<BfUsingSpecifierNode>(fieldDeclaration->mConstSpecifier))
- {
- if (usingSpecifier->mProtection != NULL)
- fieldDef->mUsingProtection = GetProtection(usingSpecifier->mProtection);
- else
- fieldDef->mUsingProtection = fieldDef->mProtection;
- }
- else if (fieldDeclaration->mNameNode == NULL)
- {
- fieldDef->mUsingProtection = fieldDef->mProtection;
- }
- fieldDef->mIsStatic = (fieldDeclaration->mStaticSpecifier != NULL) || fieldDef->mIsConst;
- fieldDef->mIsVolatile = (fieldDeclaration->mVolatileSpecifier != NULL);
- fieldDef->mTypeRef = fieldDeclaration->mTypeRef;
- if (auto varType = BfNodeDynCast<BfLetTypeReference>(fieldDef->mTypeRef))
- fieldDef->mIsReadOnly = true;
- if (fieldDef->mUsingProtection != BfProtection_Hidden)
- mCurTypeDef->mHasUsingFields = true;
- if ((mCurTypeDef->mTypeCode == BfTypeCode_Enum) && (fieldDef->mTypeRef != NULL) && (!fieldDef->mIsStatic))
- {
- // This check is a bit of a hack to determine the difference between a "MemberType mMember" and a proper case entry of "mMember(TupleType)"
- if (!isEnumEntryDecl)
- {
- Fail("Non-static field declarations are not allowed in enums", fieldDeclaration);
- }
- }
- fieldDef->mIdx = (int)mCurTypeDef->mFields.size() - 1;
- //mCurTypeDef->mSignatureHash = HashNode(fieldDeclaration, mCurTypeDef->mSignatureHash);
- if (mSignatureHashCtx != NULL)
- HashNode(*mSignatureHashCtx, fieldDeclaration);
- }
- void BfDefBuilder::Visit(BfEnumCaseDeclaration* enumCaseDeclaration)
- {
- // Using `enumCaseDeclaration->mCaseToken` breaks attribute autocompletion
- //if (!WantsNode(enumCaseDeclaration, enumCaseDeclaration->mCaseToken, 0))
- if (!WantsNode(enumCaseDeclaration))
- {
- return;
- }
- for (int entryIdx = 0; entryIdx < (int)enumCaseDeclaration->mEntries.size(); entryIdx++)
- {
- auto caseEntry = enumCaseDeclaration->mEntries[entryIdx];
- Visit(caseEntry);
- }
- }
- BfFieldDef* BfDefBuilder::AddField(BfTypeDef* typeDef, BfTypeReference* fieldType, const StringImpl& fieldName)
- {
- BfFieldDef* fieldDef = new BfFieldDef();
- fieldDef->mDeclaringType = typeDef;
- fieldDef->mTypeRef = fieldType;
- fieldDef->mName = fieldName;
- fieldDef->mIdx = (int)typeDef->mFields.size();
- typeDef->mFields.push_back(fieldDef);
- return fieldDef;
- }
- BfMethodDef* BfDefBuilder::AddMethod(BfTypeDef* typeDef, BfMethodType methodType, BfProtection protection, bool isStatic, const StringImpl& name, bool addedAfterEmit)
- {
- BF_ASSERT(typeDef->mTypeCode != BfTypeCode_TypeAlias);
- BF_ASSERT(!typeDef->mIsOpaque);
- auto methodDef = new BfMethodDef();
- methodDef->mIdx = (int)typeDef->mMethods.size();
- typeDef->mMethods.push_back(methodDef);
- methodDef->mDeclaringType = typeDef;
- methodDef->mMethodType = methodType;
- methodDef->mAddedAfterEmit = addedAfterEmit;
- if (name.empty())
- {
- if (methodType == BfMethodType_Ctor)
- {
- if (isStatic)
- methodDef->mName = "__BfStaticCtor";
- else
- methodDef->mName = "__BfCtor";
- }
- else if (methodType == BfMethodType_CtorNoBody)
- {
- methodDef->mName = "__BfCtorNoBody";
- methodDef->mIsNoReflect = true;
- }
- else if (methodType == BfMethodType_CtorClear)
- {
- methodDef->mName = "__BfCtorClear";
- methodDef->mIsNoReflect = true;
- }
- else if (methodType == BfMethodType_Init)
- {
- methodDef->mName = "__BfInit";
- }
- else if (methodType == BfMethodType_Dtor)
- {
- if (isStatic)
- {
- methodDef->mName = "__BfStaticDtor";
- }
- else
- {
- methodDef->mName = "~this";
- methodDef->mIsVirtual = true;
- methodDef->mIsOverride = true;
- }
- }
- else
- {
- BF_FATAL("Method name expected");
- }
- }
- else
- methodDef->mName = name;
- methodDef->mProtection = protection;
- methodDef->mIsStatic = isStatic;
- return methodDef;
- }
- BfMethodDef* BfDefBuilder::AddDtor(BfTypeDef* typeDef)
- {
- auto methodDef = new BfMethodDef();
- typeDef->mMethods.push_back(methodDef);
- methodDef->mDeclaringType = typeDef;
- methodDef->mName = "~this";
- methodDef->mProtection = BfProtection_Public;
- methodDef->mMethodType = BfMethodType_Dtor;
- methodDef->mIsVirtual = true;
- methodDef->mIsOverride = true;
- return methodDef;
- }
- void BfDefBuilder::AddDynamicCastMethods(BfTypeDef* typeDef, bool needsDynamicCastMethods)
- {
- if (needsDynamicCastMethods)
- {
- auto methodDef = new BfMethodDef();
- methodDef->mIdx = (int)typeDef->mMethods.size();
- typeDef->mMethods.push_back(methodDef);
- methodDef->mDeclaringType = typeDef;
- methodDef->mName = BF_METHODNAME_DYNAMICCAST;
- methodDef->mProtection = BfProtection_Protected;
- methodDef->mIsStatic = false;
- methodDef->mMethodType = BfMethodType_Normal;
- methodDef->mIsVirtual = true;
- methodDef->mIsOverride = true;
- auto paramDef = new BfParameterDef();
- paramDef->mName = "id";
- paramDef->mTypeRef = typeDef->mSystem->mDirectInt32TypeRef;
- methodDef->mParams.push_back(paramDef);
- methodDef->mReturnTypeRef = typeDef->mSystem->mDirectObjectTypeRef;
- methodDef->mIsNoReflect = true;
- }
- if (needsDynamicCastMethods)
- {
- auto methodDef = new BfMethodDef();
- methodDef->mIdx = (int)typeDef->mMethods.size();
- typeDef->mMethods.push_back(methodDef);
- methodDef->mDeclaringType = typeDef;
- methodDef->mName = BF_METHODNAME_DYNAMICCAST_INTERFACE;
- methodDef->mProtection = BfProtection_Protected;
- methodDef->mIsStatic = false;
- methodDef->mMethodType = BfMethodType_Normal;
- methodDef->mIsVirtual = true;
- methodDef->mIsOverride = true;
- auto paramDef = new BfParameterDef();
- paramDef->mName = "id";
- paramDef->mTypeRef = typeDef->mSystem->mDirectInt32TypeRef;
- methodDef->mParams.push_back(paramDef);
- methodDef->mReturnTypeRef = typeDef->mSystem->mDirectObjectTypeRef;
- methodDef->mIsNoReflect = true;
- }
- if ((typeDef->mIsDelegate) && (!typeDef->mIsClosure))
- {
- auto methodDef = new BfMethodDef();
- methodDef->mIdx = (int)typeDef->mMethods.size();
- typeDef->mMethods.push_back(methodDef);
- methodDef->mDeclaringType = typeDef;
- methodDef->mName = BF_METHODNAME_DYNAMICCAST_SIGNATURE;
- methodDef->mProtection = BfProtection_Protected;
- methodDef->mIsStatic = false;
- methodDef->mMethodType = BfMethodType_Normal;
- methodDef->mIsVirtual = true;
- methodDef->mIsOverride = true;
- auto paramDef = new BfParameterDef();
- paramDef->mName = "sig";
- paramDef->mTypeRef = typeDef->mSystem->mDirectInt32TypeRef;
- methodDef->mParams.push_back(paramDef);
- methodDef->mReturnTypeRef = typeDef->mSystem->mDirectObjectTypeRef;
- methodDef->mIsNoReflect = true;
- }
- }
- void BfDefBuilder::AddParam(BfMethodDef* methodDef, BfTypeReference* typeRef, const StringImpl& paramName)
- {
- auto paramDef = new BfParameterDef();
- paramDef->mName = paramName;
- paramDef->mTypeRef = typeRef;
- methodDef->mParams.push_back(paramDef);
- }
- BfTypeDef* BfDefBuilder::ComparePrevTypeDef(BfTypeDef* prevTypeDef, BfTypeDef* checkTypeDef)
- {
- if (!mCurTypeDef->IsExtension())
- return prevTypeDef;
- BF_ASSERT(mCurTypeDef->mGenericParamDefs.size() == prevTypeDef->mGenericParamDefs.size());
- BF_ASSERT(mCurTypeDef->mGenericParamDefs.size() == checkTypeDef->mGenericParamDefs.size());
- bool prevMatches = true;
- bool checkMatches = true;
- for (int genericParamIdx = 0; genericParamIdx < (int)mCurTypeDef->mGenericParamDefs.size(); genericParamIdx++)
- {
- BfGenericParamDef* paramDef = mCurTypeDef->mGenericParamDefs[genericParamIdx];
- BfGenericParamDef* prevParamDef = prevTypeDef->mGenericParamDefs[genericParamIdx];
- BfGenericParamDef* checkParamDef = checkTypeDef->mGenericParamDefs[genericParamIdx];
- if (*paramDef != *prevParamDef)
- prevMatches = false;
- if (*paramDef != *checkParamDef)
- checkMatches = false;
- }
- if (mCurTypeDef->mExternalConstraints.mSize == prevTypeDef->mExternalConstraints.mSize)
- {
- for (int constraintIdx = 0; constraintIdx < mCurTypeDef->mExternalConstraints.mSize; constraintIdx++)
- {
- if (mCurTypeDef->mExternalConstraints[constraintIdx] != prevTypeDef->mExternalConstraints[constraintIdx])
- prevMatches = false;
- }
- }
- else
- prevMatches = false;
- if (mCurTypeDef->mExternalConstraints.mSize == checkTypeDef->mExternalConstraints.mSize)
- {
- for (int constraintIdx = 0; constraintIdx < mCurTypeDef->mExternalConstraints.mSize; constraintIdx++)
- {
- if (mCurTypeDef->mExternalConstraints[constraintIdx] != checkTypeDef->mExternalConstraints[constraintIdx])
- checkMatches = false;
- }
- }
- else
- checkMatches = false;
- if ((!prevMatches) && (checkMatches))
- return checkTypeDef;
- return prevTypeDef;
- }
- void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration)
- {
- if (typeDeclaration->IsEmitted())
- {
- Fail("Type declarations are not allowed in emitted code", typeDeclaration);
- return;
- }
- BF_ASSERT(typeDeclaration->GetSourceData() == mCurSource->mSourceData);
-
- /*if (typeDeclaration->mNameNode != NULL)
- OutputDebugStrF("Decl: %s\n", typeDeclaration->mNameNode->ToString().c_str());*/
- bool isAnonymous = typeDeclaration->IsAnonymous();
- bool isAutoCompleteTempType = false;
- if (mResolvePassData != NULL)
- {
- isAutoCompleteTempType = (mResolvePassData->mAutoComplete != NULL);
- if (mResolvePassData->mHasCursorIdx)
- {
- auto parser = typeDeclaration->GetParser();
- if (parser != NULL)
- {
- int cursorIdx = parser->mCursorIdx;
- if (typeDeclaration->Contains(cursorIdx, 1, 0))
- {
- // Within bounds
- }
- else if (cursorIdx != -1)
- return;
- }
- }
- }
- int curLine = 0;
- int curColumn = 0;
- auto bfParser = mCurSource->ToParser();
- if (bfParser != NULL)
- {
- int srcStart = typeDeclaration->GetSrcStart();
- auto* jumpEntry = bfParser->mJumpTable + (srcStart / PARSER_JUMPTABLE_DIVIDE);
- if (jumpEntry->mCharIdx > srcStart)
- jumpEntry--;
- curLine = jumpEntry->mLineNum;
- int curSrcPos = jumpEntry->mCharIdx;
- curColumn = 0;
- while (curSrcPos < srcStart)
- {
- if (bfParser->mSrc[curSrcPos] == '\n')
- {
- curLine++;
- curColumn = 0;
- }
- else
- curColumn++;
- curSrcPos++;
- }
- }
- auto outerTypeDef = mCurTypeDef;
- auto actualOuterTypeDef = mCurActualTypeDef;
- while ((outerTypeDef != NULL) && (outerTypeDef->IsGlobalsContainer()))
- outerTypeDef = outerTypeDef->mOuterType;
- while ((actualOuterTypeDef != NULL) && (actualOuterTypeDef->IsGlobalsContainer()))
- actualOuterTypeDef = actualOuterTypeDef->mOuterType;
- SetAndRestoreValue<BfTypeDef*> prevTypeDef(mCurTypeDef, new BfTypeDef());
- SetAndRestoreValue<BfTypeDef*> prevDeclaringTypeDef(mCurDeclaringTypeDef, mCurTypeDef);
- SetAndRestoreValue<BfTypeDef*> prevActualTypeDef(mCurActualTypeDef, mCurTypeDef);
- mCurTypeDef->mSystem = mSystem;
- mCurTypeDef->mProject = mCurSource->mProject;
- mCurTypeDef->mIsStatic = typeDeclaration->mStaticSpecifier != NULL;
- mCurTypeDef->mNamespace = mNamespace;
- mSystem->AddNamespaceUsage(mCurTypeDef->mNamespace, mCurTypeDef->mProject);
- if ((typeDeclaration->mTypeNode == NULL) && (!isAnonymous))
- {
- mCurTypeDef->mIsPartial = true;
- mCurTypeDef->mIsExplicitPartial = true;
- }
- if (typeDeclaration->mNameNode == NULL)
- {
- if (typeDeclaration->mAnonymousName != NULL)
- {
- mCurTypeDef->mName = mSystem->GetAtom(typeDeclaration->mAnonymousName);
- }
- if (mCurTypeDef->mName == NULL)
- {
- if (mCurTypeDef->mIsStatic)
- {
- // Global
- mCurTypeDef->mName = mSystem->mGlobalsAtom;
- }
- else
- mCurTypeDef->mName = mSystem->mHiddenAtom;
- mCurTypeDef->mName->Ref();
- BF_ASSERT(mCurTypeDef->mSystem != NULL);
- }
- }
- else
- {
- mCurTypeDef->mName = mSystem->GetAtom(typeDeclaration->mNameNode->ToString());
- if (mCurTypeDef->mName->mIsSystemType)
- {
- Fail(StrFormat("Type name '%s' is reserved", typeDeclaration->mNameNode->ToString().c_str()), typeDeclaration->mNameNode);
- }
- }
- BfLogSys(mCurSource->mSystem, "DefBuilder %p %p TypeDecl:%s\n", mCurTypeDef, mCurSource, mCurTypeDef->mName->ToString().mPtr);
- mCurTypeDef->mProtection = ((outerTypeDef == NULL) || (isAnonymous)) ? BfProtection_Public : BfProtection_Private;
- if (typeDeclaration->mProtectionSpecifier != NULL)
- {
- if ((outerTypeDef == NULL) &&
- (typeDeclaration->mProtectionSpecifier->GetToken() != BfToken_Public) &&
- (typeDeclaration->mProtectionSpecifier->GetToken() != BfToken_Internal))
- {
- //CS1527
- Fail("Elements defined in a namespace cannot be explicitly declared as private or protected", typeDeclaration->mProtectionSpecifier);
- }
- else
- {
- mCurTypeDef->mProtection = GetProtection(typeDeclaration->mProtectionSpecifier);
- }
- }
- if (typeDeclaration->mAttributes != NULL)
- ParseAttributes(typeDeclaration->mAttributes, mCurTypeDef);
- for (auto& baseClass : typeDeclaration->mBaseClasses)
- mCurTypeDef->mBaseTypes.push_back(baseClass);
- HashContext fullHashCtx;
- HashContext signatureHashCtx;
- SetAndRestoreValue<HashContext*> prevFullHashCtx(mFullHashCtx, &fullHashCtx);
- SetAndRestoreValue<HashContext*> prevSignatureHashCtx(mSignatureHashCtx, &signatureHashCtx);
- if (bfParser != NULL)
- {
- mFullHashCtx->MixinStr(bfParser->mFileName);
- mFullHashCtx->Mixin(bfParser->mParserData->mMD5Hash);
- }
- HashNode(*mSignatureHashCtx, typeDeclaration->mTypeNode);
- for (auto& baseClassNode : typeDeclaration->mBaseClasses)
- HashNode(*mSignatureHashCtx, baseClassNode);
- HashNode(*mSignatureHashCtx, typeDeclaration->mAttributes);
- HashNode(*mSignatureHashCtx, typeDeclaration->mAbstractSpecifier);
- HashNode(*mSignatureHashCtx, typeDeclaration->mSealedSpecifier);
- HashNode(*mSignatureHashCtx, typeDeclaration->mProtectionSpecifier);
- HashNode(*mSignatureHashCtx, typeDeclaration->mPartialSpecifier);
- HashNode(*mSignatureHashCtx, typeDeclaration->mNameNode);
- HashNode(*mSignatureHashCtx, typeDeclaration->mGenericParams);
- HashNode(*mSignatureHashCtx, typeDeclaration->mGenericConstraintsDeclaration);
- HashNode(*mFullHashCtx, typeDeclaration);
- // Allow internal preprocessor flags to change a full hash change
- if (bfParser != NULL)
- {
- // Note- we insert strings from these HashSets in bucket-order, which is stable
- // for the same insertion order, but is not truly order independent. Shouldn't matter.
- fullHashCtx.Mixin(bfParser->mParserData->mDefines_Def.size());
- for (auto& defStr : bfParser->mParserData->mDefines_Def)
- fullHashCtx.MixinStr(defStr);
- fullHashCtx.Mixin(bfParser->mParserData->mDefines_NoDef.size());
- for (auto& defStr : bfParser->mParserData->mDefines_NoDef)
- fullHashCtx.MixinStr(defStr);
- }
- // We need to hash the position of the declaration in the file so we can rebuild the debug info with revised line numbers
- int hashPos[2] = { curLine, curColumn };
- mFullHashCtx->Mixin(hashPos);
- if (mSystem->mIsResolveOnly)
- {
- // We need to have the correct source index for renames and such
- fullHashCtx.Mixin(typeDeclaration->GetSrcStart());
- }
- if (auto typeAliasDeclaration = BfNodeDynCast<BfTypeAliasDeclaration>(typeDeclaration))
- {
- HashNode(*mSignatureHashCtx, typeAliasDeclaration->mAliasToType);
- }
- //TODO:
- //int randomCrap = rand();
- //HASH128_MIXIN(mCurTypeDef->mFullHash, randomCrap);
- // To cause a type rebuild when we change pragma settings or #if resolves
- //mCurTypeDef->mFullHash = Hash128(&typeDeclaration->mParser->mStateHash, sizeof(Val128), mCurTypeDef->mFullHash);
- //BfParser* bfParser = typeDeclaration->mParser;
- // Hash in ignored warnings that occur before our type declaration
- std::set<int> ignoredWarningSet;
- auto warningItr = bfParser->mParserData->mWarningEnabledChanges.begin();
- while (warningItr != bfParser->mParserData->mWarningEnabledChanges.end())
- {
- int srcIdx = warningItr->mKey;
- if (srcIdx >= typeDeclaration->GetSrcStart())
- break;
- auto& warningEntry = warningItr->mValue;
- if (!warningEntry.mEnable)
- {
- ignoredWarningSet.insert(warningEntry.mWarningNumber);
- }
- else
- {
- auto setItr = ignoredWarningSet.find(warningEntry.mWarningNumber);
- if (setItr != ignoredWarningSet.end())
- ignoredWarningSet.erase(setItr);
- }
- ++warningItr;
- }
- for (auto ignoredWarning : ignoredWarningSet)
- {
- mFullHashCtx->Mixin(ignoredWarning);
- }
- // Hash in relative mPreprocessorIgnoredSectionStarts positions that occur within the type declaration
- auto ignoredSectionItr = bfParser->mPreprocessorIgnoredSectionStarts.upper_bound(typeDeclaration->GetSrcStart());
- while (ignoredSectionItr != bfParser->mPreprocessorIgnoredSectionStarts.end())
- {
- int srcIdx = *ignoredSectionItr;
- if (srcIdx >= typeDeclaration->GetSrcEnd())
- break;
- int relSrcIdx = srcIdx - typeDeclaration->GetSrcStart();
- mFullHashCtx->Mixin(relSrcIdx);
- ++ignoredSectionItr;
- }
- SizedArray<BfAtom*, 6> expandedName;
- if (mCurTypeDef->mName != mSystem->mGlobalsAtom)
- expandedName.push_back(mCurTypeDef->mName);
- // Expanded name should container outer namespace parts
- if (outerTypeDef != NULL)
- {
- mCurTypeDef->mNestDepth = outerTypeDef->mNestDepth + 1;
- mCurTypeDef->mNamespaceSearch = outerTypeDef->mNamespaceSearch;
- mCurTypeDef->mStaticSearch = outerTypeDef->mStaticSearch;
- mCurTypeDef->mInternalAccessSet = outerTypeDef->mInternalAccessSet;
- for (auto outerGenericParamDef : outerTypeDef->mGenericParamDefs)
- {
- BfGenericParamDef* copiedGenericParamDef = new BfGenericParamDef();
- *copiedGenericParamDef = *outerGenericParamDef;
- mCurTypeDef->mGenericParamDefs.Add(copiedGenericParamDef);
- }
- BfTypeDef* parentType = outerTypeDef;
- while (parentType != NULL)
- {
- expandedName.Insert(0, parentType->mNameEx);
- parentType = parentType->mOuterType;
- }
- }
- else
- {
- BF_ASSERT(mCurTypeDef->mNamespaceSearch.size() == 0);
- mCurTypeDef->mNamespaceSearch = mNamespaceSearch;
- mCurTypeDef->mStaticSearch = mStaticSearch;
- mCurTypeDef->mInternalAccessSet = mInternalAccessSet;
- }
- // We need to mix the namespace search into the signature hash because it can change how type references are resolved
- for (auto& usingName : mCurTypeDef->mNamespaceSearch)
- {
- mSystem->RefAtomComposite(usingName);
- mSignatureHashCtx->MixinStr(usingName.ToString());
- }
- for (auto& usingName : mCurTypeDef->mStaticSearch)
- HashNode(*mSignatureHashCtx, usingName);
- for (auto& usingName : mCurTypeDef->mInternalAccessSet)
- HashNode(*mSignatureHashCtx, usingName);
- if ((typeDeclaration->mPartialSpecifier != NULL) && (!isAutoCompleteTempType))
- {
- mCurTypeDef->mIsExplicitPartial = true;
- mCurTypeDef->mIsPartial = true;
- }
- bool isExtension = false;
- if ((typeDeclaration->mTypeNode != NULL) && (typeDeclaration->mTypeNode->GetToken() == BfToken_Extension))
- {
- mCurTypeDef->mIsPartial = true;
- isExtension = true;
- }
- BfAtomComposite fullName;
- if (!expandedName.IsEmpty())
- fullName.Set(mCurTypeDef->mNamespace.mParts, mCurTypeDef->mNamespace.mSize, &expandedName[0], (int)expandedName.size());
- else
- fullName = mCurTypeDef->mNamespace;
- String fullNameStr = fullName.ToString();
- mCurTypeDef->mHash = 0xBEEF123; // Salt the hash
- for (char c : fullNameStr)
- mCurTypeDef->mHash = ((mCurTypeDef->mHash ^ c) << 4) - mCurTypeDef->mHash;
- mCurTypeDef->mFullName = fullName;
- BfTypeDef* prevRevisionTypeDef = NULL;
- BfTypeDef* otherDefinitionTypeDef = NULL;
- int numGenericParams = 0;
- if (typeDeclaration->mGenericParams != NULL)
- numGenericParams = (int)typeDeclaration->mGenericParams->mGenericParams.size();
- if (outerTypeDef != NULL)
- numGenericParams += (int)outerTypeDef->mGenericParamDefs.size();
- mCurTypeDef->mSource = mCurSource;
- mCurTypeDef->mSource->mRefCount++;
- mCurTypeDef->mTypeDeclaration = typeDeclaration;
- mCurTypeDef->mIsAbstract = (typeDeclaration->mAbstractSpecifier != NULL) && (typeDeclaration->mAbstractSpecifier->GetToken() == BfToken_Abstract);
- mCurTypeDef->mIsDelegate = false;
- mCurTypeDef->mIsFunction = false;
- BfToken typeToken = BfToken_None;
- if (typeDeclaration->mTypeNode != NULL)
- typeToken = typeDeclaration->mTypeNode->GetToken();
- if (typeDeclaration->IsAnonymousInitializerType())
- {
- mCurTypeDef->mTypeCode = BfTypeCode_Inferred;
- }
- else if (typeDeclaration->mTypeNode == NULL)
- {
- // Globals
- mCurTypeDef->mTypeCode = BfTypeCode_Struct;
- }
- else if (typeToken == BfToken_Class)
- {
- mCurTypeDef->mTypeCode = BfTypeCode_Object;
- }
- else if (typeToken == BfToken_Delegate)
- {
- mCurTypeDef->mTypeCode = BfTypeCode_Object;
- mCurTypeDef->mIsDelegate = true;
- }
- else if (typeToken == BfToken_Function)
- {
- mCurTypeDef->mTypeCode = BfTypeCode_Struct;
- mCurTypeDef->mIsFunction = true;
- }
- else if (typeToken == BfToken_Interface)
- {
- mCurTypeDef->mTypeCode = BfTypeCode_Interface;
- }
- else if (typeToken == BfToken_Enum)
- {
- mCurTypeDef->mTypeCode = BfTypeCode_Enum;
- }
- else if (typeToken == BfToken_TypeAlias)
- {
- mCurTypeDef->mTypeCode = BfTypeCode_TypeAlias;
- }
- else if (typeToken == BfToken_Struct)
- mCurTypeDef->mTypeCode = BfTypeCode_Struct;
- else if (typeToken == BfToken_Extension)
- mCurTypeDef->mTypeCode = BfTypeCode_Extension;
- else
- BF_FATAL("Unknown type token");
- if (mCurTypeDef->mIsStatic)
- {
- if ((mCurTypeDef->mTypeCode != BfTypeCode_Object) &&
- (mCurTypeDef->mTypeCode != BfTypeCode_Struct))
- {
- mPassInstance->Warn(0, StrFormat("Types declared as '%s' cannot be 'static'", BfTokenToString(typeToken)).c_str(), typeDeclaration->mStaticSpecifier);
- mCurTypeDef->mIsStatic = false;
- }
- }
- if (mCurTypeDef->mIsAbstract)
- {
- if (mCurTypeDef->mTypeCode != BfTypeCode_Object)
- {
- mPassInstance->Warn(0, StrFormat("Types declared as '%s' cannot be 'abstract'", BfTokenToString(typeToken)).c_str(), typeDeclaration->mAbstractSpecifier);
- mCurTypeDef->mIsAbstract = false;
- }
- }
- int outerGenericSize = 0;
- if (actualOuterTypeDef != NULL)
- {
- //outerGenericSize = (int)mCurTypeDef->mOuterType->mGenericParamDefs.size();
- mCurTypeDef->mExternalConstraints = actualOuterTypeDef->GetLatest()->mExternalConstraints;
- }
- bool isGeneric = (outerGenericSize != 0) || (typeDeclaration->mGenericParams != NULL);
- ParseGenericParams(typeDeclaration->mGenericParams, typeDeclaration->mGenericConstraintsDeclaration, mCurTypeDef->mGenericParamDefs, &mCurTypeDef->mExternalConstraints, outerGenericSize, isGeneric);
- if (!isAutoCompleteTempType)
- {
- BfTypeDef* prevDef = NULL;
- auto itr = mSystem->mTypeDefs.TryGet(fullName);
- while (itr)
- {
- BfTypeDef* checkTypeDef = *itr;
- if (checkTypeDef->mDefState == BfTypeDef::DefState_Deleted)
- {
- itr.MoveToNextHashMatch();
- continue;
- }
- if ((checkTypeDef->NameEquals(mCurTypeDef)) &&
- (checkTypeDef->mGenericParamDefs.size() == numGenericParams) &&
- (mCurTypeDef->mProject == checkTypeDef->mProject))
- {
- if (checkTypeDef->mIsCombinedPartial)
- {
- // Ignore
- }
- else
- {
- if (checkTypeDef->mDefState == BfTypeDef::DefState_AwaitingNewVersion)
- {
- // We don't allow "new revision" semantics if the 'isExtension' state changes, or
- // if the outer type did not use "new revision" semantics (for isExtension change on itself or other outer type)
- bool isCompatible = (isExtension == (checkTypeDef->mTypeCode == BfTypeCode_Extension)) &&
- (checkTypeDef->mTypeCode == mCurTypeDef->mTypeCode) &&
- (checkTypeDef->mIsDelegate == mCurTypeDef->mIsDelegate) &&
- (checkTypeDef->mIsFunction == mCurTypeDef->mIsFunction) &&
- (checkTypeDef->mOuterType == actualOuterTypeDef);
- if ((mCurTypeDef->mTypeCode == BfTypeCode_Inferred) && (checkTypeDef->mTypeDeclaration->IsAnonymousInitializerType()))
- isCompatible = true;
- if (isCompatible)
- {
- if (prevRevisionTypeDef == NULL)
- {
- prevRevisionTypeDef = checkTypeDef;
- prevDef = checkTypeDef;
- }
- else
- {
- auto bestTypeDef = ComparePrevTypeDef(prevRevisionTypeDef, checkTypeDef);
- prevRevisionTypeDef = bestTypeDef;
- prevDef = bestTypeDef;
- }
- }
- }
- else
- {
- //otherDefinitionTypeDef = prevRevisionTypeDef;
- }
- }
- }
- itr.MoveToNextHashMatch();
- }
- bool doInsertNew = true;
- if (prevRevisionTypeDef != NULL)
- {
- mCurTypeDef->mIsNextRevision = true;
- bfParser->mTypeDefs.Add(prevRevisionTypeDef);
- if (prevRevisionTypeDef->mDefState == BfTypeDef::DefState_AwaitingNewVersion)
- {
- if (prevRevisionTypeDef->mNextRevision != NULL)
- {
- BfLogSysM("Deleting unused nextRevision %p from prevRevision %p\n", prevRevisionTypeDef->mNextRevision, prevRevisionTypeDef);
- delete prevRevisionTypeDef->mNextRevision;
- }
- prevRevisionTypeDef->mNextRevision = mCurTypeDef;
- BF_ASSERT(mCurTypeDef->mSystem != NULL);
- mCurActualTypeDef = prevRevisionTypeDef;
- doInsertNew = false;
- }
- }
- else
- {
- mSystem->TrackName(mCurTypeDef);
- bfParser->mTypeDefs.Add(mCurTypeDef);
- }
- if (doInsertNew)
- {
- mSystem->mTypeDefs.Add(mCurTypeDef);
- mSystem->mTypeMapVersion++;
- }
- }
- else
- {
- mCurTypeDef->mIsNextRevision = true; // We don't track name
- mResolvePassData->mAutoCompleteTempTypes.push_back(mCurTypeDef);
- }
- // Insert name into there
- mCurTypeDef->mOuterType = actualOuterTypeDef;
- //dottedName = mCurTypeDef->mName;
- if ((outerTypeDef != NULL) && (!isAutoCompleteTempType))
- {
- outerTypeDef->mNestedTypes.push_back(mCurActualTypeDef);
- }
- BfLogSysM("Creating TypeDef %p Hash:%d from TypeDecl: %p Source: %p ResolvePass: %d AutoComplete:%d PrevRevision:%d\n", mCurTypeDef, mCurTypeDef->mHash, typeDeclaration,
- typeDeclaration->GetSourceData(), mResolvePassData != NULL, isAutoCompleteTempType, prevRevisionTypeDef);
- BF_ASSERT(mCurTypeDef->mNameEx == NULL);
- if (mCurTypeDef->mGenericParamDefs.size() != 0)
- {
- mCurTypeDef->mNameEx = mSystem->GetAtom(StrFormat("%s`%d", mCurTypeDef->mName->mString.mPtr, numGenericParams));
- }
- else
- {
- mCurTypeDef->mNameEx = mCurTypeDef->mName;
- mCurTypeDef->mNameEx->mRefCount++;
- }
- if (!fullName.IsEmpty())
- {
- if (mCurTypeDef->IsGlobalsContainer())
- {
- mCurTypeDef->mFullNameEx.Set(fullName.mParts, fullName.mSize, &mCurTypeDef->mNameEx, 1);
- }
- else
- {
- mCurTypeDef->mFullNameEx = fullName;
- mCurTypeDef->mFullNameEx.mParts[mCurTypeDef->mFullNameEx.mSize - 1] = mCurTypeDef->mNameEx;
- }
- }
- if (typeDeclaration->mAutoCtor != NULL)
- VisitChildNoRef(typeDeclaration->mAutoCtor);
- if (auto defineBlock = BfNodeDynCast<BfBlock>(typeDeclaration->mDefineNode))
- {
- for (auto& member : *defineBlock)
- {
- VisitChildNoRef(member);
- }
- }
- else if (auto defineTokenNode = BfNodeDynCast<BfTokenNode>(typeDeclaration->mDefineNode))
- {
- if (defineTokenNode->GetToken() == BfToken_Semicolon)
- {
- if (typeDeclaration->mAutoCtor == NULL)
- mCurTypeDef->mIsOpaque = true;
- }
- }
- for (auto& anonTypeDecl : typeDeclaration->mAnonymousTypes)
- {
- VisitChildNoRef(anonTypeDecl);
- mFullHashCtx->MixinStr(anonTypeDecl->mAnonymousName);
- }
- FinishTypeDef(mCurTypeDef->mTypeCode == BfTypeCode_Enum);
- // Map methods into the correct index from previous revision
- if (prevRevisionTypeDef != NULL)
- {
- BF_ASSERT((mCurTypeDef->mTypeCode == prevRevisionTypeDef->mTypeCode) || (mCurTypeDef->mTypeCode == BfTypeCode_Inferred));
- if (mCurTypeDef->mFullHash == prevRevisionTypeDef->mFullHash)
- {
- if ((!mFullRefresh) && (!prevRevisionTypeDef->mForceUseNextRevision))
- {
- BfLogSys(bfParser->mSystem, "DefBuilder deleting typeDef with no changes %p prevRevision: %p\n", mCurTypeDef, prevRevisionTypeDef);
- prevRevisionTypeDef->mDefState = BfTypeDef::DefState_Defined;
- BF_ASSERT(prevRevisionTypeDef->mNextRevision == mCurTypeDef);
- prevRevisionTypeDef->mNextRevision = NULL;
- delete mCurTypeDef;
- mCurTypeDef = NULL;
- }
- else
- prevRevisionTypeDef->mDefState = BfTypeDef::DefState_Refresh;
- }
- else if (mCurTypeDef->mSignatureHash != prevRevisionTypeDef->mSignatureHash)
- prevRevisionTypeDef->mDefState = BfTypeDef::DefState_Signature_Changed;
- else if (mCurTypeDef->mInlineHash != prevRevisionTypeDef->mInlineHash)
- prevRevisionTypeDef->mDefState = BfTypeDef::DefState_InlinedInternals_Changed;
- else
- prevRevisionTypeDef->mDefState = BfTypeDef::DefState_Internals_Changed;
- }
- // There's a new type with this name...
- if ((prevRevisionTypeDef == NULL) && (!isAutoCompleteTempType))
- {
- mCurTypeDef->mName->mAtomUpdateIdx = ++mSystem->mAtomUpdateIdx;
- }
- }
- void BfDefBuilder::FinishTypeDef(bool wantsToString)
- {
- auto bfSource = mCurTypeDef->mSource;
- bool isAlias = mCurTypeDef->mTypeCode == BfTypeCode_TypeAlias;
- bool hasCtor = false;
- bool needsDefaultCtor = (mCurTypeDef->mTypeCode != BfTypeCode_Interface) && (!mCurTypeDef->mIsStatic) && (!isAlias);
- bool hasDefaultCtor = false;
- BfMethodDef* ctorClear = NULL;
- BfMethodDef* staticCtor = NULL;
- BfMethodDef* dtor = NULL;
- BfMethodDef* staticDtor = NULL;
- BfMethodDef* markMethod = NULL;
- BfMethodDef* staticMarkMethod = NULL;
- BfMethodDef* dynamicCastMethod = NULL;
- BfMethodDef* toStringMethod = NULL;
- BfMethodDef* getUnderlyingMethod = NULL;
- bool needsEqualsMethod = ((mCurTypeDef->mTypeCode == BfTypeCode_Struct) || (mCurTypeDef->mTypeCode == BfTypeCode_Enum)) && (!mCurTypeDef->mIsStatic);
- BfMethodDef* equalsOpMethod = NULL;
- BfMethodDef* equalsMethod = NULL;
- BfMethodDef* strictEqualsMethod = NULL;
- bool needsStaticInit = false;
- if (mCurTypeDef->IsExtension())
- needsDefaultCtor = false;
- bool needsDtor = false;
- bool needsStaticDtor = false;
- bool hasStaticField = false;
- bool hasNonStaticField = false;
- bool hasThreadStatics = false;
- for (int methodIdx = 0; methodIdx < (int)mCurTypeDef->mMethods.size(); methodIdx++)
- {
- auto method = mCurTypeDef->mMethods[methodIdx];
- auto _SetMethod = [&](BfMethodDef*& setMethodDef, BfMethodDef* methodDef)
- {
- if ((setMethodDef != NULL) && (setMethodDef->mMethodDeclaration == NULL))
- setMethodDef->mProtection = BfProtection_Hidden;
- setMethodDef = methodDef;
- };
- if (method->mMethodType == BfMethodType_Ctor)
- {
- if (method->HasAppend())
- needsDtor = true;
- if (method->mIsStatic)
- {
- if ((staticCtor != NULL) && (staticCtor->mMethodDeclaration != NULL))
- {
- Fail("Only one static constructor is allowed", method->mMethodDeclaration);
- method->mIsStatic = false;
- }
- if (method->mParams.size() != 0)
- {
- Fail("Static constructor cannot declare parameters", method->mMethodDeclaration);
- method->mIsStatic = false;
- }
- if (method->mName == BF_METHODNAME_MARKMEMBERS_STATIC)
- _SetMethod(staticMarkMethod, method);
- _SetMethod(staticCtor, method);
- }
- else
- {
- hasCtor = true;
- if (method->mParams.size() == 0)
- hasDefaultCtor = true;
- auto ctorDeclaration = (BfConstructorDeclaration*)method->mMethodDeclaration;
- if (method->mAppendKind != BfAllowAppendKind_No)
- {
- mCurTypeDef->mHasAppendCtor = true;
- bool isHandled = !method->mParams.IsEmpty() && method->mParams[0]->mParamKind == BfParamKind_AppendIdx;
- if (!isHandled)
- {
- auto methodDef = new BfMethodDef();
- mCurTypeDef->mMethods.Insert(methodIdx + 1, methodDef);
- BF_ASSERT(mCurDeclaringTypeDef != NULL);
- methodDef->mDeclaringType = mCurDeclaringTypeDef;
- methodDef->mName = BF_METHODNAME_CALCAPPEND;
- methodDef->mProtection = BfProtection_Public;
- methodDef->mMethodType = BfMethodType_CtorCalcAppend;
- methodDef->mIsMutating = method->mIsMutating;
- methodDef->mAppendKind = method->mAppendKind;
- methodDef->mIsNoSplat = true;
- methodDef->mMethodDeclaration = method->mMethodDeclaration;
- methodDef->mReturnTypeRef = mSystem->mDirectIntTypeRef;
- methodDef->mIsStatic = true;
- methodDef->mBody = method->mBody;
- methodDef->mAddedAfterEmit = mIsComptime;
- for (auto param : method->mParams)
- {
- BfParameterDef* newParam = new BfParameterDef();
- newParam->mName = param->mName;
- newParam->mNamePrefixCount = param->mNamePrefixCount;
- newParam->mTypeRef = param->mTypeRef;
- newParam->mMethodGenericParamIdx = param->mMethodGenericParamIdx;
- methodDef->mParams.push_back(newParam);
- }
- for (auto genericParam : method->mGenericParams)
- {
- BfGenericParamDef* newGenericParam = new BfGenericParamDef();
- *newGenericParam = *genericParam;
- methodDef->mGenericParams.Add(newGenericParam);
- }
- methodDef->mExternalConstraints = method->mExternalConstraints;
- // Insert a 'appendIdx'
- BfParameterDef* newParam = new BfParameterDef();
- newParam->mName = "__appendIdx";
- newParam->mTypeRef = mSystem->mDirectRefIntTypeRef;
- newParam->mParamKind = BfParamKind_AppendIdx;
- method->mParams.Insert(0, newParam);
- }
- }
- }
- }
- if (method->mMethodType == BfMethodType_CtorClear)
- {
- ctorClear = method;
- }
- else if (method->mMethodType == BfMethodType_Init)
- {
- if (method->mIsStatic)
- needsStaticInit = true;
- }
- else if (method->mMethodType == BfMethodType_Dtor)
- {
- if (method->mIsStatic)
- {
- if ((staticDtor != NULL) && (staticDtor->mMethodDeclaration != NULL))
- {
- Fail("Only one static constructor is allowed", method->mMethodDeclaration);
- method->mIsStatic = false;
- }
- _SetMethod(staticDtor, method);
- }
- else
- {
- if ((dtor != NULL) && (dtor->mMethodDeclaration != NULL))
- {
- Fail("Only one destructor is allowed", method->mMethodDeclaration);
- method->mIsStatic = false;
- }
- _SetMethod(dtor, method);
- }
- if (method->mParams.size() != 0)
- Fail("Destructors cannot declare parameters", method->GetMethodDeclaration()->mParams[0]);
- }
- else if (method->mMethodType == BfMethodType_Normal)
- {
- if (method->mIsStatic)
- {
- if (method->mName == BF_METHODNAME_MARKMEMBERS_STATIC)
- _SetMethod(staticMarkMethod, method);
- if (method->mName == BF_METHODNAME_DEFAULT_EQUALS)
- _SetMethod(equalsMethod, method);
- if (method->mName == BF_METHODNAME_DEFAULT_STRICT_EQUALS)
- _SetMethod(strictEqualsMethod, method);
- }
- else
- {
- if (method->mName == BF_METHODNAME_MARKMEMBERS)
- _SetMethod(markMethod, method);
- if (method->mName == BF_METHODNAME_DYNAMICCAST)
- _SetMethod(dynamicCastMethod, method);
- if (method->mName == BF_METHODNAME_TO_STRING)
- _SetMethod(toStringMethod, method);
- }
- }
- else if (method->mMethodType == BfMethodType_PropertyGetter)
- {
- if (method->mName == BF_METHODNAME_ENUM_GETUNDERLYING)
- _SetMethod(getUnderlyingMethod, method);
- }
- else if ((method->mMethodType == BfMethodType_Operator) &&
- (method->mIsStatic) &&
- (method->mParams.size() == 2))
- {
- if (auto operatorDecl = BfNodeDynCast<BfOperatorDeclaration>(method->mMethodDeclaration))
- {
- if (operatorDecl->mBinOp == BfBinaryOp_Equality)
- {
- // This is a conservative check. It's okay to add a system-defined equals method even if we don't need it.
- if ((method->mParams[0]->mTypeRef->ToString() == mCurTypeDef->mName->ToString()) &&
- (method->mParams[1]->mTypeRef->ToString() == mCurTypeDef->mName->ToString()))
- {
- _SetMethod(equalsOpMethod, method);
- }
- }
- }
- }
- if ((method->mImportKind == BfImportKind_Import_Dynamic) || (method->mImportKind == BfImportKind_Import_Unknown))
- needsStaticInit = true;
- }
-
- for (auto field : mCurTypeDef->mFields)
- {
- if (field->mIsStatic)
- {
- // Resolve-only compiler wants to visit const initializers in a static ctor method, but we don't
- // want to create it for the actual binary
- if ((!field->mIsConst) || (mSystem->mIsResolveOnly))
- {
- hasStaticField = true;
- if (field->mFieldDeclaration != NULL)
- {
- if (field->GetFieldDeclaration()->mInitializer != NULL)
- {
- needsStaticInit = true;
- }
- if (field->GetFieldDeclaration()->mFieldDtor != NULL)
- needsStaticDtor = true;
- if (field->mIsAppend)
- {
- needsStaticInit = true;
- needsStaticDtor = true;
- }
- }
- }
- if (field->mFieldDeclaration != NULL)
- {
- auto attributes = field->GetFieldDeclaration()->mAttributes;
- while (attributes != NULL)
- {
- if (attributes->mAttributeTypeRef != NULL)
- {
- auto typeRefName = attributes->mAttributeTypeRef->ToCleanAttributeString();
- if (typeRefName == "ThreadStatic")
- hasThreadStatics = true;
- }
- attributes = attributes->mNextAttribute;
- }
- }
- }
- else
- {
- hasNonStaticField = true;
- if (field->GetInitializer() != NULL)
- needsDefaultCtor = true;
- if (field->mIsAppend)
- {
- needsDefaultCtor = true;
- needsDtor = true;
- }
- if (auto fieldDecl = field->GetFieldDeclaration())
- {
- if (fieldDecl->mFieldDtor != NULL)
- needsDtor = true;
- }
- }
- }
- bool needsDynamicCastMethod = dynamicCastMethod == NULL;
- if (mCurTypeDef->mIsFunction)
- {
- wantsToString = false;
- needsEqualsMethod = false;
- needsDefaultCtor = false;
- needsDynamicCastMethod = false;
- }
- if (!mCurTypeDef->mIsOpaque)
- {
- if (((mCurTypeDef->mTypeCode == BfTypeCode_Object) || (mCurTypeDef->mTypeCode == BfTypeCode_Inferred)) &&
- (!mCurTypeDef->mIsStatic) && (ctorClear == NULL))
- {
- auto methodDef = AddMethod(mCurTypeDef, BfMethodType_CtorClear, BfProtection_Private, false, "", mIsComptime);
- methodDef->mIsMutating = true;
- }
- if ((needsDtor) && (dtor == NULL))
- {
- auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Dtor, BfProtection_Public, false, "", mIsComptime);
- }
- if ((needsStaticDtor) && (staticDtor == NULL))
- {
- auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Dtor, BfProtection_Public, true, "", mIsComptime);
- }
- if ((needsStaticInit) && (staticCtor == NULL))
- {
- auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Ctor, BfProtection_Public, true, "", mIsComptime);
- }
- }
- bool makeCtorPrivate = hasCtor;
- if (mCurTypeDef->mTypeCode == BfTypeCode_TypeAlias)
- needsDefaultCtor = false;
- if (mCurTypeDef->mTypeCode == BfTypeCode_Extension)
- needsDefaultCtor = false;
- if ((needsDefaultCtor) && (!hasDefaultCtor) && (!mCurTypeDef->mIsOpaque))
- {
- BfProtection prot = hasCtor ? BfProtection_Hidden : BfProtection_Public;
- if (mCurTypeDef->mName == mSystem->mEmptyAtom)
- prot = BfProtection_Hidden;
- // Create default constructor. If it's the only constructor then make it public,
- // otherwise make it private so we can still internally use it but the user can't
- auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Ctor, prot, false, "", mIsComptime);
- methodDef->mIsMutating = true;
- }
- bool isAutocomplete = false;
- if ((mResolvePassData != NULL) && (mResolvePassData->mAutoComplete != NULL))
- isAutocomplete = true;
- //TODO: Don't do this for the autocomplete pass
- if ((mCurTypeDef->mTypeCode != BfTypeCode_Interface) && (mCurTypeDef->mTypeCode != BfTypeCode_Extension) &&
- (!mCurTypeDef->mIsStatic) && (!isAutocomplete) && (!isAlias) && (!mCurTypeDef->mIsOpaque))
- {
- AddDynamicCastMethods(mCurTypeDef, needsDynamicCastMethod);
- }
- bool isPayloadEnum = false;
- if (mCurTypeDef->mTypeCode == BfTypeCode_Enum)
- {
- for (auto fieldDef : mCurTypeDef->mFields)
- {
- if (auto enumEntryDecl = BfNodeDynCast<BfEnumEntryDeclaration>(fieldDef->mFieldDeclaration))
- {
- if (enumEntryDecl->mTypeRef != NULL)
- isPayloadEnum = true;
- }
- }
- }
- if (isPayloadEnum)
- hasNonStaticField = true;
- if ((mCurTypeDef->mTypeCode != BfTypeCode_Interface) && (!mCurTypeDef->mIsOpaque))
- {
- if ((hasStaticField) && (staticMarkMethod == NULL))
- {
- auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Normal, BfProtection_Protected, true, BF_METHODNAME_MARKMEMBERS_STATIC, mIsComptime);
- methodDef->mIsNoReflect = true;
- }
- if (hasThreadStatics)
- {
- auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Normal, BfProtection_Protected, true, BF_METHODNAME_FIND_TLS_MEMBERS, mIsComptime);
- methodDef->mIsNoReflect = true;
- }
- if ((hasNonStaticField) && (markMethod == NULL))
- {
- auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Normal, BfProtection_Protected, false, BF_METHODNAME_MARKMEMBERS, mIsComptime);
- methodDef->mIsVirtual = true;
- methodDef->mIsOverride = true;
- methodDef->mIsNoReflect = true;
- methodDef->mCallingConvention = BfCallingConvention_Cdecl;
- mCurTypeDef->mHasOverrideMethods = true;
- }
- }
- if (toStringMethod != NULL)
- wantsToString = false;
- if ((mCurTypeDef->mTypeCode == BfTypeCode_Enum) && (!isPayloadEnum) && (getUnderlyingMethod == NULL) && (!mCurTypeDef->mIsOpaque))
- {
- auto methodDef = new BfMethodDef();
- mCurTypeDef->mMethods.push_back(methodDef);
- BF_ASSERT(mCurDeclaringTypeDef != NULL);
- methodDef->mDeclaringType = mCurDeclaringTypeDef;
- methodDef->mName = BF_METHODNAME_ENUM_HASFLAG;
- methodDef->mReturnTypeRef = mSystem->mDirectBoolTypeRef;
- methodDef->mProtection = BfProtection_Public;
- AddParam(methodDef, mSystem->mDirectSelfTypeRef, "checkEnum");
- methodDef->mAddedAfterEmit = mIsComptime;
- // Underlying
- {
- auto methodDef = new BfMethodDef();
- mCurTypeDef->mMethods.push_back(methodDef);
- BF_ASSERT(mCurDeclaringTypeDef != NULL);
- methodDef->mDeclaringType = mCurDeclaringTypeDef;
- methodDef->mName = BF_METHODNAME_ENUM_GETUNDERLYING;
- methodDef->mReturnTypeRef = mSystem->mDirectSelfBaseTypeRef;
- methodDef->mMethodType = BfMethodType_PropertyGetter;
- methodDef->mProtection = BfProtection_Public;
- methodDef->mAddedAfterEmit = mIsComptime;
- auto propDef = new BfPropertyDef();
- mCurTypeDef->mProperties.Add(propDef);
- propDef->mTypeRef = mSystem->mDirectSelfBaseTypeRef;
- BF_ASSERT(mCurDeclaringTypeDef != NULL);
- propDef->mDeclaringType = mCurDeclaringTypeDef;
- propDef->mName = "Underlying";
- propDef->mMethods.Add(methodDef);
- propDef->mProtection = BfProtection_Public;
- }
- // UnderlyingRef
- {
- auto methodDef = new BfMethodDef();
- mCurTypeDef->mMethods.push_back(methodDef);
- BF_ASSERT(mCurDeclaringTypeDef != NULL);
- methodDef->mDeclaringType = mCurDeclaringTypeDef;
- methodDef->mIsMutating = true;
- methodDef->mName = BF_METHODNAME_ENUM_GETUNDERLYINGREF;
- methodDef->mReturnTypeRef = mSystem->mDirectRefSelfBaseTypeRef;
- methodDef->mMethodType = BfMethodType_PropertyGetter;
- methodDef->mProtection = BfProtection_Public;
- methodDef->mAddedAfterEmit = mIsComptime;
- auto propDef = new BfPropertyDef();
- mCurTypeDef->mProperties.Add(propDef);
- propDef->mTypeRef = mSystem->mDirectRefSelfBaseTypeRef;
- BF_ASSERT(mCurDeclaringTypeDef != NULL);
- propDef->mDeclaringType = mCurDeclaringTypeDef;
- propDef->mName = "UnderlyingRef";
- propDef->mMethods.Add(methodDef);
- propDef->mProtection = BfProtection_Public;
- }
- }
- if ((wantsToString) && (!mCurTypeDef->mIsOpaque))
- {
- auto methodDef = new BfMethodDef();
- mCurTypeDef->mMethods.push_back(methodDef);
- BF_ASSERT(mCurDeclaringTypeDef != NULL);
- methodDef->mDeclaringType = mCurDeclaringTypeDef;
- methodDef->mName = BF_METHODNAME_TO_STRING;
- methodDef->mReturnTypeRef = mSystem->mDirectVoidTypeRef;
- methodDef->mProtection = BfProtection_Public;
- methodDef->mIsOverride = true;
- methodDef->mIsVirtual = true;
- AddParam(methodDef, mSystem->mDirectStringTypeRef, "outStr");
- mCurTypeDef->mHasOverrideMethods = true;
- methodDef->mAddedAfterEmit = mIsComptime;
- }
- if ((needsEqualsMethod) && (equalsMethod == NULL) && (equalsOpMethod == NULL) && (!mCurTypeDef->mIsOpaque))
- {
- auto methodDef = new BfMethodDef();
- mCurTypeDef->mMethods.push_back(methodDef);
- BF_ASSERT(mCurDeclaringTypeDef != NULL);
- methodDef->mDeclaringType = mCurDeclaringTypeDef;
- methodDef->mName = BF_METHODNAME_DEFAULT_EQUALS;
- methodDef->mReturnTypeRef = mSystem->mDirectBoolTypeRef;
- methodDef->mProtection = BfProtection_Private;
- methodDef->mIsStatic = true;
- AddParam(methodDef, mSystem->mDirectSelfTypeRef, "lhs");
- AddParam(methodDef, mSystem->mDirectSelfTypeRef, "rhs");
- methodDef->mAddedAfterEmit = mIsComptime;
- }
- if ((needsEqualsMethod) && (strictEqualsMethod == NULL) && (!mCurTypeDef->mIsOpaque))
- {
- auto methodDef = new BfMethodDef();
- mCurTypeDef->mMethods.push_back(methodDef);
- BF_ASSERT(mCurDeclaringTypeDef != NULL);
- methodDef->mDeclaringType = mCurDeclaringTypeDef;
- methodDef->mName = BF_METHODNAME_DEFAULT_STRICT_EQUALS;
- methodDef->mReturnTypeRef = mSystem->mDirectBoolTypeRef;
- methodDef->mProtection = BfProtection_Private;
- methodDef->mIsStatic = true;
- AddParam(methodDef, mSystem->mDirectSelfTypeRef, "lhs");
- AddParam(methodDef, mSystem->mDirectSelfTypeRef, "rhs");
- methodDef->mAddedAfterEmit = mIsComptime;
- }
- HashContext inlineHashCtx;
- if (mCurSource != NULL)
- {
- auto bfParser = mCurSource->ToParser();
- if (bfParser != NULL)
- inlineHashCtx.MixinStr(bfParser->mFileName);
- }
- //for (auto methodDef : mCurTypeDef->mMethods)
- for (int methodIdx = 0; methodIdx < (int)mCurTypeDef->mMethods.size(); methodIdx++)
- {
- // Add in name so the hand-created methods can be compared by hash
- auto methodDef = mCurTypeDef->mMethods[methodIdx];
- methodDef->mIdx = methodIdx;
- methodDef->mFullHash = HashString(methodDef->mName, methodDef->mFullHash);
- if (mSignatureHashCtx != NULL)
- mSignatureHashCtx->MixinStr(methodDef->mName);
- if ((methodDef->mAlwaysInline) ||
- (methodDef->mAppendKind != BfAllowAppendKind_No) ||
- (methodDef->mMethodType == BfMethodType_Mixin))
- inlineHashCtx.Mixin(methodDef->mFullHash);
- if (mFullRefresh)
- methodDef->mCodeChanged = true;
- }
- mCurTypeDef->mInlineHash = inlineHashCtx.Finish128();
- if (mSignatureHashCtx != NULL)
- {
- mCurTypeDef->mSignatureHash = mSignatureHashCtx->Finish128();
- // We need to hash the signature in here because the preprocessor settings
- // may change so the text is the same but the signature changes
- // so fullHash needs to change too
- mFullHashCtx->Mixin(mCurTypeDef->mSignatureHash);
- }
- if (mFullHashCtx != NULL)
- mCurTypeDef->mFullHash = mFullHashCtx->Finish128();
- }
- void BfDefBuilder::Visit(BfUsingDirective* usingDirective)
- {
- if (usingDirective->mNamespace == NULL)
- {
- BF_ASSERT(mPassInstance->HasFailed());
- return;
- }
- if (mResolvePassData != NULL)
- mResolvePassData->mExteriorAutocompleteCheckNodes.push_back(usingDirective);
- String usingString = usingDirective->mNamespace->ToString();
- BfAtomComposite usingComposite;
- mSystem->ParseAtomComposite(usingString, usingComposite, true);
- if (!mNamespaceSearch.Contains(usingComposite))
- mNamespaceSearch.Insert(0, usingComposite);
- else
- mSystem->ReleaseAtomComposite(usingComposite);
- }
- void BfDefBuilder::Visit(BfUsingModDirective* usingDirective)
- {
- if (mResolvePassData != NULL)
- mResolvePassData->mExteriorAutocompleteCheckNodes.push_back(usingDirective);
- if (usingDirective->mModToken->mToken == BfToken_Internal)
- {
- if (usingDirective->mTypeRef != NULL)
- mInternalAccessSet.Add(usingDirective->mTypeRef);
- }
- else if (usingDirective->mTypeRef != NULL)
- mStaticSearch.Add(usingDirective->mTypeRef);
- }
- void BfDefBuilder::SetNamespaceState(const NamespaceState& namespaceState)
- {
- while ((int)mNamespaceSearch.size() > namespaceState.mNamespaceSearchCount)
- {
- BfAtomComposite& atomComposite = mNamespaceSearch[0];
- mSystem->ReleaseAtomComposite(atomComposite);
- mNamespaceSearch.RemoveAt(0);
- }
- mNamespace = namespaceState.mNamespace;
- }
- void BfDefBuilder::Visit(BfNamespaceDeclaration* namespaceDeclaration)
- {
- auto blockNode = BfNodeDynCast<BfBlock>(namespaceDeclaration->mBody);
- bool isFileLevel = (blockNode == NULL) && (namespaceDeclaration->mBody != NULL);
- if (mNamespaceBlockDepth < mFileLevelNamespaceState.mSize)
- {
- auto& prevNamespaceState = mFileLevelNamespaceState[mNamespaceBlockDepth];
- if (prevNamespaceState.mNamespaceSearchCount != -1)
- {
- SetNamespaceState(prevNamespaceState);
- prevNamespaceState.mNamespaceSearchCount = -1;
- }
- }
- NamespaceState namespaceState;
- namespaceState.mNamespace = mNamespace;
- namespaceState.mNamespaceSearchCount = (int)mNamespaceSearch.size();
- if (isFileLevel)
- {
- while (mNamespaceBlockDepth >= mFileLevelNamespaceState.mSize)
- mFileLevelNamespaceState.Add(NamespaceState());
- mFileLevelNamespaceState[mNamespaceBlockDepth] = namespaceState;
- }
- if (namespaceDeclaration->mNameNode == NULL)
- return;
- String namespaceLeft = namespaceDeclaration->mNameNode->ToString();
- while (true)
- {
- int dotIdx = (int)namespaceLeft.IndexOf('.');
- if (dotIdx == -1)
- {
- BfAtom* namespaceAtom = mSystem->GetAtom(namespaceLeft);
- mNamespace.Set(mNamespace.mParts, mNamespace.mSize, &namespaceAtom, 1);
- if (!mNamespaceSearch.Contains(mNamespace))
- {
- mSystem->RefAtomComposite(mNamespace);
- mNamespaceSearch.Insert(0, mNamespace);
- }
- mSystem->ReleaseAtom(namespaceAtom);
- break;
- }
- BfAtom* namespaceAtom = mSystem->GetAtom(namespaceLeft.Substring(0, dotIdx));
- mNamespace.Set(mNamespace.mParts, mNamespace.mSize, &namespaceAtom, 1);
- namespaceLeft = namespaceLeft.Substring(dotIdx + 1);
- if (!mNamespaceSearch.Contains(mNamespace))
- {
- mSystem->RefAtomComposite(mNamespace);
- mNamespaceSearch.Insert(0, mNamespace);
- }
- mSystem->ReleaseAtom(namespaceAtom);
- }
- if (blockNode != NULL)
- {
- mNamespaceBlockDepth++;
- VisitChild(blockNode);
- mNamespaceBlockDepth--;
- }
- if (!isFileLevel)
- SetNamespaceState(namespaceState);
- }
- void BfDefBuilder::Visit(BfBlock* block)
- {
- VisitMembers(block);
- }
- void BfDefBuilder::Visit(BfRootNode* rootNode)
- {
- VisitMembers(rootNode);
- }
|