@@ -8682,12 +8682,26 @@ export class Compiler extends DiagnosticEmitter {
86828682 var values = expression . values ;
86838683 var members = classReference . members ;
86848684 var hasErrors = false ;
8685- var exprs = new Array < ExpressionRef > ( numNames + 2 ) ;
8685+ var exprs = new Array < ExpressionRef > ( ) ;
86868686 var flow = this . currentFlow ;
86878687 var tempLocal = isManaged
86888688 ? flow . getAutoreleaseLocal ( classReference . type )
86898689 : flow . getTempLocal ( classReference . type ) ;
86908690 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
86918705 for ( let i = 0 , k = numNames ; i < k ; ++ i ) {
86928706 let member = members ? members . get ( names [ i ] . text ) : null ;
86938707 if ( ! member || member . kind != ElementKind . FIELD ) {
@@ -8700,27 +8714,93 @@ export class Compiler extends DiagnosticEmitter {
87008714 }
87018715 let fieldInstance = < Field > member ;
87028716 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
87048723 fieldType . byteSize ,
87058724 this . module . local_get ( tempLocal . index , this . options . nativeSizeType ) ,
8706- this . compileExpression ( values [ i ] , fieldInstance . type , Constraints . CONV_IMPLICIT ) ,
8725+ expr ,
87078726 fieldType . toNativeType ( ) ,
87088727 fieldInstance . memoryOffset
8709- ) ;
8728+ ) ) ;
8729+
8730+ // This member is no longer omitted, so delete from our omitted fields
8731+ omittedClassFieldMembers . delete ( member . name ) ;
87108732 }
87118733 this . currentType = classReference . type . nonNullableType ;
87128734 if ( hasErrors ) return module . unreachable ( ) ;
87138735
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+
87148794 // allocate a new instance first and assign 'this' to the temp. local
8715- exprs [ 0 ] = module . local_set (
8795+ exprs . unshift ( module . local_set (
87168796 tempLocal . index ,
87178797 isManaged
87188798 ? this . makeRetain ( this . makeAllocation ( classReference ) )
87198799 : this . makeAllocation ( classReference )
8720- ) ;
8800+ ) ) ;
87218801
87228802 // 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 ) ) ;
87248804
87258805 if ( ! isManaged ) flow . freeTempLocal ( tempLocal ) ;
87268806 this . currentType = classReference . type ;
0 commit comments