/src/script/index.ts
import gs from '../gamestate';
import { Label } from './label';
import * as nearley from 'nearley';
import parserGrammar from './parser';
export enum InstructionStatus {
OK,
Finish,
Goto,
}
export interface InstructionResult {
status: InstructionStatus
label?: string
}
export type InstructionPromise = Promise<InstructionResult>
export const InstructionPromise = Promise;
export interface ScriptInstruction {
execute(): InstructionPromise
}
// TODO: integrate this into script execution state?
export async function executeInstructions(l: ScriptInstruction[]): InstructionPromise {
for (const i of l) {
const r = await i.execute();
if (r.status != InstructionStatus.OK) {
return r;
}
}
return { status: InstructionStatus.OK }
}
export class Script {
instructions: ScriptInstruction[]
labels: Map<string, number>
pc: number
constructor(text?: string) {
if (text) {
this.parse(text);
} else {
this.reset();
}
}
reset() {
this.instructions = [];
this.labels = new Map();
this.pc = 0;
}
parse(text: string) {
this.reset();
// parse script source (TODO: keep parsed script objects?)
const parser = new nearley.Parser(nearley.Grammar.fromCompiled(parserGrammar));
parser.feed(text);
// Feed in an extra space because our grammar requires whitespace at the end of a statement
parser.feed(' ');
const instructions = parser.results[0]
// scan for labels
for (let i = 0; i < instructions.length; i++) {
const instr = instructions[i];
if (instr instanceof Label) {
this.labels.set(instr.name, i);
instructions.splice(i, 1);
i--;
}
}
this.instructions = instructions;
}
step(): InstructionPromise {
let r = this.instructions[this.pc].execute();
this.pc++;
return r;
}
async execute() {
this.pc = 0;
while (this.pc < this.instructions.length) {
const r = await this.step();
if (r.status == InstructionStatus.Finish) {
break;
} else if (r.status == InstructionStatus.Goto) {
if (this.labels.has(r.label)) {
this.pc = this.labels.get(r.label);
} else {
throw new Error('Invalid label: ' + r.label);
}
}
}
}
dump() {
console.log(this.instructions);
}
}