From 954f6312b8545c2ab175263fee3f3c6e76f30178 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Mon, 2 Aug 2021 10:42:53 -0700 Subject: [PATCH] Changed mixin circular reference detection --- IDE/Tests/CompileFail001/src/Methods.bf | 29 +++++++++++ IDEHelper/Compiler/BfExprEvaluator.cpp | 64 +++++++++++++------------ IDEHelper/Tests/src/Mixins.bf | 30 ++++++++++++ 3 files changed, 92 insertions(+), 31 deletions(-) diff --git a/IDE/Tests/CompileFail001/src/Methods.bf b/IDE/Tests/CompileFail001/src/Methods.bf index 2794fa2b..51c2505d 100644 --- a/IDE/Tests/CompileFail001/src/Methods.bf +++ b/IDE/Tests/CompileFail001/src/Methods.bf @@ -1,4 +1,5 @@ using System; +using System.Collections; namespace IDETest { @@ -55,11 +56,39 @@ namespace IDETest } + public static mixin MixinA() + { + MixinA!(); //FAIL + } + + public static mixin MixinB(T val) where T : var + { + } + + public static mixin MixinB(T val) where T : List + { + MixinB!(val); + } + + public static mixin MixinC(T val) where T : var + { + } + + public static mixin MixinC(T val) where T : List + { + if (!val.IsEmpty) + MixinC!(val.Front); + } + public static void Test() { ClassB cb = scope .(); MethodA(cb, 123); //FAIL MethodB(cb, 234); //FAIL + + List> list = scope .(); + MixinB!(list); //FAIL + MixinC!(list); } } } diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 90cab4c0..67c8368f 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -15200,38 +15200,40 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo auto curMethodState = mModule->mCurMethodState; // - { - bool hasCircularRef = false; - auto checkMethodState = curMethodState; - while (checkMethodState != NULL) - { - auto curMixinState = checkMethodState->mMixinState; - while (curMixinState != NULL) - { - if (curMixinState->mSource == targetSrc) - hasCircularRef = true; - curMixinState = curMixinState->mPrevMixinState; - } - - if ((checkMethodState->mClosureState != NULL) && (checkMethodState->mClosureState->mActiveDeferredLocalMethod != NULL)) - { - for (auto& mixinRecord : checkMethodState->mClosureState->mActiveDeferredLocalMethod->mMixinStateRecords) - { - if (mixinRecord.mSource == targetSrc) - hasCircularRef = true; - } - } - - checkMethodState = checkMethodState->mPrevMethodState; - } - - if (hasCircularRef) - { - mModule->Fail("Circular reference detected between mixins", targetSrc); - return; - } - } + // Why was this required? It doesn't check for matching generic args (we only want to throw an error if we call back into a mixin with the same generic args as before) +// { +// bool hasCircularRef = false; +// +// auto checkMethodState = curMethodState; +// while (checkMethodState != NULL) +// { +// auto curMixinState = checkMethodState->mMixinState; +// while (curMixinState != NULL) +// { +// if (curMixinState->mSource == targetSrc) +// hasCircularRef = true; +// curMixinState = curMixinState->mPrevMixinState; +// } +// +// if ((checkMethodState->mClosureState != NULL) && (checkMethodState->mClosureState->mActiveDeferredLocalMethod != NULL)) +// { +// for (auto& mixinRecord : checkMethodState->mClosureState->mActiveDeferredLocalMethod->mMixinStateRecords) +// { +// if (mixinRecord.mSource == targetSrc) +// hasCircularRef = true; +// } +// } +// +// checkMethodState = checkMethodState->mPrevMethodState; +// } +// +// if (hasCircularRef) +// { +// mModule->Fail("Circular reference detected between mixins", targetSrc); +// return; +// } +// } auto moduleMethodInstance = GetSelectedMethod(targetSrc, methodMatcher.mBestMethodTypeInstance, methodMatcher.mBestMethodDef, methodMatcher); if (!moduleMethodInstance) diff --git a/IDEHelper/Tests/src/Mixins.bf b/IDEHelper/Tests/src/Mixins.bf index 288d74e9..b7078cf3 100644 --- a/IDEHelper/Tests/src/Mixins.bf +++ b/IDEHelper/Tests/src/Mixins.bf @@ -1,4 +1,5 @@ using System; +using System.Collections; namespace Tests { @@ -47,6 +48,31 @@ namespace Tests a = 234; } + public static mixin CircularMixin(T value) + where T : var + { + 10 + } + + public static mixin CircularMixin(Dictionary value) + where K : var, IHashable + where V : var + { + + int total = 0; + if (value == null) + total += 1; + else + { + for (let (k, v) in ref value) + { + total += CircularMixin!(k); + total += CircularMixin!(*v); + } + } + total + 100 + } + [Test] public static void TestBasics() { @@ -73,6 +99,10 @@ namespace Tests CheckStr(sv.ToScopeCStr!()); }; func("Test"); + + Dictionary> test = scope .() {(1,null)}; + int val = CircularMixin!(test); + Test.Assert(val == 211); } [Test]