@@ -86,7 +86,8 @@ import {
8686 PropertyPrototype ,
8787 IndexSignature ,
8888 File ,
89- mangleInternalName
89+ mangleInternalName ,
90+ DeclaredElement
9091} from "./program" ;
9192
9293import {
@@ -8601,46 +8602,36 @@ export class Compiler extends DiagnosticEmitter {
86018602 private compileObjectLiteral ( expression : ObjectLiteralExpression , contextualType : Type ) : ExpressionRef {
86028603 var module = this . module ;
86038604
8604- // contextual type must be a class
8605+ // Check that contextual type is a class (TODO: hidden class for interfaces?)
86058606 var classReference = contextualType . classReference ;
8606- if ( ! classReference || classReference . is ( CommonFlags . ABSTRACT ) ) {
8607+ if ( ! contextualType . is ( TypeFlags . REFERENCE ) || ! classReference || classReference . kind != ElementKind . CLASS ) {
86078608 this . error (
86088609 DiagnosticCode . Type_0_is_not_assignable_to_type_1 ,
86098610 expression . range , "<object>" , contextualType . toString ( )
86108611 ) ;
86118612 return module . unreachable ( ) ;
86128613 }
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+ }
86138623
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 ( ) ;
86418632 }
86428633
8643- var isManaged = classReference . type . isManaged ;
8634+ var isManaged = classType . isManaged ;
86448635 if ( ! isManaged ) {
86458636 this . checkUnsafe ( expression , findDecorator ( DecoratorKind . UNMANAGED , classReference . decoratorNodes ) ) ;
86468637 }
@@ -8654,29 +8645,47 @@ export class Compiler extends DiagnosticEmitter {
86548645 var exprs = new Array < ExpressionRef > ( ) ;
86558646 var flow = this . currentFlow ;
86568647 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 ( ) ;
86598651 assert ( numNames == values . length ) ;
86608652
86618653 // 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 > ( ) ;
86638655 if ( members ) {
86648656 for ( let _keys = Map_keys ( members ) , i = 0 , k = _keys . length ; i < k ; ++ i ) {
86658657 let memberKey = _keys [ i ] ;
86668658 let member = assert ( members . get ( memberKey ) ) ;
86678659 if ( member !== null && member . kind == ElementKind . FIELD ) {
8668- omittedClassFieldMembers . add ( member . name ) ;
8660+ omittedFields . add ( < Field > member ) ; // incl. private/protected
86698661 }
86708662 }
86718663 }
86728664
86738665 // 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 ) {
86778670 this . error (
86788671 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 ( )
86808689 ) ;
86818690 hasErrors = true ;
86828691 continue ;
@@ -8685,95 +8694,98 @@ export class Compiler extends DiagnosticEmitter {
86858694 let fieldType = fieldInstance . type ;
86868695
86878696 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 ) ) {
86898698 expr = this . makeRetain ( expr ) ;
86908699 }
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+ ) ;
86988709
86998710 // This member is no longer omitted, so delete from our omitted fields
8700- omittedClassFieldMembers . delete ( member . name ) ;
8711+ omittedFields . delete ( fieldInstance ) ;
87018712 }
8702- this . currentType = classReference . type . nonNullableType ;
8713+ this . currentType = classType . nonNullableType ;
87038714 if ( hasErrors ) return module . unreachable ( ) ;
87048715
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 ;
87078720
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+ }
87148724
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 ;
87258734 }
8735+ }
87268736
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
87438754 fieldType . byteSize ,
8744- this . module . local_get ( tempLocal . index , this . options . nativeSizeType ) ,
8755+ module . local_get ( tempLocal . index , nativeClassType ) ,
87458756 this . makeZero ( fieldType ) ,
87468757 fieldType . toNativeType ( ) ,
87478758 fieldInstance . memoryOffset
8748- ) ) ;
8749- continue ;
8750- }
8759+ )
8760+ ) ;
8761+ continue ;
87518762 }
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 ;
87598763 }
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 ;
87608771 }
87618772 if ( hasErrors ) return module . unreachable ( ) ;
87628773
87638774 // 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+ ) ;
87708780
87718781 // 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+ ) ;
87738785
87748786 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 ) ;
87778789 }
87788790
87798791 private compileNewExpression (
@@ -8949,7 +8961,7 @@ export class Compiler extends DiagnosticEmitter {
89498961 this . makeZero ( this . options . usizeType ) ,
89508962 constraints
89518963 ) ;
8952- if ( getExpressionType ( expr ) != NativeType . None ) { // possibly IMM_DROPPED
8964+ if ( getExpressionType ( expr ) != NativeType . None ) { // possibly WILL_DROP
89538965 this . currentType = classInstance . type ; // important because a super ctor could be called
89548966 }
89558967 return expr ;
0 commit comments