Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
572 changes: 379 additions & 193 deletions apps/ppp/src/lib/runtime/dotnet/compiler-factory.ts

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion apps/ppp/src/lib/runtime/dotnet/info.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
import { version } from "dotnet-runtime/version";

import { LIBS } from "./test-compiler-factory";

const libs = LIBS.map(l => {
const i = l.lastIndexOf('/')
return i < 0 ? l : l.slice(i+1)
})
</script>

<p>
Expand All @@ -16,7 +21,7 @@
<p>Available libraries:</p>

<div class="grid grid-flow-row grid-cols-2 gap-x-2">
{#each LIBS as lib}
{#each libs as lib}
<p class="truncate">
{lib}
</p>
Expand Down
675 changes: 422 additions & 253 deletions apps/ppp/src/lib/runtime/dotnet/test-compiler-factory.ts

Large diffs are not rendered by default.

8 changes: 6 additions & 2 deletions apps/ppp/src/lib/runtime/gleam/compiler-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { redirect, createLogger } from 'libs/logger';
import type { CompilerFactory, Program } from 'libs/compiler';
import type { Streams } from 'libs/io';
import { compileJsModule } from 'libs/js';
import { createCachedFetch } from 'libs/fetch';
import { GleamModuleCompiler, type GleamModule, GleamProgram } from 'gleam-runtime';

import compilerWasmUrl from 'gleam-runtime/compiler.wasm?url';
Expand All @@ -14,12 +15,15 @@ const precompiledGleamStdlibIndexUrl = new URL(
).toString();

export const makeGleamCompiler: CompilerFactory<Streams, Program> = async (ctx, streams) => {
const patchedConsole = redirect(globalThis.console, createLogger(streams.out));
const logger = createLogger(streams.out);
const patchedConsole = redirect(globalThis.console, logger);
const fetcher = createCachedFetch(await caches.open('gleam-cache'));
const compiler = new GleamModuleCompiler(
streams.out,
precompiledGleamStdlibIndexUrl,
await WebAssembly.compileStreaming(fetch(compilerWasmUrl, { signal: ctx.signal }))
await WebAssembly.compileStreaming(fetcher(compilerWasmUrl, { signal: ctx.signal }))
);
logger.info(`Loaded ${compilerWasmUrl}`);
return {
async compile(_, files) {
if (files.length !== 1) {
Expand Down
88 changes: 45 additions & 43 deletions apps/ppp/src/lib/runtime/gleam/test-compiler-factory.ts
Original file line number Diff line number Diff line change
@@ -1,54 +1,56 @@
import type { Context } from "libs/context";
import type { Streams } from "libs/io";
import { createLogger, redirect } from "libs/logger";
import { compileJsModule } from "libs/js";
import type { TestCompiler } from "libs/testing";
import { JsTestProgram } from "javascript-runtime";
import { GleamModuleCompiler } from "gleam-runtime";
import type { Context } from 'libs/context';
import type { Streams } from 'libs/io';
import { createLogger, redirect, type Logger } from 'libs/logger';
import { compileJsModule } from 'libs/js';
import type { TestCompiler } from 'libs/testing';
import { createCachedFetch } from 'libs/fetch';
import { JsTestProgram } from 'javascript-runtime';
import { GleamModuleCompiler } from 'gleam-runtime';

import { base } from '$app/paths';

import compilerWasmUrl from "gleam-runtime/compiler.wasm?url";
import compilerWasmUrl from 'gleam-runtime/compiler.wasm?url';

const precompiledGleamStdlibIndexUrl = new URL(
`${base}/assets/gleam`,
globalThis.location.origin
`${base}/assets/gleam`,
globalThis.location.origin
).toString();

export type ExecuteTest<M, I, O> = (m: M, input: I) => Promise<O>;

export class GleamTestCompilerFactory {

protected readonly patchedConsole: Console;

constructor(protected readonly streams: Streams) {
this.patchedConsole = redirect(globalThis.console, createLogger(streams.out));
}

async create<M, I, O>(
ctx: Context,
executeTest: ExecuteTest<M, I, O>
): Promise<TestCompiler<I, O>> {
class TestProgram extends JsTestProgram<M, I, O> {
override async executeTest(m: M, input: I): Promise<O> {
return executeTest(m, input);
}
}
const compiler = new GleamModuleCompiler(
this.streams.out,
precompiledGleamStdlibIndexUrl,
await WebAssembly.compileStreaming(
fetch(compilerWasmUrl, { signal: ctx.signal })
)
);
return {
compile: async (_, files) => {
if (files.length !== 1) {
throw new Error("Compilation of multiple files is not implemented");
}
const jsCode = compiler.compile(files[0].content);
return new TestProgram(await compileJsModule(jsCode), this.patchedConsole);
},
};
}
protected readonly logger: Logger;
protected readonly patchedConsole: Console;

constructor(protected readonly streams: Streams) {
this.logger = createLogger(streams.out);
this.patchedConsole = redirect(globalThis.console, this.logger);
}

async create<M, I, O>(
ctx: Context,
executeTest: ExecuteTest<M, I, O>
): Promise<TestCompiler<I, O>> {
class TestProgram extends JsTestProgram<M, I, O> {
override async executeTest(m: M, input: I): Promise<O> {
return executeTest(m, input);
}
}
const fetcher = createCachedFetch(await caches.open('gleam-cache'));
const compiler = new GleamModuleCompiler(
this.streams.out,
precompiledGleamStdlibIndexUrl,
await WebAssembly.compileStreaming(fetcher(compilerWasmUrl, { signal: ctx.signal }))
);
this.logger.info(`Loaded ${compilerWasmUrl}`);
return {
compile: async (_, files) => {
if (files.length !== 1) {
throw new Error('Compilation of multiple files is not implemented');
}
const jsCode = compiler.compile(files[0].content);
return new TestProgram(await compileJsModule(jsCode), this.patchedConsole);
}
};
}
}
16 changes: 13 additions & 3 deletions apps/ppp/src/lib/runtime/go/compiler-factory.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
import type { CompilerFactory, Program } from 'libs/compiler';
import type { Streams } from 'libs/io';
import { inContext } from 'libs/context';
import { createCachedFetch } from 'libs/fetch';
import { createLogger } from 'libs/logger';
import {
GoProgram,
makeCompilerFactory,
makeGoCompilerFactory,
makeGoExecutorFactory
} from 'go-runtime';

import wasmInit from 'go-runtime/compiler.wasm?init';
import wasmUrl from 'go-runtime/compiler.wasm?url';

export const makeGoCompiler: CompilerFactory<Streams, Program> = async (ctx, streams) => {
const logger = createLogger(streams.out);
const fetcher = createCachedFetch(await caches.open('go-cache'));
const goExecutorFactory = makeGoExecutorFactory(
makeGoCompilerFactory(await makeCompilerFactory((imports) => inContext(ctx, wasmInit(imports))))
makeGoCompilerFactory(
await makeCompilerFactory((imports) =>
WebAssembly.instantiateStreaming(fetcher(wasmUrl, { signal: ctx.signal }), imports).then(
(m) => m.instance
)
)
)
);
logger.info(`Loaded ${wasmUrl}`);
return {
async compile(ctx, files) {
if (files.length !== 1) {
Expand Down
6 changes: 5 additions & 1 deletion apps/ppp/src/lib/runtime/go/description.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@
target="_blank"
class="link"
href="https://github.com/traefik/yaegi">Yaegi</a
> (compiled in WebAssembly with stdlib using go{version}) in a web worker environment.
> (compiled in WebAssembly with stdlib using go{version}, <a
target="_blank"
class="link"
href="https://github.com/traefik/yaegi/issues/1601">known limitations</a
>) in a web worker environment.
</p>

<p>
Expand Down
82 changes: 45 additions & 37 deletions apps/ppp/src/lib/runtime/go/test-compiler-factory.ts
Original file line number Diff line number Diff line change
@@ -1,45 +1,53 @@
import { inContext, type Context } from "libs/context";
import type { Streams } from "libs/io";
import type { TestCompiler } from "libs/testing";
import type { Context } from 'libs/context';
import type { Streams } from 'libs/io';
import type { TestCompiler } from 'libs/testing';
import { createLogger, type Logger } from 'libs/logger';
import { createCachedFetch } from 'libs/fetch';
import {
makeCompilerFactory,
makeGoCompilerFactory,
makeGoEvaluatorFactory,
GoTestProgram,
} from "go-runtime";
makeCompilerFactory,
makeGoCompilerFactory,
makeGoEvaluatorFactory,
GoTestProgram
} from 'go-runtime';

import wasmInit from "go-runtime/compiler.wasm?init";
import wasmUrl from 'go-runtime/compiler.wasm?url';

export type GenerateCaseExecutionCode<I> = (input: I) => string;

export class GoTestCompilerFactory {
constructor(protected readonly streams: Streams) {}
protected readonly logger: Logger;

async create<I, O>(
ctx: Context,
generateCaseExecutionCode: GenerateCaseExecutionCode<I>
): Promise<TestCompiler<I, O>> {
class TestProgram extends GoTestProgram<I, O> {
protected override generateCaseExecutionCode(input: I): string {
return generateCaseExecutionCode(input);
}
}
const goEvaluatorFactory = makeGoEvaluatorFactory<O>(
makeGoCompilerFactory(
await makeCompilerFactory((imports) =>
inContext(ctx, wasmInit(imports))
)
)
);
return {
compile: async (ctx, files) => {
if (files.length !== 1) {
throw new Error("Compilation of multiple files is not implemented");
}
return new TestProgram(
await goEvaluatorFactory(ctx, this.streams, files[0].content)
);
},
};
}
constructor(protected readonly streams: Streams) {
this.logger = createLogger(streams.out);
}

async create<I, O>(
ctx: Context,
generateCaseExecutionCode: GenerateCaseExecutionCode<I>
): Promise<TestCompiler<I, O>> {
class TestProgram extends GoTestProgram<I, O> {
protected override generateCaseExecutionCode(input: I): string {
return generateCaseExecutionCode(input);
}
}
const fetcher = createCachedFetch(await caches.open('go-cache'));
const goEvaluatorFactory = makeGoEvaluatorFactory<O>(
makeGoCompilerFactory(
await makeCompilerFactory((imports) =>
WebAssembly.instantiateStreaming(fetcher(wasmUrl, { signal: ctx.signal }), imports).then(
(m) => m.instance
)
)
)
);
this.logger.info(`Loaded ${wasmUrl}`);
return {
compile: async (ctx, files) => {
if (files.length !== 1) {
throw new Error('Compilation of multiple files is not implemented');
}
return new TestProgram(await goEvaluatorFactory(ctx, this.streams, files[0].content));
}
};
}
}
49 changes: 24 additions & 25 deletions apps/ppp/src/lib/runtime/java/compiler-factory.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,30 @@
import type { CompilerFactory, Program } from "libs/compiler";
import type { CompilerFactory, Program } from 'libs/compiler';
import type { Streams } from 'libs/io';
import {
initFs,
JavaCompiler,
JavaProgram,
makeJVMFactory,
} from "java-runtime";
import { createLogger } from 'libs/logger';
import { createCachedFetch } from 'libs/fetch';
import { initFs, JavaCompiler, JavaProgram, makeJVMFactory } from 'java-runtime';

import libZipUrl from "java-runtime/doppio.zip?url";
import libZipUrl from 'java-runtime/doppio.zip?url';

const CLASSNAME = "Program";
const CLASSNAME = 'Program';

export const makeJavaCompiler: CompilerFactory<Streams, Program> = async (ctx, streams) => {
const jvmFactory = makeJVMFactory(streams);
const libZipData = await fetch(libZipUrl, {
signal: ctx.signal,
cache: "force-cache",
}).then((response) => response.arrayBuffer());
const fs = await initFs(libZipData);
const compiler = new JavaCompiler(jvmFactory, `/home/${CLASSNAME}.java`, fs);
return {
async compile(ctx, files) {
if (files.length !== 1) {
throw new Error("Compilation of multiple files is not implemented");
}
await compiler.compile(ctx, files[0].content);
return new JavaProgram(CLASSNAME, jvmFactory);
},
};
const jvmFactory = makeJVMFactory(streams);
const logger = createLogger(streams.out);
const fetcher = createCachedFetch(await caches.open('java-cache'));
const libZipData = await fetcher(libZipUrl, {
signal: ctx.signal
}).then((response) => response.arrayBuffer());
logger.info(`Loaded ${libZipUrl}`);
const fs = await initFs(libZipData);
const compiler = new JavaCompiler(jvmFactory, `/home/${CLASSNAME}.java`, fs);
return {
async compile(ctx, files) {
if (files.length !== 1) {
throw new Error('Compilation of multiple files is not implemented');
}
await compiler.compile(ctx, files[0].content);
return new JavaProgram(CLASSNAME, jvmFactory);
}
};
};
Loading