add debug_print
All checks were successful
Check / Explore-Gitea-Actions (push) Successful in 8s

This commit is contained in:
sfja 2026-03-17 18:55:54 +01:00
parent 9d03272db8
commit a42917b485
10 changed files with 197 additions and 202 deletions

View File

@ -1,23 +0,0 @@
import { Ty } from "../ty.ts";
export type Builtin = {
id: string;
ty: Ty;
};
export const builtins: Builtin[] = [
{
id: "print_int",
ty: Ty.create("Fn", {
params: [Ty.Int],
retTy: Ty.Void,
}),
},
{
id: "__add",
ty: Ty.create("Fn", {
params: [Ty.Int, Ty.Int],
retTy: Ty.Int,
}),
},
];

View File

@ -1,7 +1,6 @@
import * as ast from "../ast.ts";
import { FileReporter, Loc } from "../diagnostics.ts";
import { Ty } from "../ty.ts";
import { builtins } from "./builtins.ts";
import { Syms } from "./resolve.ts";
export class Tys {
@ -131,7 +130,8 @@ class Checker {
return Ty.Bool;
}
if (sym.tag === "Builtin") {
return builtins.find((s) => s.id === sym.id)!.ty;
this.error(node.loc, `invalid use of builtin '${sym.id}'`);
this.fail();
}
if (sym.tag === "FnParam") {
return this.tys.expr(sym.param);
@ -308,6 +308,17 @@ class Checker {
}
private checkCall(node: ast.NodeWithKind<"CallExpr">): Ty {
if (node.kind.value.is("IdentExpr")) {
const sym = this.syms.get(node.kind.value);
if (sym && sym.tag === "Builtin") {
if (sym.id === "debug_print") {
const _argTys = node.kind.args
.map((arg) => this.tys.expr(arg));
return Ty.Void;
}
}
}
const calleeTy = this.tys.expr(node.kind.value);
const callableTy = calleeTy.is("Fn")

View File

@ -1,6 +1,5 @@
import * as ast from "../ast.ts";
import { FileReporter } from "../diagnostics.ts";
import { builtins } from "./builtins.ts";
export class Syms {
constructor(
@ -113,12 +112,9 @@ export function resolve(
class ResolverSyms {
static root(): ResolverSyms {
return new ResolverSyms(
new Map(
builtins.map<[string, Sym]>((sym) => [
sym.id,
{ tag: "Builtin", id: sym.id },
new Map([
["debug_print", { tag: "Builtin", id: "debug_print" }],
]),
),
null,
);
}

View File

@ -57,14 +57,35 @@ class FnLowerer {
return this.lowerLetStmt(stmt);
}
if (stmt.is("ReturnStmt")) {
return this.lowerReturnStmt(stmt);
}
if (stmt.is("IfStmt")) {
return this.lowerIfStmt(stmt);
}
if (stmt.is("WhileStmt")) {
return this.lowerWhileStmt(stmt);
}
if (stmt.is("BreakStmt")) {
return this.lowerBreakStmt(stmt);
}
if (stmt.is("AssignStmt")) {
return this.lowerAssignStmt(stmt);
}
if (stmt.is("ExprStmt")) {
return this.lowerExpr(stmt.kind.expr);
}
throw new Error(`'${stmt.kind.tag}' not handled`);
}
private lowerReturnStmt(stmt: ast.NodeWithKind<"ReturnStmt">) {
const source = stmt.kind.expr
? this.lowerExpr(stmt.kind.expr)
: this.makeVoid();
this.pushInst(Ty.Void, "Return", { source });
this.bbs.push(new BasicBlock());
return;
}
if (stmt.is("IfStmt")) {
private lowerIfStmt(stmt: ast.NodeWithKind<"IfStmt">) {
const cond = this.lowerExpr(stmt.kind.cond);
const condBlock = this.bbs.at(-1)!;
@ -100,9 +121,9 @@ class FnLowerer {
falsyEnd?.insts.push(
new Inst(Ty.Void, { tag: "Jump", target: done }),
);
return;
}
if (stmt.is("WhileStmt")) {
private lowerWhileStmt(stmt: ast.NodeWithKind<"WhileStmt">) {
const before = this.bbs.at(-1)!;
this.bbs.push(new BasicBlock());
@ -135,9 +156,9 @@ class FnLowerer {
bodyEnd.insts.push(
new Inst(Ty.Void, { tag: "Jump", target: condBlock }),
);
return;
}
if (stmt.is("BreakStmt")) {
private lowerBreakStmt(stmt: ast.NodeWithKind<"BreakStmt">) {
const sym = this.syms.get(stmt);
if (sym.tag !== "Loop") {
throw new Error();
@ -148,16 +169,6 @@ class FnLowerer {
}
this.pushInst(Ty.Void, "Jump", { target: loopEnd });
this.bbs.push(new BasicBlock());
return;
}
if (stmt.is("AssignStmt")) {
return this.lowerAssignStmt(stmt);
}
if (stmt.is("ExprStmt")) {
this.lowerExpr(stmt.kind.expr);
return;
}
throw new Error(`'${stmt.kind.tag}' not handled`);
}
private lowerLetStmt(stmt: ast.NodeWithKind<"LetStmt">) {
@ -291,11 +302,7 @@ class FnLowerer {
if (expr.kind.value.is("IdentExpr")) {
const sym = this.syms.get(expr.kind.value);
if (sym.tag === "Builtin") {
if (sym.id === "__add") {
const [left, right] = args;
return this.pushInst(ty, "Add", { left, right });
}
if (sym.id === "print_int") {
if (sym.id === "debug_print") {
return this.pushInst(ty, "DebugPrint", { args });
}
throw new Error(`builtin '${sym.id}' not handled`);
@ -306,6 +313,32 @@ class FnLowerer {
return this.pushInst(ty, "Call", { callee, args });
}
if (expr.is("UnaryExpr")) {
return this.lowerUnaryExpr(expr);
}
if (expr.is("BinaryExpr")) {
const resultTy = this.tys.expr(expr);
const leftTy = this.tys.expr(expr.kind.left);
const rightTy = this.tys.expr(expr.kind.right);
const binaryOp = binaryOpPatterns
.find((pat) =>
expr.kind.op === pat.op &&
resultTy.compatibleWith(pat.result) &&
leftTy.compatibleWith(pat.left ?? pat.result) &&
rightTy.compatibleWith(pat.right ?? pat.left ?? pat.result)
);
if (!binaryOp) {
throw new Error(
`'${expr.kind.op}' with '${resultTy.pretty()}' not handled`,
);
}
const left = this.lowerExpr(expr.kind.left);
const right = this.lowerExpr(expr.kind.right);
return this.pushInst(resultTy, binaryOp.tag, { left, right });
}
throw new Error(`'${expr.kind.tag}' not handled`);
}
private lowerUnaryExpr(expr: ast.NodeWithKind<"UnaryExpr">) {
const resultTy = this.tys.expr(expr);
const operandTy = this.tys.expr(expr.kind.expr);
if (
@ -361,28 +394,6 @@ class FnLowerer {
`'${expr.kind.op}' with '${resultTy.pretty()}' not handled`,
);
}
if (expr.is("BinaryExpr")) {
const resultTy = this.tys.expr(expr);
const leftTy = this.tys.expr(expr.kind.left);
const rightTy = this.tys.expr(expr.kind.right);
const binaryOp = binaryOpPatterns
.find((pat) =>
expr.kind.op === pat.op &&
resultTy.compatibleWith(pat.result) &&
leftTy.compatibleWith(pat.left ?? pat.result) &&
rightTy.compatibleWith(pat.right ?? pat.left ?? pat.result)
);
if (!binaryOp) {
throw new Error(
`'${expr.kind.op}' with '${resultTy.pretty()}' not handled`,
);
}
const left = this.lowerExpr(expr.kind.left);
const right = this.lowerExpr(expr.kind.right);
return this.pushInst(resultTy, binaryOp.tag, { left, right });
}
throw new Error(`'${expr.kind.tag}' not handled`);
}
private makeVoid(): Inst {
return this.pushInst(Ty.Void, "Void", {});

View File

@ -5,20 +5,20 @@ fn main()
let elem: int = array[0];
// expect: 1
print_int(elem);
debug_print(elem);
let ptr_to_array: *[int; 3] = &array;
// expect: 2
print_int(ptr_to_array.*[1]);
debug_print(ptr_to_array.*[1]);
let slice: *[int] = &array[..];
// expect: 3
print_int(slice.*[2]);
debug_print(slice.*[2]);
let slice_mut: *mut [int] = &mut array[1..3];
slice_mut.*[0] = 4;
// expect: 4
print_int(array[1]);
debug_print(array[1]);
}
// vim: syntax=rust commentstring=//\ %s

View File

@ -4,6 +4,6 @@ fn main()
{
let v: int = 123;
v = 456;
print_int(v);
debug_print(v);
}

View File

@ -13,7 +13,7 @@ fn main()
a = 3;
}
print_int(a);
debug_print(a);
if false {
a = 4;
@ -21,5 +21,5 @@ fn main()
a = 5;
}
print_int(a);
debug_print(a);
}

View File

@ -9,7 +9,7 @@ fn main()
a = a + 1;
}
print_int(a);
debug_print(a);
while a < 10 {
if a >= 8 {
@ -18,5 +18,5 @@ fn main()
a = a + 1;
}
print_int(a);
debug_print(a);
}

View File

@ -13,20 +13,20 @@ fn main()
let a = 5;
let b = 3;
print_int(a + b);
print_int(a - b);
print_int(a * b);
print_int(a * b / 2);
print_int(a % b);
print_int(-a);
debug_print(a + b);
debug_print(a - b);
debug_print(a * b);
debug_print(a * b / 2);
debug_print(a % b);
debug_print(-a);
let c = false;
if not c {
print_int(123);
debug_print(123);
}
print_int(2 * 3 + 4);
print_int(2 * (3 + 4));
debug_print(2 * 3 + 4);
debug_print(2 * (3 + 4));
}

View File

@ -9,21 +9,21 @@ fn main()
let a = 1;
let b: *int = &a;
// expect: 1
print_int(*b);
debug_print(*b);
a = 2;
// expect: 2
print_int(*b);
debug_print(*b);
let c: *mut int = &mut a;
*c = 3;
// expect: 3
print_int(a);
debug_print(a);
// expect: 3
print_int(*c);
debug_print(*c);
change_to(&mut a, 4);
// expect: 4
print_int(a);
debug_print(a);
}