-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathJBasic.ts
More file actions
executable file
·68 lines (58 loc) · 2.58 KB
/
Copy pathJBasic.ts
File metadata and controls
executable file
·68 lines (58 loc) · 2.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import Workspace from './Workspace';
import Parser from './language/Parser';
import Interpreter, { InterpreterIO, ConsoleIO, TestIO } from './runtime/Interpreter';
import Debugger from './runtime/Debugger';
import RunResult from './RunResult';
import ScriptError from './ScriptError';
export { InterpreterIO, ConsoleIO, TestIO, RunResult, ScriptError, Debugger };
export type { DebugState, DebugVariable, DebugArray, DebugFrame, DebugEvent, DebugEventCallback, BreakpointInfo, QBValue } from './runtime/Debugger';
export { StepMode } from './runtime/Debugger';
export default class JBasic {
private io: InterpreterIO;
private dbg: Debugger | undefined;
private virtualFiles: Map<string, string> = new Map();
private currentInterpreter: Interpreter | null = null;
constructor(io?: InterpreterIO, dbg?: Debugger) {
this.io = io ?? new ConsoleIO();
this.dbg = dbg;
}
/** Signal the running interpreter to stop at the next yield point. */
cancel(): void {
this.currentInterpreter?.cancel();
}
setVirtualFile(name: string, content: string): void {
this.virtualFiles.set(name, content);
}
getVirtualFile(name: string): string | undefined {
return this.virtualFiles.get(name);
}
async execute(workspace: Workspace): Promise<RunResult> {
if (!workspace.entryPoint) {
return RunResult.fail(ScriptError.runtime('No entry point specified in workspace'));
}
const source = workspace.getFile(workspace.entryPoint);
if (!source) {
return RunResult.fail(ScriptError.runtime(`File not found: ${workspace.entryPoint}`));
}
return this.run(source);
}
async run(source: string): Promise<RunResult> {
try {
const parser = new Parser(source);
const module = parser.parse();
const interpreter = new Interpreter(this.io, this.dbg);
this.currentInterpreter = interpreter;
// Load virtual files into interpreter
for (const [name, content] of this.virtualFiles) {
interpreter.setVirtualFile(name, content);
}
await interpreter.execute(module);
// Sync virtual filesystem back (replace entirely to reflect deletions)
this.virtualFiles = new Map(interpreter.getVirtualFiles());
this.currentInterpreter = null;
return RunResult.success();
} catch (err: unknown) {
return RunResult.fail(ScriptError.fromError(err));
}
}
}