model/model_contract: Move contract model representation
authorFlorian Deljarry <deljarry.florian@gmail.com>
Tue, 2 Jun 2020 22:46:33 +0000 (18:46 -0400)
committerFlorian Deljarry <deljarry.florian@gmail.com>
Thu, 4 Jun 2020 12:33:22 +0000 (08:33 -0400)
Signed-off-by: Florian Deljarry <deljarry.florian@gmail.com>

src/contracts.nit
src/model/model_contract.nit [new file with mode: 0644]

index 0055c45..e8d440b 100644 (file)
@@ -21,6 +21,7 @@ module contracts
 import parse_annotations
 import phase
 import semantize
+intrude import model_contract
 intrude import astbuilder
 intrude import modelize_property
 intrude import scope
@@ -301,12 +302,7 @@ redef class AAnnotation
        end
 end
 
-# The root of all contracts
-#
-# The objective of this class is to provide the set
-# of services must be implemented or provided by a contract
-abstract class MContract
-       super MMethod
+redef class MContract
 
        # Define the name of the contract
        fun contract_name: String is abstract
@@ -393,10 +389,7 @@ abstract class MContract
        end
 end
 
-# A expect (precondition) contract representation
-# This method check if the requirements of the called method is true.
-class MExpect
-       super MContract
+redef class MExpect
 
        # Define the name of the contract
        redef fun contract_name: String do return "expect"
@@ -462,9 +455,7 @@ class MExpect
        end
 end
 
-# The root of all contracts where the call is after the execution of the original method (`invariant` and `ensure`).
-abstract class BottomMContract
-       super MContract
+redef class BottomMContract
 
        redef fun create_nblock(v: ContractsVisitor, n_condition: AExpr, args: Array[AExpr]): ABlockExpr
        do
@@ -524,10 +515,7 @@ abstract class BottomMContract
        end
 end
 
-# A ensure (postcondition) representation
-# This method check if the called method respects the expectations of the caller.
-class MEnsure
-       super BottomMContract
+redef class MEnsure
 
        # Define the name of the contract
        redef fun contract_name: String do return "ensure"
@@ -604,59 +592,13 @@ redef class MClass
        end
 end
 
-redef class MMethod
-
-       # The contract facet of the method
-       # it's representing the method with contract
-       # This method call the contract and the method
-       var mcontract_facet: nullable MMethod = null
-
-       # The expected contract method
-       var mexpect: nullable MExpect = null
-
-       # The ensure contract method
-       var mensure: nullable MEnsure = null
-
-       # Check if the MMethod has no ensure contract
-       # if this is the case returns false and built it
-       # else return true
-       private fun check_exist_ensure: Bool
-       do
-               if self.mensure != null then return true
-               # build a new `MEnsure` contract
-               self.mensure = new MEnsure(intro_mclassdef, "_ensure_{name}", intro_mclassdef.location, public_visibility)
-               return false
-       end
-
-       # Check if the MMethod has no expect contract
-       # if this is the case returns false and built it
-       # else return true
-       private fun check_exist_expect: Bool
-       do
-               if self.mexpect != null then return true
-               # build a new `MExpect` contract
-               self.mexpect = new MExpect(intro_mclassdef, "_expect_{name}", intro_mclassdef.location, public_visibility)
-               return false
-       end
-
-       # Check if the MMethod has an contract facet
-       # If the method has no contract facet she create it
-       private fun check_exist_contract_facet(mpropdef : MMethodDef): Bool
-       do
-               if self.mcontract_facet != null then return true
-               # build a new `MMethod` contract
-               self.mcontract_facet = new MMethod(intro_mclassdef, "_contract_{name}", intro_mclassdef.location, public_visibility)
-               return false
-       end
-end
-
 redef class MMethodDef
 
        # Verification of the contract facet
        # Check if a contract facet already exists to use it again or if it is necessary to create it.
        private fun check_contract_facet(v: ContractsVisitor, n_signature: ASignature, classdef: MClassDef, mcontract: MContract, exist_contract: Bool)
        do
-               var exist_contract_facet = mproperty.check_exist_contract_facet(self)
+               var exist_contract_facet = mproperty.has_contract_facet
                if exist_contract_facet and exist_contract then return
 
                var contract_facet: AMethPropdef
@@ -693,8 +635,7 @@ redef class MMethodDef
        # Method to create a contract facet of the method
        private fun create_contract_facet(v: ContractsVisitor, classdef: MClassDef, n_signature: ASignature): AMethPropdef
        do
-               var contract_facet = mproperty.mcontract_facet
-               assert contract_facet != null
+               var contract_facet = mproperty.build_contract_facet
                # Defines the contract phase is an init or not
                # it is necessary to use the contracts on constructor
                contract_facet.is_init = self.mproperty.is_init
@@ -804,12 +745,12 @@ redef class AMethPropdef
        do
                if n_annotation.name == "expect" then
                        if not v.check_usage_expect(mpropdef.mclassdef.mmodule) then return
-                       var exist_contract = mpropdef.mproperty.check_exist_expect
-                       mpropdef.construct_contract(v, self.n_signature.as(not null), n_annotation, mpropdef.mproperty.mexpect.as(not null), exist_contract)
+                       var exist_contract = mpropdef.mproperty.has_expect
+                       mpropdef.construct_contract(v, self.n_signature.as(not null), n_annotation, mpropdef.mproperty.build_expect, exist_contract)
                else if n_annotation.name == "ensure" then
                        if not v.check_usage_ensure(mpropdef.mclassdef.mmodule) then return
-                       var exist_contract = mpropdef.mproperty.check_exist_ensure
-                       mpropdef.construct_contract(v, self.n_signature.as(not null), n_annotation, mpropdef.mproperty.mensure.as(not null), exist_contract)
+                       var exist_contract = mpropdef.mproperty.has_ensure
+                       mpropdef.construct_contract(v, self.n_signature.as(not null), n_annotation, mpropdef.mproperty.build_ensure, exist_contract)
                else if n_annotation.name == "no_contract" then
                        # no_contract found set the flag to true
                        v.find_no_contract = true
diff --git a/src/model/model_contract.nit b/src/model/model_contract.nit
new file mode 100644 (file)
index 0000000..2e13a45
--- /dev/null
@@ -0,0 +1,120 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# The abstract concept of a contract in the model
+module model_contract
+
+import model
+import scope
+
+# The root of all contracts
+abstract class MContract
+       super MMethod
+
+       # Is the contract is it already applied on the given `mfacet`
+       fun is_already_applied(mfacet: MFacet): Bool is abstract
+end
+
+# An expect (precondition) contract representation
+class MExpect
+       super MContract
+
+       redef fun is_already_applied(mfacet: MFacet): Bool do return mfacet.has_applied_expect
+end
+
+# The root of all contracts where the call is after the execution of the original method (`invariant` and `ensure`).
+abstract class BottomMContract
+       super MContract
+end
+
+# A ensure (postcondition) representation
+class MEnsure
+       super BottomMContract
+
+       redef fun is_already_applied(mfacet: MFacet): Bool do return mfacet.has_applied_ensure
+end
+
+# A facet contract representation
+# This class is created to keep the information of which method is a contract facet
+class MFacet
+       super MMethod
+
+       # Is there an `expect` contract applied?
+       var has_applied_expect: Bool = false
+
+       # Is there an `ensure` contract applied?
+       var has_applied_ensure: Bool = false
+end
+
+redef class MMethod
+
+       # The contract facet of the method
+       # is representing the method with a contract
+       # This method calls contracts (expect, ensure) and the method
+       var mcontract_facet: nullable MFacet = null
+
+       # The `MExpect` contract if any
+       var mexpect: nullable MExpect = null
+
+       # The `MEnsure` contract if any
+       var mensure: nullable MEnsure = null
+
+       # Build `mensure` if is not exist and return it
+       private fun build_ensure: MEnsure
+       do
+               var m_mensure = self.mensure
+               # build a new `MEnsure` contract
+               if m_mensure == null then m_mensure = new MEnsure(intro_mclassdef, "_ensure_{name}", intro_mclassdef.location, public_visibility)
+               self.mensure = m_mensure
+               return m_mensure
+       end
+
+       # Is there an ensure contract?
+       fun has_ensure: Bool
+       do
+               return self.mensure != null
+       end
+
+       # Build `mexpect` if is not exist and return it
+       private fun build_expect: MExpect
+       do
+               var m_mexpect = self.mexpect
+               # build a new `MExpect` contract
+               if m_mexpect == null then m_mexpect = new MExpect(intro_mclassdef, "_expect_{name}", intro_mclassdef.location, public_visibility)
+               self.mexpect = m_mexpect
+               return m_mexpect
+       end
+
+       # Is there an expect contract?
+       fun has_expect: Bool
+       do
+               return self.mexpect != null
+       end
+
+       # Build `mcontract_facet` if is not exist and return it
+       private fun build_contract_facet: MFacet
+       do
+               var m_mcontract_facet = self.mcontract_facet
+               # build a new `MFacet` contract
+               if m_mcontract_facet == null then m_mcontract_facet = new MFacet(intro_mclassdef, "_contract_{name}", intro_mclassdef.location, public_visibility)
+               self.mcontract_facet = m_mcontract_facet
+               return m_mcontract_facet
+       end
+
+       # Is there an contract facet?
+       fun has_contract_facet: Bool
+       do
+               return self.mcontract_facet != null
+       end
+end