1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 11:38:21 +02:00

Changed mixin circular reference detection

This commit is contained in:
Brian Fiete 2021-08-02 10:42:53 -07:00
parent e5f92fb21b
commit 954f6312b8
3 changed files with 92 additions and 31 deletions

View file

@ -1,4 +1,5 @@
using System; using System;
using System.Collections;
namespace IDETest namespace IDETest
{ {
@ -55,11 +56,39 @@ namespace IDETest
} }
public static mixin MixinA()
{
MixinA!(); //FAIL
}
public static mixin MixinB<T>(T val) where T : var
{
}
public static mixin MixinB<T, T2>(T val) where T : List<T2>
{
MixinB!(val);
}
public static mixin MixinC<T>(T val) where T : var
{
}
public static mixin MixinC<T, T2>(T val) where T : List<T2>
{
if (!val.IsEmpty)
MixinC!(val.Front);
}
public static void Test() public static void Test()
{ {
ClassB cb = scope .(); ClassB cb = scope .();
MethodA(cb, 123); //FAIL MethodA(cb, 123); //FAIL
MethodB(cb, 234); //FAIL MethodB(cb, 234); //FAIL
List<List<int>> list = scope .();
MixinB!(list); //FAIL
MixinC!(list);
} }
} }
} }

View file

@ -15200,38 +15200,40 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo
auto curMethodState = mModule->mCurMethodState; auto curMethodState = mModule->mCurMethodState;
// //
{
bool hasCircularRef = false;
auto checkMethodState = curMethodState; // 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)
while (checkMethodState != NULL) // {
{ // bool hasCircularRef = false;
auto curMixinState = checkMethodState->mMixinState; //
while (curMixinState != NULL) // auto checkMethodState = curMethodState;
{ // while (checkMethodState != NULL)
if (curMixinState->mSource == targetSrc) // {
hasCircularRef = true; // auto curMixinState = checkMethodState->mMixinState;
curMixinState = curMixinState->mPrevMixinState; // while (curMixinState != NULL)
} // {
// if (curMixinState->mSource == targetSrc)
if ((checkMethodState->mClosureState != NULL) && (checkMethodState->mClosureState->mActiveDeferredLocalMethod != NULL)) // hasCircularRef = true;
{ // curMixinState = curMixinState->mPrevMixinState;
for (auto& mixinRecord : checkMethodState->mClosureState->mActiveDeferredLocalMethod->mMixinStateRecords) // }
{ //
if (mixinRecord.mSource == targetSrc) // if ((checkMethodState->mClosureState != NULL) && (checkMethodState->mClosureState->mActiveDeferredLocalMethod != NULL))
hasCircularRef = true; // {
} // for (auto& mixinRecord : checkMethodState->mClosureState->mActiveDeferredLocalMethod->mMixinStateRecords)
} // {
// if (mixinRecord.mSource == targetSrc)
checkMethodState = checkMethodState->mPrevMethodState; // hasCircularRef = true;
} // }
// }
if (hasCircularRef) //
{ // checkMethodState = checkMethodState->mPrevMethodState;
mModule->Fail("Circular reference detected between mixins", targetSrc); // }
return; //
} // if (hasCircularRef)
} // {
// mModule->Fail("Circular reference detected between mixins", targetSrc);
// return;
// }
// }
auto moduleMethodInstance = GetSelectedMethod(targetSrc, methodMatcher.mBestMethodTypeInstance, methodMatcher.mBestMethodDef, methodMatcher); auto moduleMethodInstance = GetSelectedMethod(targetSrc, methodMatcher.mBestMethodTypeInstance, methodMatcher.mBestMethodDef, methodMatcher);
if (!moduleMethodInstance) if (!moduleMethodInstance)

View file

@ -1,4 +1,5 @@
using System; using System;
using System.Collections;
namespace Tests namespace Tests
{ {
@ -47,6 +48,31 @@ namespace Tests
a = 234; a = 234;
} }
public static mixin CircularMixin<T>(T value)
where T : var
{
10
}
public static mixin CircularMixin<K, V>(Dictionary<K, V> 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] [Test]
public static void TestBasics() public static void TestBasics()
{ {
@ -73,6 +99,10 @@ namespace Tests
CheckStr(sv.ToScopeCStr!()); CheckStr(sv.ToScopeCStr!());
}; };
func("Test"); func("Test");
Dictionary<int, Dictionary<int, int>> test = scope .() {(1,null)};
int val = CircularMixin!(test);
Test.Assert(val == 211);
} }
[Test] [Test]