mirror of
https://github.com/Noratrieb/riverdelta.git
synced 2026-01-15 00:45:04 +01:00
make it a wasi executable
This commit is contained in:
parent
8dd7c174ee
commit
1d0e3a3aff
7 changed files with 87 additions and 13 deletions
11
src/ast.ts
11
src/ast.ts
|
|
@ -1,6 +1,6 @@
|
|||
import { Span } from "./error";
|
||||
|
||||
export type Ast = Item[];
|
||||
export type Ast = { items: Item[]; typeckResults?: TypeckResults };
|
||||
|
||||
export type Identifier = {
|
||||
name: string;
|
||||
|
|
@ -273,6 +273,10 @@ export const TY_STRING: Ty = { kind: "string" };
|
|||
export const TY_BOOL: Ty = { kind: "bool" };
|
||||
export const TY_INT: Ty = { kind: "int", signed: false };
|
||||
|
||||
export type TypeckResults = {
|
||||
main: ItemId;
|
||||
};
|
||||
|
||||
// folders
|
||||
|
||||
export type FoldFn<T> = (value: T) => T;
|
||||
|
|
@ -300,7 +304,10 @@ export const DEFAULT_FOLDER: Folder = {
|
|||
};
|
||||
|
||||
export function foldAst(ast: Ast, folder: Folder): Ast {
|
||||
return ast.map((item) => folder.item(item));
|
||||
return {
|
||||
items: ast.items.map((item) => folder.item(item)),
|
||||
typeckResults: ast.typeckResults,
|
||||
};
|
||||
}
|
||||
|
||||
export function superFoldItem(item: Item, folder: Folder): Item {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ import fs from "fs";
|
|||
import { exec } from "child_process";
|
||||
|
||||
const input = `
|
||||
function main(i: Int, j: Int): Bool = false == (i == 0);
|
||||
function main() = ();
|
||||
function test(i: Int, j: Int): Bool = false == (i == 0);
|
||||
`;
|
||||
|
||||
function main() {
|
||||
|
|
|
|||
43
src/lower.ts
43
src/lower.ts
|
|
@ -1,9 +1,10 @@
|
|||
import { AST } from "prettier";
|
||||
import { Ast, Expr, FunctionDef, Item, Ty, TyFn, varUnreachable } from "./ast";
|
||||
import * as wasm from "./wasm/defs";
|
||||
|
||||
type StringifiedForMap<T> = string;
|
||||
|
||||
type Context = {
|
||||
export type Context = {
|
||||
mod: wasm.Module;
|
||||
funcTypes: Map<StringifiedForMap<wasm.FuncType>, wasm.TypeIdx>;
|
||||
funcIndices: Map<number, wasm.FuncIdx>;
|
||||
|
|
@ -34,9 +35,21 @@ export function lower(ast: Ast): wasm.Module {
|
|||
exports: [],
|
||||
};
|
||||
|
||||
mod.mems.push({ _name: "memory", type: { min: 1024, max: 1024 } });
|
||||
mod.exports.push({ name: "memory", desc: { kind: "memory", idx: 0 } });
|
||||
|
||||
mod.tables.push({
|
||||
_name: "__indirect_function_table",
|
||||
type: { limits: { min: 0, max: 0 }, reftype: "funcref" },
|
||||
});
|
||||
mod.exports.push({
|
||||
name: "__indirect_function_table",
|
||||
desc: { kind: "table", idx: 0 },
|
||||
});
|
||||
|
||||
const cx: Context = { mod, funcTypes: new Map(), funcIndices: new Map() };
|
||||
|
||||
ast.forEach((item) => {
|
||||
ast.items.forEach((item) => {
|
||||
switch (item.kind) {
|
||||
case "function": {
|
||||
lowerFunc(cx, item, item.node);
|
||||
|
|
@ -44,6 +57,8 @@ export function lower(ast: Ast): wasm.Module {
|
|||
}
|
||||
});
|
||||
|
||||
addRt(cx, ast);
|
||||
|
||||
return mod;
|
||||
}
|
||||
|
||||
|
|
@ -384,6 +399,26 @@ function todo(msg: string): never {
|
|||
throw new Error(`TODO: ${msg}`);
|
||||
}
|
||||
|
||||
function exists<T>(val: T | undefined): val is T {
|
||||
return val !== undefined;
|
||||
// Make the program runnable using wasi-preview-1
|
||||
function addRt(cx: Context, ast: Ast) {
|
||||
const { mod } = cx;
|
||||
|
||||
console.log(cx.funcIndices);
|
||||
|
||||
const main = cx.funcIndices.get(ast.typeckResults!.main);
|
||||
if (main === undefined) {
|
||||
throw new Error(`main function (${main}) was not compiled.`);
|
||||
}
|
||||
|
||||
const start: wasm.Func = {
|
||||
_name: "_start",
|
||||
type: internFuncType(cx, { params: [], returns: [] }),
|
||||
locals: [],
|
||||
body: [{ kind: "call", func: main }],
|
||||
};
|
||||
|
||||
const startIdx = mod.funcs.length;
|
||||
mod.funcs.push(start);
|
||||
|
||||
mod.exports.push({ name: "_start", desc: { kind: "func", idx: startIdx } });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ export function parse(t: Token[]): Ast {
|
|||
|
||||
const withIds = items.map((item, i) => ({ ...item, id: i }));
|
||||
|
||||
return withIds;
|
||||
return { items: withIds };
|
||||
}
|
||||
|
||||
function parseItem(t: Token[]): [Token[], Item] {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import {
|
|||
} from "./ast";
|
||||
|
||||
export function printAst(ast: Ast): string {
|
||||
return ast.map(printItem).join("\n");
|
||||
return ast.items.map(printItem).join("\n");
|
||||
}
|
||||
|
||||
function printItem(item: Item): string {
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ const BUILTIN_SET = new Set<string>(BUILTINS);
|
|||
export function resolve(ast: Ast): Ast {
|
||||
const items = new Map<string, number>();
|
||||
|
||||
for (let i = 0; i < ast.length; i++) {
|
||||
const item = ast[i];
|
||||
for (let i = 0; i < ast.items.length; i++) {
|
||||
const item = ast.items[i];
|
||||
const existing = items.get(item.node.name);
|
||||
if (existing !== undefined) {
|
||||
throw new CompilerError(
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ export function typeck(ast: Ast): Ast {
|
|||
throw Error(`cycle computing type of #G${index}`);
|
||||
}
|
||||
itemTys.set(index, null);
|
||||
const item = ast[index];
|
||||
const item = ast.items[index];
|
||||
switch (item.kind) {
|
||||
case "function": {
|
||||
const args = item.node.params.map((arg) => lowerAstTy(arg.type));
|
||||
|
|
@ -168,7 +168,38 @@ export function typeck(ast: Ast): Ast {
|
|||
},
|
||||
};
|
||||
|
||||
return foldAst(ast, checker);
|
||||
const typecked = foldAst(ast, checker);
|
||||
|
||||
const main = typecked.items.find((item) => {
|
||||
if (item.kind === "function" && item.node.name === "main") {
|
||||
const func = item.node;
|
||||
if (func.returnType !== undefined) {
|
||||
const ty = func.returnType.ty!;
|
||||
if (ty.kind !== "tuple" || ty.elems.length !== 0) {
|
||||
throw new CompilerError(
|
||||
`\`main\` has an invalid signature. main takes no arguments and returns nothing`,
|
||||
item.span
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
if (!main) {
|
||||
throw new CompilerError(`\`main\` function not found`, {
|
||||
start: 0,
|
||||
end: 1,
|
||||
});
|
||||
}
|
||||
|
||||
typecked.typeckResults = {
|
||||
main: main.id,
|
||||
};
|
||||
|
||||
return typecked;
|
||||
}
|
||||
|
||||
type TyVarRes =
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue