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"; } }