From 170f5c496054c9c5c2df9b8a1c5c8df7643ea004 Mon Sep 17 00:00:00 2001 From: Elizabeth Hunt Date: Sat, 21 Feb 2026 12:29:54 -0800 Subject: work --- .../grid/system/LambdaEvaluatorSystemTest.java | 43 +++++++++++++++++----- .../coffee/liz/lambda/format/ValueEmitterTest.java | 34 ++++++++++++----- 2 files changed, 57 insertions(+), 20 deletions(-) (limited to 'core/src/test') diff --git a/core/src/test/java/coffee/liz/abstractionengine/grid/system/LambdaEvaluatorSystemTest.java b/core/src/test/java/coffee/liz/abstractionengine/grid/system/LambdaEvaluatorSystemTest.java index 6829417..b70f669 100644 --- a/core/src/test/java/coffee/liz/abstractionengine/grid/system/LambdaEvaluatorSystemTest.java +++ b/core/src/test/java/coffee/liz/abstractionengine/grid/system/LambdaEvaluatorSystemTest.java @@ -15,6 +15,7 @@ import coffee.liz.lambda.ast.SourceCode; import org.junit.jupiter.api.Test; import java.time.Duration; +import java.util.List; import java.util.Map; import java.util.Set; @@ -23,7 +24,7 @@ import static org.junit.jupiter.api.Assertions.assertInstanceOf; public class LambdaEvaluatorSystemTest { private static final Vec2 GRID_DIMENSIONS = Vec2i.builder().x(3).y(3).build(); - private static final SourceCode IDENTITY = SourceCode.ofArrow("(x -> x)(y)"); + private static final SourceCode IDENTITY_FUNCTION = SourceCode.ofArrow("x -> x"); private static final SourceCode FREE = SourceCode.ofArrow("z"); @Test @@ -31,8 +32,8 @@ public class LambdaEvaluatorSystemTest { final World world = new DAGWorld<>(new GridIndexSystem(GRID_DIMENSIONS), new LambdaEvaluatorSystem(SourceCode.Syntax.ARROW)); - world.createEntity().add(new GridPosition(Vec2i.builder().x(1).y(1).build())).add(new LambdaTerm(IDENTITY)) - .add(new Substitution(Vec2i.EAST, Map.of("y", Vec2i.builder().x(0).y(0).build()))); + world.createEntity().add(new GridPosition(Vec2i.builder().x(1).y(1).build())).add(new LambdaTerm(IDENTITY_FUNCTION)) + .add(new Substitution(Vec2i.EAST, List.of(Vec2i.builder().x(0).y(0).build()))); world.createEntity().add(new GridPosition(Vec2i.builder().x(0).y(0).build())).add(new LambdaTerm(FREE)); world.update(GridInputState.builder().build(), Duration.ZERO); @@ -50,8 +51,8 @@ public class LambdaEvaluatorSystemTest { final World world = new DAGWorld<>(new GridIndexSystem(GRID_DIMENSIONS), new LambdaEvaluatorSystem(SourceCode.Syntax.LAMBDA)); - world.createEntity().add(new GridPosition(Vec2i.builder().x(1).y(1).build())).add(new LambdaTerm(IDENTITY)) - .add(new Substitution(Vec2i.EAST, Map.of("y", Vec2i.builder().x(0).y(0).build()))); + world.createEntity().add(new GridPosition(Vec2i.builder().x(1).y(1).build())).add(new LambdaTerm(IDENTITY_FUNCTION)) + .add(new Substitution(Vec2i.EAST, List.of(Vec2i.builder().x(0).y(0).build()))); world.createEntity().add(new GridPosition(Vec2i.builder().x(0).y(0).build())).add(new LambdaTerm(FREE)); world.update(GridInputState.builder().build(), Duration.ZERO); @@ -68,8 +69,8 @@ public class LambdaEvaluatorSystemTest { final World world = new DAGWorld<>(new GridIndexSystem(GRID_DIMENSIONS), new LambdaEvaluatorSystem(SourceCode.Syntax.ARROW)); - world.createEntity().add(new GridPosition(Vec2i.builder().x(1).y(1).build())).add(new LambdaTerm(IDENTITY)) - .add(new Substitution(Vec2i.EAST, Map.of("y", Vec2i.builder().x(0).y(0).build()))); + world.createEntity().add(new GridPosition(Vec2i.builder().x(1).y(1).build())).add(new LambdaTerm(IDENTITY_FUNCTION)) + .add(new Substitution(Vec2i.EAST, List.of(Vec2i.builder().x(0).y(0).build()))); world.update(GridInputState.builder().build(), Duration.ZERO); @@ -79,12 +80,12 @@ public class LambdaEvaluatorSystemTest { @Test public void testSpawnsInSubstitutionDirection() { - final Vec2 spawnMomentum = Vec2i.builder().x(0).y(-1).build(); + final Vec2 spawnMomentum = Vec2i.SOUTH; final World world = new DAGWorld<>(new GridIndexSystem(GRID_DIMENSIONS), new LambdaEvaluatorSystem(SourceCode.Syntax.ARROW)); - world.createEntity().add(new GridPosition(Vec2i.builder().x(1).y(1).build())).add(new LambdaTerm(IDENTITY)) - .add(new Substitution(spawnMomentum, Map.of("y", Vec2i.builder().x(0).y(0).build()))); + world.createEntity().add(new GridPosition(Vec2i.builder().x(1).y(1).build())).add(new LambdaTerm(IDENTITY_FUNCTION)) + .add(new Substitution(spawnMomentum, List.of(Vec2i.builder().x(0).y(0).build()))); world.createEntity().add(new GridPosition(Vec2i.builder().x(0).y(0).build())).add(new LambdaTerm(FREE)); world.update(GridInputState.builder().build(), Duration.ZERO); @@ -94,4 +95,26 @@ public class LambdaEvaluatorSystemTest { final GridMomentum momentum = emittedTerms.iterator().next().get(GridMomentum.class); assertEquals(new GridMomentum(spawnMomentum), momentum); } + + @Test + public void testDependenciesAppliedInNumericOrder() { + final Vec2 firstDependencyPos = Vec2i.builder().x(0).y(0).build(); + final Vec2 secondDependencyPos = Vec2i.builder().x(2).y(0).build(); + final World world = new DAGWorld<>(new GridIndexSystem(GRID_DIMENSIONS), + new LambdaEvaluatorSystem(SourceCode.Syntax.ARROW)); + + world.createEntity().add(new GridPosition(Vec2i.builder().x(1).y(1).build())) + .add(new LambdaTerm(SourceCode.ofArrow("f -> g -> f"))) + .add(new Substitution(Vec2i.EAST, List.of(firstDependencyPos, secondDependencyPos))); + world.createEntity().add(new GridPosition(firstDependencyPos)).add(new LambdaTerm(SourceCode.ofArrow("one"))); + world.createEntity().add(new GridPosition(secondDependencyPos)).add(new LambdaTerm(SourceCode.ofArrow("two"))); + + world.update(GridInputState.builder().build(), Duration.ZERO); + + final Set emittedTerms = world.resolve(Query.allOf(GridMomentum.class, LambdaTerm.class)); + assertEquals(1, emittedTerms.size()); + final SourceCode emitted = emittedTerms.iterator().next().get(LambdaTerm.class).getTerm(); + final SourceCode.Arrow arrow = assertInstanceOf(SourceCode.Arrow.class, emitted); + assertEquals("one", arrow.source()); + } } diff --git a/core/src/test/java/coffee/liz/lambda/format/ValueEmitterTest.java b/core/src/test/java/coffee/liz/lambda/format/ValueEmitterTest.java index c1ab704..959f45d 100644 --- a/core/src/test/java/coffee/liz/lambda/format/ValueEmitterTest.java +++ b/core/src/test/java/coffee/liz/lambda/format/ValueEmitterTest.java @@ -12,7 +12,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; class ValueEmitterTest { @Test - void emitsFreeInBothSyntaxes() { + public void testEmitsFreeInBothSyntaxes() { final Value value = LambdaDriver.interpret(SourceCode.ofArrow("z")); final SourceCode arrow = ValueEmitter.emit(value, SourceCode.Syntax.ARROW); @@ -23,7 +23,7 @@ class ValueEmitterTest { } @Test - void emitsApplicationInBothSyntaxes() { + public void testEmitsApplicationInBothSyntaxes() { final Value value = LambdaDriver.interpret(SourceCode.ofArrow("f(x)")); final SourceCode arrow = ValueEmitter.emit(value, SourceCode.Syntax.ARROW); @@ -34,27 +34,41 @@ class ValueEmitterTest { } @Test - void emitsClosureWithCaptureMacros() { + public void testEmitsClosureWithCaptureMacros() { final Value value = LambdaDriver.interpret(SourceCode.ofArrow("(x -> y -> x)(z)")); final SourceCode emitted = ValueEmitter.emit(value, SourceCode.Syntax.ARROW); final String source = assertInstanceOf(SourceCode.Arrow.class, emitted).source(); - assertTrue(source.contains("let _cap")); - assertTrue(source.contains("y -> _cap")); + assertEquals(""" + let x = z; + + y -> x""", source); - // Validate emitted program is parsable and evaluates. final Value roundTrip = LambdaDriver.interpret(emitted); assertInstanceOf(Value.Closure.class, roundTrip); } @Test - void emitsHygienicCapturesWhenNamesShadow() { + public void testEmitsHygienicCapturesWhenNamesShadow() { final Value value = LambdaDriver.interpret(SourceCode.ofArrow("(x -> y -> x)(y)")); final SourceCode emitted = ValueEmitter.emit(value, SourceCode.Syntax.ARROW); final String source = assertInstanceOf(SourceCode.Arrow.class, emitted).source(); - assertTrue(source.contains("let _cap")); - assertTrue(source.contains("y -> _cap")); - assertFalse(source.contains("let y =")); + assertEquals(""" + let x = y; + + y -> x""", source); + } + + @Test + public void testPrunesUnusedEnvironmentCaptures() { + final Value value = LambdaDriver.interpret(SourceCode.ofArrow("(x -> w -> y -> x)(z)(q)")); + final SourceCode emitted = ValueEmitter.emit(value, SourceCode.Syntax.ARROW); + final String source = assertInstanceOf(SourceCode.Arrow.class, emitted).source(); + + assertEquals(""" + let x = z; + + y -> x""", source); } } -- cgit v1.3