import { mapFilterMap , mapFilter , mapTranspose , hashString } from "collection-utils" ; import { panic , assert } from "../support/Support" ; import { Type , TypeKind } from "../Type" ; import { BaseGraphRewriteBuilder } from "../GraphRewriting" ; export class TypeAttributeKind < T > { constructor ( readonly name ) { } appliesToTypeKind ( kind ) { return kind !== "any" ; } combine ( _attrs ) { return panic ( `Cannot combine type attribute ${ this . name }` ) ; } intersect ( attrs ) { return this . combine ( attrs ) ; } makeInferred ( _ ) { return panic ( `Cannot make type attribute ${ this . name } inferred` ) ; } increaseDistance ( attrs ) { return attrs ; } addToSchema ( _schema , _t , _attrs ) { return ; } children ( _ ) { return new Set ( ) ; } stringify ( _ ) { return undefined ; } get inIdentity ( ) : boolean { return false ; } requiresUniqueIdentity ( _ ) { return false ; } reconstitute < TBuilder extends BaseGraphRewriteBuilder > ( _builder , a ) { return a ; } makeAttributes ( value ) { const kvps = [ [ this , value ] ] ; return new Map ( kvps ) ; } tryGetInAttributes ( a ) { return a . get ( this ) ; } private setInAttributes ( a , value ) { return new Map ( a ) . set ( this , value ) ; } modifyInAttributes ( a , modify ) { const modified = modify ( this . tryGetInAttributes ( a ) ) ; if ( modified === undefined ) { const result = new Map ( a ) ; result . delete ( this ) ; return result ; } return this . setInAttributes ( a , modified ) ; } setDefaultInAttributes ( a , makeDefault ) { if ( this . tryGetInAttributes ( a ) !== undefined ) return a ; return this . modifyInAttributes ( a , makeDefault ) ; } removeInAttributes ( a ) { return mapFilter ( a , ( _ , k ) => k !== this ) ; } equals ( other ) { if ( ! ( other instanceof TypeAttributeKind ) ) { return false ; } return this . name === other . name ; } hashCode ( ) { return hashString ( this . name ) ; } } export type TypeAttributes = ReadonlyMap < TypeAttributeKind < any > , any > ; export const emptyTypeAttributes = new Map ( ) ; export type CombinationKind = "union" | "intersect" ; export function combineTypeAttributes ( kind , attributeArray ) ; export function combineTypeAttributes ( kind , a , b ) ; export function combineTypeAttributes ( combinationKind , firstOrArray , second ? ) { const union = combinationKind === "union" ; let attributeArray ; if ( Array . isArray ( firstOrArray ) ) { attributeArray = firstOrArray ; } else { if ( second === undefined ) { return panic ( "Must have on array or two attributes" ) ; } attributeArray = [ firstOrArray , second ] ; } const attributesByKind = mapTranspose ( attributeArray ) ; function combine ( attrs , kind ) { assert ( attrs . length > 0 , "Cannot combine zero type attributes" ) ; if ( attrs . length === 1 ) return attrs [ 0 ] ; if ( union ) { return kind . combine ( attrs ) ; } else { return kind . intersect ( attrs ) ; } } return mapFilterMap ( attributesByKind , combine ) ; } export function makeTypeAttributesInferred ( attr ) { return mapFilterMap ( attr , ( value , kind ) => kind . makeInferred ( value ) ) ; } export function increaseTypeAttributesDistance ( attr ) { return mapFilterMap ( attr , ( value , kind ) => kind . increaseDistance ( value ) ) ; }