2024-12-31 03:38:38 +01:00
|
|
|
import {
|
|
|
|
AstCreator,
|
|
|
|
ETypeKind,
|
|
|
|
Expr,
|
|
|
|
ExprKind,
|
|
|
|
Stmt,
|
|
|
|
StmtKind,
|
|
|
|
} from "../ast.ts";
|
|
|
|
import {
|
|
|
|
AstVisitor,
|
|
|
|
visitField,
|
|
|
|
VisitRes,
|
|
|
|
visitStmts,
|
|
|
|
} from "../ast_visitor.ts";
|
|
|
|
import { Pos } from "../token.ts";
|
|
|
|
|
|
|
|
export class StructLiteralDesugarer implements AstVisitor {
|
|
|
|
public constructor(
|
|
|
|
private astCreator: AstCreator,
|
|
|
|
) {}
|
|
|
|
|
|
|
|
public desugar(stmts: Stmt[]) {
|
|
|
|
visitStmts(stmts, this);
|
|
|
|
}
|
|
|
|
|
|
|
|
visitStructExpr(expr: Expr): VisitRes {
|
|
|
|
if (expr.kind.type !== "struct") {
|
|
|
|
throw new Error();
|
|
|
|
}
|
|
|
|
const npos: Pos = { index: 0, line: 1, col: 1 };
|
|
|
|
const Expr = (kind: ExprKind, pos = npos) =>
|
|
|
|
this.astCreator.expr(kind, pos);
|
|
|
|
const Stmt = (kind: StmtKind, pos = npos) =>
|
|
|
|
this.astCreator.stmt(kind, pos);
|
|
|
|
const EType = (kind: ETypeKind, pos = npos) =>
|
|
|
|
this.astCreator.etype(kind, pos);
|
|
|
|
|
|
|
|
const std = (ident: string): Expr =>
|
|
|
|
Expr({
|
|
|
|
type: "path",
|
|
|
|
subject: Expr({
|
|
|
|
type: "ident",
|
|
|
|
ident: "std",
|
|
|
|
}),
|
|
|
|
ident,
|
|
|
|
});
|
|
|
|
|
|
|
|
const fields = expr.kind.fields;
|
|
|
|
|
|
|
|
expr.kind = {
|
|
|
|
type: "block",
|
|
|
|
stmts: [
|
|
|
|
Stmt({
|
|
|
|
type: "let",
|
2025-01-02 06:46:51 +01:00
|
|
|
param: this.astCreator.param({
|
2024-12-31 03:38:38 +01:00
|
|
|
ident: "::value",
|
2025-01-17 07:44:53 +01:00
|
|
|
mut: true,
|
2024-12-31 03:38:38 +01:00
|
|
|
pos: npos,
|
2025-01-02 06:46:51 +01:00
|
|
|
}),
|
2024-12-31 03:38:38 +01:00
|
|
|
value: Expr({
|
|
|
|
type: "call",
|
|
|
|
subject: Expr({
|
|
|
|
type: "etype_args",
|
|
|
|
subject: std("struct_new"),
|
|
|
|
etypeArgs: [
|
2024-12-31 05:32:41 +01:00
|
|
|
EType({
|
|
|
|
type: "type_of",
|
|
|
|
expr: Expr({ ...expr.kind }),
|
|
|
|
}),
|
2024-12-31 03:38:38 +01:00
|
|
|
],
|
|
|
|
}),
|
|
|
|
args: [],
|
|
|
|
}),
|
|
|
|
}),
|
|
|
|
...expr.kind.fields
|
|
|
|
.map((field) =>
|
|
|
|
Stmt({
|
|
|
|
type: "assign",
|
|
|
|
assignType: "=",
|
|
|
|
subject: Expr({
|
|
|
|
type: "field",
|
|
|
|
subject: Expr({
|
|
|
|
type: "ident",
|
|
|
|
ident: "::value",
|
|
|
|
}),
|
|
|
|
ident: field.ident,
|
|
|
|
}),
|
|
|
|
value: field.expr,
|
|
|
|
})
|
|
|
|
),
|
|
|
|
],
|
|
|
|
expr: Expr({ type: "ident", ident: "::value" }),
|
|
|
|
};
|
|
|
|
|
|
|
|
for (const field of fields) {
|
|
|
|
visitField(field, this);
|
|
|
|
}
|
|
|
|
|
|
|
|
return "stop";
|
|
|
|
}
|
|
|
|
}
|