aboutsummaryrefslogtreecommitdiff
path: root/core/src/main/java/coffee/liz/abstractionengine/grid
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/main/java/coffee/liz/abstractionengine/grid')
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/grid/component/Substitution.java19
-rw-r--r--core/src/main/java/coffee/liz/abstractionengine/grid/system/LambdaEvaluatorSystem.java52
2 files changed, 44 insertions, 27 deletions
diff --git a/core/src/main/java/coffee/liz/abstractionengine/grid/component/Substitution.java b/core/src/main/java/coffee/liz/abstractionengine/grid/component/Substitution.java
index 77ff4e8..9f58ff2 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/grid/component/Substitution.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/grid/component/Substitution.java
@@ -2,14 +2,29 @@ package coffee.liz.abstractionengine.grid.component;
import coffee.liz.ecs.math.Vec2;
import coffee.liz.ecs.model.Component;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
import lombok.Data;
import lombok.RequiredArgsConstructor;
-import java.util.Map;
+import java.util.List;
@RequiredArgsConstructor
+@AllArgsConstructor
@Data
+@Builder(toBuilder = true)
public class Substitution implements Component {
+ /**
+ * Produced terms spawn with this momentum.
+ */
private final Vec2<Integer> spawnMomentum;
- private final Map<String, Vec2<Integer>> termDependencies;
+
+ /**
+ * Left-to-right dependencies' grid positions to apply in order.
+ * i.e. [(0, 0), (0, 1)] would apply lambda term at (0, 0) then (0, 1) to a -> b -> a => (0, 0)
+ */
+ private final List<Vec2<Integer>> termDependencies;
+
+ @Builder.Default
+ private boolean isActive = true;
}
diff --git a/core/src/main/java/coffee/liz/abstractionengine/grid/system/LambdaEvaluatorSystem.java b/core/src/main/java/coffee/liz/abstractionengine/grid/system/LambdaEvaluatorSystem.java
index 74bc3fc..f93d60b 100644
--- a/core/src/main/java/coffee/liz/abstractionengine/grid/system/LambdaEvaluatorSystem.java
+++ b/core/src/main/java/coffee/liz/abstractionengine/grid/system/LambdaEvaluatorSystem.java
@@ -8,12 +8,16 @@ import coffee.liz.abstractionengine.grid.component.GridPosition;
import coffee.liz.abstractionengine.grid.component.LambdaTerm;
import coffee.liz.abstractionengine.grid.component.Substitution;
import coffee.liz.ecs.math.Vec2;
+import coffee.liz.ecs.model.Entity;
import coffee.liz.ecs.model.System;
import coffee.liz.ecs.model.World;
import coffee.liz.ecs.model.Query;
import coffee.liz.lambda.LambdaDriver;
+import coffee.liz.lambda.ast.LambdaProgram;
import coffee.liz.lambda.ast.SourceCode;
import coffee.liz.lambda.eval.Environment;
+import coffee.liz.lambda.eval.NormalOrderEvaluator;
+import coffee.liz.lambda.eval.Thunk;
import coffee.liz.lambda.eval.Value;
import coffee.liz.lambda.format.ValueEmitter;
import lombok.extern.log4j.Log4j2;
@@ -21,10 +25,7 @@ import lombok.extern.log4j.Log4j2;
import java.time.Duration;
import java.util.Collection;
import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.function.Supplier;
-import java.util.stream.Collectors;
+import java.util.Objects;
@Log4j2
public class LambdaEvaluatorSystem implements System<GridInputState> {
@@ -45,38 +46,39 @@ public class LambdaEvaluatorSystem implements System<GridInputState> {
world.resolve(Query.allOf(Substitution.class, LambdaTerm.class, GridPosition.class)).forEach(entity -> {
final LambdaTerm term = entity.get(LambdaTerm.class);
- final Substitution substitution = entity.get(Substitution.class);
final GridPosition position = entity.get(GridPosition.class);
+ final Substitution substitution = entity.get(Substitution.class);
- final Map<String, Supplier<Value>> dependencies = substitution.getTermDependencies().entrySet().stream()
- .map(e -> {
- final String symbol = e.getKey();
- // Ideally we should only ever have one match to replace the symbol with.
- // But maybe there's a use-case where this is not the case?
- final Optional<SourceCode> sourceCode = gridIndexSystem.entitiesAt(e.getValue()).stream()
- .filter(_entity -> _entity.has(LambdaTerm.class))
- .map(_entity -> _entity.get(LambdaTerm.class)).map(LambdaTerm::getTerm).findFirst();
- // TODO: Map error
- final Optional<Supplier<Value>> val = sourceCode.map(s -> () -> LambdaDriver.interpret(s));
- return Map.entry(symbol, val);
- }).filter(e -> e.getValue().isPresent())
- .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().get()));
+ final List<Entity> resolvedDependencies = substitution.getTermDependencies().stream()
+ .map(dependencyPos -> gridIndexSystem.entitiesAt(dependencyPos).stream()
+ .filter(_entity -> _entity.has(LambdaTerm.class))
+ .findFirst()
+ .orElse(null))
+ .toList();
- final boolean dependenciesSatisified = dependencies.keySet()
- .equals(substitution.getTermDependencies().keySet());
+ final boolean dependenciesSatisified = resolvedDependencies.stream().allMatch(Objects::nonNull);
if (!dependenciesSatisified) {
+ entity.add(substitution.toBuilder().isActive(true).build());
return;
}
- final Environment env = dependencies.entrySet().stream().reduce(Environment.root(),
- (_env, e) -> _env.extend(e.getKey(), e.getValue()), (a, b) -> b);
- final Value evaluationResult = LambdaDriver.interpret(term.getTerm(), List.of(), env);
- final SourceCode emittedResult = ValueEmitter.emit(evaluationResult, preferredSyntax);
+ if (!substitution.isActive()) {
+ return;
+ }
+
+ Value result = LambdaDriver.interpret(term.getTerm());
+ for (final Entity dependency : resolvedDependencies) {
+ result = new Value.Application(result, LambdaDriver.interpret(dependency.get(LambdaTerm.class).getTerm()));
+ }
+
+ final SourceCode emittedResult = ValueEmitter.emit(LambdaDriver.interpret(ValueEmitter.emit(result, preferredSyntax)), preferredSyntax);
final Vec2<Integer> spawnMomentum = substitution.getSpawnMomentum();
- EntityFactory.Abstraction.addToWorld(world, position.getPosition(), new LambdaTerm(emittedResult))
+ final Entity producedTerm = EntityFactory.Abstraction.addToWorld(world, position.getPosition(), new LambdaTerm(emittedResult))
.add(EntityType.ABSTRACTION).add(new GridPosition(position.getPosition()))
.add(new GridMomentum(spawnMomentum));
+ entity.add(substitution.toBuilder().isActive(false).build());
+ log.info("Entity {} produced {}", entity, producedTerm);
});
}
}