From 27a4ecc46b40947ba0228ad94358e20b2ec5c018 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sat, 29 Jul 2023 18:31:39 +0200 Subject: [PATCH] lower if --- src/index.ts | 14 ++++++-------- src/lower.ts | 40 ++++++++++++++++++++++++++++++++-------- src/typeck.ts | 3 ++- 3 files changed, 40 insertions(+), 17 deletions(-) diff --git a/src/index.ts b/src/index.ts index 2a09306..793f47b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -10,14 +10,12 @@ import fs from "fs"; import { exec } from "child_process"; const input = ` -function printInt(a: Int) = ( - let a = 0; - let b = 0; - let c = (); - - a + b; - - c +function printInt(a: Int): Int = ( + if true then ( + 0; + 1; + ); + 0 ); function main() = ; diff --git a/src/lower.ts b/src/lower.ts index e8a9931..f8ea544 100644 --- a/src/lower.ts +++ b/src/lower.ts @@ -137,6 +137,8 @@ function lowerExpr(fcx: FuncContext, instrs: wasm.Instr[], expr: Expr) { instrs.push({ kind: "local.set", imm: local }); fcx.varLocations.push({ kind: "local", idx: local }); + } else { + todo("complex locals"); } break; @@ -149,15 +151,10 @@ function lowerExpr(fcx: FuncContext, instrs: wasm.Instr[], expr: Expr) { } else if (expr.exprs.length === 1) { lowerExpr(fcx, instrs, expr.exprs[0]); } else { - 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 }, + type: blockTypeForBody(fcx.cx, expr.ty!), }; instrs.push(instr); @@ -306,8 +303,27 @@ function lowerExpr(fcx: FuncContext, instrs: wasm.Instr[], expr: Expr) { } case "call": todo("call"); - case "if": - todo("ifs"); + case "if": { + lowerExpr(fcx, instrs, expr.cond!); + + const thenInstrs: wasm.Instr[] = []; + lowerExpr(fcx, thenInstrs, expr.then); + + const elseInstrs: wasm.Instr[] = []; + // If there is no else, the type is (), so an empty instr array is correct. + if (expr.else) { + lowerExpr(fcx, elseInstrs, expr.else); + } + + instrs.push({ + kind: "if", + then: thenInstrs, + else: elseInstrs, + type: blockTypeForBody(fcx.cx, expr.ty!), + }); + + break; + } } } @@ -467,6 +483,14 @@ function wasmTypeForBody(ty: Ty): wasm.ValType[] { } } +function blockTypeForBody(cx: Context, ty: Ty): wasm.Blocktype { + const typeIdx = internFuncType(cx, { + params: [], + returns: wasmTypeForBody(ty), + }); + return { kind: "typeidx", idx: typeIdx }; +} + function todo(msg: string): never { throw new Error(`TODO: ${msg}`); } diff --git a/src/typeck.ts b/src/typeck.ts index 0d4e2eb..8d34118 100644 --- a/src/typeck.ts +++ b/src/typeck.ts @@ -546,12 +546,13 @@ export function checkBody( infcx.assign(TY_BOOL, cond.ty!, cond.span); - let ty; + let ty: Ty; if (elsePart) { infcx.assign(then.ty!, elsePart.ty!, elsePart.span); ty = then.ty!; } else { infcx.assign(TY_UNIT, then.ty!, then.span); + ty = TY_UNIT; } return { ...expr, cond, then, else: elsePart, ty };