From 14a3dd8e7d024ed87a8ef3ab775ac180417168e9 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Fri, 8 Nov 2024 09:16:27 -0500 Subject: [PATCH] Handle zero-sized enums (<= 1 member) --- IDE/src/ui/AutoComplete.bf | 286 +++++++++++++-------- IDEHelper/Compiler/BfAst.cpp | 5 + IDEHelper/Compiler/BfAst.h | 11 + IDEHelper/Compiler/BfAutoComplete.cpp | 35 ++- IDEHelper/Compiler/BfAutoComplete.h | 4 + IDEHelper/Compiler/BfCompiler.cpp | 4 +- IDEHelper/Compiler/BfElementVisitor.cpp | 8 + IDEHelper/Compiler/BfElementVisitor.h | 1 + IDEHelper/Compiler/BfExprEvaluator.cpp | 14 +- IDEHelper/Compiler/BfIRBuilder.cpp | 9 +- IDEHelper/Compiler/BfModule.cpp | 9 +- IDEHelper/Compiler/BfModuleTypeUtils.cpp | 24 +- IDEHelper/Compiler/BfPrinter.cpp | 9 + IDEHelper/Compiler/BfPrinter.h | 1 + IDEHelper/Compiler/BfReducer.cpp | 34 ++- IDEHelper/Compiler/BfResolvedTypeUtils.cpp | 101 ++++++++ IDEHelper/Compiler/BfResolvedTypeUtils.h | 18 ++ IDEHelper/Compiler/BfSourceClassifier.cpp | 11 + IDEHelper/Compiler/BfSourceClassifier.h | 1 + IDEHelper/Compiler/BfSystem.cpp | 6 + IDEHelper/Compiler/BfSystem.h | 5 +- 21 files changed, 461 insertions(+), 135 deletions(-) diff --git a/IDE/src/ui/AutoComplete.bf b/IDE/src/ui/AutoComplete.bf index e2178cc2..9dc13e96 100644 --- a/IDE/src/ui/AutoComplete.bf +++ b/IDE/src/ui/AutoComplete.bf @@ -196,7 +196,6 @@ namespace IDE.ui { public AutoComplete mAutoComplete; public bool mIsInitted; - public int mIgnoreMove; public bool mOwnsWindow; public float mRightBoxAdjust; public float mWantHeight; @@ -237,7 +236,7 @@ namespace IDE.ui return; } - if ((mIgnoreMove == 0) && (mWidgetWindow != null) && (!mWidgetWindow.mHasClosed)) + if ((mAutoComplete.mIgnoreMove == 0) && (mWidgetWindow != null) && (!mWidgetWindow.mHasClosed)) mAutoComplete.Close(); } @@ -345,7 +344,6 @@ namespace IDE.ui public override void Update() { base.Update(); - Debug.Assert((mIgnoreMove >= 0) && (mIgnoreMove <= 4)); } } @@ -591,15 +589,11 @@ namespace IDE.ui int windowHeight = (int)(mWantHeight + Math.Max(0, mDocHeight - GS!(32))); - mIgnoreMove++; - if (mAutoComplete.mInvokeWidget != null) - mAutoComplete.mInvokeWidget.mIgnoreMove++; + mAutoComplete.mIgnoreMove++; mWidgetWindow.Resize(mWidgetWindow.mNormX, mWidgetWindow.mNormY, windowWidth, windowHeight); mScrollContent.mWidth = mWidth; //Resize(0, 0, mWidgetWindow.mClientWidth, mWidgetWindow.mClientHeight); - mIgnoreMove--; - if (mAutoComplete.mInvokeWidget != null) - mAutoComplete.mInvokeWidget.mIgnoreMove--; + mAutoComplete.mIgnoreMove--; ResizeContent(-1, -1, mVertScrollbar != null); } } @@ -653,7 +647,7 @@ namespace IDE.ui entryWidget.mDocumentation = new:mAlloc String(documentation); entryWidget.mIcon = icon; - entryWidget.SetMatches(matchIndices); + entryWidget.SetMatches(matchIndices ?? scope .()); UpdateEntry(entryWidget, mEntryList.Count); mEntryList.Add(entryWidget); @@ -860,6 +854,7 @@ namespace IDE.ui { public String mText ~ delete _; public String mDocumentation ~ delete _; + public int32 mArgMatchCount; public int GetParamCount() { @@ -941,9 +936,9 @@ namespace IDE.ui { if (mOwnsWindow) { - mIgnoreMove++; + mAutoComplete.mIgnoreMove++; mAutoComplete.UpdateWindow(ref mWidgetWindow, this, mAutoComplete.mInvokeSrcPositions[0], (int32)extWidth, (int32)extHeight); - mIgnoreMove--; + mAutoComplete.mIgnoreMove--; } else { @@ -966,11 +961,15 @@ namespace IDE.ui mSelectIdx = 0; } - public void SelectDirection(int32 dir) + public bool SelectDirection(int32 dir) { int32 newSelection = mSelectIdx + dir; if ((newSelection >= 0) && (newSelection < mEntryList.Count)) + { Select(newSelection); + return true; + } + return false; } public override void Update() @@ -979,36 +978,15 @@ namespace IDE.ui } - void DrawInfo(Graphics g, out float extWidth, out float extHeight) + public void GetState(out int cursorSection) { - var font = IDEApp.sApp.mCodeFont; - - extWidth = 0; - - float curX = GS!(8); - float curY = GS!(5); - - if (mEntryList.Count > 1) - { - String numStr = scope String(); - numStr.AppendF("{0}/{1}", mSelectIdx + 1, mEntryList.Count); - if (g != null) - { - using (g.PushColor(gApp.mSettings.mUISettings.mColors.mAutoCompleteSubText)) - g.DrawString(numStr, curX, curY); - } - curX += font.GetWidth(numStr) + GS!(8); - } + cursorSection = -1; var selectedEntry = mEntryList[mSelectIdx]; - - float maxWidth = mWidth; - StringView paramName = .(); List textSections = scope List(selectedEntry.mText.Split('\x01')); int cursorPos = mAutoComplete.mTargetEditWidget.Content.CursorTextPos; - int cursorSection = -1; for (int sectionIdx = 0; sectionIdx < mAutoComplete.mInvokeSrcPositions.Count - 1; sectionIdx++) { if (cursorPos > mAutoComplete.mInvokeSrcPositions[sectionIdx]) @@ -1085,6 +1063,37 @@ namespace IDE.ui } } } + } + + void DrawInfo(Graphics g, out float extWidth, out float extHeight) + { + var font = IDEApp.sApp.mCodeFont; + + extWidth = 0; + + float curX = GS!(8); + float curY = GS!(5); + + if (mEntryList.Count > 1) + { + String numStr = scope String(); + numStr.AppendF("{0}/{1}", mSelectIdx + 1, mEntryList.Count); + if (g != null) + { + using (g.PushColor(gApp.mSettings.mUISettings.mColors.mAutoCompleteSubText)) + g.DrawString(numStr, curX, curY); + } + curX += font.GetWidth(numStr) + GS!(8); + } + + var selectedEntry = mEntryList[mSelectIdx]; + + float maxWidth = mWidth; + + StringView paramName = .(); + List textSections = scope List(selectedEntry.mText.Split('\x01')); + + GetState(var cursorSection); float paramX = 0; for (int sectionIdx = 0; sectionIdx < textSections.Count; sectionIdx++) @@ -1259,6 +1268,7 @@ namespace IDE.ui public bool mIsDocumentationPass; public bool mIsUserRequested; + public int mIgnoreMove; bool mClosed; bool mPopulating; float mWantX; @@ -1412,6 +1422,8 @@ namespace IDE.ui public void Update() { + Debug.Assert((mIgnoreMove >= 0) && (mIgnoreMove <= 4)); + if ((mInvokeWindow != null) && (!mInvokeWidget.mIsAboveText)) { int textIdx = mTargetEditWidget.Content.CursorTextPos; @@ -1440,18 +1452,13 @@ namespace IDE.ui int insertLine = line; if ((insertLine != invokeLine) && ((insertLine - invokeLine) * gApp.mCodeFont.GetHeight() < GS!(40))) { - mInvokeWidget.mIgnoreMove++; - if (mListWindow != null) - mAutoCompleteListWidget.mIgnoreMove++; + mIgnoreMove++; mInvokeWidget.mIsAboveText = true; mInvokeWidget.ResizeContent(false); UpdateWindow(ref mInvokeWindow, mInvokeWidget, mInvokeSrcPositions[0], (int32)mInvokeWidget.mWidth, (int32)mInvokeWidget.mHeight); if (mListWindow != null) - { UpdateWindow(ref mListWindow, mAutoCompleteListWidget, mInsertStartIdx, mListWindow.mWindowWidth, mListWindow.mWindowHeight); - mAutoCompleteListWidget.mIgnoreMove--; - } - mInvokeWidget.mIgnoreMove--; + mIgnoreMove--; } } @@ -1470,6 +1477,67 @@ namespace IDE.ui Close(); } } + + /*if (mInvokeWidget != null) + { + var invokeEntry = mInvokeWidget.mEntryList[mInvokeWidget.mSelectIdx]; + + mInvokeWidget.GetState(var cursorSection); + + if (mAutoCompleteListWidget != null) + { + + } + else + { + if (cursorSection > 0) + { + int sectionStartIdx = -1; + int sectionEndIdx = -1; + + int foundSectionIdx = 0; + for (var c in invokeEntry.mText.RawChars) + { + if (c == '\x01') + { + foundSectionIdx++; + if (foundSectionIdx == cursorSection) + sectionStartIdx = @c.Index; + else if (foundSectionIdx == cursorSection + 1) + sectionEndIdx = @c.Index; + } + } + + if (sectionEndIdx != -1) + { + StringView argText = invokeEntry.mText.Substring(sectionStartIdx + 1, sectionEndIdx - sectionStartIdx - 1); + argText.Trim(); + while (!argText.IsEmpty) + { + char8 c = argText[argText.Length - 1]; + if ((c.IsLetterOrDigit) || (c == '_')) + break; + argText.RemoveFromEnd(1); + } + + if (argText.StartsWith("tag ")) + { + int spacePos = argText.IndexOf(' ', 4); + if (spacePos == -1) + spacePos = argText.Length; + StringView tagName = argText.Substring(4, spacePos - 4); + + mInsertStartIdx = mInvokeSrcPositions[cursorSection - 1]; + mInsertEndIdx = mInsertStartIdx; + mAutoCompleteListWidget = new AutoCompleteListWidget(this); + mAutoCompleteListWidget.AddEntry("value", scope $".{tagName}", DarkTheme.sDarkTheme.GetImage(.IconValue)); + HandleAutoCompleteListWidget(1); + mAutoCompleteListWidget.mSelectIdx = 0; + } + } + } + } + }*/ } public void GetFilter(String outFilter) @@ -1718,10 +1786,7 @@ namespace IDE.ui public void SetIgnoreMove(bool ignoreMove) { - if (mAutoCompleteListWidget != null) - mAutoCompleteListWidget.mIgnoreMove += ignoreMove ? 1 : -1; - if (mInvokeWidget != null) - mInvokeWidget.mIgnoreMove += ignoreMove ? 1 : -1; + mIgnoreMove += ignoreMove ? 1 : -1; } // IDEHelper/third_party/FtsFuzzyMatch.h @@ -1996,61 +2061,7 @@ namespace IDE.ui if (mAutoCompleteListWidget != null) { - if (mAutoCompleteListWidget.mEntryList.Count > 0) - { - mAutoCompleteListWidget.mOwnsWindow = !IsInPanel(); - mAutoCompleteListWidget.mAutoFocus = IsInPanel(); - int32 windowWidth = (int32)mAutoCompleteListWidget.mMaxWidth; - if (mAutoCompleteListWidget.mRightBoxAdjust != 0) - windowWidth += (int32)mAutoCompleteListWidget.mRightBoxAdjust; // - GS!(16); - //windowWidth += (int32)mAutoCompleteListWidget.mDocWidth; - windowWidth += GS!(16); - - int32 contentHeight = (int32)(visibleCount * mAutoCompleteListWidget.mItemSpacing); - int32 windowHeight = contentHeight + GS!(20); - int32 maxWindowHeight = GetMaxWindowHeight(); - bool wantScrollbar = false; - if (windowHeight > maxWindowHeight) - { - windowHeight = maxWindowHeight; - wantScrollbar = true; - windowWidth += GS!(12); - } - contentHeight += GS!(8); - mAutoCompleteListWidget.ResizeContent(windowWidth, contentHeight, wantScrollbar); - if ((mInsertStartIdx != -1) && (!IsInPanel())) - { - UpdateWindow(ref mListWindow, mAutoCompleteListWidget, mInsertStartIdx, windowWidth, windowHeight); - mAutoCompleteListWidget.mWantHeight = windowHeight; - } - mAutoCompleteListWidget.UpdateScrollbars(); - mAutoCompleteListWidget.CenterSelection(); - mAutoCompleteListWidget.UpdateWidth(); - } - else - { - if ((mListWindow == null) || (mListWindow.mRootWidget != mAutoCompleteListWidget)) - { - if (IsInPanel()) - { - gApp.mAutoCompletePanel.Unbind(this); - if (mInvokeWidget != null) - { - if (mInvokeWidget.mParent != null) - mInvokeWidget.RemoveSelf(); - delete mInvokeWidget; - mInvokeWidget = null; - } - } - delete mAutoCompleteListWidget; - } - if (mListWindow != null) - { - mListWindow.Close(); - mListWindow = null; - } - mAutoCompleteListWidget = null; - } + HandleAutoCompleteListWidget(visibleCount); } gApp.mAutoCompletePanel.FinishBind(); SetIgnoreMove(false); @@ -2174,6 +2185,65 @@ namespace IDE.ui //Debug.WriteLine("UpdateInfo {0} {1}", mInsertStartIdx, mInsertEndIdx); } + public void HandleAutoCompleteListWidget(int visibleCount) + { + if (mAutoCompleteListWidget.mEntryList.Count > 0) + { + mAutoCompleteListWidget.mOwnsWindow = !IsInPanel(); + mAutoCompleteListWidget.mAutoFocus = IsInPanel(); + int32 windowWidth = (int32)mAutoCompleteListWidget.mMaxWidth; + if (mAutoCompleteListWidget.mRightBoxAdjust != 0) + windowWidth += (int32)mAutoCompleteListWidget.mRightBoxAdjust; // - GS!(16); + //windowWidth += (int32)mAutoCompleteListWidget.mDocWidth; + windowWidth += GS!(16); + + int32 contentHeight = (int32)(visibleCount * mAutoCompleteListWidget.mItemSpacing); + int32 windowHeight = contentHeight + GS!(20); + int32 maxWindowHeight = GetMaxWindowHeight(); + bool wantScrollbar = false; + if (windowHeight > maxWindowHeight) + { + windowHeight = maxWindowHeight; + wantScrollbar = true; + windowWidth += GS!(12); + } + contentHeight += GS!(8); + mAutoCompleteListWidget.ResizeContent(windowWidth, contentHeight, wantScrollbar); + if ((mInsertStartIdx != -1) && (!IsInPanel())) + { + UpdateWindow(ref mListWindow, mAutoCompleteListWidget, mInsertStartIdx, windowWidth, windowHeight); + mAutoCompleteListWidget.mWantHeight = windowHeight; + } + mAutoCompleteListWidget.UpdateScrollbars(); + mAutoCompleteListWidget.CenterSelection(); + mAutoCompleteListWidget.UpdateWidth(); + } + else + { + if ((mListWindow == null) || (mListWindow.mRootWidget != mAutoCompleteListWidget)) + { + if (IsInPanel()) + { + gApp.mAutoCompletePanel.Unbind(this); + if (mInvokeWidget != null) + { + if (mInvokeWidget.mParent != null) + mInvokeWidget.RemoveSelf(); + delete mInvokeWidget; + mInvokeWidget = null; + } + } + delete mAutoCompleteListWidget; + } + if (mListWindow != null) + { + mListWindow.Close(); + mListWindow = null; + } + mAutoCompleteListWidget = null; + } + } + public void SetInfo(String info, bool clearList = true, int32 textOffset = 0, bool changedAfterInfo = false) { scope AutoBeefPerf("AutoComplete.SetInfo"); @@ -2196,7 +2266,7 @@ namespace IDE.ui { if (mAutoCompleteListWidget != null) { - mAutoCompleteListWidget.mIgnoreMove++; + mIgnoreMove++; if (IsInPanel()) { mAutoCompleteListWidget.RemoveSelf(); @@ -2210,6 +2280,7 @@ namespace IDE.ui else delete mAutoCompleteListWidget; mAutoCompleteListWidget = null; + mIgnoreMove--; } } if (mAutoCompleteListWidget == null) @@ -2434,6 +2505,7 @@ namespace IDE.ui var invokeEntry = new InvokeWidget.Entry(); invokeEntry.mText = new String(entryDisplay); + invokeEntry.mArgMatchCount = int32.Parse(entryInsert).GetValueOrDefault(); if (!documentation.IsEmpty) invokeEntry.mDocumentation = new String(documentation); mInvokeWidget.AddEntry(invokeEntry); @@ -2846,6 +2918,14 @@ namespace IDE.ui } } + public void GetInsertText(String outStr) + { + if (mAutoCompleteListWidget != null) + { + var entry = mAutoCompleteListWidget.mEntryList[mAutoCompleteListWidget.mSelectIdx]; + outStr.Append(entry.mEntryInsert ?? entry.mEntryDisplay); + } + } public void InsertSelection(char32 keyChar, String insertType = null, String insertStr = null) { diff --git a/IDEHelper/Compiler/BfAst.cpp b/IDEHelper/Compiler/BfAst.cpp index 50a5027a..daefb8f7 100644 --- a/IDEHelper/Compiler/BfAst.cpp +++ b/IDEHelper/Compiler/BfAst.cpp @@ -301,6 +301,11 @@ void BfStructuralVisitor::Visit(BfTupleTypeRef* typeRef) Visit(typeRef->ToBase()); } +void BfStructuralVisitor::Visit(BfTagTypeRef* typeRef) +{ + Visit(typeRef->ToBase()); +} + void BfStructuralVisitor::Visit(BfDelegateTypeRef* typeRef) { Visit(typeRef->ToBase()); diff --git a/IDEHelper/Compiler/BfAst.h b/IDEHelper/Compiler/BfAst.h index 229f4119..eec1d0b0 100644 --- a/IDEHelper/Compiler/BfAst.h +++ b/IDEHelper/Compiler/BfAst.h @@ -389,6 +389,7 @@ class BfVarRefTypeReference; class BfLetTypeReference; class BfGenericInstanceTypeRef; class BfTupleTypeRef; +class BfTagTypeRef; class BfDelegateTypeRef; class BfExprModTypeRef; class BfCommentNode; @@ -561,6 +562,7 @@ public: virtual void Visit(BfArrayTypeRef* typeRef); virtual void Visit(BfGenericInstanceTypeRef* typeRef); virtual void Visit(BfTupleTypeRef* typeRef); + virtual void Visit(BfTagTypeRef* typeRef); virtual void Visit(BfDelegateTypeRef* typeRef); virtual void Visit(BfExprModTypeRef* declTypeRef); virtual void Visit(BfPointerTypeRef* typeRef); @@ -2667,6 +2669,15 @@ public: } }; BF_AST_DECL(BfTupleTypeRef, BfElementedTypeRef); +class BfTagTypeRef : public BfTypeReference +{ +public: + BF_AST_TYPE(BfTagTypeRef, BfTypeReference); + + BfIdentifierNode* mTagNode; + BfIdentifierNode* mNameNode; +}; BF_AST_DECL(BfTagTypeRef, BfTypeReference); + class BfDelegateTypeRef : public BfTypeReference { public: diff --git a/IDEHelper/Compiler/BfAutoComplete.cpp b/IDEHelper/Compiler/BfAutoComplete.cpp index 84fc5455..2c540670 100644 --- a/IDEHelper/Compiler/BfAutoComplete.cpp +++ b/IDEHelper/Compiler/BfAutoComplete.cpp @@ -797,12 +797,21 @@ void BfAutoComplete::AddField(BfTypeInstance* typeInst, BfFieldDef* fieldDef, Bf { mModule->PopulateType(typeInst); - String str; - str += mModule->TypeToString(fieldInstance->mResolvedType); - str += " "; - str += mModule->TypeToString(typeInst); - str += "."; - str += fieldDef->mName; + bool isTag = typeInst->IsEnum() && typeInst->IsOnDemand(); + + String str; + if (!isTag) + { + if (!fieldInstance->GetFieldDef()->IsEnumCaseEntry()) + { + str += mModule->TypeToString(fieldInstance->mResolvedType); + str += " "; + } + str += mModule->TypeToString(typeInst); + str += "."; + str += fieldDef->mName; + } + if (entryAdded->mDocumentation != NULL) { str += "\x04"; @@ -813,7 +822,9 @@ void BfAutoComplete::AddField(BfTypeInstance* typeInst, BfFieldDef* fieldDef, Bf str += "\x05"; documentation->GetDocString(str); } - entryAdded->mDocumentation = mAlloc.AllocString(str); + + if (!str.IsEmpty()) + entryAdded->mDocumentation = mAlloc.AllocString(str); } if ((mIsGetDefinition) && (mDefType == NULL)) @@ -1270,7 +1281,11 @@ void BfAutoComplete::AddEnumTypeMembers(BfTypeInstance* typeInst, const StringIm AutoCompleteEntry entry(hasPayload ? "payloadEnum" : "value", fieldDef->mName); if (auto entryAdded = AddEntry(entry, filter)) { - if (CheckDocumentation(entryAdded, fieldDef->GetFieldDeclaration()->mDocumentation)) + auto fieldDecl = fieldDef->GetFieldDeclaration(); + if (fieldDecl == NULL) + continue; + + if (CheckDocumentation(entryAdded, fieldDecl->mDocumentation)) { } @@ -1278,8 +1293,8 @@ void BfAutoComplete::AddEnumTypeMembers(BfTypeInstance* typeInst, const StringIm { mDefType = typeInst->mTypeDef; mDefField = fieldDef; - if (fieldDef->mFieldDeclaration != NULL) - SetDefinitionLocation(fieldDef->GetFieldDeclaration()->mNameNode); + if (fieldDecl != NULL) + SetDefinitionLocation(fieldDecl->mNameNode); } } } diff --git a/IDEHelper/Compiler/BfAutoComplete.h b/IDEHelper/Compiler/BfAutoComplete.h index adb40c3f..ff3c1fca 100644 --- a/IDEHelper/Compiler/BfAutoComplete.h +++ b/IDEHelper/Compiler/BfAutoComplete.h @@ -137,6 +137,8 @@ public: BfTypeInstance* mTypeInstance; BfTypeVector mGenericArguments; BfMethodInstance* mCurMethodInstance; + bool mIsMatch; + int mArgMatchCount; MethodMatchEntry() { @@ -144,6 +146,8 @@ public: mPayloadEnumField = NULL; mTypeInstance = NULL; mCurMethodInstance = NULL; + mIsMatch = false; + mArgMatchCount = false; } }; diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index 9281d354..5ab7cc2d 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -8608,7 +8608,9 @@ void BfCompiler::GenerateAutocompleteInfo() } } - autoCompleteResultString += "invoke\t" + methodText + "\n"; + autoCompleteResultString += "invoke\t" + methodText; + autoCompleteResultString += StrFormat("\t%d", methodEntry.mArgMatchCount); + autoCompleteResultString += "\n"; idx++; } diff --git a/IDEHelper/Compiler/BfElementVisitor.cpp b/IDEHelper/Compiler/BfElementVisitor.cpp index 05300009..8a18b5e5 100644 --- a/IDEHelper/Compiler/BfElementVisitor.cpp +++ b/IDEHelper/Compiler/BfElementVisitor.cpp @@ -447,6 +447,14 @@ void BfElementVisitor::Visit(BfTupleTypeRef* typeRef) VisitChild(typeRef->mCloseParen); } +void BfElementVisitor::Visit(BfTagTypeRef* typeRef) +{ + Visit(typeRef->ToBase()); + + VisitChild(typeRef->mTagNode); + VisitChild(typeRef->mNameNode); +} + void BfElementVisitor::Visit(BfExprModTypeRef* typeRef) { Visit(typeRef->ToBase()); diff --git a/IDEHelper/Compiler/BfElementVisitor.h b/IDEHelper/Compiler/BfElementVisitor.h index 9e16a604..948e260d 100644 --- a/IDEHelper/Compiler/BfElementVisitor.h +++ b/IDEHelper/Compiler/BfElementVisitor.h @@ -64,6 +64,7 @@ public: virtual void Visit(BfArrayTypeRef* typeRef); virtual void Visit(BfGenericInstanceTypeRef* typeRef); virtual void Visit(BfTupleTypeRef* typeRef); + virtual void Visit(BfTagTypeRef* typeRef); virtual void Visit(BfExprModTypeRef* typeRef); virtual void Visit(BfDelegateTypeRef* typeRef); virtual void Visit(BfPointerTypeRef* typeRef); diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 562e88ba..2de0f72c 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -1680,7 +1680,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst BP_ZONE("BfMethodMatcher::CheckMethod"); BackupMatchKind curMatchKind = BackupMatchKind_None; - bool hadMatch = false; + bool hadMatch = false; // Never consider overrides - they only get found at original method declaration // mBypassVirtual gets set when we are doing an explicit "base" call, or when we are a struct -- @@ -2599,12 +2599,16 @@ NoMatch: } Done: - if ((autoComplete != NULL) && (autoComplete->mIsCapturingMethodMatchInfo) && (genericArgumentsSubstitute != NULL)) + if ((autoComplete != NULL) && (autoComplete->mIsCapturingMethodMatchInfo)) { auto methodMatchInfo = autoComplete->mMethodMatchInfo; if (!methodMatchInfo->mInstanceList.IsEmpty()) - { - methodMatchInfo->mInstanceList[methodMatchInfo->mInstanceList.size() - 1].mGenericArguments = *genericArgumentsSubstitute; + { + auto& matchInstance = methodMatchInfo->mInstanceList[methodMatchInfo->mInstanceList.size() - 1]; + matchInstance.mArgMatchCount = argMatchCount; + matchInstance.mIsMatch = hadMatch; + if (genericArgumentsSubstitute != NULL) + matchInstance.mGenericArguments = *genericArgumentsSubstitute; } } @@ -5249,6 +5253,8 @@ BfTypedValue BfExprEvaluator::LoadField(BfAstNode* targetSrc, BfTypedValue targe BF_ASSERT(fieldInstance->mConstIdx != -1); auto foreignConst = typeInstance->mConstHolder->GetConstantById(fieldInstance->mConstIdx); + if (resolvedFieldType->IsValuelessType()) + return BfTypedValue(BfIRValue::sValueless, resolvedFieldType); auto retVal = mModule->ConstantToCurrent(foreignConst, typeInstance->mConstHolder, resolvedFieldType); return BfTypedValue(retVal, resolvedFieldType); } diff --git a/IDEHelper/Compiler/BfIRBuilder.cpp b/IDEHelper/Compiler/BfIRBuilder.cpp index 8d5dc23b..42b4bdd9 100644 --- a/IDEHelper/Compiler/BfIRBuilder.cpp +++ b/IDEHelper/Compiler/BfIRBuilder.cpp @@ -928,6 +928,10 @@ BfIRValue BfIRConstHolder::CreateConst(BfConstant* fromConst, BfIRConstHolder* f { return CreateConstArrayZero(fromConst->mInt32); } + else if (fromConst->mTypeCode == BfTypeCode_None) + { + return CreateConst(fromConst->mTypeCode, 0); + } else if ((IsInt(fromConst->mTypeCode)) || (fromConst->mTypeCode == BfTypeCode_Boolean) || (fromConst->mTypeCode == BfTypeCode_StringId)) { return CreateConst(fromConst->mTypeCode, fromConst->mUInt64); @@ -975,7 +979,7 @@ BfIRValue BfIRConstHolder::CreateConst(BfConstant* fromConst, BfIRConstHolder* f box->mTarget = copiedTarget.mId; box->mToType = fromBox->mToType; copiedConst = (BfConstant*)box; - } + } else { BF_FATAL("not handled"); @@ -3283,7 +3287,8 @@ void BfIRBuilder::CreateDbgTypeDefinition(BfType* type) if (fieldInstance->mConstIdx != -1) { constant = typeInstance->mConstHolder->GetConstantById(fieldInstance->mConstIdx); - staticValue = mModule->ConstantToCurrent(constant, typeInstance->mConstHolder, resolvedFieldType); + if (!resolvedFieldType->IsValuelessType()) + staticValue = mModule->ConstantToCurrent(constant, typeInstance->mConstHolder, resolvedFieldType); } if (fieldInstance->mResolvedType->IsComposite()) diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 4167f860..720e65e9 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -21841,10 +21841,10 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup, mBfIRBuilder->SaveDebugLocation(); mBfIRBuilder->ClearDebugLocation(); BfIRValue fromBool; - if (!mCurTypeInstance->IsTypedPrimitive()) + if ((!mCurTypeInstance->IsTypedPrimitive()) || (mCurTypeInstance->IsValuelessType())) { fromBool = GetDefaultValue(methodInstance->mReturnType); - } + } else { auto andResult = mBfIRBuilder->CreateAnd(mCurMethodState->mLocals[0]->mValue, mCurMethodState->mLocals[1]->mValue); @@ -21872,7 +21872,10 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup, mBfIRBuilder->ClearDebugLocation(); BfIRValue fromBool; mBfIRBuilder->RestoreDebugLocation(); - ret = mBfIRBuilder->CreateRet(GetThis().mValue); + if (!mCurTypeInstance->IsValuelessType()) + ret = mBfIRBuilder->CreateRet(GetThis().mValue); + else + mBfIRBuilder->CreateRetVoid(); //ExtendLocalLifetimes(0); EmitLifetimeEnds(&mCurMethodState->mHeadScope); diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 867a466d..098898c6 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -3600,7 +3600,9 @@ void BfModule::DoPopulateType_FinishEnum(BfTypeInstance* typeInstance, bool unde { BfTypeCode typeCode; - if ((min >= -0x80) && (max <= 0x7F)) + if ((min == 0) && (max == 0)) + typeCode = BfTypeCode_None; + else if ((min >= -0x80) && (max <= 0x7F)) typeCode = BfTypeCode_Int8; else if ((min >= 0) && (max <= 0xFF)) typeCode = BfTypeCode_UInt8; @@ -12232,6 +12234,19 @@ BfType* BfModule::ResolveTypeRef_Ref(BfTypeReference* typeRef, BfPopulateType po return ResolveTypeResult(typeRef, tupleType, populateType, resolveFlags); } + else if (auto tagTypeRef = BfNodeDynCast(typeRef)) + { + auto baseType = (BfTypeInstance*)ResolveTypeDef(mContext->mCompiler->mEnumTypeDef, BfPopulateType_Identity); + + BfTagType* tagType = new BfTagType(); + tagType->Init(baseType->mTypeDef->mProject, baseType, tagTypeRef->mNameNode->ToString()); + + resolvedEntry->mValue = tagType; + BF_ASSERT(BfResolvedTypeSet::Hash(tagType, &lookupCtx) == resolvedEntry->mHashCode); + populateModule->InitType(tagType, populateType); + + return ResolveTypeResult(typeRef, tagType, populateType, resolveFlags); + } else if (auto nullableTypeRef = BfNodeDynCast(typeRef)) { BfTypeReference* elementTypeRef = nullableTypeRef->mElementType; @@ -15781,6 +15796,13 @@ void BfModule::DoTypeToString(StringImpl& str, BfType* resolvedType, BfTypeNameF str += ")"; return; } + else if ((resolvedType->IsOnDemand()) && (resolvedType->IsEnum())) + { + auto typeInst = resolvedType->ToTypeInstance(); + str += "tag "; + str += typeInst->mTypeDef->mFields[0]->mName; + return; + } else if (resolvedType->IsDelegateFromTypeRef() || resolvedType->IsFunctionFromTypeRef()) { SetAndRestoreValue prevTypeInstance(mCurTypeInstance); diff --git a/IDEHelper/Compiler/BfPrinter.cpp b/IDEHelper/Compiler/BfPrinter.cpp index b2c81ae4..36c9bc60 100644 --- a/IDEHelper/Compiler/BfPrinter.cpp +++ b/IDEHelper/Compiler/BfPrinter.cpp @@ -1674,6 +1674,15 @@ void BfPrinter::Visit(BfTupleTypeRef* typeRef) VisitChild(typeRef->mCloseParen); } +void BfPrinter::Visit(BfTagTypeRef* typeRef) +{ + Visit((BfAstNode*)typeRef); + + VisitChild(typeRef->mTagNode); + ExpectSpace(); + VisitChild(typeRef->mNameNode); +} + void BfPrinter::Visit(BfDelegateTypeRef* typeRef) { Visit((BfAstNode*)typeRef); diff --git a/IDEHelper/Compiler/BfPrinter.h b/IDEHelper/Compiler/BfPrinter.h index e0a6dcd8..d37f9dc6 100644 --- a/IDEHelper/Compiler/BfPrinter.h +++ b/IDEHelper/Compiler/BfPrinter.h @@ -167,6 +167,7 @@ public: virtual void Visit(BfArrayTypeRef* typeRef) override; virtual void Visit(BfGenericInstanceTypeRef* typeRef) override; virtual void Visit(BfTupleTypeRef * typeRef) override; + virtual void Visit(BfTagTypeRef* typeRef) override; virtual void Visit(BfDelegateTypeRef* typeRef) override; virtual void Visit(BfPointerTypeRef* typeRef) override; virtual void Visit(BfNullableTypeRef* typeRef) override; diff --git a/IDEHelper/Compiler/BfReducer.cpp b/IDEHelper/Compiler/BfReducer.cpp index 26b2f4b2..73776fcb 100644 --- a/IDEHelper/Compiler/BfReducer.cpp +++ b/IDEHelper/Compiler/BfReducer.cpp @@ -937,7 +937,7 @@ bool BfReducer::IsTypeReference(BfAstNode* checkNode, BfToken successToken, int // Ignore } else if ((checkNode->IsA()) || (checkNode->IsA())) - { + { // Identifier is always allowed in tuple (parenDepth == 0), because it's potentially the field name // (successToken == BfToken_RParen) infers we are already checking inside parentheses, such as // when we see a potential cast expression @@ -954,8 +954,15 @@ bool BfReducer::IsTypeReference(BfAstNode* checkNode, BfToken successToken, int hadUnexpectedIdentifier = true; } - hadIdentifier = true; - identifierExpected = false; +// if (checkNode->Equals("tag")) +// { +// // Keep looking for tag name +// } +// else + { + hadIdentifier = true; + identifierExpected = false; + } } else if (checkNode->IsA()) { @@ -5195,6 +5202,19 @@ BfTypeReference* BfReducer::DoCreateTypeRef(BfAstNode* firstNode, CreateTypeRefF BfTypeReference* typeRef = BfNodeDynCast(firstNode); if (typeRef == NULL) { +// if (identifierNode->Equals("tag")) +// { +// auto rightIdentifer = ExpectIdentifierAfter(identifierNode); +// if (rightIdentifer != NULL) +// { +// auto tagTypeRef = mAlloc->Alloc(); +// ReplaceNode(identifierNode, tagTypeRef); +// tagTypeRef->mTagNode = identifierNode; +// MEMBER_SET(tagTypeRef, mNameNode, rightIdentifer); +// return tagTypeRef; +// } +// } + typeRef = DoCreateNamedTypeRef(identifierNode); } @@ -5250,7 +5270,7 @@ BfTypeReference* BfReducer::DoCreateTypeRef(BfAstNode* firstNode, CreateTypeRefF { auto rightIdentifer = ExpectIdentifierAfter(qualifiedTypeRef); if (rightIdentifer == NULL) - return qualifiedTypeRef; + return qualifiedTypeRef; auto namedTypeRef = mAlloc->Alloc(); namedTypeRef->mNameNode = rightIdentifer; @@ -7346,7 +7366,7 @@ BfAstNode* BfReducer::ReadTypeMember(BfAstNode* node, bool declStarted, int dept if (openToken == NULL) return indexerDeclaration; MEMBER_SET(indexerDeclaration, mOpenBracket, openToken); - auto endToken = ParseMethodParams(indexerDeclaration, ¶ms, &commas, BfToken_RBracket, true); + auto endToken = ParseMethodParams(indexerDeclaration, ¶ms, &commas, BfToken_RBracket, false); if (endToken == NULL) return indexerDeclaration; MEMBER_SET(indexerDeclaration, mCloseBracket, endToken); @@ -7780,7 +7800,7 @@ BfLambdaBindExpression* BfReducer::CreateLambdaBindExpression(BfAstNode* allocNo if (auto tokenNode = BfNodeDynCast(nextNode)) isRParen = tokenNode->GetToken() == BfToken_RParen; if (!isRParen) - { + { auto nameIdentifier = ExpectIdentifierAfter(lambdaBindExpr, "parameter name"); if (nameIdentifier == NULL) return lambdaBindExpr; @@ -10028,7 +10048,7 @@ bool BfReducer::ParseMethod(BfMethodDeclaration* methodDeclaration, SizedArrayIm } } - methodDeclaration->mCloseParen = ParseMethodParams(methodDeclaration, params, commas, BfToken_RParen, true); + methodDeclaration->mCloseParen = ParseMethodParams(methodDeclaration, params, commas, BfToken_RParen, false); // RParen if (methodDeclaration->mCloseParen == NULL) diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp index 783f6958..8181bef5 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp @@ -2987,6 +2987,79 @@ void BfTupleType::Finish() ////////////////////////////////////////////////////////////////////////// +BfTagType::BfTagType() +{ + mCreatedTypeDef = false; + mSource = NULL; + mTypeDef = NULL; +} + +BfTagType::~BfTagType() +{ + mMethodInstanceGroups.Clear(); + if (mCreatedTypeDef) + { + delete mTypeDef; + mTypeDef = NULL; + } + delete mSource; +} + +void BfTagType::Init(BfProject* bfProject, BfTypeInstance* valueTypeInstance, const StringImpl& name) +{ + auto srcTypeDef = valueTypeInstance->mTypeDef; + auto system = valueTypeInstance->mModule->mSystem; + + if (mTypeDef == NULL) + mTypeDef = new BfTypeDef(); + for (auto field : mTypeDef->mFields) + delete field; + mTypeDef->mFields.Clear(); + mTypeDef->mSystem = system; + mTypeDef->mProject = bfProject; + mTypeDef->mTypeCode = srcTypeDef->mTypeCode; + mTypeDef->mName = system->mEmptyAtom; + mTypeDef->mSystem = system; + + mTypeDef->mHash = srcTypeDef->mHash; + mTypeDef->mSignatureHash = srcTypeDef->mSignatureHash; + mTypeDef->mTypeCode = BfTypeCode_Enum; + + mCreatedTypeDef = true; + + auto field = BfDefBuilder::AddField(mTypeDef, NULL, name); + field->mIsStatic = true; + field->mIsConst = true; +} + +void BfTagType::Dispose() +{ + if (mCreatedTypeDef) + { + delete mTypeDef; + mTypeDef = NULL; + mCreatedTypeDef = false; + } + BfTypeInstance::Dispose(); +} + +void BfTagType::Finish() +{ + BF_ASSERT(!mTypeFailed); + + auto bfSystem = mTypeDef->mSystem; + mSource = new BfSource(bfSystem); + mTypeDef->mSource = mSource; + mTypeDef->mSource->mRefCount++; + + BfDefBuilder bfDefBuilder(bfSystem); + bfDefBuilder.mCurTypeDef = mTypeDef; + bfDefBuilder.mCurDeclaringTypeDef = mTypeDef; + bfDefBuilder.FinishTypeDef(true); +} + +////////////////////////////////////////////////////////////////////////// + BfBoxedType::~BfBoxedType() { //if ((mTypeDef != NULL) && (mTypeDef->mEmitParent != NULL)) @@ -3132,6 +3205,7 @@ BfResolvedTypeSet::~BfResolvedTypeSet() #define HASH_CONSTEXPR 12 #define HASH_GLOBAL 13 #define HASH_DOTDOTDOT 14 +#define HASH_TAG 15 BfVariant BfResolvedTypeSet::EvaluateToVariant(LookupContext* ctx, BfExpression* expr, BfType*& outType) { @@ -3234,6 +3308,13 @@ int BfResolvedTypeSet::DoHash(BfType* type, LookupContext* ctx, bool allowRef, i return hashVal; } + else if ((type->IsEnum()) && (type->IsOnDemand())) + { + BfTypeInstance* typeInstance = type->ToTypeInstance(); + auto fieldName = typeInstance->mTypeDef->mFields[0]->mName; + int nameHash = (int)Hash64(fieldName.c_str(), (int)fieldName.length()); + return nameHash ^ HASH_TAG; + } else if (type->IsTypeInstance()) { BfTypeInstance* typeInst = (BfTypeInstance*)type; @@ -4156,6 +4237,17 @@ int BfResolvedTypeSet::DoHash(BfTypeReference* typeRef, LookupContext* ctx, BfHa ctx->mFailed = true; return 0; } + else if (auto tagTypeRef = BfNodeDynCastExact(typeRef)) + { + int nameHash = 0; + if (tagTypeRef->mNameNode != NULL) + { + auto fieldName = tagTypeRef->mNameNode; + const char* nameStr = fieldName->GetSourceData()->mSrc + fieldName->GetSrcStart(); + nameHash = (int)Hash64(nameStr, fieldName->GetSrcLength()); + } + return nameHash ^ HASH_TAG; + } else { BF_FATAL("Not handled"); @@ -4839,6 +4931,15 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfTypeReference* rhs, LookupContext* return true; } + else if ((lhs->IsEnum()) && (lhs->IsOnDemand())) + { + BfTypeInstance* typeInstance = lhs->ToTypeInstance(); + auto fieldName = typeInstance->mTypeDef->mFields[0]->mName; + auto tagTypeRef = BfNodeDynCastExact(rhs); + if (tagTypeRef == NULL) + return false; + return tagTypeRef->mNameNode->Equals(fieldName); + } else if (lhs->IsTypeInstance()) { BfTypeInstance* lhsInst = (BfTypeInstance*) lhs; diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index 48f109da..ae9e8494 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -2401,6 +2401,24 @@ public: virtual int GetGenericDepth() override { return mGenericDepth; } }; +class BfTagType : public BfTypeInstance +{ +public: + bool mCreatedTypeDef; + String mNameAdd; + BfSource* mSource; + +public: + BfTagType(); + ~BfTagType(); + + void Init(BfProject* bfProject, BfTypeInstance* valueTypeInstance, const StringImpl& name); + virtual void Dispose() override; + void Finish(); + + virtual bool IsOnDemand() override { return true; } +}; + class BfConcreteInterfaceType : public BfType { public: diff --git a/IDEHelper/Compiler/BfSourceClassifier.cpp b/IDEHelper/Compiler/BfSourceClassifier.cpp index 388460ec..b407a1d5 100644 --- a/IDEHelper/Compiler/BfSourceClassifier.cpp +++ b/IDEHelper/Compiler/BfSourceClassifier.cpp @@ -329,6 +329,17 @@ void BfSourceClassifier::Visit(BfNamedTypeReference* typeRef) } } +void BfSourceClassifier::Visit(BfTagTypeRef* typeRef) +{ + Visit((BfAstNode*)typeRef); + + VisitChild(typeRef->mTagNode); + SetElementType(typeRef->mTagNode, BfSourceElementType_Keyword); + + VisitChild(typeRef->mNameNode); + SetElementType(typeRef->mNameNode, BfSourceElementType_Type); +} + void BfSourceClassifier::Visit(BfQualifiedTypeReference* qualifiedType) { Visit((BfAstNode*)qualifiedType); diff --git a/IDEHelper/Compiler/BfSourceClassifier.h b/IDEHelper/Compiler/BfSourceClassifier.h index 169ad52e..66f22eaa 100644 --- a/IDEHelper/Compiler/BfSourceClassifier.h +++ b/IDEHelper/Compiler/BfSourceClassifier.h @@ -113,6 +113,7 @@ public: virtual void Visit(BfArrayTypeRef* arrayType) override; virtual void Visit(BfPointerTypeRef* pointerType) override; virtual void Visit(BfNamedTypeReference* typeRef) override; + virtual void Visit(BfTagTypeRef* typeRef) override; virtual void Visit(BfGenericInstanceTypeRef* typeRef) override; virtual void Visit(BfLocalMethodDeclaration * methodDecl) override; virtual void Visit(BfLiteralExpression* literalExpr) override; diff --git a/IDEHelper/Compiler/BfSystem.cpp b/IDEHelper/Compiler/BfSystem.cpp index 61fd7933..1946d10f 100644 --- a/IDEHelper/Compiler/BfSystem.cpp +++ b/IDEHelper/Compiler/BfSystem.cpp @@ -427,6 +427,12 @@ void BfParameterDef::SetName(BfAstNode* nameNode) ////////////////////////////////////////////////////////////////////////// +bool BfFieldDef::IsEnumCaseEntry() +{ + return ((mFieldDeclaration != NULL) && (BfNodeIsA(mFieldDeclaration))) || + ((mFieldDeclaration == NULL) && (mIsConst) && (mDeclaringType->mTypeCode == BfTypeCode_Enum)); +} + bool BfPropertyDef::IsVirtual() { if (((BfPropertyDeclaration*)mFieldDeclaration)->mVirtualSpecifier) diff --git a/IDEHelper/Compiler/BfSystem.h b/IDEHelper/Compiler/BfSystem.h index 1e47e2df..d08c1b81 100644 --- a/IDEHelper/Compiler/BfSystem.h +++ b/IDEHelper/Compiler/BfSystem.h @@ -655,10 +655,7 @@ public: return (mName[0] >= '0') && (mName[0] <= '9'); } - bool IsEnumCaseEntry() - { - return (mFieldDeclaration != NULL) && (BfNodeIsA(mFieldDeclaration)); - } + bool IsEnumCaseEntry(); bool IsNonConstStatic() {