Add breakpoints and ack-based comms to worker

This commit is contained in:
Nilay Majorwar
2021-12-15 15:19:44 +05:30
parent c9afb3a68b
commit 29b243d6f2
5 changed files with 87 additions and 32 deletions

View File

@ -12,6 +12,7 @@ type ExecuteAllArgs<RS> = {
class ExecutionController<RS> {
private _engine: LanguageEngine<RS>;
private _breakpoints: number[] = [];
private _result: StepExecutionResult<RS> | null;
/**
@ -42,12 +43,20 @@ class ExecutionController<RS> {
this._engine.prepare(code, input);
}
/**
* Update debugging breakpoints
* @param points Array of line numbers having breakpoints
*/
updateBreakpoints(points: number[]) {
this._breakpoints = points;
}
async executeAll({ interval, onResult }: ExecuteAllArgs<RS>) {
while (true) {
this._result = this._engine.executeStep();
onResult && onResult(this._result);
if (!this._result.nextStepLocation) break;
if (interval) await this.sleep(interval);
await this.sleep(interval || 0);
}
return this._result;
}

View File

@ -1,5 +1,6 @@
import { StepExecutionResult } from "./types";
/** Types of requests the worker handles */
export type WorkerRequestData =
| {
type: "Init";
@ -13,11 +14,19 @@ export type WorkerRequestData =
type: "Prepare";
params: { code: string; input: string };
}
| {
type: "UpdateBreakpoints";
params: { points: number[] };
}
| {
type: "Execute";
params: { interval?: number };
};
/** Kinds of acknowledgement responses the worker can send */
export type WorkerAckType = "init" | "reset" | "bp-update" | "prepare";
/** Types of responses the worker can send */
export type WorkerResponseData<RS> =
| { type: "state"; data: "empty" | "ready" }
| { type: "ack"; data: WorkerAckType }
| { type: "result"; data: StepExecutionResult<RS> };

View File

@ -1,16 +1,17 @@
import BrainfuckLanguageEngine from "./brainfuck/engine";
import ExecutionController from "./execution-controller";
import SampleLanguageEngine from "./sample-lang/engine";
import { StepExecutionResult } from "./types";
import { WorkerRequestData, WorkerResponseData } from "./worker-constants";
import {
WorkerAckType,
WorkerRequestData,
WorkerResponseData,
} from "./worker-constants";
let _controller: ExecutionController<any> | null = null;
/** Create a worker response for state update */
const stateMessage = <RS>(
state: "empty" | "ready"
): WorkerResponseData<RS> => ({
type: "state",
/** Create a worker response for update acknowledgement */
const ackMessage = <RS>(state: WorkerAckType): WorkerResponseData<RS> => ({
type: "ack",
data: state,
});
@ -26,10 +27,9 @@ const resultMessage = <RS>(
* Initialize the execution controller.
*/
const initController = () => {
// const engine = new SampleLanguageEngine();
const engine = new BrainfuckLanguageEngine();
_controller = new ExecutionController(engine);
postMessage(stateMessage("empty"));
postMessage(ackMessage("init"));
};
/**
@ -38,7 +38,7 @@ const initController = () => {
*/
const resetController = () => {
_controller!.resetState();
postMessage(stateMessage("empty"));
postMessage(ackMessage("reset"));
};
/**
@ -47,7 +47,16 @@ const resetController = () => {
*/
const prepare = ({ code, input }: { code: string; input: string }) => {
_controller!.prepare(code, input);
postMessage(stateMessage("ready"));
postMessage(ackMessage("prepare"));
};
/**
* Update debugging breakpoints
* @param points List of line numbers having breakpoints
*/
const updateBreakpoints = (points: number[]) => {
_controller!.updateBreakpoints(points);
postMessage(ackMessage("bp-update"));
};
/**
@ -67,5 +76,7 @@ addEventListener("message", (ev: MessageEvent<WorkerRequestData>) => {
if (ev.data.type === "Reset") return resetController();
if (ev.data.type === "Prepare") return prepare(ev.data.params);
if (ev.data.type === "Execute") return execute(ev.data.params.interval);
if (ev.data.type === "UpdateBreakpoints")
return updateBreakpoints(ev.data.params.points);
throw new Error("Invalid worker message type");
});