export class Runtime { private runtimeProcess?: Deno.ChildProcess; constructor(private port: number) {} async checkRuntimeRev() { const currentRev = new TextDecoder().decode( await new Deno.Command("git", { args: ["rev-parse", "HEAD"] }) .output() .then((output) => output.stdout), ).trim(); const runtimeRev = (await Deno.readTextFile("../runtime/build/rev")) .trim(); if (runtimeRev !== currentRev) { console.error( "runtime out-of-date; run 'make' inside runtime/ folder", ); Deno.exit(1); } } async start() { await this.checkRuntimeRev(); this.runtimeProcess = new Deno.Command("../runtime/build/sliger", { args: [], stdout: "piped", }).spawn(); } stop() { this.runtimeProcess?.kill(); this.runtimeProcess = undefined; } async connect(): Promise { // return await new Promise((resolve) => { // setTimeout(async () => { // resolve( // new RuntimeConnection( // await Deno.connect({ // port: this.port, // }), // ), // ); // }, 100); // }); return new RuntimeConnection( await Deno.connect({ port: this.port, }), ); } } export class RuntimeConnection { constructor(private connection: Deno.Conn) {} async write(text: string): Promise { const req = new TextEncoder().encode(text); await this.connection.write(req); } async send(value: T): Promise { await this.write(JSON.stringify(value)); } async read(): Promise { let result = ""; while (true) { const buf = new Uint8Array(256); const readRes = await this.connection.read(buf); if (readRes != null) { result += new TextDecoder().decode(buf.slice(0, readRes)); } else { break; } } return result; } async receive(): Promise { return JSON.parse(await this.read()) as T; } close() { this.connection.close(); } }