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:
parent
e5f92fb21b
commit
954f6312b8
3 changed files with 92 additions and 31 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue