@@ -8682,12 +8682,26 @@ export class Compiler extends DiagnosticEmitter {
8682
8682
var values = expression . values ;
8683
8683
var members = classReference . members ;
8684
8684
var hasErrors = false ;
8685
- var exprs = new Array < ExpressionRef > ( numNames + 2 ) ;
8685
+ var exprs = new Array < ExpressionRef > ( ) ;
8686
8686
var flow = this . currentFlow ;
8687
8687
var tempLocal = isManaged
8688
8688
? flow . getAutoreleaseLocal ( classReference . type )
8689
8689
: flow . getTempLocal ( classReference . type ) ;
8690
8690
assert ( numNames == values . length ) ;
8691
+
8692
+ // Assume all class fields will be omitted, and add them to our omitted list
8693
+ let omittedClassFieldMembers = new Set < string > ( ) ;
8694
+ if ( members ) {
8695
+ for ( let _keys = Map_keys ( members ) , i = 0 , k = _keys . length ; i < k ; ++ i ) {
8696
+ let memberKey = _keys [ i ] ;
8697
+ let member = assert ( members . get ( memberKey ) ) ;
8698
+ if ( member !== null && member . kind == ElementKind . FIELD ) {
8699
+ omittedClassFieldMembers . add ( member . name ) ;
8700
+ }
8701
+ }
8702
+ }
8703
+
8704
+ // Iterate through the members defined in our expression
8691
8705
for ( let i = 0 , k = numNames ; i < k ; ++ i ) {
8692
8706
let member = members ? members . get ( names [ i ] . text ) : null ;
8693
8707
if ( ! member || member . kind != ElementKind . FIELD ) {
@@ -8700,27 +8714,93 @@ export class Compiler extends DiagnosticEmitter {
8700
8714
}
8701
8715
let fieldInstance = < Field > member ;
8702
8716
let fieldType = fieldInstance . type ;
8703
- exprs [ i + 1 ] = this . module . store ( // TODO: handle setters as well
8717
+
8718
+ let expr = this . compileExpression ( values [ i ] , fieldType , Constraints . CONV_IMPLICIT | Constraints . WILL_RETAIN ) ;
8719
+ if ( isManaged && fieldType . isManaged && ! this . skippedAutoreleases . has ( expr ) ) {
8720
+ expr = this . makeRetain ( expr ) ;
8721
+ }
8722
+ exprs . push ( this . module . store ( // TODO: handle setters as well
8704
8723
fieldType . byteSize ,
8705
8724
this . module . local_get ( tempLocal . index , this . options . nativeSizeType ) ,
8706
- this . compileExpression ( values [ i ] , fieldInstance . type , Constraints . CONV_IMPLICIT ) ,
8725
+ expr ,
8707
8726
fieldType . toNativeType ( ) ,
8708
8727
fieldInstance . memoryOffset
8709
- ) ;
8728
+ ) ) ;
8729
+
8730
+ // This member is no longer omitted, so delete from our omitted fields
8731
+ omittedClassFieldMembers . delete ( member . name ) ;
8710
8732
}
8711
8733
this . currentType = classReference . type . nonNullableType ;
8712
8734
if ( hasErrors ) return module . unreachable ( ) ;
8713
8735
8736
+ // Iterate through the remaining omittedClassFieldMembers.
8737
+ if ( members ) {
8738
+
8739
+ for ( let _values = Set_values ( omittedClassFieldMembers ) , j = 0 , l = _values . length ; j < l ; ++ j ) {
8740
+ let omittedMemberKey = _values [ j ] ;
8741
+ let member = assert ( members . get ( omittedMemberKey ) ) ;
8742
+
8743
+ let fieldInstance = < Field > member ;
8744
+ let fieldType = fieldInstance . type ;
8745
+
8746
+ if ( fieldType . is ( TypeFlags . REFERENCE ) && fieldType . classReference !== null ) {
8747
+ // TODO: Check if it is a class, with a default value (constructor with no params).
8748
+ if ( ! fieldType . is ( TypeFlags . NULLABLE ) ) {
8749
+ this . error (
8750
+ DiagnosticCode . Property_0_is_missing_in_type_1_but_required_in_type_2 ,
8751
+ expression . range , "<object>" , classReference . toString ( )
8752
+ ) ;
8753
+ hasErrors = true ;
8754
+ continue ;
8755
+ }
8756
+ }
8757
+
8758
+ switch ( fieldType . kind ) {
8759
+ // Number Types (and Number alias types)
8760
+ case TypeKind . I8 :
8761
+ case TypeKind . I16 :
8762
+ case TypeKind . I32 :
8763
+ case TypeKind . U8 :
8764
+ case TypeKind . U16 :
8765
+ case TypeKind . U32 :
8766
+ case TypeKind . USIZE :
8767
+ case TypeKind . ISIZE :
8768
+ case TypeKind . BOOL :
8769
+ case TypeKind . I64 :
8770
+ case TypeKind . U64 :
8771
+ case TypeKind . F32 :
8772
+ case TypeKind . F64 : {
8773
+ exprs . push ( this . module . store ( // TODO: handle setters as well
8774
+ fieldType . byteSize ,
8775
+ this . module . local_get ( tempLocal . index , this . options . nativeSizeType ) ,
8776
+ this . makeZero ( fieldType ) ,
8777
+ fieldType . toNativeType ( ) ,
8778
+ fieldInstance . memoryOffset
8779
+ ) ) ;
8780
+ continue ;
8781
+ }
8782
+ }
8783
+
8784
+ // Otherwise, error
8785
+ this . error (
8786
+ DiagnosticCode . Property_0_is_missing_in_type_1_but_required_in_type_2 ,
8787
+ expression . range , "<object>" , classReference . toString ( )
8788
+ ) ;
8789
+ hasErrors = true ;
8790
+ }
8791
+ }
8792
+ if ( hasErrors ) return module . unreachable ( ) ;
8793
+
8714
8794
// allocate a new instance first and assign 'this' to the temp. local
8715
- exprs [ 0 ] = module . local_set (
8795
+ exprs . unshift ( module . local_set (
8716
8796
tempLocal . index ,
8717
8797
isManaged
8718
8798
? this . makeRetain ( this . makeAllocation ( classReference ) )
8719
8799
: this . makeAllocation ( classReference )
8720
- ) ;
8800
+ ) ) ;
8721
8801
8722
8802
// once all field values have been set, return 'this'
8723
- exprs [ exprs . length - 1 ] = module . local_get ( tempLocal . index , this . options . nativeSizeType ) ;
8803
+ exprs . push ( module . local_get ( tempLocal . index , this . options . nativeSizeType ) ) ;
8724
8804
8725
8805
if ( ! isManaged ) flow . freeTempLocal ( tempLocal ) ;
8726
8806
this . currentType = classReference . type ;
0 commit comments