| 16513 | } |
| 16514 | |
| 16515 | BfScopeData* BfModule::FindScope(BfAstNode* scopeName, BfMixinState* fromMixinState, bool allowAcrossDeferredBlock) |
| 16516 | { |
| 16517 | bool inMixinDecl = (mCurMethodInstance != NULL) && (mCurMethodInstance->IsMixin()); |
| 16518 | |
| 16519 | if (auto tokenNode = BfNodeDynCast<BfTokenNode>(scopeName)) |
| 16520 | { |
| 16521 | if (tokenNode->GetToken() == BfToken_Colon) |
| 16522 | { |
| 16523 | if ((!allowAcrossDeferredBlock) && (mCurMethodState->mInDeferredBlock)) |
| 16524 | { |
| 16525 | Fail("Cannot access method scope across deferred block boundary", scopeName); |
| 16526 | return NULL; |
| 16527 | } |
| 16528 | |
| 16529 | return &mCurMethodState->mHeadScope; |
| 16530 | } |
| 16531 | else if (tokenNode->GetToken() == BfToken_Mixin) |
| 16532 | { |
| 16533 | if (fromMixinState == NULL) |
| 16534 | { |
| 16535 | if (mCurMethodInstance->mMethodDef->mMethodType != BfMethodType_Mixin) |
| 16536 | Fail("'mixin' scope specifier can only be used within a mixin declaration", scopeName); |
| 16537 | return mCurMethodState->mCurScope; |
| 16538 | } |
| 16539 | |
| 16540 | fromMixinState->mUsedInvocationScope = true; |
| 16541 | return fromMixinState->mTargetScope; |
| 16542 | } |
| 16543 | else if (tokenNode->GetToken() == BfToken_New) |
| 16544 | return NULL; |
| 16545 | } |
| 16546 | |
| 16547 | if (auto identifier = BfNodeDynCast<BfIdentifierNode>(scopeName)) |
| 16548 | { |
| 16549 | auto findLabel = scopeName->ToString(); |
| 16550 | |
| 16551 | bool crossedDeferredBlock = false; |
| 16552 | |
| 16553 | auto checkScope = mCurMethodState->mCurScope; |
| 16554 | while (checkScope != NULL) |
| 16555 | { |
| 16556 | if (checkScope->mIsDeferredBlock) |
| 16557 | crossedDeferredBlock = true; |
| 16558 | |
| 16559 | if (checkScope->mLabel == findLabel) |
| 16560 | { |
| 16561 | if ((crossedDeferredBlock) && (!allowAcrossDeferredBlock)) |
| 16562 | { |
| 16563 | Fail(StrFormat("Cannot access scope '%s' across deferred block boundary", findLabel.c_str()), scopeName); |
| 16564 | return NULL; |
| 16565 | } |
| 16566 | return checkScope; |
| 16567 | } |
| 16568 | checkScope = checkScope->mPrevScope; |
| 16569 | } |
| 16570 | |
| 16571 | if (!inMixinDecl) |
| 16572 | Fail(StrFormat("Unable to locate label '%s'", findLabel.c_str()), scopeName); |