diff --git a/compiler/lowerer.ts b/compiler/lowerer.ts index 23e58a0..e939fde 100644 --- a/compiler/lowerer.ts +++ b/compiler/lowerer.ts @@ -116,6 +116,30 @@ export class Lowerer { this.program.add(Ops.Jump, this.breakStack.at(-1)!); } + private lowerBuiltinAnno(annoArgs: Expr[]) { + if (annoArgs.length !== 1) { + throw new Error("invalid # of arguments to builtin annotation"); + } + const anno = annoArgs[0]; + if (anno.kind.type !== "ident") { + throw new Error( + `unexpected argument type '${anno.kind.type}' expected 'ident'`, + ); + } + const value = anno.kind.value; + switch (value) { + case "print": { + this.program.add(Ops.Builtin, Builtins.Print); + break; + } + default: { + throw new Error( + `unrecognized builtin '${value}'`, + ); + } + } + } + private lowerFnStmt(stmt: Stmt) { if (stmt.kind.type !== "fn") { throw new Error(); @@ -135,24 +159,7 @@ export class Lowerer { this.locals.allocSym(ident); } if (stmt.kind.anno?.ident === "builtin") { - const anno = stmt.kind.anno.values[0]; - if (!anno) { - throw new Error("builtin annotation without ident"); - } - if (anno.kind.type !== "ident") { - throw new Error("builtin annotation without ident"); - } - const value = anno.kind.value; - switch (value) { - case "print": { - this.program.add(Ops.LoadLocal, 0); - this.program.add(Ops.Builtin, Builtins.Print); - break; - } - default: { - throw new Error("unrecognized builtin"); - } - } + this.lowerBuiltinAnno(stmt.kind.anno.values); } else { this.lowerExpr(stmt.kind.body); }