95 lines
2.8 KiB
TypeScript
95 lines
2.8 KiB
TypeScript
import {
|
|
AstCreator,
|
|
ETypeKind,
|
|
Expr,
|
|
ExprKind,
|
|
Stmt,
|
|
StmtKind,
|
|
} from "../ast.ts";
|
|
import { AstVisitor, visitExpr, VisitRes, visitStmts } from "../ast_visitor.ts";
|
|
import { Pos } from "../token.ts";
|
|
|
|
export class ArrayLiteralDesugarer implements AstVisitor {
|
|
public constructor(
|
|
private astCreator: AstCreator,
|
|
) {}
|
|
|
|
public desugar(stmts: Stmt[]) {
|
|
visitStmts(stmts, this);
|
|
}
|
|
|
|
visitArrayExpr(expr: Expr): VisitRes {
|
|
if (expr.kind.type !== "array") {
|
|
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,
|
|
});
|
|
|
|
if (expr.kind.exprs.length < 1) {
|
|
throw new Error("");
|
|
}
|
|
|
|
expr.kind = {
|
|
type: "block",
|
|
stmts: [
|
|
Stmt({
|
|
type: "let",
|
|
param: this.astCreator.param({
|
|
ident: "::value",
|
|
mut: true,
|
|
pos: npos,
|
|
}),
|
|
value: Expr({
|
|
type: "call",
|
|
subject: Expr({
|
|
type: "etype_args",
|
|
subject: std("array_new"),
|
|
etypeArgs: [
|
|
EType({
|
|
type: "type_of",
|
|
expr: expr.kind.exprs[0],
|
|
}),
|
|
],
|
|
}),
|
|
args: [],
|
|
}),
|
|
}),
|
|
...expr.kind.exprs
|
|
.map((expr) =>
|
|
Stmt({
|
|
type: "expr",
|
|
expr: Expr({
|
|
type: "call",
|
|
subject: std("array_push"),
|
|
args: [
|
|
Expr({ type: "ident", ident: "::value" }),
|
|
expr,
|
|
],
|
|
}),
|
|
})
|
|
),
|
|
],
|
|
expr: Expr({ type: "ident", ident: "::value" }),
|
|
};
|
|
|
|
visitExpr(expr, this);
|
|
|
|
return "stop";
|
|
}
|
|
}
|