@@ -35,8 +35,9 @@ type TypeFactory = (...typeParameters: Type[]) => Type;
3535export class TypeMapper {
3636 private readonly openTypesFactories : Map < string , TypeFactory > ;
3737 private readonly closedTypesMap : Map < string , Type > ;
38+ private readonly learnedTypesMap : Map < string , Type > ;
3839
39- constructor ( customTypes : CustomType [ ] = [ ] ) {
40+ constructor ( learnedTypes : CustomType [ ] = [ ] ) {
4041 this . openTypesFactories = new Map < string , TypeFactory > ( [
4142 [ "Option" , ( ...typeParameters : Type [ ] ) => new OptionType ( typeParameters [ 0 ] ) ] ,
4243 [ "List" , ( ...typeParameters : Type [ ] ) => new ListType ( typeParameters [ 0 ] ) ] ,
@@ -61,7 +62,7 @@ export class TypeMapper {
6162 [ "tuple7" , ( ...typeParameters : Type [ ] ) => new TupleType ( ...typeParameters ) ] ,
6263 [ "tuple8" , ( ...typeParameters : Type [ ] ) => new TupleType ( ...typeParameters ) ] ,
6364 // Known-length arrays.
64- // TODO: Handle these in typeExpressionParser, perhaps?
65+ // TODO: Handle these in typeExpressionParser!
6566 [ "array20" , ( ...typeParameters : Type [ ] ) => new ArrayVecType ( 20 , typeParameters [ 0 ] ) ] ,
6667 [ "array32" , ( ...typeParameters : Type [ ] ) => new ArrayVecType ( 32 , typeParameters [ 0 ] ) ] ,
6768 [ "array46" , ( ...typeParameters : Type [ ] ) => new ArrayVecType ( 46 , typeParameters [ 0 ] ) ] ,
@@ -93,14 +94,41 @@ export class TypeMapper {
9394 [ "AsyncCall" , new NothingType ( ) ]
9495 ] ) ;
9596
96- for ( const customType of customTypes ) {
97- this . closedTypesMap . set ( customType . getName ( ) , customType ) ;
97+ this . learnedTypesMap = new Map < string , Type > ( ) ;
98+
99+ // Boostrap from previously learned types, if any.
100+ for ( const type of learnedTypes ) {
101+ this . learnedTypesMap . set ( type . getName ( ) , type ) ;
102+ }
103+ }
104+
105+ mapType ( type : Type ) : Type {
106+ let mappedType = this . mapRecursiveType ( type ) ;
107+ if ( mappedType ) {
108+ // We do not learn generic types (that also have type parameters)
109+ if ( ! mappedType . isGenericType ( ) ) {
110+ this . learnType ( mappedType ) ;
111+ }
112+
113+ return mappedType ;
98114 }
115+
116+ throw new errors . ErrTypingSystem ( `Cannot map the type "${ type . getName ( ) } " to a known type` ) ;
99117 }
100118
101119 mapRecursiveType ( type : Type ) : Type | null {
102120 let isGeneric = type . isGenericType ( ) ;
103121
122+ let previouslyLearnedType = this . learnedTypesMap . get ( type . getName ( ) ) ;
123+ if ( previouslyLearnedType ) {
124+ return previouslyLearnedType ;
125+ }
126+
127+ let knownClosedType = this . closedTypesMap . get ( type . getName ( ) ) ;
128+ if ( knownClosedType ) {
129+ return knownClosedType ;
130+ }
131+
104132 if ( type . hasExactClass ( EnumType . ClassName ) ) {
105133 // This will call mapType() recursively, for all the enum variant fields.
106134 return this . mapEnumType ( < EnumType > type ) ;
@@ -115,27 +143,13 @@ export class TypeMapper {
115143 // This will call mapType() recursively, for all the type parameters.
116144 return this . mapGenericType ( type ) ;
117145 }
118-
119- return null ;
120- }
121-
122- mapType ( type : Type ) : Type {
123- let mappedType = this . mapRecursiveType ( type ) ;
124- if ( mappedType !== null ) {
125- return mappedType ;
126- }
127-
128- let knownClosedType = this . closedTypesMap . get ( type . getName ( ) ) ;
129- if ( ! knownClosedType ) {
130- throw new errors . ErrTypingSystem ( `Cannot map the type "${ type . getName ( ) } " to a known type` ) ;
131- }
132146
133- return this . mapRecursiveType ( knownClosedType ) ?? knownClosedType ;
147+ return null ;
134148 }
135149
136- feedCustomType ( type : Type ) : void {
137- this . closedTypesMap . delete ( type . getName ( ) ) ;
138- this . closedTypesMap . set ( type . getName ( ) , type ) ;
150+ private learnType ( type : Type ) : void {
151+ this . learnedTypesMap . delete ( type . getName ( ) ) ;
152+ this . learnedTypesMap . set ( type . getName ( ) , type ) ;
139153 }
140154
141155 private mapStructType ( type : StructType ) : StructType {
0 commit comments