@@ -58,15 +58,18 @@ export class Type {
5858 functionType : Function | null ;
5959 /** Whether nullable or not. */
6060 isNullable : bool = false ;
61- /** Respective nullable type, if nullable. */
61+ /** Respective nullable type, if non- nullable. */
6262 nullableType : Type | null = null ;
63+ /** Respective non-nullable type, if nullable. */
64+ nonNullableType : Type ;
6365
6466 /** Constructs a new resolved type. */
6567 constructor ( kind : TypeKind , size : i32 ) {
6668 this . kind = kind ;
6769 this . size = size ;
6870 this . byteSize = < i32 > ceil < f64 > ( < f64 > size / 8 ) ;
6971 this . classType = null ;
72+ this . nonNullableType = this ;
7073 }
7174
7275 /** Sign-extending 32-bit shift, if a small signed integer. */
@@ -75,23 +78,157 @@ export class Type {
7578 get smallIntegerMask ( ) : i32 { return - 1 >>> ( 32 - this . size ) ; }
7679
7780 /** Tests if this type is of any integer kind. */
78- get isAnyInteger ( ) : bool { return this . kind >= TypeKind . I8 && this . kind <= TypeKind . BOOL ; }
79- /** Tests if this type is of any small integer kind. */
80- get isSmallInteger ( ) : bool { return this . size != 0 && this . size < 32 ; }
81- /** Tests if this type is of any long integer kind. */
82- get isLongInteger ( ) : bool { return this . size == 64 && this . kind != TypeKind . F64 ; }
81+ get isAnyInteger ( ) : bool {
82+ switch ( this . kind ) {
83+ case TypeKind . I8 :
84+ case TypeKind . I16 :
85+ case TypeKind . I32 :
86+ case TypeKind . I64 :
87+ case TypeKind . ISIZE :
88+ case TypeKind . U8 :
89+ case TypeKind . U16 :
90+ case TypeKind . U32 :
91+ case TypeKind . U64 :
92+ case TypeKind . USIZE :
93+ case TypeKind . BOOL :
94+ return true ;
95+ default :
96+ return false ;
97+ }
98+ }
99+
83100 /** Tests if this type is of any unsigned integer kind. */
84- get isUnsignedInteger ( ) : bool { return this . kind >= TypeKind . U8 && this . kind <= TypeKind . BOOL ; }
101+ get isAnyUnsignedInteger ( ) : bool {
102+ switch ( this . kind ) {
103+ case TypeKind . U8 :
104+ case TypeKind . U16 :
105+ case TypeKind . U32 :
106+ case TypeKind . U64 :
107+ case TypeKind . USIZE :
108+ case TypeKind . BOOL :
109+ return true ;
110+ default :
111+ return false ;
112+ }
113+ }
114+
85115 /** Tests if this type is of any signed integer kind. */
86- get isSignedInteger ( ) : bool { return this . kind >= TypeKind . I8 && this . kind <= TypeKind . ISIZE ; }
87- /** Tests if this type is of any size kind, i.e., `isize` or `usize`. */
88- get isAnySize ( ) : bool { return this . kind == TypeKind . ISIZE || this . kind == TypeKind . USIZE ; }
116+ get isAnySignedInteger ( ) : bool {
117+ switch ( this . kind ) {
118+ case TypeKind . I8 :
119+ case TypeKind . I16 :
120+ case TypeKind . I32 :
121+ case TypeKind . I64 :
122+ case TypeKind . ISIZE :
123+ return true ;
124+ default :
125+ return false ;
126+ }
127+ }
128+
129+ /** Tests if this type is of any small integer kind. */
130+ get isSmallInteger ( ) : bool {
131+ switch ( this . kind ) {
132+ case TypeKind . I8 :
133+ case TypeKind . I16 :
134+ case TypeKind . U8 :
135+ case TypeKind . U16 :
136+ case TypeKind . BOOL :
137+ return true ;
138+ default :
139+ return false ;
140+ }
141+ }
142+
143+ /** Tests if this type is of any small signed integer kind. */
144+ get isSmallSignedInteger ( ) : bool {
145+ switch ( this . kind ) {
146+ case TypeKind . I8 :
147+ case TypeKind . I16 :
148+ return true ;
149+ default :
150+ return false ;
151+ }
152+ }
153+
154+ /** Tests if this type is of any small unsigned integer kind. */
155+ get isSmallUnsignedInteger ( ) : bool {
156+ switch ( this . kind ) {
157+ case TypeKind . U8 :
158+ case TypeKind . U16 :
159+ case TypeKind . BOOL :
160+ return true ;
161+ default :
162+ return false ;
163+ }
164+ }
165+
166+ /** Tests if this type is of any long integer kind. */
167+ get isLongInteger ( ) : bool {
168+ switch ( this . kind ) {
169+ case TypeKind . I64 :
170+ case TypeKind . U64 :
171+ return true ;
172+ case TypeKind . ISIZE :
173+ case TypeKind . USIZE :
174+ return this . size == 64 ;
175+ default :
176+ return false ;
177+ }
178+ }
179+
180+ /** Tests if this type is of any long signed integer kind. */
181+ get isLongSignedInteger ( ) : bool {
182+ switch ( this . kind ) {
183+ case TypeKind . I64 :
184+ return true ;
185+ case TypeKind . ISIZE :
186+ return this . size == 64 ;
187+ default :
188+ return false ;
189+ }
190+ }
191+
192+ /** Tests if this type is of any long unsigned integer kind. */
193+ get isLongUnsignedInteger ( ) : bool {
194+ switch ( this . kind ) {
195+ case TypeKind . U64 :
196+ return true ;
197+ case TypeKind . USIZE :
198+ return this . size == 64 ;
199+ default :
200+ return false ;
201+ }
202+ }
203+
204+ /** Tests if this type is of any size kind, that is `isize` or `usize`. */
205+ get isAnySize ( ) : bool {
206+ switch ( this . kind ) {
207+ case TypeKind . ISIZE :
208+ case TypeKind . USIZE :
209+ return true ;
210+ default :
211+ return false ;
212+ }
213+ }
214+
89215 /** Tests if this type is of any float kind, i.e., `f32` or `f64`. */
90- get isAnyFloat ( ) : bool { return this . kind == TypeKind . F32 || this . kind == TypeKind . F64 ; }
216+ get isAnyFloat ( ) : bool {
217+ switch ( this . kind ) {
218+ case TypeKind . F32 :
219+ case TypeKind . F64 :
220+ return true ;
221+ default :
222+ return false ;
223+ }
224+ }
225+
91226 /** Tests if this type is a class type. */
92227 get isClass ( ) : bool { return this . classType != null ; }
93228 /** Tests if this type is a function type. */
94229 get isFunction ( ) : bool { return this . functionType != null ; }
230+ /** Tests if this type is a reference type. */
231+ get isReference ( ) : bool { return this . classType != null || this . functionType != null ; }
95232
96233 /** Composes a class type from this type and a class. */
97234 asClass ( classType : Class ) : Type {
@@ -103,17 +240,20 @@ export class Type {
103240
104241 /** Composes a function type from this type and a function. */
105242 asFunction ( functionType : Function ) : Type {
106- assert ( this . kind == TypeKind . USIZE ) ;
243+ assert ( this . kind == TypeKind . USIZE && ! this . isReference ) ;
107244 var ret = new Type ( this . kind , this . size ) ;
108245 ret . functionType = functionType ;
109246 return ret ;
110247 }
111248
112249 /** Composes the respective nullable type of this type. */
113250 asNullable ( ) : Type | null {
114- assert ( this . kind == TypeKind . USIZE ) ;
115- if ( this . isNullable && ! this . nullableType )
251+ assert ( this . kind == TypeKind . USIZE && ! this . isReference ) ;
252+ if ( this . isNullable && ! this . nullableType ) {
116253 ( this . nullableType = new Type ( this . kind , this . size ) ) . isNullable = true ;
254+ this . nullableType . classType = this . classType ;
255+ this . nullableType . functionType = this . functionType ;
256+ }
117257 return this . nullableType ;
118258 }
119259
@@ -226,6 +366,34 @@ export class Type {
226366 }
227367 }
228368
369+ /** Converts this type to its native `-1` value. */
370+ toNativeNegOne ( module : Module ) : ExpressionRef {
371+ switch ( this . kind ) {
372+
373+ case TypeKind . VOID :
374+ assert ( false ) ;
375+
376+ default :
377+ return module . createI32 ( - 1 ) ;
378+
379+ case TypeKind . ISIZE :
380+ case TypeKind . USIZE :
381+ if ( this . size != 64 )
382+ return module . createI32 ( - 1 ) ;
383+ // fall-through
384+
385+ case TypeKind . I64 :
386+ case TypeKind . U64 :
387+ return module . createI64 ( - 1 , - 1 ) ;
388+
389+ case TypeKind . F32 :
390+ return module . createF32 ( - 1 ) ;
391+
392+ case TypeKind . F64 :
393+ return module . createF64 ( - 1 ) ;
394+ }
395+ }
396+
229397 /** Converts this type to its signature string. */
230398 toSignatureString ( ) : string {
231399 switch ( this . kind ) {
0 commit comments