@@ -8736,11 +8736,7 @@ export class Compiler extends DiagnosticEmitter {
8736
8736
break ;
8737
8737
}
8738
8738
case Token . TYPEOF : {
8739
- this . error (
8740
- DiagnosticCode . Operation_not_supported ,
8741
- expression . range
8742
- ) ;
8743
- return module . unreachable ( ) ;
8739
+ return this . compileTypeof ( expression , contextualType , constraints ) ;
8744
8740
}
8745
8741
default : {
8746
8742
assert ( false ) ;
@@ -8761,6 +8757,88 @@ export class Compiler extends DiagnosticEmitter {
8761
8757
) ;
8762
8758
}
8763
8759
8760
+ compileTypeof (
8761
+ expression : UnaryPrefixExpression ,
8762
+ contextualType : Type ,
8763
+ constraints : Constraints
8764
+ ) : ExpressionRef {
8765
+ var operand = expression . operand ;
8766
+ var expr : ExpressionRef = 0 ;
8767
+ var stringInstance = this . program . stringInstance ;
8768
+ var typeString : string ;
8769
+ if ( operand . kind == NodeKind . NULL ) {
8770
+ typeString = "object" ; // special since `null` without type context is usize
8771
+ } else {
8772
+ let element = this . resolver . lookupExpression ( operand , this . currentFlow , Type . auto , ReportMode . SWALLOW ) ;
8773
+ if ( ! element ) {
8774
+ switch ( operand . kind ) {
8775
+ case NodeKind . PROPERTYACCESS :
8776
+ case NodeKind . ELEMENTACCESS : {
8777
+ operand = operand . kind == NodeKind . PROPERTYACCESS
8778
+ ? ( < PropertyAccessExpression > operand ) . expression
8779
+ : ( < ElementAccessExpression > operand ) . expression ;
8780
+ let targetType = this . resolver . resolveExpression ( operand , this . currentFlow , Type . auto , ReportMode . REPORT ) ;
8781
+ if ( ! targetType ) {
8782
+ this . currentType = stringInstance . type ;
8783
+ return this . module . unreachable ( ) ;
8784
+ }
8785
+ expr = this . compileExpression ( operand , Type . auto ) ; // might have side-effects
8786
+ break ;
8787
+ }
8788
+ case NodeKind . IDENTIFIER : break ; // ignore error
8789
+ default : expr = this . compileExpression ( operand , Type . auto ) ; // trigger error
8790
+ }
8791
+ typeString = "undefined" ;
8792
+ } else {
8793
+ switch ( element . kind ) {
8794
+ case ElementKind . CLASS_PROTOTYPE :
8795
+ case ElementKind . NAMESPACE :
8796
+ case ElementKind . ENUM : {
8797
+ typeString = "object" ;
8798
+ break ;
8799
+ }
8800
+ case ElementKind . FUNCTION_PROTOTYPE : {
8801
+ typeString = "function" ;
8802
+ break ;
8803
+ }
8804
+ default : {
8805
+ expr = this . compileExpression ( operand , Type . auto ) ;
8806
+ let type = this . currentType ;
8807
+ expr = this . convertExpression ( expr , type , Type . void , true , false , operand ) ;
8808
+ if ( type . is ( TypeFlags . REFERENCE ) ) {
8809
+ let signatureReference = type . signatureReference ;
8810
+ if ( signatureReference ) {
8811
+ typeString = "function" ;
8812
+ } else {
8813
+ let classReference = type . classReference ;
8814
+ if ( classReference ) {
8815
+ if ( classReference . prototype === stringInstance . prototype ) {
8816
+ typeString = "string" ;
8817
+ } else {
8818
+ typeString = "object" ;
8819
+ }
8820
+ } else {
8821
+ typeString = "anyref" ; // TODO?
8822
+ }
8823
+ }
8824
+ } else if ( type == Type . bool ) {
8825
+ typeString = "boolean" ;
8826
+ } else if ( type . isAny ( TypeFlags . FLOAT | TypeFlags . INTEGER ) ) {
8827
+ typeString = "number" ;
8828
+ } else {
8829
+ typeString = "undefined" ; // failed to compile?
8830
+ }
8831
+ break ;
8832
+ }
8833
+ }
8834
+ }
8835
+ }
8836
+ this . currentType = stringInstance . type ;
8837
+ return expr
8838
+ ? this . module . block ( null , [ expr , this . ensureStaticString ( typeString ) ] , this . options . nativeSizeType )
8839
+ : this . ensureStaticString ( typeString ) ;
8840
+ }
8841
+
8764
8842
/** Makes sure that a 32-bit integer value is wrapped to a valid value of the specified type. */
8765
8843
ensureSmallIntegerWrap ( expr : ExpressionRef , type : Type ) : ExpressionRef {
8766
8844
var module = this . module ;
0 commit comments