@@ -86,7 +86,8 @@ import {
86
86
PropertyPrototype ,
87
87
IndexSignature ,
88
88
File ,
89
- mangleInternalName
89
+ mangleInternalName ,
90
+ DeclaredElement
90
91
} from "./program" ;
91
92
92
93
import {
@@ -8601,46 +8602,36 @@ export class Compiler extends DiagnosticEmitter {
8601
8602
private compileObjectLiteral ( expression : ObjectLiteralExpression , contextualType : Type ) : ExpressionRef {
8602
8603
var module = this . module ;
8603
8604
8604
- // contextual type must be a class
8605
+ // Check that contextual type is a class (TODO: hidden class for interfaces?)
8605
8606
var classReference = contextualType . classReference ;
8606
- if ( ! classReference || classReference . is ( CommonFlags . ABSTRACT ) ) {
8607
+ if ( ! contextualType . is ( TypeFlags . REFERENCE ) || ! classReference || classReference . kind != ElementKind . CLASS ) {
8607
8608
this . error (
8608
8609
DiagnosticCode . Type_0_is_not_assignable_to_type_1 ,
8609
8610
expression . range , "<object>" , contextualType . toString ( )
8610
8611
) ;
8611
8612
return module . unreachable ( ) ;
8612
8613
}
8614
+ var classType = classReference . type ;
8615
+ this . currentType = classType . nonNullableType ;
8616
+ if ( classReference . is ( CommonFlags . ABSTRACT ) ) {
8617
+ this . error (
8618
+ DiagnosticCode . Cannot_create_an_instance_of_an_abstract_class ,
8619
+ expression . range
8620
+ ) ;
8621
+ return module . unreachable ( ) ;
8622
+ }
8613
8623
8614
- // if present, check that the constructor is compatible with object literals
8615
- var ctor = classReference . constructorInstance ;
8616
- if ( ctor ) {
8617
- // TODO: if the constructor requires parameters, check whether these are given as part of the
8618
- // object literal and use them to call the ctor while not generating a store.
8619
- if ( ctor . signature . requiredParameters ) {
8620
- this . error (
8621
- DiagnosticCode . Constructor_of_class_0_must_not_require_any_arguments ,
8622
- expression . range , classReference . toString ( )
8623
- ) ;
8624
- return module . unreachable ( ) ;
8625
- }
8626
- if ( ctor . is ( CommonFlags . PRIVATE ) ) {
8627
- this . error (
8628
- DiagnosticCode . Constructor_of_class_0_is_private_and_only_accessible_within_the_class_declaration ,
8629
- expression . range , classReference . toString ( )
8630
- ) ;
8631
- return module . unreachable ( ) ;
8632
- }
8633
- if ( ctor . is ( CommonFlags . PROTECTED ) ) {
8634
- this . error (
8635
- DiagnosticCode . Constructor_of_class_0_is_protected_and_only_accessible_within_the_class_declaration ,
8636
- expression . range , classReference . toString ( )
8637
- ) ;
8638
- return module . unreachable ( ) ;
8639
- }
8640
- if ( ctor . hasDecorator ( DecoratorFlags . UNSAFE ) ) this . checkUnsafe ( expression ) ;
8624
+ // Check that the class is compatible with object literals
8625
+ var ctorPrototype = classReference . prototype . constructorPrototype ;
8626
+ if ( ctorPrototype ) {
8627
+ this . errorRelated (
8628
+ DiagnosticCode . Class_0_cannot_declare_a_constructor_when_instantiated_from_an_object_literal ,
8629
+ expression . range , ctorPrototype . identifierNode . range , classType . toString ( )
8630
+ ) ;
8631
+ return module . unreachable ( ) ;
8641
8632
}
8642
8633
8643
- var isManaged = classReference . type . isManaged ;
8634
+ var isManaged = classType . isManaged ;
8644
8635
if ( ! isManaged ) {
8645
8636
this . checkUnsafe ( expression , findDecorator ( DecoratorKind . UNMANAGED , classReference . decoratorNodes ) ) ;
8646
8637
}
@@ -8654,29 +8645,47 @@ export class Compiler extends DiagnosticEmitter {
8654
8645
var exprs = new Array < ExpressionRef > ( ) ;
8655
8646
var flow = this . currentFlow ;
8656
8647
var tempLocal = isManaged
8657
- ? flow . getAutoreleaseLocal ( classReference . type )
8658
- : flow . getTempLocal ( classReference . type ) ;
8648
+ ? flow . getAutoreleaseLocal ( classType )
8649
+ : flow . getTempLocal ( classType ) ;
8650
+ var nativeClassType = classType . toNativeType ( ) ;
8659
8651
assert ( numNames == values . length ) ;
8660
8652
8661
8653
// Assume all class fields will be omitted, and add them to our omitted list
8662
- let omittedClassFieldMembers = new Set < string > ( ) ;
8654
+ var omittedFields = new Set < Field > ( ) ;
8663
8655
if ( members ) {
8664
8656
for ( let _keys = Map_keys ( members ) , i = 0 , k = _keys . length ; i < k ; ++ i ) {
8665
8657
let memberKey = _keys [ i ] ;
8666
8658
let member = assert ( members . get ( memberKey ) ) ;
8667
8659
if ( member !== null && member . kind == ElementKind . FIELD ) {
8668
- omittedClassFieldMembers . add ( member . name ) ;
8660
+ omittedFields . add ( < Field > member ) ; // incl. private/protected
8669
8661
}
8670
8662
}
8671
8663
}
8672
8664
8673
8665
// Iterate through the members defined in our expression
8674
- for ( let i = 0 , k = numNames ; i < k ; ++ i ) {
8675
- let member = members ? members . get ( names [ i ] . text ) : null ;
8676
- if ( ! member || member . kind != ElementKind . FIELD ) {
8666
+ for ( let i = 0 ; i < numNames ; ++ i ) {
8667
+ let memberName = names [ i ] . text ;
8668
+ let member : DeclaredElement ;
8669
+ if ( ! members || ! members . has ( memberName ) || ( member = assert ( members . get ( memberName ) ) ) . kind != ElementKind . FIELD ) {
8677
8670
this . error (
8678
8671
DiagnosticCode . Property_0_does_not_exist_on_type_1 ,
8679
- names [ i ] . range , names [ i ] . text , classReference . toString ( )
8672
+ names [ i ] . range , memberName , classType . toString ( )
8673
+ ) ;
8674
+ hasErrors = true ;
8675
+ continue ;
8676
+ }
8677
+ if ( member . is ( CommonFlags . PRIVATE ) ) {
8678
+ this . error (
8679
+ DiagnosticCode . Property_0_is_private_and_only_accessible_within_class_1 ,
8680
+ names [ i ] . range , memberName , classType . toString ( )
8681
+ ) ;
8682
+ hasErrors = true ;
8683
+ continue ;
8684
+ }
8685
+ if ( member . is ( CommonFlags . PROTECTED ) ) {
8686
+ this . error (
8687
+ DiagnosticCode . Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses ,
8688
+ names [ i ] . range , memberName , classType . toString ( )
8680
8689
) ;
8681
8690
hasErrors = true ;
8682
8691
continue ;
@@ -8685,95 +8694,98 @@ export class Compiler extends DiagnosticEmitter {
8685
8694
let fieldType = fieldInstance . type ;
8686
8695
8687
8696
let expr = this . compileExpression ( values [ i ] , fieldType , Constraints . CONV_IMPLICIT | Constraints . WILL_RETAIN ) ;
8688
- if ( isManaged && fieldType . isManaged && ! this . skippedAutoreleases . has ( expr ) ) {
8697
+ if ( fieldType . isManaged && ! this . skippedAutoreleases . has ( expr ) ) {
8689
8698
expr = this . makeRetain ( expr ) ;
8690
8699
}
8691
- exprs . push ( this . module . store ( // TODO: handle setters as well
8692
- fieldType . byteSize ,
8693
- this . module . local_get ( tempLocal . index , this . options . nativeSizeType ) ,
8694
- expr ,
8695
- fieldType . toNativeType ( ) ,
8696
- fieldInstance . memoryOffset
8697
- ) ) ;
8700
+ exprs . push (
8701
+ module . store ( // TODO: handle setters as well
8702
+ fieldType . byteSize ,
8703
+ module . local_get ( tempLocal . index , nativeClassType ) ,
8704
+ expr ,
8705
+ fieldType . toNativeType ( ) ,
8706
+ fieldInstance . memoryOffset
8707
+ )
8708
+ ) ;
8698
8709
8699
8710
// This member is no longer omitted, so delete from our omitted fields
8700
- omittedClassFieldMembers . delete ( member . name ) ;
8711
+ omittedFields . delete ( fieldInstance ) ;
8701
8712
}
8702
- this . currentType = classReference . type . nonNullableType ;
8713
+ this . currentType = classType . nonNullableType ;
8703
8714
if ( hasErrors ) return module . unreachable ( ) ;
8704
8715
8705
- // Iterate through the remaining omittedClassFieldMembers.
8706
- if ( members ) {
8716
+ // Check remaining omitted fields
8717
+ for ( let _values = Set_values ( omittedFields ) , j = 0 , l = _values . length ; j < l ; ++ j ) {
8718
+ let fieldInstance = _values [ j ] ;
8719
+ let fieldType = fieldInstance . type ;
8707
8720
8708
- for ( let _values = Set_values ( omittedClassFieldMembers ) , j = 0 , l = _values . length ; j < l ; ++ j ) {
8709
- let omittedMemberKey = _values [ j ] ;
8710
- let member = assert ( members . get ( omittedMemberKey ) ) ;
8711
-
8712
- let fieldInstance = < Field > member ;
8713
- let fieldType = fieldInstance . type ;
8721
+ if ( fieldInstance . initializerNode ) {
8722
+ continue ; // set by default ctor
8723
+ }
8714
8724
8715
- if ( fieldType . is ( TypeFlags . REFERENCE ) && fieldType . classReference !== null ) {
8716
- // TODO: Check if it is a class, with a default value (constructor with no params).
8717
- if ( ! fieldType . is ( TypeFlags . NULLABLE ) ) {
8718
- this . error (
8719
- DiagnosticCode . Property_0_is_missing_in_type_1_but_required_in_type_2 ,
8720
- expression . range , "<object>" , classReference . toString ( )
8721
- ) ;
8722
- hasErrors = true ;
8723
- continue ;
8724
- }
8725
+ if ( fieldType . is ( TypeFlags . REFERENCE ) && fieldType . classReference !== null ) {
8726
+ // TODO: Check if it is a class, with a default value (constructor with no params).
8727
+ if ( ! fieldType . is ( TypeFlags . NULLABLE ) ) {
8728
+ this . error (
8729
+ DiagnosticCode . Property_0_is_missing_in_type_1_but_required_in_type_2 ,
8730
+ expression . range , fieldInstance . name , "<object>" , classType . toString ( )
8731
+ ) ;
8732
+ hasErrors = true ;
8733
+ continue ;
8725
8734
}
8735
+ }
8726
8736
8727
- switch ( fieldType . kind ) {
8728
- // Number Types (and Number alias types)
8729
- case TypeKind . I8 :
8730
- case TypeKind . I16 :
8731
- case TypeKind . I32 :
8732
- case TypeKind . U8 :
8733
- case TypeKind . U16 :
8734
- case TypeKind . U32 :
8735
- case TypeKind . USIZE :
8736
- case TypeKind . ISIZE :
8737
- case TypeKind . BOOL :
8738
- case TypeKind . I64 :
8739
- case TypeKind . U64 :
8740
- case TypeKind . F32 :
8741
- case TypeKind . F64 : {
8742
- exprs . push ( this . module . store ( // TODO: handle setters as well
8737
+ switch ( fieldType . kind ) {
8738
+ // Number Types (and Number alias types)
8739
+ case TypeKind . I8 :
8740
+ case TypeKind . I16 :
8741
+ case TypeKind . I32 :
8742
+ case TypeKind . I64 :
8743
+ case TypeKind . ISIZE :
8744
+ case TypeKind . U8 :
8745
+ case TypeKind . U16 :
8746
+ case TypeKind . U32 :
8747
+ case TypeKind . U64 :
8748
+ case TypeKind . USIZE :
8749
+ case TypeKind . BOOL :
8750
+ case TypeKind . F32 :
8751
+ case TypeKind . F64 : {
8752
+ exprs . push (
8753
+ module . store ( // TODO: handle setters as well
8743
8754
fieldType . byteSize ,
8744
- this . module . local_get ( tempLocal . index , this . options . nativeSizeType ) ,
8755
+ module . local_get ( tempLocal . index , nativeClassType ) ,
8745
8756
this . makeZero ( fieldType ) ,
8746
8757
fieldType . toNativeType ( ) ,
8747
8758
fieldInstance . memoryOffset
8748
- ) ) ;
8749
- continue ;
8750
- }
8759
+ )
8760
+ ) ;
8761
+ continue ;
8751
8762
}
8752
-
8753
- // Otherwise, error
8754
- this . error (
8755
- DiagnosticCode . Property_0_is_missing_in_type_1_but_required_in_type_2 ,
8756
- expression . range , "<object>" , classReference . toString ( )
8757
- ) ;
8758
- hasErrors = true ;
8759
8763
}
8764
+
8765
+ // Otherwise error
8766
+ this . error (
8767
+ DiagnosticCode . Property_0_is_missing_in_type_1_but_required_in_type_2 ,
8768
+ expression . range , fieldInstance . name , "<object>" , classType . toString ( )
8769
+ ) ;
8770
+ hasErrors = true ;
8760
8771
}
8761
8772
if ( hasErrors ) return module . unreachable ( ) ;
8762
8773
8763
8774
// allocate a new instance first and assign 'this' to the temp. local
8764
- exprs . unshift ( module . local_set (
8765
- tempLocal . index ,
8766
- isManaged
8767
- ? this . makeRetain ( this . makeAllocation ( classReference ) )
8768
- : this . makeAllocation ( classReference )
8769
- ) ) ;
8775
+ exprs . unshift (
8776
+ module . local_set ( tempLocal . index ,
8777
+ this . compileInstantiate ( classReference , [ ] , Constraints . WILL_RETAIN , expression )
8778
+ )
8779
+ ) ;
8770
8780
8771
8781
// once all field values have been set, return 'this'
8772
- exprs . push ( module . local_get ( tempLocal . index , this . options . nativeSizeType ) ) ;
8782
+ exprs . push (
8783
+ module . local_get ( tempLocal . index , nativeClassType )
8784
+ ) ;
8773
8785
8774
8786
if ( ! isManaged ) flow . freeTempLocal ( tempLocal ) ;
8775
- this . currentType = classReference . type ;
8776
- return module . flatten ( exprs , this . options . nativeSizeType ) ;
8787
+ this . currentType = classType . nonNullableType ;
8788
+ return module . flatten ( exprs , nativeClassType ) ;
8777
8789
}
8778
8790
8779
8791
private compileNewExpression (
@@ -8949,7 +8961,7 @@ export class Compiler extends DiagnosticEmitter {
8949
8961
this . makeZero ( this . options . usizeType ) ,
8950
8962
constraints
8951
8963
) ;
8952
- if ( getExpressionType ( expr ) != NativeType . None ) { // possibly IMM_DROPPED
8964
+ if ( getExpressionType ( expr ) != NativeType . None ) { // possibly WILL_DROP
8953
8965
this . currentType = classInstance . type ; // important because a super ctor could be called
8954
8966
}
8955
8967
return expr ;
0 commit comments