/**
 * Type Signature System
 *
 * Implements structural typing through canonical type signatures.
 * Two types with identical structure map to the same signature,
 * enabling duck typing while maintaining static analysis.
 */
/**
 * Generates canonical type signatures for structural typing
 */
export class TypeSignatureGenerator {
    signatureCache = new Map();
    typeStringCache = new Map();
    /**
     * Get or generate signature for an interface
     */
    getInterfaceSignature(iface) {
        const key = `interface:${iface.name}`;
        if (this.signatureCache.has(key)) {
            return this.signatureCache.get(key);
        }
        const methods = iface.methods.map(m => ({
            name: m.name,
            params: m.params.map(p => ({
                name: p.name,
                type: this.getTypeString(p.type),
            })),
            returnType: this.getTypeString(m.returnType),
        }));
        // Sort methods by name for deterministic signature
        methods.sort((a, b) => a.name.localeCompare(b.name));
        const signature = this.createSignature([], methods);
        this.signatureCache.set(key, signature);
        return signature;
    }
    /**
     * Get or generate signature for a class (public interface only)
     */
    getClassSignature(cls) {
        const key = `class:${cls.name}`;
        if (this.signatureCache.has(key)) {
            return this.signatureCache.get(key);
        }
        const properties = cls.fields
            .filter(f => !f.name.startsWith('_')) // Exclude private fields
            .map(f => ({
            name: f.name,
            type: this.getTypeString(f.type),
            readonly: f.isReadonly,
        }));
        const methods = cls.methods
            .filter(m => !m.isStatic && !m.name.startsWith('_'))
            .map(m => ({
            name: m.name,
            params: m.params.map(p => ({
                name: p.name,
                type: this.getTypeString(p.type),
            })),
            returnType: this.getTypeString(m.returnType),
        }));
        // Sort for deterministic signature
        properties.sort((a, b) => a.name.localeCompare(b.name));
        methods.sort((a, b) => a.name.localeCompare(b.name));
        const signature = this.createSignature(properties, methods);
        this.signatureCache.set(key, signature);
        return signature;
    }
    /**
     * Check if two types have compatible signatures (structural typing)
     */
    areCompatible(type1, type2) {
        // Primitive types must match exactly
        if (type1.kind === 'primitive' && type2.kind === 'primitive') {
            return type1.type === type2.type;
        }
        // For complex types, compare canonical strings
        const str1 = this.getTypeString(type1);
        const str2 = this.getTypeString(type2);
        return str1 === str2;
    }
    /**
     * Get canonical string representation of a type
     */
    getTypeString(type) {
        if (this.typeStringCache.has(type)) {
            return this.typeStringCache.get(type);
        }
        let result;
        switch (type.kind) {
            case 'primitive':
                result = type.type;
                break;
            case 'class':
            case 'interface':
                result = `${type.name}<${type.ownership}>`;
                if (type.typeArgs && type.typeArgs.length > 0) {
                    const args = type.typeArgs.map(t => this.getTypeString(t)).join(',');
                    result += `[${args}]`;
                }
                break;
            case 'struct':
                // Struct types are structural - generate signature from sorted fields
                const fields = type.fields
                    .map(f => `${f.name}:${this.getTypeString(f.type)}`)
                    .sort()
                    .join(',');
                result = `{${fields}}<${type.ownership}>`;
                break;
            case 'array':
                result = `Array<${this.getTypeString(type.element)},${type.ownership}>`;
                break;
            case 'map':
                result = `Map<${this.getTypeString(type.key)},${this.getTypeString(type.value)},${type.ownership}>`;
                break;
            case 'promise':
                result = `Promise<${this.getTypeString(type.resultType)}>`;
                break;
            case 'function':
                const params = type.params.map(p => this.getTypeString(p)).join(',');
                result = `(${params})->${this.getTypeString(type.returnType)}`;
                break;
            case 'union':
                const types = type.types.map(t => this.getTypeString(t)).sort();
                result = types.join('|');
                break;
            case 'intersection':
                const intersectionTypes = type.types.map(t => this.getTypeString(t)).sort();
                result = intersectionTypes.join('&');
                break;
            case 'typeAlias':
                result = this.getTypeString(type.aliasedType);
                break;
            case 'nullable':
                result = `${this.getTypeString(type.inner)}?`;
                break;
            default:
                result = 'unknown';
                break;
        }
        this.typeStringCache.set(type, result);
        return result;
    }
    /**
     * Create signature from properties and methods
     */
    createSignature(properties, methods) {
        // Build canonical string
        const parts = [];
        for (const prop of properties) {
            const readonly = prop.readonly ? 'readonly ' : '';
            parts.push(`${readonly}${prop.name}:${prop.type}`);
        }
        for (const method of methods) {
            const params = method.params.map(p => `${p.name}:${p.type}`).join(',');
            parts.push(`${method.name}(${params}):${method.returnType}`);
        }
        const canonical = parts.join(';');
        const hash = this.hashString(canonical);
        return {
            hash,
            canonical,
            properties,
            methods,
        };
    }
    /**
     * Simple string hash (FNV-1a)
     */
    hashString(str) {
        let hash = 2166136261;
        for (let i = 0; i < str.length; i++) {
            hash ^= str.charCodeAt(i);
            hash = Math.imul(hash, 16777619);
        }
        return (hash >>> 0).toString(16).padStart(8, '0');
    }
    /**
     * Clear all caches
     */
    reset() {
        this.signatureCache.clear();
        this.typeStringCache.clear();
    }
}
//# sourceMappingURL=signatures.js.map