@@ -421,12 +421,17 @@ export class Type {
421
421
422
422
/** Tests if this type equals the specified. */
423
423
equals ( other : Type ) : bool {
424
- if ( this . kind != other . kind ) return false ;
424
+ if ( this . kind != other . kind ) {
425
+ return false ;
426
+ }
425
427
if ( this . isReference ) {
428
+ let selfSignatureReference = this . signatureReference ;
429
+ let otherSignatureReference = other . signatureReference ;
430
+
426
431
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
430
435
) ;
431
436
}
432
437
return true ;
@@ -882,58 +887,71 @@ export function typesToString(types: Type[]): string {
882
887
883
888
/** Represents a fully resolved function signature. */
884
889
export 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. */
904
893
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
915
906
let usizeType = program . options . usizeType ;
916
907
let type = new Type (
917
908
usizeType . kind ,
918
909
usizeType . flags & ~ TypeFlags . Value | TypeFlags . Reference ,
919
910
usizeType . size
920
911
) ;
921
- this . type = type ;
922
- type . signatureReference = this ;
923
912
913
+ // calculate the properties
924
914
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 ;
932
926
}
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 ;
935
933
}
936
934
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
+
937
955
get paramRefs ( ) : TypeRef {
938
956
let thisType = this . thisType ;
939
957
let parameterTypes = this . parameterTypes ;
@@ -975,15 +993,15 @@ export class Signature {
975
993
if ( ! this . returnType . equals ( other . returnType ) ) return false ;
976
994
977
995
// check parameter types
978
- let thisParameterTypes = this . parameterTypes ;
996
+ let selfParameterTypes = this . parameterTypes ;
979
997
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 ;
982
1000
983
1001
for ( let i = 0 ; i < numParameters ; ++ i ) {
984
- let thisParameterType = unchecked ( thisParameterTypes [ i ] ) ;
1002
+ let selfParameterType = unchecked ( selfParameterTypes [ i ] ) ;
985
1003
let otherParameterType = unchecked ( otherParameterTypes [ i ] ) ;
986
- if ( ! thisParameterType . equals ( otherParameterType ) ) return false ;
1004
+ if ( ! selfParameterType . equals ( otherParameterType ) ) return false ;
987
1005
}
988
1006
return true ;
989
1007
}
@@ -1105,7 +1123,6 @@ export class Signature {
1105
1123
let thisType = this . thisType ;
1106
1124
if ( thisType ) {
1107
1125
sb . push ( validWat ? "this:" : "this: " ) ;
1108
- assert ( ! thisType . signatureReference ) ;
1109
1126
sb . push ( thisType . toString ( validWat ) ) ;
1110
1127
index = 1 ;
1111
1128
}
@@ -1127,18 +1144,20 @@ export class Signature {
1127
1144
}
1128
1145
1129
1146
/** 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 {
1131
1148
let parameterTypes = this . parameterTypes ;
1132
1149
let numParameterTypes = parameterTypes . length ;
1133
1150
let cloneParameterTypes = new Array < Type > ( numParameterTypes ) ;
1134
1151
for ( let i = 0 ; i < numParameterTypes ; ++ i ) {
1135
1152
unchecked ( cloneParameterTypes [ i ] = parameterTypes [ i ] ) ;
1136
1153
}
1137
- return new Signature (
1154
+ return Signature . create (
1138
1155
this . program ,
1139
1156
cloneParameterTypes ,
1140
1157
this . returnType ,
1141
- this . thisType
1158
+ this . thisType ,
1159
+ requiredParameters ,
1160
+ hasRest
1142
1161
) ;
1143
1162
}
1144
1163
}
0 commit comments