aboutsummaryrefslogtreecommitdiff
path: root/core/src/test/java/coffee/liz/lambda
diff options
context:
space:
mode:
authorElizabeth Hunt <me@liz.coffee>2026-02-15 10:08:30 -0800
committerElizabeth Hunt <me@liz.coffee>2026-02-15 10:12:08 -0800
commitd6a294e14604aecd9046cbc19dc1837ca694fbb0 (patch)
tree616e87e59f9ee95253acce05aa26405523a9acd7 /core/src/test/java/coffee/liz/lambda
parent347564c592325007cb81dbdf1a07831c2ae003c3 (diff)
downloadthe-abstraction-engine-java-d6a294e14604aecd9046cbc19dc1837ca694fbb0.tar.gz
the-abstraction-engine-java-d6a294e14604aecd9046cbc19dc1837ca694fbb0.zip
feat: Adding ValueEmitter, LambdaEvaluatorSystem
Diffstat (limited to 'core/src/test/java/coffee/liz/lambda')
-rw-r--r--core/src/test/java/coffee/liz/lambda/format/ValueEmitterTest.java60
1 files changed, 60 insertions, 0 deletions
diff --git a/core/src/test/java/coffee/liz/lambda/format/ValueEmitterTest.java b/core/src/test/java/coffee/liz/lambda/format/ValueEmitterTest.java
new file mode 100644
index 0000000..c1ab704
--- /dev/null
+++ b/core/src/test/java/coffee/liz/lambda/format/ValueEmitterTest.java
@@ -0,0 +1,60 @@
+package coffee.liz.lambda.format;
+
+import coffee.liz.lambda.LambdaDriver;
+import coffee.liz.lambda.ast.SourceCode;
+import coffee.liz.lambda.eval.Value;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class ValueEmitterTest {
+ @Test
+ void emitsFreeInBothSyntaxes() {
+ final Value value = LambdaDriver.interpret(SourceCode.ofArrow("z"));
+
+ final SourceCode arrow = ValueEmitter.emit(value, SourceCode.Syntax.ARROW);
+ final SourceCode lambda = ValueEmitter.emit(value, SourceCode.Syntax.LAMBDA);
+
+ assertEquals("z", assertInstanceOf(SourceCode.Arrow.class, arrow).source());
+ assertEquals("z", assertInstanceOf(SourceCode.Lambda.class, lambda).source());
+ }
+
+ @Test
+ void emitsApplicationInBothSyntaxes() {
+ final Value value = LambdaDriver.interpret(SourceCode.ofArrow("f(x)"));
+
+ final SourceCode arrow = ValueEmitter.emit(value, SourceCode.Syntax.ARROW);
+ final SourceCode lambda = ValueEmitter.emit(value, SourceCode.Syntax.LAMBDA);
+
+ assertEquals("f(x)", assertInstanceOf(SourceCode.Arrow.class, arrow).source());
+ assertEquals("f x", assertInstanceOf(SourceCode.Lambda.class, lambda).source());
+ }
+
+ @Test
+ void emitsClosureWithCaptureMacros() {
+ 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"));
+
+ // Validate emitted program is parsable and evaluates.
+ final Value roundTrip = LambdaDriver.interpret(emitted);
+ assertInstanceOf(Value.Closure.class, roundTrip);
+ }
+
+ @Test
+ void emitsHygienicCapturesWhenNamesShadow() {
+ 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 ="));
+ }
+}