summaryrefslogtreecommitdiff
path: root/src/engine/entities
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/entities')
-rw-r--r--src/engine/entities/FunctionApplication.ts120
1 files changed, 95 insertions, 25 deletions
diff --git a/src/engine/entities/FunctionApplication.ts b/src/engine/entities/FunctionApplication.ts
index 4d5729f..f4201de 100644
--- a/src/engine/entities/FunctionApplication.ts
+++ b/src/engine/entities/FunctionApplication.ts
@@ -24,8 +24,9 @@ import { Game } from "..";
import { Grid as GridSystem, SystemNames } from "../systems";
import { colors, tryWrap } from "../utils";
import {
- InvalidLambdaTermError,
+ DebrujinIndex,
SymbolTable,
+ Visitors,
emitNamed,
interpret,
} from "../../interpreter";
@@ -41,16 +42,9 @@ const APPLICATION_RESULTS: Record<
export class FunctionApplication extends Entity {
private static spriteSpec = SPRITE_SPECS.get(Sprites.BUBBLE) as SpriteSpec;
- private symbolTable: SymbolTable;
-
constructor(gridPosition: Coord2D, lambdaTerm: string) {
super(EntityNames.FunctionApplication);
- this.symbolTable = new SymbolTable();
- Object.keys(APPLICATION_RESULTS).forEach((key) => {
- this.symbolTable.add(key);
- });
-
const dimension = {
width: FunctionApplication.spriteSpec.width,
height: FunctionApplication.spriteSpec.height,
@@ -151,7 +145,10 @@ export class FunctionApplication extends Entity {
);
const newCode = applicationTerm.code.replace("_INPUT", functionTerm.code);
- const result = tryWrap(() => interpret(newCode, this.symbolTable, true));
+ const { symbolTable, visitors } = this.getVisitors(game);
+ const result = tryWrap(() =>
+ interpret(newCode, symbolTable, true, visitors),
+ );
applicationTerm.last = result;
if (result.error || !result.data) {
console.error(result.error);
@@ -166,13 +163,6 @@ export class FunctionApplication extends Entity {
let applicationResultingEntity: Entity | null = null; // this should be its own function
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);
@@ -187,20 +177,100 @@ export class FunctionApplication extends Entity {
}
game.removeEntity(entity.id);
- if (applicationResultingEntity) {
- const grid = applicationResultingEntity.getComponent<Grid>(
+ if (!applicationResultingEntity) {
+ return;
+ }
+
+ applicationResultingEntity.getComponent<Grid>(
+ ComponentNames.Grid,
+ ).movingDirection = entityGrid.previousDirection;
+ game.addEntity(applicationResultingEntity);
+ }
+
+ private getVisitors(game: Game): {
+ visitors: Visitors;
+ symbolTable: SymbolTable;
+ } {
+ const directionKeywords = {
+ _LEFT: Direction.LEFT,
+ _RIGHT: Direction.RIGHT,
+ _DOWN: Direction.DOWN,
+ _UP: Direction.UP,
+ };
+ const entityKeywords = {
+ _KEY: (pos: Coord2D) => new Key(pos),
+ };
+
+ const visitors: Visitors = new Map();
+ visitors.set("_SPAWN", (_term) => {
+ const position = this.getComponent<Grid>(
ComponentNames.Grid,
- );
- grid.movingDirection = entityGrid.previousDirection;
- applicationResultingEntity.addComponent(grid);
+ ).gridPosition;
+ return {
+ abstraction: {
+ param: "_DIRECTION",
+ body: (direction) => {
+ const destinationDirection =
+ directionKeywords[
+ (direction as DebrujinIndex)
+ .name! as keyof typeof directionKeywords
+ ];
+ const destination = game
+ .getSystem<GridSystem>(SystemNames.Grid)
+ .getNewGridPosition(position, destinationDirection);
+ return {
+ abstraction: {
+ param: "_ENTITY",
+ body: (entityType) => {
+ const entityFactory =
+ entityKeywords[
+ (entityType as DebrujinIndex)
+ .name! as keyof typeof entityKeywords
+ ];
+ const newEntity = entityFactory(destination);
+ game.addEntity(newEntity);
+ return {
+ abstraction: {
+ param: "_x",
+ body: (_t) => {
+ return {
+ application: {
+ left: {
+ index: 1,
+ name: "_SPAWN",
+ },
+ args: [direction, entityType],
+ },
+ };
+ },
+ },
+ };
+ },
+ },
+ };
+ },
+ },
+ };
+ });
- game.addEntity(applicationResultingEntity);
- }
+ return {
+ visitors,
+ symbolTable: SymbolTable.from(
+ Array.from(visitors.keys())
+ .concat(Object.keys(APPLICATION_RESULTS))
+ .concat(Object.keys(directionKeywords))
+ .concat(Object.keys(entityKeywords))
+ .concat(["_x"]),
+ ),
+ };
+ }
- SOUNDS.get(LambdaTransformSound.name)!.play();
+ private addParticles(game: Game, position: Coord2D) {
+ const gridSystem = game.getSystem<GridSystem>(SystemNames.Grid);
const { dimension } = gridSystem;
+ SOUNDS.get(LambdaTransformSound.name)!.play();
const particles = new Particles({
- center: gridSystem.gridToScreenPosition(nextPosition),
+ center: gridSystem.gridToScreenPosition(position),
spawnerDimensions: {
width: dimension.width / 2,
height: dimension.height / 2,