lower blocks

This commit is contained in:
nora 2023-07-29 17:32:42 +02:00
parent 7c2faaecb8
commit 162d71c8b8
2 changed files with 48 additions and 13 deletions

View file

@ -10,13 +10,15 @@ import fs from "fs";
import { exec } from "child_process"; import { exec } from "child_process";
const input = ` const input = `
function printInt(a: Int) = ; function printInt(a: Int) = (
0;
function main() = ( (
let a = 0; 0;
let b = 0; 1
printInt(a + b); );
); );
function main() = ;
`; `;
function main() { function main() {

View file

@ -1,4 +1,4 @@
import { Ast, Expr, FunctionDef, Item, Ty, TyFn, varUnreachable } from "./ast"; import { Ast, Expr, ExprBlock, FunctionDef, Item, Ty, TyFn, varUnreachable } from "./ast";
import * as wasm from "./wasm/defs"; import * as wasm from "./wasm/defs";
type StringifiedForMap<T> = string; type StringifiedForMap<T> = string;
@ -111,6 +111,7 @@ Expression lowering.
function lowerExpr(fcx: FuncContext, instrs: wasm.Instr[], expr: Expr) { function lowerExpr(fcx: FuncContext, instrs: wasm.Instr[], expr: Expr) {
const ty = expr.ty!; const ty = expr.ty!;
switch (expr.kind) { switch (expr.kind) {
case "empty": case "empty":
// A ZST, do nothing. // A ZST, do nothing.
@ -119,10 +120,23 @@ function lowerExpr(fcx: FuncContext, instrs: wasm.Instr[], expr: Expr) {
// Let, that's complicated. // Let, that's complicated.
todo("let"); todo("let");
case "block": case "block":
if (expr.exprs.length === 1) { if (expr.exprs.length === 0) {
// do nothing
} else if (expr.exprs.length === 1) {
lowerExpr(fcx, instrs, expr.exprs[0]); lowerExpr(fcx, instrs, expr.exprs[0]);
} else { } else {
todo("complex blocks"); const typeIdx = internFuncType(fcx.cx, {
params: [],
returns: wasmTypeForBody(expr.ty!),
});
const instr: wasm.Instr = {
kind: "block",
instrs: lowerExprBlockBody(fcx, expr),
type: { kind: "typeidx", idx: typeIdx },
};
instrs.push(instr);
} }
break; break;
case "literal": case "literal":
@ -266,6 +280,23 @@ function lowerExpr(fcx: FuncContext, instrs: wasm.Instr[], expr: Expr) {
} }
} }
function lowerExprBlockBody(fcx: FuncContext, expr: ExprBlock & Expr): wasm.Instr[] {
const innerInstrs: wasm.Instr[] = [];
const headExprs = expr.exprs.slice(0, -1);
const tailExpr = expr.exprs[expr.exprs.length - 1];
headExprs.forEach((inner) => {
lowerExpr(fcx, innerInstrs, inner);
const types = wasmTypeForBody(inner.ty!);
types.forEach(() => innerInstrs.push({ kind: "drop" }));
});
lowerExpr(fcx, innerInstrs, tailExpr);
return innerInstrs;
}
function loadVariable(instrs: wasm.Instr[], loc: VarLocation) { function loadVariable(instrs: wasm.Instr[], loc: VarLocation) {
switch (loc.kind) { switch (loc.kind) {
case "local": { case "local": {
@ -376,25 +407,27 @@ function wasmTypeForAbi(abi: Abi): {
return { type: { params, returns }, paramLocations }; return { type: { params, returns }, paramLocations };
} }
function wasmTypeForBody(ty: Ty): wasm.ValType | undefined { function wasmTypeForBody(ty: Ty): wasm.ValType[] {
switch (ty.kind) { switch (ty.kind) {
case "string": case "string":
todo("string types"); todo("string types");
case "int": case "int":
return "i64"; return ["i64"];
case "bool": case "bool":
return "i32"; return ["i32"];
case "list": case "list":
todo("list types"); todo("list types");
case "tuple": case "tuple":
if (ty.elems.length === 0) { if (ty.elems.length === 0) {
return undefined; return [];
} else if (ty.elems.length === 1) { } else if (ty.elems.length === 1) {
return wasmTypeForBody(ty.elems[0]); return wasmTypeForBody(ty.elems[0]);
} }
todo("complex tuples"); todo("complex tuples");
case "fn": case "fn":
todo("fn types"); todo("fn types");
case "struct":
todo("struct types");
case "var": case "var":
varUnreachable(); varUnreachable();
} }