summaryrefslogtreecommitdiff
path: root/src/engine/entities/FunctionApplication.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/entities/FunctionApplication.ts')
-rw-r--r--src/engine/entities/FunctionApplication.ts108
1 files changed, 69 insertions, 39 deletions
diff --git a/src/engine/entities/FunctionApplication.ts b/src/engine/entities/FunctionApplication.ts
index a266941..f15fcb9 100644
--- a/src/engine/entities/FunctionApplication.ts
+++ b/src/engine/entities/FunctionApplication.ts
@@ -1,17 +1,13 @@
-import {
- Entity,
- EntityNames,
- FunctionBox,
- Key,
- Particles,
- makeLambdaTermHighlightComponent,
-} from ".";
+import { Entity, EntityNames, FunctionBox, Key, Particles } from ".";
import {
BoundingBox,
Colliding,
ComponentNames,
Grid,
+ Highlight,
+ Interactable,
LambdaTerm,
+ Modal,
Sprite,
} from "../components";
import {
@@ -26,9 +22,9 @@ import {
import { Coord2D, Direction } from "../interfaces";
import { Game } from "..";
import { Grid as GridSystem, SystemNames } from "../systems";
-import { colors } from "../utils";
+import { colors, tryWrap } from "../utils";
import {
- DebrujinifiedLambdaTerm,
+ InvalidLambdaTermError,
SymbolTable,
emitNamed,
interpret,
@@ -62,8 +58,8 @@ export class FunctionApplication extends Entity {
y: 0,
},
dimension,
- 0,
- ),
+ 0
+ )
);
this.addComponent(new Grid(gridPosition));
@@ -76,13 +72,48 @@ export class FunctionApplication extends Entity {
{ x: 0, y: 0 },
dimension,
FunctionApplication.spriteSpec.msPerFrame,
- FunctionApplication.spriteSpec.frames,
- ),
+ FunctionApplication.spriteSpec.frames
+ )
);
this.addComponent(new Colliding(this.handleCollision.bind(this)));
- this.addComponent(makeLambdaTermHighlightComponent(this));
+ this.addComponent(
+ new Highlight(this.onHighlight.bind(this), this.onUnhighlight.bind(this))
+ );
+ }
+
+ private onHighlight(_direction: Direction) {
+ this.addComponent(new Interactable(this.interaction.bind(this)));
+ }
+
+ private interaction() {
+ const codeConsumer = (_code: string) => {
+ this.removeComponent(ComponentNames.Modal);
+ return { consumed: true };
+ };
+ const { last, code } = this.getComponent<LambdaTerm>(
+ ComponentNames.LambdaTerm
+ );
+ this.addComponent(
+ new Modal({
+ type: "CODE_EDITOR",
+ codeInit: {
+ code,
+ codeConsumer,
+ readonly: true,
+ result: {
+ error: last?.error && `Error: ${last.error.message}`,
+ data: last?.data && `Last Result: ${emitNamed(last.data)}`,
+ },
+ },
+ })
+ );
+ }
+
+ private onUnhighlight() {
+ this.removeComponent(ComponentNames.Modal);
+ this.removeComponent(ComponentNames.Interactable);
}
public handleCollision(game: Game, entity: Entity) {
@@ -100,7 +131,7 @@ export class FunctionApplication extends Entity {
const gridSystem = game.getSystem<GridSystem>(SystemNames.Grid);
const fail = () => {
entityGrid.movingDirection = gridSystem.oppositeDirection(
- entityGrid.previousDirection,
+ entityGrid.previousDirection
);
entity.addComponent(entityGrid);
@@ -109,18 +140,17 @@ export class FunctionApplication extends Entity {
};
const applicationTerm = this.getComponent<LambdaTerm>(
- ComponentNames.LambdaTerm,
+ ComponentNames.LambdaTerm
);
const functionTerm = entity.getComponent<LambdaTerm>(
- ComponentNames.LambdaTerm,
+ ComponentNames.LambdaTerm
);
const newCode = applicationTerm.code.replace("_INPUT", functionTerm.code);
- let result: DebrujinifiedLambdaTerm | null = null;
- try {
- result = interpret(newCode, this.symbolTable, true);
- } catch (e) {
- console.error(e);
+ const result = tryWrap(() => interpret(newCode, this.symbolTable, true));
+ applicationTerm.last = result;
+ if (result.error || !result.data) {
+ console.error(result.error);
fail();
return;
}
@@ -128,29 +158,34 @@ export class FunctionApplication extends Entity {
const { dimension } = gridSystem;
const nextPosition = gridSystem.getNewGridPosition(
grid.gridPosition,
- entityGrid.previousDirection,
+ entityGrid.previousDirection
);
let applicationResultingEntity: Entity | null = null; // this should be its own function
- if ("abstraction" in result) {
- const code = emitNamed(result);
-
+ const { data } = result;
+ if ("application" in data) {
+ // if we get an application that means we didn't interpret correctly.
+ // this should "not" happen and should be fatal.
+ throw new InvalidLambdaTermError(
+ "produced term should not be an application"
+ );
+ }
+ if ("abstraction" in data) {
+ const code = emitNamed(data);
applicationResultingEntity = new FunctionBox(grid.gridPosition, code);
- } else if ("name" in result) {
- const { name } = result;
+ }
+ if ("name" in data) {
+ const { name } = data;
const entityFactory = APPLICATION_RESULTS[name];
if (entityFactory) {
game.addEntity(entityFactory(nextPosition));
}
- } else {
- fail();
- return;
}
game.removeEntity(entity.id);
if (applicationResultingEntity) {
const grid = applicationResultingEntity.getComponent<Grid>(
- ComponentNames.Grid,
+ ComponentNames.Grid
);
grid.movingDirection = entityGrid.previousDirection;
applicationResultingEntity.addComponent(grid);
@@ -158,7 +193,7 @@ export class FunctionApplication extends Entity {
game.addEntity(applicationResultingEntity);
}
- this.playTransformSound();
+ SOUNDS.get(LambdaTransformSound.name)!.play();
const particles = new Particles({
center: gridSystem.gridToScreenPosition(nextPosition),
spawnerDimensions: {
@@ -183,9 +218,4 @@ export class FunctionApplication extends Entity {
});
game.addEntity(particles);
}
-
- private playTransformSound() {
- const audio = SOUNDS.get(LambdaTransformSound.name)!;
- audio.play();
- }
}