From 6e57cd4ebe6db3b9537e958a9d358bae148a9fe1 Mon Sep 17 00:00:00 2001 From: Jamiras Date: Sat, 13 Dec 2025 15:41:51 -0700 Subject: [PATCH] ensure 'this' gets captured for lambda expressions --- .../ClassMemberReferenceExpression.cs | 9 ++---- .../ClassDefinitionExpressionTests.cs | 18 ++++++++++-- .../ClassMemberReferenceExpressionTests.cs | 28 +++++++++++++++++++ 3 files changed, 47 insertions(+), 8 deletions(-) diff --git a/Source/Parser/Expressions/ClassMemberReferenceExpression.cs b/Source/Parser/Expressions/ClassMemberReferenceExpression.cs index 0c9be692..284f2482 100644 --- a/Source/Parser/Expressions/ClassMemberReferenceExpression.cs +++ b/Source/Parser/Expressions/ClassMemberReferenceExpression.cs @@ -224,12 +224,9 @@ void INestedExpressions.GetDependencies(HashSet dependencies) if (nested != null) nested.GetDependencies(dependencies); - if (Variable != null && Variable.Name != "this") - { - nested = Variable as INestedExpressions; - if (nested != null) - nested.GetDependencies(dependencies); - } + nested = Variable as INestedExpressions; + if (nested != null) + nested.GetDependencies(dependencies); // we can't know the type of the source object, so just // declare dependance on all fields matching the provided name diff --git a/Tests/Parser/Expressions/ClassDefinitionExpressionTests.cs b/Tests/Parser/Expressions/ClassDefinitionExpressionTests.cs index 7368f53a..0866fb72 100644 --- a/Tests/Parser/Expressions/ClassDefinitionExpressionTests.cs +++ b/Tests/Parser/Expressions/ClassDefinitionExpressionTests.cs @@ -78,6 +78,18 @@ public void TestParseFunction() Assert.That(expr.ToString(), Is.EqualTo("class Entity(1 field, 1 function)")); } + [Test] + public void TestParseLambdaReference() + { + var expr = Parse( + "class Entity {\n" + + " addr = 4\n" + + " function hp() => sum_of(range(0, 5), (i) => i < this.addr)\n" + + "}"); + Assert.That(expr.Name.Name, Is.EqualTo("Entity")); + Assert.That(expr.ToString(), Is.EqualTo("class Entity(1 field, 1 function)")); + } + [Test] public void TestParseErrorInsideField() { @@ -263,8 +275,9 @@ public void TestGetDependencies() var dependencies = new HashSet(); ((INestedExpressions)expr).GetDependencies(dependencies); - Assert.That(dependencies.Count, Is.EqualTo(3)); + Assert.That(dependencies.Count, Is.EqualTo(4)); Assert.That(dependencies.Contains("word")); + Assert.That(dependencies.Contains("this")); Assert.That(dependencies.Contains(".addr")); Assert.That(dependencies.Contains("global_var")); } @@ -281,8 +294,9 @@ public void TestGetDependenciesNested() var dependencies = new HashSet(); ((INestedExpressions)expr).GetDependencies(dependencies); - Assert.That(dependencies.Count, Is.EqualTo(5)); + Assert.That(dependencies.Count, Is.EqualTo(6)); Assert.That(dependencies.Contains("word")); + Assert.That(dependencies.Contains("this")); Assert.That(dependencies.Contains(".addr")); Assert.That(dependencies.Contains(".x")); Assert.That(dependencies.Contains("global")); diff --git a/Tests/Parser/Expressions/ClassMemberReferenceExpressionTests.cs b/Tests/Parser/Expressions/ClassMemberReferenceExpressionTests.cs index 8a3a01e0..1c685292 100644 --- a/Tests/Parser/Expressions/ClassMemberReferenceExpressionTests.cs +++ b/Tests/Parser/Expressions/ClassMemberReferenceExpressionTests.cs @@ -410,5 +410,33 @@ public void TestReadFromNestedIndexNonArray() var error = assign.Execute(scope); ExpressionTests.AssertError(error, "Cannot index integer: this.points"); } + + [Test] + public void TestLambdaReference() + { + var entityClass = ExpressionTests.Parse( + "class Entity {\n" + + " addr = 2\n" + + " function multiplyBy6() => sum_of(range(0, 5), (i) => this.addr)\n" + + "}"); + + var scope = new InterpreterScope(AchievementScriptInterpreter.GetGlobalScope()); + scope.Context = new AchievementScriptContext(); + entityClass.Execute(scope); + + var constructor = new FunctionCallExpression("Entity", new ExpressionBase[] { new IntegerConstantExpression(4) }); + var entity = constructor.Evaluate(scope); + Assert.That(entity, Is.InstanceOf()); + + scope.AssignVariable(new VariableExpression("e"), entity); + + var assign = Parse("n = e.multiplyBy6()"); + var error = assign.Execute(scope); + Assert.That(error, Is.Null); + + var n = scope.GetVariable("n"); + Assert.That(n, Is.InstanceOf()); + Assert.That(((IntegerConstantExpression)n).Value, Is.EqualTo(24)); // 4+4+4+4+4+4 + } } }