compiler: add builtins

This commit is contained in:
sfja 2025-03-03 02:19:27 +01:00 committed by SimonFJ20
parent 6e5ac26c84
commit 0bdfd78ca2
6 changed files with 56 additions and 18 deletions

View File

@ -122,8 +122,16 @@ export class FnLowerer {
return this.lowerAssignStmt(stmt, k); return this.lowerAssignStmt(stmt, k);
case "expr": { case "expr": {
const rval = this.lowerExpr(k.expr); const rval = this.lowerExpr(k.expr);
// ignore the fuck out of the value // ignore the fuck out of the value
void rval; const ty = this.ch.exprTy(k.expr);
const local = this.local(ty);
this.addStmt({
tag: "assign",
place: { local, proj: [] },
rval,
});
return; return;
} }
} }
@ -374,6 +382,29 @@ export class FnLowerer {
return this.lowerCallExprTupleVariantCtor(expr, kind); return this.lowerCallExprTupleVariantCtor(expr, kind);
} }
const args = kind.args.map((arg) => this.lowerExprToOperand(arg)); const args = kind.args.map((arg) => this.lowerExprToOperand(arg));
const calleeTy = this.ch.exprTy(kind.expr);
if (calleeTy.kind.tag !== "fn") {
throw new Error();
}
const builtinAttr = calleeTy.kind.item.attrs
.find((attr) => attr.ident.text === "builtin");
if (builtinAttr) {
if (
builtinAttr.args?.length !== 1 ||
builtinAttr.args[0].kind.tag !== "path" ||
builtinAttr.args[0].kind.path.segments.length !== 1 ||
!["Hello"].includes(
builtinAttr.args[0].kind.path.segments[0].ident.text,
)
) {
return { tag: "error" };
}
const builtinId =
builtinAttr.args[0].kind.path.segments[0].ident.text;
return { tag: "builtin", builtinId, args };
}
const func = this.lowerExprToOperand(kind.expr); const func = this.lowerExprToOperand(kind.expr);
return { tag: "call", func, args }; return { tag: "call", func, args };
} }

View File

@ -86,7 +86,8 @@ export type RVal =
| { tag: "binary"; binaryType: BinaryType; left: Operand; right: Operand } | { tag: "binary"; binaryType: BinaryType; left: Operand; right: Operand }
| { tag: "unary"; unaryType: UnaryType; operand: Operand } | { tag: "unary"; unaryType: UnaryType; operand: Operand }
| { tag: "adt"; ty: Ty; fields: Operand[]; variant?: ast.Variant } | { tag: "adt"; ty: Ty; fields: Operand[]; variant?: ast.Variant }
| { tag: "call"; func: Operand; args: Operand[] }; | { tag: "call"; func: Operand; args: Operand[] }
| { tag: "builtin"; builtinId: string; args: Operand[] };
export type BinaryType = export type BinaryType =
| "add" | "add"

View File

@ -113,7 +113,6 @@ export class Parser {
const ident = this.parseIdent(); const ident = this.parseIdent();
let args: Expr[] | undefined = undefined; let args: Expr[] | undefined = undefined;
if (this.test("(")) { if (this.test("(")) {
this.step();
args = this.parseDelimitedList( args = this.parseDelimitedList(
this.parseAttrArg, this.parseAttrArg,
")", ")",

View File

@ -1,15 +1,9 @@
enum S { #[builtin(Hello)]
A(int), fn c_hello() -> int {}
B { v: int },
}
fn main() { fn main() {
let s = S::A(123); c_hello();
let r = match s {
S::A(v) => { 3 + 2 },
S::B { v: v } => { 4 },
};
} }

View File

@ -44,22 +44,25 @@ export class HirStringifyer {
} }
public item(item: ast.Item, d = 0): string { public item(item: ast.Item, d = 0): string {
const attrs = item.attrs.map((attr) => `${this.attr(attr)}\n`);
const ident = item.ident.text; const ident = item.ident.text;
const pub = item.pub ? "pub " : ""; const pub = item.pub ? "pub " : "";
const k = item.kind; const k = item.kind;
switch (k.tag) { switch (k.tag) {
case "error": case "error":
return "<error>;"; return `${attrs}<error>;`;
case "mod_block": case "mod_block":
return `${pub}mod ${ident} ${this.block(k.block, d)}`; return `${attrs}${pub}mod ${ident} ${this.block(k.block, d)}`;
case "mod_file": case "mod_file":
return `${pub}mod ${ident} {\n${this.file(k.ast!, d + 1)}\n}`; return `${attrs}${pub}mod ${ident} {\n${
this.file(k.ast!, d + 1)
}\n}`;
case "enum": case "enum":
return `enum ${ident}: ${ return `${attrs}enum ${ident}: ${
this.ty(this.ch.enumItemTy(item, k)) this.ty(this.ch.enumItemTy(item, k))
};`; };`;
case "struct": case "struct":
return `struct ${ident}: ${ return `${attrs}struct ${ident}: ${
this.ty(this.ch.structItemTy(item, k)) this.ty(this.ch.structItemTy(item, k))
};`; };`;
case "fn": { case "fn": {
@ -70,7 +73,7 @@ export class HirStringifyer {
const params = k.params const params = k.params
.map((param) => this.pat(param.pat, d)) .map((param) => this.pat(param.pat, d))
.join(", "); .join(", ");
return `${pub}fn ${ident}(${params}) -> ${ return `${attrs}${pub}fn ${ident}(${params}) -> ${
this.ty(ty.kind.returnTy) this.ty(ty.kind.returnTy)
} ${this.block(k.body!, d)}`; } ${this.block(k.body!, d)}`;
} }
@ -218,6 +221,12 @@ export class HirStringifyer {
.join("::"); .join("::");
} }
public attr(attr: ast.Attr): string {
return `#[${attr.ident.text}${
attr.args && `(${attr.args.map((arg) => this.expr(arg, 1))})` || ""
}]`;
}
public ty(ty: Ty): string { public ty(ty: Ty): string {
return tyToString(this.ctx, ty); return tyToString(this.ctx, ty);
} }

View File

@ -233,6 +233,10 @@ export class MirFnStringifyer {
return `call ${this.operand(rval.func)}(${ return `call ${this.operand(rval.func)}(${
rval.args.map((arg) => this.operand(arg)).join(", ") rval.args.map((arg) => this.operand(arg)).join(", ")
})`; })`;
case "builtin":
return `builtin ${rval.builtinId}(${
rval.args.map((arg) => this.operand(arg)).join(", ")
})`;
} }
exhausted(rval); exhausted(rval);
} }