@@ -421,12 +421,17 @@ export class Type {
421421
422422 /** Tests if this type equals the specified. */
423423 equals ( other : Type ) : bool {
424- if ( this . kind != other . kind ) return false ;
424+ if ( this . kind != other . kind ) {
425+ return false ;
426+ }
425427 if ( this . isReference ) {
428+ let selfSignatureReference = this . signatureReference ;
429+ let otherSignatureReference = other . signatureReference ;
430+
426431 return (
427- this . classReference == other . classReference &&
428- this . signatureReference == other . signatureReference &&
429- this . isNullableReference == other . isNullableReference
432+ this . classReference == other . classReference
433+ && selfSignatureReference == otherSignatureReference
434+ && this . isNullableReference == other . isNullableReference
430435 ) ;
431436 }
432437 return true ;
@@ -882,58 +887,71 @@ export function typesToString(types: Type[]): string {
882887
883888/** Represents a fully resolved function signature. */
884889export class Signature {
885- /** Unique id representing this signature. */
886- id : u32 = 0 ;
887- /** Parameter types, if any, excluding `this`. */
888- parameterTypes : Type [ ] ;
889- /** Number of required parameters excluding `this`. Other parameters are considered optional. */
890- requiredParameters : i32 ;
891- /** Return type. */
892- returnType : Type ;
893- /** This type, if an instance signature. */
894- thisType : Type | null ;
895- /** Whether the last parameter is a rest parameter. */
896- hasRest : bool ;
897- /** Respective function type. */
898- type : Type ;
899- /** The program that created this signature. */
900- program : Program ;
901-
902- /** Constructs a new signature. */
903- constructor (
890+ /** Construct a new signature. */
891+ public static create (
892+ /** The program that created this signature. */
904893 program : Program ,
905- parameterTypes : Type [ ] | null = null ,
906- returnType : Type | null = null ,
907- thisType : Type | null = null
908- ) {
909- this . parameterTypes = parameterTypes ? parameterTypes : [ ] ;
910- this . requiredParameters = 0 ;
911- this . returnType = returnType ? returnType : Type . void ;
912- this . thisType = thisType ;
913- this . program = program ;
914- this . hasRest = false ;
894+ /** Parameter types, if any, excluding `this`. */
895+ parameterTypes : Type [ ] = [ ] ,
896+ /** Return type. */
897+ returnType : Type = Type . void ,
898+ /** This type, if an instance signature. */
899+ thisType : Type | null = null ,
900+ /** Number of required parameters excluding `this`. Other parameters are considered optional. */
901+ requiredParameters : i32 = parameterTypes ? parameterTypes . length : 0 ,
902+ /** Whether the last parameter is a rest parameter. */
903+ hasRest : bool = false ,
904+ ) : Signature {
905+ // get the usize type, and the type of the signature
915906 let usizeType = program . options . usizeType ;
916907 let type = new Type (
917908 usizeType . kind ,
918909 usizeType . flags & ~ TypeFlags . Value | TypeFlags . Reference ,
919910 usizeType . size
920911 ) ;
921- this . type = type ;
922- type . signatureReference = this ;
923912
913+ // calculate the properties
924914 let signatureTypes = program . uniqueSignatures ;
925- let length = signatureTypes . length ;
926- for ( let i = 0 ; i < length ; i ++ ) {
927- let compare = unchecked ( signatureTypes [ i ] ) ;
928- if ( this . equals ( compare ) ) {
929- this . id = compare . id ;
930- return this ;
931- }
915+ let nextId = program . nextSignatureId ;
916+
917+ // construct the signature and calculate it's unique key
918+ let signature = new Signature ( program , parameterTypes , returnType , thisType , requiredParameters , hasRest , nextId , type ) ;
919+ let uniqueKey = signature . toString ( ) ;
920+
921+ // check if it exists, and return it
922+ if ( signatureTypes . has ( uniqueKey ) ) {
923+ let existing = assert ( signatureTypes . get ( uniqueKey ) ) ;
924+ assert ( signature . equals ( existing ) ) ;
925+ return existing ;
932926 }
933- this . id = program . nextSignatureId ++ ;
934- signatureTypes . push ( this ) ;
927+
928+ // otherwise increment the program's signature id, set the signature reference of the type, and memoize the signature
929+ program . nextSignatureId = nextId + 1 ;
930+ type . signatureReference = signature ;
931+ signatureTypes . set ( uniqueKey , signature ) ;
932+ return signature ;
935933 }
936934
935+ /** Constructs a new signature. */
936+ private constructor (
937+ /** The program that created this signature. */
938+ public readonly program : Program ,
939+ /** Parameter types, if any, excluding `this`. */
940+ public readonly parameterTypes : Type [ ] ,
941+ /** Return type. */
942+ public readonly returnType : Type ,
943+ /** This type, if an instance signature. */
944+ public readonly thisType : Type | null ,
945+ /** Number of required parameters excluding `this`. Other parameters are considered optional. */
946+ public readonly requiredParameters : i32 ,
947+ /** Whether the last parameter is a rest parameter. */
948+ public readonly hasRest : bool ,
949+ /** Unique id representing this signature. */
950+ public readonly id : u32 ,
951+ /** Respective function type. */
952+ public readonly type : Type ,
953+ ) { }
954+
937955 get paramRefs ( ) : TypeRef {
938956 let thisType = this . thisType ;
939957 let parameterTypes = this . parameterTypes ;
@@ -975,15 +993,15 @@ export class Signature {
975993 if ( ! this . returnType . equals ( other . returnType ) ) return false ;
976994
977995 // check parameter types
978- let thisParameterTypes = this . parameterTypes ;
996+ let selfParameterTypes = this . parameterTypes ;
979997 let otherParameterTypes = other . parameterTypes ;
980- let numParameters = thisParameterTypes . length ;
981- if ( numParameters != otherParameterTypes . length ) return false ;
998+ let numParameters = selfParameterTypes . length ;
999+ if ( numParameters != otherParameterTypes . length ) return false ;
9821000
9831001 for ( let i = 0 ; i < numParameters ; ++ i ) {
984- let thisParameterType = unchecked ( thisParameterTypes [ i ] ) ;
1002+ let selfParameterType = unchecked ( selfParameterTypes [ i ] ) ;
9851003 let otherParameterType = unchecked ( otherParameterTypes [ i ] ) ;
986- if ( ! thisParameterType . equals ( otherParameterType ) ) return false ;
1004+ if ( ! selfParameterType . equals ( otherParameterType ) ) return false ;
9871005 }
9881006 return true ;
9891007 }
@@ -1105,7 +1123,6 @@ export class Signature {
11051123 let thisType = this . thisType ;
11061124 if ( thisType ) {
11071125 sb . push ( validWat ? "this:" : "this: " ) ;
1108- assert ( ! thisType . signatureReference ) ;
11091126 sb . push ( thisType . toString ( validWat ) ) ;
11101127 index = 1 ;
11111128 }
@@ -1127,18 +1144,20 @@ export class Signature {
11271144 }
11281145
11291146 /** Creates a clone of this signature that is safe to modify. */
1130- clone ( ) : Signature {
1147+ clone ( requiredParameters : i32 = this . requiredParameters , hasRest : bool = this . hasRest ) : Signature {
11311148 let parameterTypes = this . parameterTypes ;
11321149 let numParameterTypes = parameterTypes . length ;
11331150 let cloneParameterTypes = new Array < Type > ( numParameterTypes ) ;
11341151 for ( let i = 0 ; i < numParameterTypes ; ++ i ) {
11351152 unchecked ( cloneParameterTypes [ i ] = parameterTypes [ i ] ) ;
11361153 }
1137- return new Signature (
1154+ return Signature . create (
11381155 this . program ,
11391156 cloneParameterTypes ,
11401157 this . returnType ,
1141- this . thisType
1158+ this . thisType ,
1159+ requiredParameters ,
1160+ hasRest
11421161 ) ;
11431162 }
11441163}
0 commit comments