mirror of
https://git.sfja.dk/Mikkel/slige.git
synced 2025-01-18 10:36:31 +00:00
web, runtime, compiler, connections
This commit is contained in:
parent
7806b64783
commit
af8ce1d47a
14
compiler/mod.ts
Normal file
14
compiler/mod.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { Stmt } from "./ast.ts";
|
||||
import { Lexer } from "./Lexer.ts";
|
||||
import { Parser } from "./Parser.ts";
|
||||
|
||||
export * from "./Parser.ts";
|
||||
export * from "./ast.ts";
|
||||
export * from "./arch.ts";
|
||||
export * from "./Lexer.ts";
|
||||
export * from "./Token.ts";
|
||||
|
||||
export async function compileWithDebug(filepath: string): Promise<Stmt[]> {
|
||||
const text = await Deno.readTextFile(filepath);
|
||||
return new Parser(new Lexer(text)).parseStmts();
|
||||
}
|
@ -6,6 +6,7 @@
|
||||
"jsr:@std/assert@1": "1.0.8",
|
||||
"jsr:@std/bytes@1": "1.0.4",
|
||||
"jsr:@std/bytes@^1.0.2": "1.0.4",
|
||||
"jsr:@std/cli@*": "1.0.6",
|
||||
"jsr:@std/crypto@1": "1.0.3",
|
||||
"jsr:@std/encoding@1": "1.0.5",
|
||||
"jsr:@std/encoding@^1.0.5": "1.0.5",
|
||||
@ -48,6 +49,9 @@
|
||||
"@std/bytes@1.0.4": {
|
||||
"integrity": "11a0debe522707c95c7b7ef89b478c13fb1583a7cfb9a85674cd2cc2e3a28abc"
|
||||
},
|
||||
"@std/cli@1.0.6": {
|
||||
"integrity": "d22d8b38c66c666d7ad1f2a66c5b122da1704f985d3c47f01129f05abb6c5d3d"
|
||||
},
|
||||
"@std/crypto@1.0.3": {
|
||||
"integrity": "a2a32f51ddef632d299e3879cd027c630dcd4d1d9a5285d6e6788072f4e51e7f"
|
||||
},
|
||||
|
105
web/main.ts
105
web/main.ts
@ -1,13 +1,110 @@
|
||||
import { Application, Router } from "jsr:@oak/oak";
|
||||
import { parseArgs } from "jsr:@std/cli/parse-args";
|
||||
import { Runtime } from "./runtime.ts";
|
||||
import * as compiler from "../compiler/mod.ts";
|
||||
|
||||
const port = 8000;
|
||||
|
||||
const app = new Application();
|
||||
const flags = parseArgs(Deno.args, {
|
||||
boolean: ["flame-graph", "code-coverage"],
|
||||
});
|
||||
|
||||
if (flags._.length !== 1) {
|
||||
throw new Error("please specify a filename");
|
||||
}
|
||||
|
||||
const filepath = flags._[0] as string;
|
||||
const text = await Deno.readTextFile(filepath);
|
||||
|
||||
const runtime = new Runtime(13370);
|
||||
|
||||
async function compileProgram(filepath: string) {
|
||||
const result = await compiler.compileWithDebug(filepath);
|
||||
}
|
||||
|
||||
async function runProgramWithDebug(program: string) {
|
||||
const connection = await runtime.connect();
|
||||
connection.send({
|
||||
type: "run-debug",
|
||||
program,
|
||||
});
|
||||
const res = await connection.receive<{
|
||||
ok: boolean;
|
||||
}>();
|
||||
connection.close();
|
||||
if (!res.ok) {
|
||||
throw new Error("could not run code");
|
||||
}
|
||||
}
|
||||
|
||||
const router = new Router();
|
||||
|
||||
router.get("/api/source", (ctx) => {
|
||||
ctx.response.body = { ok: true, filepath, text };
|
||||
ctx.response.status = 200;
|
||||
ctx.respond = true;
|
||||
});
|
||||
|
||||
router.get("/api/status", async (ctx) => {
|
||||
const connection = await runtime.connect();
|
||||
connection.send({ type: "status" });
|
||||
const res = await connection.receive<{
|
||||
ok: boolean;
|
||||
status: "running" | "done";
|
||||
}>();
|
||||
connection.close();
|
||||
if (!res.ok) {
|
||||
ctx.response.body = { ok: false };
|
||||
ctx.response.status = 500;
|
||||
ctx.respond = true;
|
||||
return;
|
||||
}
|
||||
ctx.response.body = { ok: true, status: res.status };
|
||||
ctx.response.status = 200;
|
||||
ctx.respond = true;
|
||||
});
|
||||
|
||||
router.get("/api/flame-graph", async (ctx) => {
|
||||
const connection = await runtime.connect();
|
||||
connection.send({ type: "flame-graph" });
|
||||
const res = await connection.receive<{
|
||||
ok: boolean;
|
||||
flameGraph: string;
|
||||
}>();
|
||||
connection.close();
|
||||
if (!res.ok) {
|
||||
ctx.response.body = { ok: false };
|
||||
ctx.response.status = 500;
|
||||
ctx.respond = true;
|
||||
return;
|
||||
}
|
||||
ctx.response.body = { ok: true, flameGraph: res.flameGraph };
|
||||
ctx.response.status = 200;
|
||||
ctx.respond = true;
|
||||
});
|
||||
|
||||
router.get("/api/code-coverage", async (ctx) => {
|
||||
const connection = await runtime.connect();
|
||||
connection.send({ type: "code-coverage" });
|
||||
const res = await connection.receive<{
|
||||
ok: boolean;
|
||||
codeCoverage: string;
|
||||
}>();
|
||||
connection.close();
|
||||
if (!res.ok) {
|
||||
ctx.response.body = { ok: false };
|
||||
ctx.response.status = 500;
|
||||
ctx.respond = true;
|
||||
return;
|
||||
}
|
||||
ctx.response.body = { ok: true, codeCoverage: res.codeCoverage };
|
||||
ctx.response.status = 200;
|
||||
ctx.respond = true;
|
||||
});
|
||||
|
||||
const app = new Application();
|
||||
app.use(router.routes());
|
||||
app.use(router.allowedMethods());
|
||||
|
||||
app.use(async (ctx, next) => {
|
||||
try {
|
||||
await ctx.send({ root: "./public", index: "index.html" });
|
||||
@ -15,8 +112,6 @@ app.use(async (ctx, next) => {
|
||||
next();
|
||||
}
|
||||
});
|
||||
|
||||
const port = 8000;
|
||||
const listener = app.listen({ port });
|
||||
console.log(`Listening at http://localhost:${port}/`);
|
||||
console.log(`Devtools at http://localhost:${port}/`);
|
||||
await listener;
|
||||
|
@ -30,6 +30,11 @@ function loadCodeCoverage(text, codeCoverageData) {
|
||||
let line = 1;
|
||||
let col = 1;
|
||||
for (let index = 0; index < text.length; ++index) {
|
||||
if (text[index] == "\n") {
|
||||
col = 1;
|
||||
line += 1;
|
||||
continue;
|
||||
}
|
||||
const entry = entries.find((entry) => index >= entry.index);
|
||||
charEntries[`${line}-${col}`] = entry;
|
||||
ctx.fillStyle = color(Math.min(entry.covers / 25, 1));
|
||||
@ -40,10 +45,6 @@ function loadCodeCoverage(text, codeCoverageData) {
|
||||
chHeight,
|
||||
);
|
||||
col += 1;
|
||||
if (text[index] == "\n") {
|
||||
col = 1;
|
||||
line += 1;
|
||||
}
|
||||
}
|
||||
|
||||
const tooltip = document.getElementById("covers-tooltip");
|
||||
|
@ -50,7 +50,7 @@ main {
|
||||
}
|
||||
#code-coverage #covers-tooltip {
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
padding: 3px;
|
||||
@ -78,7 +78,7 @@ main {
|
||||
}
|
||||
#flame-graph #flame-graph-tooltip {
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
padding: 3px;
|
||||
|
45
web/runtime.ts
Normal file
45
web/runtime.ts
Normal file
@ -0,0 +1,45 @@
|
||||
export class Runtime {
|
||||
constructor(private port: number) {}
|
||||
|
||||
async connect(): Promise<RuntimeConnection> {
|
||||
return new RuntimeConnection(
|
||||
await Deno.connect({
|
||||
port: this.port,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class RuntimeConnection {
|
||||
constructor(private connection: Deno.Conn) {}
|
||||
|
||||
async write(text: string): Promise<void> {
|
||||
const req = new TextEncoder().encode(text);
|
||||
await this.connection.write(req);
|
||||
}
|
||||
|
||||
async send<T>(value: T): Promise<void> {
|
||||
await this.write(JSON.stringify(value));
|
||||
}
|
||||
|
||||
async read(): Promise<string> {
|
||||
let result = "";
|
||||
while (true) {
|
||||
const buf = new Uint8Array(256);
|
||||
const readRes = await this.connection.read(buf);
|
||||
result += new TextDecoder().decode(buf);
|
||||
if (readRes == null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
async receive<T>(): Promise<T> {
|
||||
return JSON.parse(await this.read()) as T;
|
||||
}
|
||||
|
||||
close() {
|
||||
this.connection.close();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user