add unreachable for unreachable things

This commit is contained in:
nora 2023-07-30 00:17:05 +02:00
parent 1d9ab31baf
commit 89dbb50add
2 changed files with 26 additions and 89 deletions

View file

@ -10,14 +10,15 @@ import fs from "fs";
import { exec } from "child_process"; import { exec } from "child_process";
const input = ` const input = `
function main() = uwu(10); function main() = (
loop (no(break););
uwu(10);
);
function print_a( function no(a: !): String = a;
a: String,
): String = a;
function uwu(a: Int) = if a != 0 then ( function uwu(a: Int) = if a != 0 then (
print(print_a("uwu\n")); print("uwu\n");
uwu(a - 1); uwu(a - 1);
); );
`; `;

View file

@ -19,10 +19,7 @@ const USIZE: wasm.ValType = "i32";
const POINTER: wasm.ValType = USIZE; const POINTER: wasm.ValType = USIZE;
const STRING_TYPES: wasm.ValType[] = [POINTER, USIZE]; const STRING_TYPES: wasm.ValType[] = [POINTER, USIZE];
const STRING_ABI: ArgRetAbi = { const STRING_ABI: ArgRetAbi = STRING_TYPES;
kind: "aggregate",
types: STRING_TYPES,
};
const WASM_PAGE = 65536; const WASM_PAGE = 65536;
@ -173,10 +170,7 @@ type FuncContext = {
type FnAbi = { params: ArgRetAbi[]; ret: ArgRetAbi }; type FnAbi = { params: ArgRetAbi[]; ret: ArgRetAbi };
type ArgRetAbi = type ArgRetAbi = wasm.ValType[];
| { kind: "scalar"; type: wasm.ValType }
| { kind: "zst" }
| { kind: "aggregate"; types: wasm.ValType[] };
type VarLocation = { localIdx: number; types: wasm.ValType[] }; type VarLocation = { localIdx: number; types: wasm.ValType[] };
@ -482,6 +476,11 @@ function lowerExpr(fcx: FuncContext, instrs: wasm.Instr[], expr: Expr) {
const _: never = expr; const _: never = expr;
} }
} }
if (ty.kind === "never") {
instrs.push({ kind: "unreachable" });
return;
}
} }
function lowerExprBlockBody( function lowerExprBlockBody(
@ -517,72 +516,34 @@ function loadVariable(instrs: wasm.Instr[], loc: VarLocation) {
} }
function computeAbi(ty: TyFn): FnAbi { function computeAbi(ty: TyFn): FnAbi {
const scalar = (type: wasm.ValType): ArgRetAbi => function argRetAbi(param: Ty): ArgRetAbi {
({ kind: "scalar", type } as const);
const zst: ArgRetAbi = { kind: "zst" };
function paramAbi(param: Ty): ArgRetAbi {
switch (param.kind) { switch (param.kind) {
case "string": case "string":
return STRING_ABI; return STRING_ABI;
case "fn": case "fn":
todo("fn abi"); todo("fn abi");
case "int": case "int":
return scalar("i64"); return ["i64"];
case "bool": case "bool":
return scalar("i32"); return ["i32"];
case "list": case "list":
todo("list abi"); todo("list abi");
case "tuple": case "tuple":
if (param.elems.length === 0) { if (param.elems.length === 0) {
return zst; return [];
} else if (param.elems.length === 1) {
return paramAbi(param.elems[0]);
} }
todo("complex tuple abi"); todo("complex tuple abi");
case "struct": case "struct":
todo("struct ABI"); todo("struct ABI");
case "never": case "never":
return zst; return [];
case "var": case "var":
varUnreachable(); varUnreachable();
} }
} }
const params = ty.params.map(paramAbi); const params = ty.params.map(argRetAbi);
const ret = argRetAbi(ty.returnTy);
let ret: ArgRetAbi;
switch (ty.returnTy.kind) {
case "string":
ret = STRING_ABI;
break;
case "fn":
todo("fn abi");
case "int":
ret = scalar("i64");
break;
case "bool":
ret = scalar("i32");
break;
case "list":
todo("list abi");
case "tuple":
if (ty.returnTy.elems.length === 0) {
ret = zst;
break;
} else if (ty.returnTy.elems.length === 1) {
ret = paramAbi(ty.returnTy.elems[0]);
break;
}
todo("complex tuple abi");
case "struct":
todo("struct ABI");
case "never":
ret = zst;
break;
case "var":
varUnreachable();
}
return { params, ret }; return { params, ret };
} }
@ -595,39 +556,14 @@ function wasmTypeForAbi(abi: FnAbi): {
const paramLocations: VarLocation[] = []; const paramLocations: VarLocation[] = [];
abi.params.forEach((arg) => { abi.params.forEach((arg) => {
switch (arg.kind) { paramLocations.push({
case "scalar": localIdx: params.length,
paramLocations.push({ types: arg,
localIdx: params.length, });
types: [arg.type], params.push(...arg);
});
params.push(arg.type);
break;
case "zst":
paramLocations.push({ localIdx: /* dummy */ 0, types: [] });
break;
case "aggregate":
paramLocations.push({
localIdx: params.length,
types: arg.types,
});
params.push(...arg.types);
break;
}
}); });
let returns: wasm.ValType[];
switch (abi.ret.kind) {
case "scalar":
returns = [abi.ret.type];
break;
case "zst":
returns = [];
break;
case "aggregate":
returns = abi.ret.types;
}
return { type: { params, returns }, paramLocations }; return { type: { params, returns: abi.ret }, paramLocations };
} }
function wasmTypeForBody(ty: Ty): wasm.ValType[] { function wasmTypeForBody(ty: Ty): wasm.ValType[] {