diff options
Diffstat (limited to 'src/engine/entities/FunctionApplication.ts')
-rw-r--r-- | src/engine/entities/FunctionApplication.ts | 108 |
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(); - } } |