@@ -3039,10 +3039,9 @@ impl AstVisitor for RustVisitor {
3039
3039
) -> AstVisitorReturnType {
3040
3040
self . add_code ( & format ! (
3041
3041
"self.{}" ,
3042
- interface_method_call_expr_node. identifier. name. lexeme
3042
+ self . format_value_name ( & interface_method_call_expr_node. identifier. name. lexeme)
3043
3043
) ) ;
3044
3044
interface_method_call_expr_node. call_expr_list . accept ( self ) ;
3045
- // self.add_code(&format!(""));
3046
3045
// TODO: review this return as I think it is a nop.
3047
3046
AstVisitorReturnType :: InterfaceMethodCallExpressionNode { }
3048
3047
}
@@ -3056,13 +3055,11 @@ impl AstVisitor for RustVisitor {
3056
3055
) -> AstVisitorReturnType {
3057
3056
output. push_str ( & format ! (
3058
3057
"self.{}" ,
3059
- interface_method_call_expr_node. identifier. name. lexeme
3058
+ self . format_value_name ( & interface_method_call_expr_node. identifier. name. lexeme)
3060
3059
) ) ;
3061
3060
interface_method_call_expr_node
3062
3061
. call_expr_list
3063
3062
. accept_to_string ( self , output) ;
3064
- // self.add_code(&format!(""));
3065
-
3066
3063
// TODO: review this return as I think it is a nop.
3067
3064
AstVisitorReturnType :: InterfaceMethodCallExpressionNode { }
3068
3065
}
@@ -3761,11 +3758,48 @@ impl AstVisitor for RustVisitor {
3761
3758
3762
3759
//* --------------------------------------------------------------------- *//
3763
3760
3761
+ // NOTE: Interface method calls must be treated specially since they may transition.
3762
+ //
3763
+ // The current approach is conservative, essentially assuming that an interface method call
3764
+ // always transitions. This assumption imposes the following restrictions:
3765
+ //
3766
+ // * Interface method calls cannot occur in a chain (they must be a standalone call).
3767
+ // * Interface method calls terminate the execution of their handler (like transitions).
3768
+ //
3769
+ // It would be possible to lift these restrictions and track the execution of a handler more
3770
+ // precisely, but this would require embedding some logic in the generated code and would make
3771
+ // handlers harder to reason about. The conservative approach has the advantage of both
3772
+ // simplifying the implementation and reasoning about Frame programs.
3764
3773
fn visit_call_chain_literal_statement_node (
3765
3774
& mut self ,
3766
3775
method_call_chain_literal_stmt_node : & CallChainLiteralStmtNode ,
3767
3776
) -> AstVisitorReturnType {
3768
3777
self . newline ( ) ;
3778
+
3779
+ // special case for interface method calls
3780
+ let call_chain = & method_call_chain_literal_stmt_node
3781
+ . call_chain_literal_expr_node
3782
+ . call_chain ;
3783
+ if call_chain. len ( ) == 1 {
3784
+ if let CallChainLiteralNodeType :: InterfaceMethodCallT {
3785
+ interface_method_call_expr_node,
3786
+ } = & call_chain[ 0 ]
3787
+ {
3788
+ self . this_branch_transitioned = true ;
3789
+ self . add_code ( & format ! (
3790
+ "drop({});" ,
3791
+ self . config. this_state_context_var_name
3792
+ ) ) ;
3793
+ self . newline ( ) ;
3794
+ interface_method_call_expr_node. accept ( self ) ;
3795
+ self . add_code ( ";" ) ;
3796
+ self . newline ( ) ;
3797
+ self . add_code ( "return;" ) ;
3798
+ return AstVisitorReturnType :: CallChainLiteralStmtNode { } ;
3799
+ }
3800
+ }
3801
+
3802
+ // standard case
3769
3803
method_call_chain_literal_stmt_node
3770
3804
. call_chain_literal_expr_node
3771
3805
. accept ( self ) ;
@@ -3780,7 +3814,6 @@ impl AstVisitor for RustVisitor {
3780
3814
method_call_chain_expression_node : & CallChainLiteralExprNode ,
3781
3815
) -> AstVisitorReturnType {
3782
3816
// TODO: maybe put this in an AST node
3783
-
3784
3817
let mut separator = "" ;
3785
3818
3786
3819
for node in & method_call_chain_expression_node. call_chain {
@@ -3792,10 +3825,10 @@ impl AstVisitor for RustVisitor {
3792
3825
CallChainLiteralNodeType :: CallT { call } => {
3793
3826
call. accept ( self ) ;
3794
3827
}
3795
- CallChainLiteralNodeType :: InterfaceMethodCallT {
3796
- interface_method_call_expr_node ,
3797
- } => {
3798
- interface_method_call_expr_node . accept ( self ) ;
3828
+ CallChainLiteralNodeType :: InterfaceMethodCallT { .. } => {
3829
+ self . errors . push ( String :: from (
3830
+ "Error: Interface method calls may not appear in call chains." ,
3831
+ ) ) ;
3799
3832
}
3800
3833
CallChainLiteralNodeType :: ActionCallT {
3801
3834
action_call_expr_node,
@@ -3832,10 +3865,10 @@ impl AstVisitor for RustVisitor {
3832
3865
CallChainLiteralNodeType :: CallT { call } => {
3833
3866
call. accept_to_string ( self , output) ;
3834
3867
}
3835
- CallChainLiteralNodeType :: InterfaceMethodCallT {
3836
- interface_method_call_expr_node ,
3837
- } => {
3838
- interface_method_call_expr_node . accept_to_string ( self , output ) ;
3868
+ CallChainLiteralNodeType :: InterfaceMethodCallT { .. } => {
3869
+ self . errors . push ( String :: from (
3870
+ "Error: Interface method calls may not appear in call chains." ,
3871
+ ) ) ;
3839
3872
}
3840
3873
CallChainLiteralNodeType :: ActionCallT {
3841
3874
action_call_expr_node,
0 commit comments