"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ReflectionEngine = void 0;
exports.expandReflection = expandReflection;
exports.reflectTypeInfo = reflectTypeInfo;
/**
 * Compile-time reflection & metaprogramming.
 * Synthesizes JSON serializers and field mappers from struct declarations.
 */
class ReflectionEngine {
    types = new Map();
    expand(program) {
        const errors = [];
        const synthesized = [];
        for (const stmt of program.statements) {
            if (stmt.type === "StructDeclaration") {
                const decl = stmt;
                const reflected = {
                    name: decl.name.value,
                    kind: "struct",
                    fields: decl.fields.map((f) => ({
                        name: f.name.value,
                        typeName: f.typeName,
                    })),
                    attributes: decl.attributes.map((a) => a.name),
                };
                this.types.set(reflected.name, reflected);
                synthesized.push(...this.synthesizeJsonHelpers(decl));
            }
        }
        return {
            program: {
                type: "Program",
                statements: [...program.statements, ...synthesized],
                tokenLiteral: program.tokenLiteral,
            },
            errors,
        };
    }
    getType(name) {
        return this.types.get(name);
    }
    listTypes() {
        return [...this.types.values()];
    }
    synthesizeJsonHelpers(decl) {
        const typeName = decl.name.value;
        const tok = (literal, type = "IDENT") => ({
            type,
            literal,
            line: decl.token.line,
            column: decl.token.column,
        });
        const ident = (name) => {
            const token = tok(name);
            return {
                kind: "expression",
                type: "Identifier",
                token,
                value: name,
                tokenLiteral: () => name,
            };
        };
        const summary = decl.fields
            .map((f) => `${f.name.value}:${f.typeName}`)
            .join(",");
        const retValue = {
            kind: "expression",
            type: "StringLiteral",
            token: tok(`{${summary}}`, "STRING"),
            value: `{${summary}}`,
            tokenLiteral: () => `"${summary}"`,
        };
        const ret = {
            kind: "statement",
            type: "ReturnStatement",
            token: tok("return", "RETURN"),
            returnValue: retValue,
            tokenLiteral: () => "return",
        };
        const fn = {
            kind: "expression",
            type: "FunctionLiteral",
            token: tok("fn", "FN"),
            parameters: [ident("value")],
            body: {
                kind: "statement",
                type: "BlockStatement",
                token: tok("{", "{"),
                statements: [ret],
                tokenLiteral: () => "{",
            },
            isAsync: false,
            tokenLiteral: () => "fn",
        };
        const letStmt = {
            kind: "statement",
            type: "LetStatement",
            token: tok("let", "LET"),
            name: ident(`${typeName}_to_json`),
            mutable: false,
            typeAnnotation: null,
            value: fn,
            tokenLiteral: () => "let",
        };
        const fieldsLit = {
            kind: "expression",
            type: "StringLiteral",
            token: tok(decl.fields.map((f) => f.name.value).join(","), "STRING"),
            value: decl.fields.map((f) => f.name.value).join(","),
            tokenLiteral: () => "fields",
        };
        const fieldsLet = {
            kind: "statement",
            type: "LetStatement",
            token: tok("let", "LET"),
            name: ident(`${typeName}_fields`),
            mutable: false,
            typeAnnotation: null,
            value: fieldsLit,
            tokenLiteral: () => "let",
        };
        return [letStmt, fieldsLet];
    }
}
exports.ReflectionEngine = ReflectionEngine;
function expandReflection(program) {
    return new ReflectionEngine().expand(program);
}
function reflectTypeInfo(program, name) {
    const engine = new ReflectionEngine();
    engine.expand(program);
    return engine.getType(name) ?? null;
}
//# sourceMappingURL=reflection.js.map