Add automatic syntax checker, fix editor bugs
This commit is contained in:
@ -28,6 +28,10 @@ export default class BrainfuckLanguageEngine implements LanguageEngine<BFRS> {
|
||||
this._pc = DEFAULT_PC;
|
||||
}
|
||||
|
||||
validateCode(code: string) {
|
||||
this.parseCode(code);
|
||||
}
|
||||
|
||||
prepare(code: string, input: string) {
|
||||
this._input = input;
|
||||
this._ast = this.parseCode(code);
|
||||
|
@ -36,6 +36,10 @@ export default class ChefLanguageEngine implements LanguageEngine<T.ChefRS> {
|
||||
this._input = DEFAULT_INPUT();
|
||||
}
|
||||
|
||||
validateCode(code: string) {
|
||||
parseProgram(code);
|
||||
}
|
||||
|
||||
prepare(code: string, input: string) {
|
||||
this._ast = parseProgram(code);
|
||||
this._input = new InputStream(input);
|
||||
|
@ -21,6 +21,10 @@ export default class DeadfishLanguageEngine implements LanguageEngine<DFRS> {
|
||||
this._pc = DEFAULT_PC;
|
||||
}
|
||||
|
||||
validateCode(code: string) {
|
||||
this.parseCode(code);
|
||||
}
|
||||
|
||||
prepare(code: string, _input: string) {
|
||||
this._ast = this.parseCode(code);
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
import { LanguageEngine, StepExecutionResult } from "./types";
|
||||
import {
|
||||
isParseError,
|
||||
isRuntimeError,
|
||||
serializeParseError,
|
||||
serializeRuntimeError,
|
||||
WorkerRuntimeError,
|
||||
} from "./worker-errors";
|
||||
@ -58,6 +60,19 @@ class ExecutionController<RS> {
|
||||
this._breakpoints = points;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the syntax of the given code
|
||||
* @param code Code content, lines separated by '\n'
|
||||
*/
|
||||
validateCode(code: string) {
|
||||
try {
|
||||
this._engine.validateCode(code);
|
||||
} catch (error) {
|
||||
if (isParseError(error)) return serializeParseError(error);
|
||||
else throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pause the ongoing execution.
|
||||
* - If already paused, returns immediately
|
||||
|
@ -13,6 +13,11 @@ const ackMessage = <RS, A extends C.WorkerAckType>(
|
||||
error,
|
||||
});
|
||||
|
||||
/** Create a worker response for code validation result */
|
||||
const validationMessage = <RS, A extends C.WorkerAckType>(
|
||||
error?: E.WorkerParseError
|
||||
): C.WorkerResponseData<RS, A> => ({ type: "validate", error });
|
||||
|
||||
/** Create a worker response for execution result */
|
||||
const resultMessage = <RS, A extends C.WorkerAckType>(
|
||||
result: StepExecutionResult<RS>,
|
||||
@ -72,6 +77,15 @@ const updateBreakpoints = <RS>(
|
||||
postMessage(ackMessage("bp-update"));
|
||||
};
|
||||
|
||||
/** Validate the user's program syntax */
|
||||
const validateCode = <RS>(
|
||||
controller: ExecutionController<RS>,
|
||||
code: string
|
||||
) => {
|
||||
const error = controller.validateCode(code);
|
||||
postMessage(validationMessage(error));
|
||||
};
|
||||
|
||||
/**
|
||||
* Execute the entire program loaded on engine,
|
||||
* and return result of execution.
|
||||
@ -112,6 +126,8 @@ export const setupWorker = <RS>(engine: LanguageEngine<RS>) => {
|
||||
if (ev.data.type === "Reset") return resetController(controller);
|
||||
if (ev.data.type === "Prepare")
|
||||
return prepare(controller, ev.data.params);
|
||||
if (ev.data.type === "ValidateCode")
|
||||
return validateCode(controller, ev.data.params.code);
|
||||
if (ev.data.type === "Execute")
|
||||
return execute(controller, ev.data.params.interval);
|
||||
if (ev.data.type === "Pause") return await pauseExecution(controller);
|
||||
|
@ -45,6 +45,9 @@ export type StepExecutionResult<RS> = {
|
||||
* execution and debugging API to the platform.
|
||||
*/
|
||||
export interface LanguageEngine<RS> {
|
||||
/** Validate the syntax of the given code. Throw ParseError if any */
|
||||
validateCode: (code: string) => void;
|
||||
|
||||
/** Load code and user input into the engine and prepare for execution */
|
||||
prepare: (code: string, input: string) => void;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { DocumentRange, StepExecutionResult } from "./types";
|
||||
import { StepExecutionResult } from "./types";
|
||||
import * as E from "./worker-errors";
|
||||
|
||||
/** Types of requests the worker handles */
|
||||
@ -19,6 +19,10 @@ export type WorkerRequestData =
|
||||
type: "UpdateBreakpoints";
|
||||
params: { points: number[] };
|
||||
}
|
||||
| {
|
||||
type: "ValidateCode";
|
||||
params: { code: string };
|
||||
}
|
||||
| {
|
||||
type: "Execute";
|
||||
params: { interval: number };
|
||||
@ -57,6 +61,11 @@ export type WorkerResponseData<RS, A extends WorkerAckType> =
|
||||
data: A;
|
||||
error?: WorkerAckError[A];
|
||||
}
|
||||
/** Result of code validation, containing parsing error (if any) */
|
||||
| {
|
||||
type: "validate";
|
||||
error?: E.WorkerParseError;
|
||||
}
|
||||
/** Response containing step execution result, and runtime error (if any) */
|
||||
| {
|
||||
type: "result";
|
||||
|
Reference in New Issue
Block a user