@@ -349,7 +349,7 @@ func (d *Desugar) desugarPreConditions(
349
349
conditions = funcBlock .PreConditions
350
350
351
351
for _ , condition := range conditions .Conditions {
352
- desugaredCondition := d .desugarCondition (condition )
352
+ desugaredCondition := d .desugarCondition (condition , false )
353
353
desugaredConditions = append (desugaredConditions , desugaredCondition )
354
354
}
355
355
}
@@ -383,7 +383,7 @@ func (d *Desugar) desugarPostConditions(
383
383
beforeStatements = postConditionsRewrite .BeforeStatements
384
384
385
385
for _ , condition := range conditionsList {
386
- desugaredCondition := d .desugarCondition (condition )
386
+ desugaredCondition := d .desugarCondition (condition , false )
387
387
desugaredConditions = append (desugaredConditions , desugaredCondition )
388
388
}
389
389
}
@@ -438,7 +438,7 @@ func (d *Desugar) desugarInheritedCondition(condition ast.Condition, inheritedFu
438
438
prevElaboration := d .elaboration
439
439
d .elaboration = inheritedFunc .elaboration
440
440
441
- desugaredCondition := d .desugarCondition (condition )
441
+ desugaredCondition := d .desugarCondition (condition , true )
442
442
d .elaboration = prevElaboration
443
443
444
444
// Elaboration to be used by the condition must be set in the current elaboration.
@@ -464,7 +464,7 @@ var panicFuncInvocationTypes = sema.InvocationExpressionTypes{
464
464
},
465
465
}
466
466
467
- func (d * Desugar ) desugarCondition (condition ast.Condition ) ast.Statement {
467
+ func (d * Desugar ) desugarCondition (condition ast.Condition , isInherited bool ) ast.Statement {
468
468
switch condition := condition .(type ) {
469
469
case * ast.TestCondition :
470
470
@@ -533,12 +533,115 @@ func (d *Desugar) desugarCondition(condition ast.Condition) ast.Statement {
533
533
return ifStmt
534
534
case * ast.EmitCondition :
535
535
emitStmt := (* ast .EmitStatement )(condition )
536
- return emitStmt
536
+
537
+ if ! isInherited {
538
+ return emitStmt
539
+ }
540
+
541
+ // If the condition is inherited, then re-write
542
+ // the emit statement to be type-qualified.
543
+ // i.e: `emit Event()` will be re-written as `emit Contract.Event()`.
544
+ // Otherwise, the compiler can't find the symbol.
545
+
546
+ eventType := d .elaboration .EmitStatementEventType (emitStmt )
547
+
548
+ // Get the contract in which the event was declared.
549
+ // This is guaranteed, since events can only be declared in contracts.
550
+ declaredContract := declaredContract (eventType ).(sema.CompositeKindedType )
551
+
552
+ eventConstructorInvocation := emitStmt .InvocationExpression
553
+
554
+ // If the event constructor is already type-qualified, then no need to change anything.
555
+ if _ , ok := eventConstructorInvocation .InvokedExpression .(* ast.MemberExpression ); ok {
556
+ return emitStmt
557
+ }
558
+
559
+ // Otherwise, make it type-qualified
560
+ invocationTypes := d .elaboration .InvocationExpressionTypes (eventConstructorInvocation )
561
+
562
+ pos := eventConstructorInvocation .StartPosition ()
563
+
564
+ memberExpression := ast .NewMemberExpression (
565
+ d .memoryGauge ,
566
+ ast .NewIdentifierExpression (
567
+ d .memoryGauge ,
568
+ ast .NewIdentifier (
569
+ d .memoryGauge ,
570
+ declaredContract .GetIdentifier (),
571
+ pos ,
572
+ ),
573
+ ),
574
+ false ,
575
+ pos ,
576
+ ast .NewIdentifier (
577
+ d .memoryGauge ,
578
+ eventType .Identifier ,
579
+ pos ,
580
+ ),
581
+ )
582
+
583
+ newEventConstructorInvocation := ast .NewInvocationExpression (
584
+ d .memoryGauge ,
585
+ memberExpression ,
586
+ eventConstructorInvocation .TypeArguments ,
587
+ eventConstructorInvocation .Arguments ,
588
+ eventConstructorInvocation .ArgumentsStartPos ,
589
+ eventConstructorInvocation .EndPos ,
590
+ )
591
+
592
+ newEmitStmt := ast .NewEmitStatement (
593
+ d .memoryGauge ,
594
+ newEventConstructorInvocation ,
595
+ emitStmt .StartPos ,
596
+ )
597
+
598
+ //Inject a static import so the compiler can link the functions.
599
+ d .addImport (eventType .Location )
600
+
601
+ d .elaboration .SetInvocationExpressionTypes (newEventConstructorInvocation , invocationTypes )
602
+ d .elaboration .SetEmitStatementEventType (newEmitStmt , eventType )
603
+
604
+ // TODO: Is there a way to get the type for the constructor
605
+ // from the elaboration, rather than manually constructing it here?
606
+ eventConstructorFuncType := sema .NewSimpleFunctionType (
607
+ sema .FunctionPurityImpure ,
608
+ // Parameters are not needed, since they are not used in the compiler
609
+ nil ,
610
+ sema .NewTypeAnnotation (eventType ),
611
+ )
612
+ eventConstructorFuncType .IsConstructor = true
613
+
614
+ memberAccessInfo := sema.MemberAccessInfo {
615
+ AccessedType : declaredContract ,
616
+ ResultingType : eventType ,
617
+ Member : sema .NewPublicFunctionMember (
618
+ d .memoryGauge ,
619
+ declaredContract ,
620
+ eventType .Identifier ,
621
+ eventConstructorFuncType ,
622
+ "" ,
623
+ ),
624
+ IsOptional : false ,
625
+ ReturnReference : false ,
626
+ }
627
+
628
+ d .elaboration .SetMemberExpressionMemberAccessInfo (memberExpression , memberAccessInfo )
629
+
630
+ return newEmitStmt
537
631
default :
538
632
panic (errors .NewUnreachableError ())
539
633
}
540
634
}
541
635
636
+ func declaredContract (containedType sema.ContainedType ) sema.Type {
637
+ containerType := containedType .GetContainerType ()
638
+ if containerType == nil {
639
+ return containedType
640
+ }
641
+
642
+ return declaredContract (containerType .(sema.ContainedType ))
643
+ }
644
+
542
645
func (d * Desugar ) VisitSpecialFunctionDeclaration (declaration * ast.SpecialFunctionDeclaration ) ast.Declaration {
543
646
desugaredDecl := d .desugarDeclaration (declaration .FunctionDeclaration ).(* ast.FunctionDeclaration )
544
647
if desugaredDecl == declaration .FunctionDeclaration {
@@ -921,8 +1024,13 @@ func (d *Desugar) interfaceDelegationMethodCall(
921
1024
// Given these invocations are treated as static calls,
922
1025
// we need to inject a static import as well, so the
923
1026
// compiler can link these functions.
1027
+ d .addImport (interfaceType .Location )
1028
+
1029
+ return invocation
1030
+ }
924
1031
925
- interfaceLocation , isAddressLocation := interfaceType .Location .(common.AddressLocation )
1032
+ func (d * Desugar ) addImport (location common.Location ) {
1033
+ interfaceLocation , isAddressLocation := location .(common.AddressLocation )
926
1034
if isAddressLocation {
927
1035
if _ , exists := d .importsSet [interfaceLocation ]; ! exists {
928
1036
d .newImports = append (
@@ -940,8 +1048,6 @@ func (d *Desugar) interfaceDelegationMethodCall(
940
1048
d .importsSet [interfaceLocation ] = struct {}{}
941
1049
}
942
1050
}
943
-
944
- return invocation
945
1051
}
946
1052
947
1053
func (d * Desugar ) VisitInterfaceDeclaration (declaration * ast.InterfaceDeclaration ) ast.Declaration {
0 commit comments