@@ -105,11 +105,6 @@ private class ContractsVisitor
105105 # is `no_contract` annotation was found
106106 var find_no_contract = false
107107
108- # The reference to the `in_contract` attribute.
109- # This attribute is used to disable contract verification when you are already in a contract verification.
110- # Keep the `in_contract` attribute to avoid searching at each contrat
111- var in_contract_attribute : nullable MAttribute = null
112-
113108 redef fun visit (node )
114109 do
115110 node .create_contracts (self )
@@ -140,78 +135,12 @@ private class ContractsVisitor
140135 end
141136 end
142137
143- # Inject the incontract attribute (`_in_contract_`) in the `Sys` class
144- # This attribute allows to check if the contract need to be executed
145- private fun inject_incontract_in_sys
146- do
147- # If the `in_contract_attribute` already know just return
148- if in_contract_attribute != null then return
149-
150- var sys_class = toolcontext .modelbuilder .get_mclass_by_name (visited_module , mainmodule , "Sys " )
151-
152- # Try to get the `in_contract` property, if it has already defined in a previously visited module.
153- var in_contract_property = toolcontext .modelbuilder .try_get_mproperty_by_name (visited_module , sys_class .intro , "__in_contract_ " )
154- if in_contract_property != null then
155- self .in_contract_attribute = in_contract_property .as (MAttribute )
156- return
157- end
158-
159- var bool_false = new AFalseExpr .make (mainmodule .bool_type )
160- var n_in_contract_attribute = toolcontext .modelbuilder .create_attribute_from_name ("__in_contract_ " , sys_class .intro , mainmodule .bool_type , public_visibility ).create_setter (toolcontext .modelbuilder , true ).define_default (bool_false )
161-
162- in_contract_attribute = n_in_contract_attribute .mpropdef .mproperty
163- end
164-
165- # Return the `_in_contract_` attribute.
166- # If the attribute `_in_contract_` does not exist it's injected with `inject_incontract_in_sys`
167- private fun get_incontract : MAttribute
168- do
169- if self .in_contract_attribute == null then inject_incontract_in_sys
170- return in_contract_attribute .as (not null )
171- end
172-
173- # Return an `AIfExpr` with the contract encapsulated by an `if` to check if it's already in a contract verification.
174- #
175- # Example:
176- # ~~~nitish
177- # class A
178- # fun bar([...]) is except([...])
179- #
180- # fun _contract_bar([...])
181- # do
182- # if not sys._in_contract_ then
183- # sys._in_contract_ = true
184- # _bar_expect([...])
185- # sys._in_contract_ = false
186- # end
187- # bar([...])
188- # end
189- #
190- # fun _bar_expect([...])
191- # end
192- # ~~~~
193- #
194- private fun encapsulated_contract_call (visited_method : AMethPropdef , call_to_contracts : Array [ACallExpr ]): AIfExpr
138+ # Return an `AIfAssertion` with the contract encapsulated by an `if` to check if it's already in a contract verification.
139+ private fun encapsulated_contract_call (visited_method : AMethPropdef , call_to_contracts : Array [ACallExpr ]): AIfInAssertion
195140 do
196- var sys_property = toolcontext .modelbuilder .model .get_mproperties_by_name ("sys " ). first .as (MMethod )
197- var callsite_sys = ast_builder .create_callsite (toolcontext .modelbuilder , visited_method , sys_property , true )
198-
199- var incontract_attribute = get_incontract
200-
201- var callsite_get_incontract = ast_builder .create_callsite (toolcontext .modelbuilder , visited_method , incontract_attribute .getter .as (MMethod ), false )
202- var callsite_set_incontract = ast_builder .create_callsite (toolcontext .modelbuilder , visited_method , incontract_attribute .setter .as (MMethod ), false )
203-
204- var n_condition = ast_builder .make_not (ast_builder .make_call (ast_builder .make_call (new ASelfExpr , callsite_sys , null ), callsite_get_incontract , null ))
205-
206- var n_if = ast_builder .make_if (n_condition , null )
207-
208- var if_then_block = n_if .n_then .as (ABlockExpr )
209-
210- if_then_block .add (ast_builder .make_call (ast_builder .make_call (new ASelfExpr , callsite_sys , null ), callsite_set_incontract , [new ATrueExpr .make (mainmodule .bool_type )]))
211- if_then_block .add_all (call_to_contracts )
212- if_then_block .add (ast_builder .make_call (ast_builder .make_call (new ASelfExpr , callsite_sys , null ), callsite_set_incontract , [new AFalseExpr .make (mainmodule .bool_type )]))
213-
214- return n_if
141+ var n_block = ast_builder .make_block
142+ n_block .add_all (call_to_contracts )
143+ return new AIfInAssertion (n_block )
215144 end
216145end
217146
@@ -847,3 +776,31 @@ redef class ANewExpr
847776 end
848777 end
849778end
779+
780+ # Ast representation of the `in_assertion` checking
781+ # Note, the node if is only composed with a then body (`n_body`)
782+ class AIfInAssertion
783+ super AExpr
784+
785+ # The body of the if
786+ var n_body : AExpr is writable
787+
788+ redef fun accept_scope_visitor (v )
789+ do
790+ v .enter_visit_block (n_body , null )
791+ end
792+
793+ redef fun visit_all (v : Visitor )
794+ do
795+ v .enter_visit (n_body )
796+ end
797+
798+ redef fun accept_typing (v )
799+ do
800+ v .visit_stmt (n_body )
801+
802+ self .is_typed = true
803+
804+ self .mtype = n_body .mtype
805+ end
806+ end
0 commit comments