Merge: doc: fixed some typos and other misc. corrections master
authorJean Privat <jean@pryen.org>
Fri, 22 Apr 2022 17:04:57 +0000 (13:04 -0400)
committerJean Privat <jean@pryen.org>
Fri, 22 Apr 2022 17:04:57 +0000 (13:04 -0400)
This PR is fairly basic and only contains the following changes:
- Corrected various sentence structures, typos and text formatting across several markdown pages (language doc, README, etc.)

Note: There are a few sections I would rewrite differently to sound more professional/neutral and to include more details about how the language behaves in certain cases, but I felt like it was outside of this PR's scope.

Pull-Request: #2833
Reviewed-by: Jean Privat <jean@pryen.org>

40 files changed:
CONTRIBUTING.md
README.md
doc/manual/basic_type.md
doc/manual/class.md
doc/manual/constructor.md
doc/manual/method.md
doc/manual/module.md
doc/manual/nitreference.tex
doc/manual/structure.md
doc/manual/variable.md
src/astbuilder.nit
src/compiler/abstract_compiler.nit
src/compiler/global_compiler.nit
src/compiler/separate_compiler.nit
src/compiler/separate_erasure_compiler.nit
src/contracts.nit
src/metrics/mclassdef_collect.nit
src/metrics/method_analyze_metrics.nit
src/model/model_contract.nit [new file with mode: 0644]
src/nit.nit
src/test_test_phase.nit
tests/contracts_null_parameter.nit [new file with mode: 0644]
tests/sav/contracts.res
tests/sav/contracts_abstract.res
tests/sav/contracts_add.res
tests/sav/contracts_constructor.res
tests/sav/contracts_ensures.res
tests/sav/contracts_ensures_1.res
tests/sav/contracts_ensures_2.res
tests/sav/contracts_ensures_3.res
tests/sav/contracts_ensures_4.res
tests/sav/contracts_ensures_sequence.res
tests/sav/contracts_error.res
tests/sav/contracts_expects_1.res
tests/sav/contracts_generic_type.res
tests/sav/contracts_inheritance.res
tests/sav/contracts_same_contract.res
tests/sav/contracts_static.res
tests/sav/contracts_virtual_type.res
tests/sav/nit_args9.res

index 8850808..5292526 100644 (file)
@@ -18,5 +18,5 @@ We are always open for suggestions or any other kind of contribution.
 If you do not want to submit code for some reason, you are always welcome to ask questions about the language or related topics via the issue system.
 
 You may also proof-read and correct documentation if you are willing!
-All the documents on this repository are written in English, however most of our contributors are not native anglophones.
+All the documents in this repository are written in English. However, most of our contributors are not native anglophones.
 Therefore we encourage people, especially those coming of an english-speaking culture to read the documentation available and submit patches to correct bad formulations, typos or related mistakes on our part through the usual system.
index e499bbb..ddd682a 100644 (file)
--- a/README.md
+++ b/README.md
@@ -45,7 +45,7 @@ Important files and directories:
  * lib/                Nit standard library
  * LICENCE     License of the software
  * Makefile    Bootstrap the Nit tools
- * misc/       Some additional files for commons text editors and tools
+ * misc/       Some additional files for common text editors and tools
  * NOTICE.md   List of the authors
  * README      This file
  * share/      Common resources used by tools
index a94912f..e1d050d 100644 (file)
@@ -35,8 +35,8 @@ the `to_f` and `to_i` methods.
 Literal strings are enclosed within quotes (`"`).
 To insert a value
 inside a literal string, include the values inside braces (`{}`).
-Braces has to be escaped.
-`+` is the concatenation operator but is less efficient than the brace form.
+Braces have to be escaped.
+`+` is the concatenation operator, but is less efficient than the brace form.
 
 ~~~
 var j = 5
@@ -52,7 +52,7 @@ print "hel\"lo\nwo\{rld"
 ~~~
 
 Multi-line strings are enclosed with triple quotes (`"""`).
-Values are inserted with a triple braces (`{{{value}}}`).
+Values are inserted with triple braces (`{{{value}}}`).
 The multi-line form thus allows verbatim new-lines, quotes and braces
 
 ~~~
@@ -65,8 +65,8 @@ but {{{ 1+2 }}} is rendered as 3
 
 All objects have a `to_s` method that converts the object to a String.
 `print` is a top-level method that takes any number of arguments and
-prints to the standard output. `print` always add a newline, another
-top-level method, `printn`, does not add the newline.
+prints them to the standard output. `print` always adds a newline to the output, another
+top-level method, `printn`, does not add a newline.
 
 ~~~
 var x: String
@@ -84,7 +84,7 @@ Common comparison operators are available: `==` and `!=` on all objects;
 `<`, `>`, `<=`, `>=` and `<=>` on `Comparable` objects (which include
 `Int`, `String` and others).
 
-- `==`, `<`, `>`, `<=`, `>=` and `<=>` are standard Nit operators (so they are redefinable).
+- `==`, `<`, `>`, `<=`, `>=` and `<=>` are standard Nit operators thus are redefinable.
 
 - `and`, `or` and `not` are not standard Nit operators: they are not
   redefinable, also they are lazy and have adaptive typing flow
@@ -93,7 +93,7 @@ Common comparison operators are available: `==` and `!=` on all objects;
 - `==` is not for reference equality but for value equality (like
   `equals` in Java). There is a special reference equality operator,
   `is`, but it cannot be redefined and its usage is not recommended.
-  Note also that while `==` is redefinable, it has a special adaptive
+  Note that while `==` is redefinable, it has a special adaptive
   typing flow effect when used with `null`.
 
 - `!=` is not a standard Nit operator. In fact `x != y` is
index b778c43..615907d 100644 (file)
@@ -12,7 +12,7 @@ Here are the differences:
 
 -   enums (e.g. `Int` or `Bool`) can only specialize interfaces, cannot have attributes, cannot have constructors, have proper instances but they are not instantiated by the programmer—it means no `new Int`. Note that at this point there is no user-defined enums.
 
-All kinds of classes must have a name, can have some superclasses and can have some definitions of properties. Properties are methods, attributes, constructors and virtual types. All kinds of classes can also be generic. When we talk about “classes” in general, it means all these four kinds. We say “concrete classes” to designate only the classes declared with the `class` keyword alone.
+All kinds of classes must have a name, can have some superclasses and can have some definitions of properties. Properties are methods, attributes, constructors and virtual types. All kinds of classes can also be generic. When documentation refers to “classes” , it generally refers to all four kinds. The term “concrete classes” is used to designate the classes declared with the `class` keyword alone.
 
 ## Class Specialization
 
@@ -32,7 +32,7 @@ There is no repeated inheritance nor private inheritance. The specialization bet
 
 -   adding new superclasses.
 
-Note that the kind or the visibility of a class cannot be changed by a refinement. Therefore, it is allowed to just write `redef class X` whatever is the kind or the visibility of `X`.
+Note that the kind or the visibility of a class cannot be changed by a refinement. Therefore, it is allowed to just write `redef class X` regardless of the kind or the visibility of `X`.
 
 In programs, the real instantiated classes are always the combination of all their refinements.
 
index 38a32c3..77a1283 100644 (file)
@@ -12,7 +12,7 @@ Their objective is double :
 
 Classes in OO models are often a simple aggregates of attributes and methods.
 
-By default, the `new` construction require a value for each attribute defined in a class without a default value.
+By default, the `new` construction requires a value for each attribute defined in a class without a default value.
 
 ~~~
 class Product
@@ -68,7 +68,7 @@ assert op.price.is_approx(159.50, 0.001)
 
 ## Uncollected attributes
 
-There is three cases for an attributes to not be collected in the `new`.
+There are three cases for which an attribute is not collected in a `new` construction.
 
 * Attributes with a default value
 * Attributes with the annotation `noinit`
@@ -104,8 +104,8 @@ Therefore, `total_price` cannot be initialised with a default value, because at
 
 ## Generalized initializers
 
-Initializers are methods that are automatically invoked by the new.
-In fact, by default, the setter of an attribute is used as a initializer.
+Initializers are methods that are automatically invoked by `new`.
+In fact, by default, the setter of an attribute is used as an initializer.
 
 `autoinit` is used to register a method as a setter.
 
@@ -124,8 +124,8 @@ var fp = new FooProduct("ABC", "Bla bla", 15.96, 1, 3)
 assert fp.z == 13
 ~~~
 
-Generalized setters are a powerful tool but often needed in only rare specific cases.
-In most case, there is no reason that an argument of a `new` construction is not stored in the object as a real attribute.
+Generalized setters are a powerful tool, but only needed in rare specific cases.
+In most cases, there is no reason for an argument of a `new` construction to not be stored in the object as a real attribute.
 
 
 ## Inheritance
@@ -213,7 +213,7 @@ They should not be used since they will be removed in a near future.
 
 ## `new` factories
 
-`new` factories permit to completely shortcut the class instantiation mechanim.
+`new` factories allow to completely shortcut the class instantiation mechanism.
 It could be used to provide `new` syntax on non-concrete class (mainly `extern class`).
 
 `new` factories behave like a top-level function that return the result of the construction.
index ded7093..979d104 100644 (file)
@@ -81,10 +81,10 @@ Concrete classes may have abstract methods. It is up to a refinement to provide
 
 `super` calls the “previous” definition of the method. It is used in a redefinition of a method in a subclass or in a refinement, It can be used with or without arguments; in the latter case, the original arguments are implicitly used.
 
-The `super` of Nit behave more like the `call-next-method` of CLOS that the `super` of Java or Smalltalk. It permits the traversal of complex class hierarchies and refinement. Basically, `super` is polymorphic: the method called by `super` is not only determined by the class of
-definition of the method but also by the dynamic type of `self`.
+The `super` of Nit behaves more like the `call-next-method` of CLOS than the `super` of Java or Smalltalk. It permits the traversal of complex class hierarchies and refinement. Basically, `super` is polymorphic: the method called by `super` is not only determined by the class of
+definition of the method, but also by the dynamic type of `self`.
 
-The principle it to produce a strict order of the redefinitions of a method (the linearization). Each call to `super` call the next method definition in the linearization. From a technical point of view, the linearization algorithm used is based on C3. It ensures that:
+The principle is to produce a strict order of the redefinitions of a method (the linearization). Each call to `super` call the next method definition in the linearization. From a technical point of view, the linearization algorithm used is based on C3. It ensures that:
 
 -   A definition comes after its redefinition.
 
@@ -134,7 +134,7 @@ Operators and setters are methods that require a special syntax for their defini
 
 -   bracket operator: `[]`. Its definition requires one parameter or more and a return value. Its invocation is done with `x[y, z]` where `x` is the receiver, `y` the first argument and `z` the second argument.
 
--   setters: `something=` where `something` can be any valid method identifier. Their definitions require one parameter or more and no return value. If there is only one parameter, the invocation is done with `x.something = y` where `x` is the receiver and y the argument. If there is more that one parameter, the invocation is done with `x.something(y, z) = t` where `x` is the receiver, `y` the first argument, `z` the second argument and `t` the last argument.
+-   setters: `something=` where `something` can be any valid method identifier. Their definitions require one parameter or more and no return value. If there is only one parameter, the invocation is done with `x.something = y` where `x` is the receiver and `y` the argument. If there is more that one parameter, the invocation is done with `x.something(y, z) = t` where `x` is the receiver, `y` the first argument, `z` the second argument and `t` the last argument.
 
 -   bracket setter: `[]=`. Its definition requires two parameters or more and no return value. Its invocation is done with `x[y, z] = t` where `x` is the receiver, `y` the first argument, `z` the second argument and `t` the last argument.
 
index 9fcd7e9..5657b7c 100644 (file)
@@ -1,6 +1,6 @@
 # Modules
 
-`module` declares the name of a module. While optional it is recommended to use it, at least for documentation purpose. The basename of the source file must match the name declared with `module`. The extension of the source file must be `nit`.
+`module` declares the name of a module. While optional, it is recommended to use it, at least for documentation purposes. The basename of the source file must match the name declared with `module`. The extension of the source file must be `nit`.
 
 A module is made of, in order:
 
@@ -18,7 +18,7 @@ A module is made of, in order:
 
 -   `private import` indicates a private importation. Importers of a given module will not  automatically import its privately imported modules. An analogy is using `#include` in a body file (`.c`) in C/C++.
 
--   `intrude import` indicates an intrusive importation. `intrude` `import` bypasses the `private` visibility and gives to the importer module a full access on the imported module. Such an import may only be considered when modules are strongly bounded and developed together. The closest, but insufficient, analogy is something like including a body file in a body file in C/C++.
+-   `intrude import` indicates an intrusive importation. `intrude` `import` bypasses the `private` visibility and gives to the importer module full access on the imported module. Such an import may only be considered when modules are strongly bounded and developed together. The closest, but insufficient, analogy is something like including a body file in a body file in C/C++.
 
 ## Visibility
 
index 432dba9..0bfdddd 100644 (file)
@@ -65,7 +65,7 @@
 
 \noindent\textbf{A Concise Reference of the Nit Language}
 
-This document attempts to be as short as possible while covering all features of the language in deepth.
+This document attempts to be as short as possible while covering all features of the language in depth.
 It is not a real manual to learn the language since concepts are covered when required.
 %Forward and backward references about concepts are written like this~\goto{redef} which means Section~\ref*{redef}.
 %An index\goto{index} also lists concepts and keywords for an improved navigation.
index b3a319d..0cbbc22 100644 (file)
@@ -16,7 +16,7 @@ program. Nit heavily refers to the control flow in its specification:
 
 -   Adaptive typing.
 
-Some structures alter the control flow but are not described in this
+Some structures alter the control flow, but are not described in this
 section: `and`, `or`, `not`, `or else` and `return`.
 
 Note that the control flow is determined only from the position, the
@@ -118,11 +118,11 @@ loop
 end
 ~~~
 
-Note that `loop` is different from `while true` because the control flow does not consider the values of expression.
+Note that `loop` is different from `while true` because the control flow does not consider the values of expressions.
 
 ## do
 
-Single `do` are used to create scope for variables or to be attached with labeled breaks.
+Single `do` are used to create scoped variables or to be attached with labeled breaks.
 
 ~~~
 do
index 906714e..f5e527e 100644 (file)
@@ -1,6 +1,6 @@
 # Local Variables and Static Typing
 
-`var` declares local variables. In fact there is no global variable in Nit, so in this document *variable* always refers to a local variable. A variable is visible up to the end of the current
+`var` declares local variables. In fact, there is no global variable in Nit, so in this document *variable* always refers to a local variable. A variable is visible up to the end of the current
 control structure. Two variables with the same name cannot coexist: no nesting nor masking.
 
 Variables are bound to values. A variable cannot be used unless it has a value in all control flow paths (à la Java).
@@ -54,7 +54,7 @@ print d + 1
 
 ## Variable Upper Bound
 
-An optional type information can be added to a variable declaration. This type is used as an upper bound of the type of the variable. When a initial value is given in a variable declaration without a specific type information, the static type of the initial value is used as an upper bound. If no type and no initial value are given, the upper bound is set to `nullable Object`.
+An optional type information can be added to a variable declaration. This type is used as an upper bound of the type of the variable. When an initial value is given in a variable declaration without a specific type information, the static type of the initial value is used as an upper bound. If no type and no initial value are given, the upper bound is set to `nullable Object`.
 
 ~~~nitish
 var e: Int # Upper bound is Int
@@ -130,7 +130,7 @@ end
 print max # outputs 11
 ~~~
 
-Note that type adaptation occurs only in an `isa` if the target type is more specific that the current type.
+Note that type adaptation occurs only in an `isa` if the target type is more specific than the current type.
 
 ~~~
 var col: Collection[Int] = [1, 2, 3]
index 8644213..0b911c6 100644 (file)
@@ -203,11 +203,11 @@ class ASTBuilder
 
        # Build a callsite to call the `mproperty` in the current method `caller_method`.
        # `is_self_call` indicate if the method caller is a property of `self`
-       fun create_callsite(modelbuilder: ModelBuilder, caller_method : AMethPropdef, mproperty: MMethod, is_self_call: Bool): CallSite
+       fun create_callsite(modelbuilder: ModelBuilder, caller_property: APropdef, mproperty: MMethod, is_self_call: Bool): CallSite
        do
                # FIXME It's not the better solution to call `TypeVisitor` here to build a model entity, but some make need to have a callsite
-               var type_visitor = new TypeVisitor(modelbuilder, caller_method.mpropdef.as(not null))
-               var callsite = type_visitor.build_callsite_by_property(caller_method, mproperty.intro_mclassdef.bound_mtype, mproperty, is_self_call)
+               var type_visitor = new TypeVisitor(modelbuilder, caller_property.mpropdef.as(not null))
+               var callsite = type_visitor.build_callsite_by_property(caller_property, mproperty.intro_mclassdef.bound_mtype, mproperty, is_self_call)
                assert callsite != null
                return callsite
        end
@@ -418,6 +418,17 @@ redef class AMethPropdef
                self.mpropdef = mmethoddef
                if mpropdef != null then self.location = mmethoddef.location
        end
+
+       # Execute all method verification scope flow and typing.
+       # It also execute an ast validation to define all parents and all locations
+       fun do_all(toolcontext: ToolContext)
+       do
+               self.validate
+               # FIXME: The `do_` usage it is maybe to much (verification...). Solution: Cut the `do_` methods into simpler parts
+               self.do_scope(toolcontext)
+               self.do_flow(toolcontext)
+               self.do_typing(toolcontext.modelbuilder)
+       end
 end
 
 redef class AAssertExpr
index e4b8ce6..e10be39 100644 (file)
@@ -26,6 +26,7 @@ import mixin
 import counter
 import pkgconfig
 private import explain_assert_api
+import contracts
 
 # Add compiling options
 redef class ToolContext
index ac5a2a1..737ec48 100644 (file)
@@ -30,7 +30,7 @@ redef class ToolContext
        # option --global
        var opt_global = new OptionBool("Use global compilation", "--global")
 
-       var global_compiler_phase = new GlobalCompilerPhase(self, null)
+       var global_compiler_phase = new GlobalCompilerPhase(self, [contracts_phase])
 
        redef init do
                super
index 4fa8fd8..38bc466 100644 (file)
@@ -97,7 +97,7 @@ redef class ToolContext
                end
        end
 
-       var separate_compiler_phase = new SeparateCompilerPhase(self, null)
+       var separate_compiler_phase = new SeparateCompilerPhase(self, [contracts_phase])
 end
 
 class SeparateCompilerPhase
index 635e601..813e7fb 100644 (file)
@@ -46,7 +46,7 @@ redef class ToolContext
                end
        end
 
-       var erasure_compiler_phase = new ErasureCompilerPhase(self, null)
+       var erasure_compiler_phase = new ErasureCompilerPhase(self, [contracts_phase])
 end
 
 class ErasureCompilerPhase
index e2bad53..f732065 100644 (file)
 # FIXME Split the module in three parts: extension of the modele, building phase and the "re-driving"
 module contracts
 
-import astbuilder
 import parse_annotations
 import phase
 import semantize
+intrude import model_contract
+intrude import astbuilder
 intrude import modelize_property
 intrude import scope
 intrude import typing
@@ -34,41 +35,45 @@ end
 private class ContractsPhase
        super Phase
 
-       # The entry point of the contract phase
-       # In reality, the contract phase is executed on each module
-       # FIXME: Actually all method is checked to add method if any contract is inherited
        redef fun process_nmodule(nmodule)do
                # Check if the contracts are disabled
                if toolcontext.opt_no_contract.value then return
                nmodule.do_contracts(self.toolcontext)
        end
+
+       redef fun process_mainmodule(mainmodule: MModule, given_mmodules: SequenceRead[MModule]) do
+               # Visit all loaded modules `toolcontext.nmodules` to do contract weaving
+               for nmodule in toolcontext.modelbuilder.nmodules do
+                       nmodule.do_weaving_contracts(self.toolcontext)
+               end
+       end
 end
 
 redef class AModule
-       # Compile all contracts
-       #
-       # The implementation of the contracts is done in two visits.
-       #
-       # - First step, the visitor analyzes and constructs the contracts
-       #   for each class (invariant) and method (expect, ensure).
-       #
-       # - Second step the visitor analyzes each `ASendExpr` to see
-       #   if the callsite calls a method with a contract. If this is
-       #       the case the callsite is replaced by another callsite to the contract method.
+
+       # Entry point to generate the entire contract infrastructure.
+       # Once this method is called we must call the `do_weaving_contracts` method (see it for more information).
        fun do_contracts(toolcontext: ToolContext) do
+               var ast_builder = new ASTBuilder(mmodule.as(not null))
                #
-               var contract_visitor = new ContractsVisitor(toolcontext, toolcontext.modelbuilder.identified_modules.first, self, new ASTBuilder(mmodule.as(not null)))
+               var contract_visitor = new ContractsVisitor(toolcontext, toolcontext.modelbuilder.identified_modules.first, self, ast_builder)
                contract_visitor.enter_visit(self)
-               #
-               var callsite_visitor = new CallSiteVisitor(toolcontext)
+       end
+
+       # Entry point to execute the weaving in order to redirect the calls to the contract sides if it's needed.
+       fun do_weaving_contracts(toolcontext: ToolContext)
+       do
+               var ast_builder = new ASTBuilder(mmodule.as(not null))
+               var callsite_visitor = new CallSiteVisitor(toolcontext, ast_builder)
                callsite_visitor.enter_visit(self)
        end
 end
 
-# This visitor checks the `AMethPropdef` and the `AClassDef` to check if they have a contract annotation or it's a redefinition with a inheritance contract
+# Visitor to build all contracts.
 private class ContractsVisitor
        super Visitor
 
+       # Instance of the toolcontext
        var toolcontext: ToolContext
 
        # The main module
@@ -90,6 +95,8 @@ private class ContractsVisitor
        var current_location: Location is noinit
 
        # Is the contrat is an introduction or not?
+       # This attribute has the same value as the `is_intro` of the propdef attached to the contract.
+       # Note : For MClassDef `is_intro_contract == false`. This is due to the fact that a method for checking invariants is systematically added to the root object class.
        var is_intro_contract: Bool is noinit
 
        # Actual visited class
@@ -98,6 +105,11 @@ private class ContractsVisitor
        # is `no_contract` annotation was found
        var find_no_contract = false
 
+       # The reference to the `in_contract` attribute.
+       # This attribute is used to disable contract verification when you are already in a contract verification.
+       # Keep the `in_contract` attribute to avoid searching at each contrat
+       var in_contract_attribute: nullable MAttribute = null
+
        redef fun visit(node)
        do
                node.create_contracts(self)
@@ -114,64 +126,106 @@ private class ContractsVisitor
        end
 
        # Define the new contract take in consideration that an old contract exist or not
-       private fun build_contract(n_annotation: AAnnotation, mcontract: MContract, mclassdef: MClassDef): MMethodDef
+       private fun build_contract(n_annotations: Array[AAnnotation], mcontract: MContract, mclassdef: MClassDef)
        do
-               self.current_location = n_annotation.location
+               var n_conditions = new Array[AExpr]
                # Retrieving the expression provided in the annotation
-               var n_condition = n_annotation.construct_condition(self)
-               var m_contractdef: AMethPropdef
+               for n_annotation in n_annotations do n_conditions.add n_annotation.construct_condition(self)
                if is_intro_contract then
                        # Create new contract method
-                       m_contractdef = mcontract.create_intro_contract(self, n_condition, mclassdef)
+                       mcontract.create_intro_contract(self, n_conditions, mclassdef)
                else
                        # Create a redef of contract to take in consideration the new condition
-                       m_contractdef = mcontract.create_subcontract(self, n_condition, mclassdef)
+                       mcontract.create_subcontract(self, n_conditions, mclassdef)
                end
-               var contract_propdef = m_contractdef.mpropdef
-               # The contract has a null mpropdef, this should never happen
-               assert contract_propdef != null
-               return contract_propdef
        end
 
-       # Verification if the construction of the contract is necessary.
-       # Three cases are checked for `expect`:
-       #
-       # - Is the `--full-contract` option it's use?
-       # - Is the method is in the main package
-       # - Is the method is in a direct imported package.
-       #
-       fun check_usage_expect(actual_mmodule: MModule): Bool
+       # Inject the incontract attribute (`_in_contract_`) in the `Sys` class
+       # This attribute allows to check if the contract need to be executed
+       private fun inject_incontract_in_sys
        do
-               var main_package = mainmodule.mpackage
-               var actual_package = actual_mmodule.mpackage
-               if main_package != null and actual_package != null then
-                       var condition_direct_arc = toolcontext.modelbuilder.model.mpackage_importation_graph.has_arc(main_package, actual_package)
-                       return toolcontext.opt_full_contract.value or condition_direct_arc or main_package == actual_package
+               # If the `in_contract_attribute` already know just return
+               if in_contract_attribute != null then return
+
+               var sys_class = toolcontext.modelbuilder.get_mclass_by_name(visited_module, mainmodule, "Sys")
+
+               # Try to get the `in_contract` property, if it has already defined in a previously visited module.
+               var in_contract_property = toolcontext.modelbuilder.try_get_mproperty_by_name(visited_module, sys_class.intro, "__in_contract_")
+               if in_contract_property != null then
+                       self.in_contract_attribute = in_contract_property.as(MAttribute)
+                       return
                end
-               return false
+
+               var bool_false = new AFalseExpr.make(mainmodule.bool_type)
+               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)
+
+               in_contract_attribute = n_in_contract_attribute.mpropdef.mproperty
        end
 
-       # Verification if the construction of the contract is necessary.
-       # Two cases are checked for `ensure`:
+       # Return the `_in_contract_` attribute.
+       # If the attribute `_in_contract_` does not exist it's injected with `inject_incontract_in_sys`
+       private fun get_incontract: MAttribute
+       do
+               if self.in_contract_attribute == null then inject_incontract_in_sys
+               return in_contract_attribute.as(not null)
+       end
+
+       # Return an `AIfExpr` with the contract encapsulated by an `if` to check if it's already in a contract verification.
+       #
+       # Example:
+       # ~~~nitish
+       # class A
+       #       fun bar([...]) is except([...])
+       #
+       #       fun _contract_bar([...])
+       #       do
+       #               if not sys._in_contract_ then
+       #                       sys._in_contract_ = true
+       #                       _bar_expect([...])
+       #                       sys._in_contract_ = false
+       #               end
+       #               bar([...])
+       #       end
        #
-       # - Is the `--full-contract` option it's use?
-       # - Is the method is in the main package
+       #       fun _bar_expect([...])
+       # end
+       # ~~~~
        #
-       fun check_usage_ensure(actual_mmodule: MModule): Bool
+       private fun encapsulated_contract_call(visited_method: AMethPropdef, call_to_contracts: Array[ACallExpr]): AIfExpr
        do
-               return toolcontext.opt_full_contract.value or mainmodule.mpackage == actual_mmodule.mpackage
-       end
+               var sys_property = toolcontext.modelbuilder.model.get_mproperties_by_name("sys").first.as(MMethod)
+               var callsite_sys = ast_builder.create_callsite(toolcontext.modelbuilder, visited_method, sys_property, true)
+
+               var incontract_attribute = get_incontract
+
+               var callsite_get_incontract = ast_builder.create_callsite(toolcontext.modelbuilder, visited_method, incontract_attribute.getter.as(MMethod), false)
+               var callsite_set_incontract = ast_builder.create_callsite(toolcontext.modelbuilder, visited_method, incontract_attribute.setter.as(MMethod), false)
+
+               var n_condition = ast_builder.make_not(ast_builder.make_call(ast_builder.make_call(new ASelfExpr, callsite_sys, null), callsite_get_incontract, null))
+
+               var n_if = ast_builder.make_if(n_condition, null)
 
+               var if_then_block = n_if.n_then.as(ABlockExpr)
+
+               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)]))
+               if_then_block.add_all(call_to_contracts)
+               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)]))
+
+               return n_if
+       end
 end
 
 # This visitor checks the `callsite` to see if the target `mpropdef` has a contract.
 private class CallSiteVisitor
        super Visitor
 
+       # Instance of the toolcontext
        var toolcontext: ToolContext
 
+       var ast_builder: ASTBuilder
+
        # Actual visited method
-       var visited_method: APropdef is noinit
+       var visited_propdef: APropdef is noinit
 
        redef fun visit(node)
        do
@@ -179,22 +233,18 @@ private class CallSiteVisitor
                node.visit_all(self)
        end
 
-       # Check if the callsite calls a method with a contract.
-       # If it's the case the callsite is replaced by another callsite to the contract method.
-       private fun drive_method_contract(callsite: CallSite): CallSite
+       # Check if the callsite is bound on a property with a contract.
+       # If the property is linked to a contract a new callsite will be created towards the correct facet,
+       # in the other case the returned callsite wall be the same as the given `callsite`
+       private fun drive_callsite_to_contract(callsite: CallSite): CallSite
        do
-               if callsite.mproperty.mcontract_facet != null then
-                       var contract_facet = callsite.mproperty.mcontract_facet
-                       var visited_mpropdef = visited_method.mpropdef
-                       assert contract_facet != null and visited_mpropdef != null
+               var contract_facet = callsite.mproperty.mcontract_facet
+               var visited_mpropdef = visited_propdef.mpropdef
 
-                       var type_visitor = new TypeVisitor(toolcontext.modelbuilder, visited_mpropdef)
-                       var drived_callsite = type_visitor.build_callsite_by_property(visited_method, callsite.recv, contract_facet, callsite.recv_is_self)
-                       # This never happen this check is here for debug
-                       assert drived_callsite != null
-                       return drived_callsite
-               end
-               return callsite
+               if visited_mpropdef isa MContract or visited_mpropdef isa MFacet then return callsite
+               if visited_mpropdef == null or contract_facet == null then return callsite
+
+               return ast_builder.create_callsite(toolcontext.modelbuilder, visited_propdef, contract_facet, callsite.recv_is_self)
        end
 end
 
@@ -205,46 +255,48 @@ end
 
 redef class AAnnotation
 
-       # Returns the conditions of annotation parameters in the form of and expr
-       # exemple:
-       # the contract ensure(true, i == 10, f >= 1.0)
-       # return this condition (true and i == 10 and f >= 1.0)
+       # Returns the conditions of annotation parameters. If there are several parameters, the result is an `AAndExpr`
+       # Example:
+       # the contract `ensure(true, i == 10, f >= 1.0)`
+       # return this condition `(true and i == 10 and f >= 1.0)`
        private fun construct_condition(v : ContractsVisitor): AExpr
        do
                var n_condition = n_args.first
                n_args.remove_at(0)
                for n_arg in n_args do n_condition = v.ast_builder.make_and(n_condition, n_arg)
+               n_condition.location = self.location
                return n_condition
        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
+       # Should contract be called?
+       # return `true` if the contract needs to be called.
+       private fun is_called(v: ContractsVisitor, mpropdef: MPropDef): Bool
+       do
+               return v.toolcontext.opt_full_contract.value
+       end
 
        # Method use to diplay warning when the contract is not present at the introduction
-       private fun no_intro_contract(v: ContractsVisitor, a: AAnnotation)do end
+       private fun no_intro_contract(v: ContractsVisitor, a: Array[AAnnotation])do end
 
        # Creating specific inheritance block contract
-       private fun create_nblock(v: ContractsVisitor, n_condition: AExpr, args: Array[AExpr]): ABlockExpr is abstract
+       #
+       # `super_args` : Correspond to the `super` call arguments
+       private fun create_inherit_nblock(v: ContractsVisitor, n_conditions: Array[AExpr], super_args: Array[AExpr]): ABlockExpr is abstract
 
-       # Method to adapt the `n_mpropdef.n_block` to the contract
-       private fun adapt_block_to_contract(v: ContractsVisitor, n_mpropdef: AMethPropdef) is abstract
+       # Method to adapt the given `n_mpropdef.n_block` to the contract
+       private fun adapt_method_to_contract(v: ContractsVisitor, mfacet: MFacet, n_mpropdef: AMethPropdef) is abstract
 
-       # Adapt the msignature specifically for the contract method
-       private fun adapt_specific_msignature(m_signature: MSignature): MSignature do return m_signature.adapt_to_condition
+       # Create and return an adapted `MSignature` specifically for the contract in fonction of the given `m_signature`
+       private fun adapt_specific_msignature(m_signature: MSignature): MSignature do return m_signature.adapt_to_contract
 
-       # Adapt the nsignature specifically for the contract method
-       private fun adapt_specific_nsignature(n_signature: ASignature): ASignature do return n_signature.adapt_to_condition(null)
+       # Create and return an adapted `ASignature` specifically for the contract in fonction of the given `n_signature`
+       private fun adapt_specific_nsignature(n_signature: ASignature): ASignature do return n_signature.adapt_to_contract
 
        # Adapt the `m_signature` to the contract
-       # If it is not null call the specific adapt `m_signature` for the contract
+       # If `m_signature == null` return a new `MSignature` else it calls a specific adapt method see `adapt_specific_msignature`
        private fun adapt_msignature(m_signature: nullable MSignature): MSignature
        do
                if m_signature == null then return new MSignature(new Array[MParameter])
@@ -252,74 +304,89 @@ abstract class MContract
        end
 
        # Adapt the `n_signature` to the contract
-       # If it is not null call the specific adapt `n_signature` for the contract
+       # If `n_signature == null` return a new `ASignature` else it calls a specific adapt method see `adapt_specific_nsignature`
        private fun adapt_nsignature(n_signature: nullable ASignature): ASignature
        do
                if n_signature == null then return new ASignature
                return adapt_specific_nsignature(n_signature)
        end
 
-       # Create a new empty contract
-       private fun create_empty_contract(v: ContractsVisitor, mclassdef: MClassDef, msignature: nullable MSignature, n_signature: ASignature)
-       do
-               var n_contract_def = intro_mclassdef.mclass.create_empty_method(v, self, mclassdef, msignature, n_signature)
-               n_contract_def.do_all(v.toolcontext)
-       end
-
        # Create the initial contract (intro)
        # All contracts have the same implementation for the introduction.
        #
+       # Example:
+       # ~~~nitish
        # fun contrat([...])
        # do
        #       assert contract_condition
        # end
+       # ~~~
        #
-       private fun create_intro_contract(v: ContractsVisitor, n_condition: nullable AExpr, mclassdef: MClassDef): AMethPropdef
+       private fun create_intro_contract(v: ContractsVisitor, n_conditions: Array[AExpr], mclassdef: MClassDef)
        do
                var n_block = v.ast_builder.make_block
-               if n_condition != null then
+               for n_condition in n_conditions do
                        # Create a new tid to set the name of the assert for more explicit error
-                       var tid = new TId.init_tk(self.location)
-                       tid.text = "{self.contract_name}"
-                       n_block.add v.ast_builder.make_assert(tid, n_condition, null)
+                       var tid = new TId.init_tk(n_condition.location)
+                       tid.text = "{n_condition.location.text}"
+                       var n_assert = v.ast_builder.make_assert(tid, n_condition, null)
+                       # Define the assert location to reference the annoation
+                       n_assert.location = n_condition.location
+                       n_block.add n_assert
                end
-               return make_contract(v, n_block, mclassdef)
+               make_contract(v, n_block, mclassdef)
        end
 
-       # Create a contract with old (super) and the new conditions
-       private fun create_subcontract(v: ContractsVisitor, ncondition: nullable AExpr, mclassdef: MClassDef): AMethPropdef
+       # Create a contract to check the old (super call) and the new conditions
+       #
+       # Example:
+       # ~~~nitish
+       # fun contrat([...])
+       # do
+       #       super # Call the old contracts
+       #       assert new_condition
+       # end
+       # ~~~
+       #
+       private fun create_subcontract(v: ContractsVisitor, n_conditions: Array[AExpr], mclassdef: MClassDef)
        do
                var args = v.n_signature.make_parameter_read(v.ast_builder)
                var n_block = v.ast_builder.make_block
-               if ncondition != null then n_block = self.create_nblock(v, ncondition, args)
-               return make_contract(v, n_block, mclassdef)
+               n_block = self.create_inherit_nblock(v, n_conditions, args)
+               make_contract(v, n_block, mclassdef)
        end
 
-       # Build a method with a specific block `n_block` in a specified `mclassdef`
-       private fun make_contract(v: ContractsVisitor, n_block: AExpr, mclassdef: MClassDef): AMethPropdef
+       # Build a new contract method with a specific block `n_block` in a specified `mclassdef`
+       private fun make_contract(v: ContractsVisitor, n_block: AExpr, mclassdef: MClassDef)
        do
-               var n_contractdef = intro_mclassdef.mclass.create_empty_method(v, self, mclassdef, v.m_signature, v.n_signature)
+               var n_contractdef = v.toolcontext.modelbuilder.create_method_from_property(self, mclassdef, false, v.m_signature)
+               # Set the signature to keep the same variable
+               n_contractdef.n_signature = v.n_signature
                n_contractdef.n_block = n_block
                # Define the location of the new method for corresponding of the annotation location
                n_contractdef.location = v.current_location
                n_contractdef.do_all(v.toolcontext)
-               return n_contractdef
        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"
+       redef fun is_called(v: ContractsVisitor, mpropdef: MPropDef): Bool
+       do
+               var main_package = v.mainmodule.mpackage
+               var actual_package = mpropdef.mclassdef.mmodule.mpackage
+               if main_package != null and actual_package != null then
+                       var condition_direct_arc = v.toolcontext.modelbuilder.model.mpackage_importation_graph.has_arc(main_package, actual_package)
+                       return super or main_package == actual_package or condition_direct_arc
+               end
+               return false
+       end
 
        # Display warning if no contract is defined at introduction `expect`,
        # because if no contract is defined at the introduction the added
        # contracts will not cause any error even if they are not satisfied.
        #
-       # exemple
+       # Example:
        # ~~~nitish
        # class A
        #       fun bar [...]
@@ -333,91 +400,95 @@ class MExpect
        #       redef fun bar is expect(contract_condition)
        #       redef fun _bar_expect([...])
        #       do
-       #               if not (contract_condition) then super
+       #               if (contract_condition) then return
+       #               super
        #       end
        # end
        # ~~~~
        #
-       redef fun no_intro_contract(v: ContractsVisitor, a: AAnnotation)
+       redef fun no_intro_contract(v: ContractsVisitor, a: Array[AAnnotation])
        do
-               v.toolcontext.warning(a.location,"","Useless contract: No contract defined at the introduction of the method")
+               v.toolcontext.warning(a.first.location,"useless_contract","Useless contract: No contract defined at the introduction of the method")
        end
 
-       redef fun create_nblock(v: ContractsVisitor, n_condition: AExpr, args: Array[AExpr]): ABlockExpr
+       redef fun create_inherit_nblock(v: ContractsVisitor, n_conditions: Array[AExpr], super_args: Array[AExpr]): ABlockExpr
        do
-               # Creating the if expression with the new condition
-               var if_block = v.ast_builder.make_if(n_condition, n_condition.mtype)
-               # Creating and adding return expr to the then case
-               if_block.n_then = v.ast_builder.make_return(null)
-               # Creating the super call to the contract and adding this to else case
-               if_block.n_else = v.ast_builder.make_super_call(args,null)
                var n_block = v.ast_builder.make_block
-               n_block.add if_block
+               for n_condition in n_conditions do
+                       # Creating the if expression with the new condition
+                       var if_block = v.ast_builder.make_if(n_condition, n_condition.mtype)
+                       # Creating and adding return expr to the then case
+                       if_block.n_then = v.ast_builder.make_return
+                       if_block.location = n_condition.location
+                       n_block.add if_block
+               end
+               n_block.add v.ast_builder.make_super_call(super_args)
                return n_block
        end
 
-       redef fun adapt_block_to_contract(v: ContractsVisitor, n_mpropdef: AMethPropdef)
+       redef fun adapt_method_to_contract(v: ContractsVisitor, mfacet: MFacet, n_mpropdef: AMethPropdef)
        do
                var callsite = v.ast_builder.create_callsite(v.toolcontext.modelbuilder, n_mpropdef, self, true)
-               var n_self = new ASelfExpr
                var args = n_mpropdef.n_signature.make_parameter_read(v.ast_builder)
-               var n_callexpect = v.ast_builder.make_call(n_self,callsite,args)
+               var n_callexpect = v.ast_builder.make_call(new ASelfExpr, callsite,args)
                # Creation of the new instruction block with the call to expect condition
                var actual_expr = n_mpropdef.n_block
                var new_block = new ABlockExpr
-               new_block.n_expr.push n_callexpect
+               new_block.n_expr.push v.encapsulated_contract_call(n_mpropdef, [n_callexpect])
                if actual_expr isa ABlockExpr then
                        new_block.n_expr.add_all(actual_expr.n_expr)
                else if actual_expr != null then
                        new_block.n_expr.push(actual_expr)
                end
                n_mpropdef.n_block = new_block
+               mfacet.has_applied_expect = true
        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
+       redef fun is_called(v: ContractsVisitor, mpropdef: MPropDef): Bool
+       do
+               return super or v.mainmodule.mpackage == mpropdef.mclassdef.mmodule.mpackage
+       end
+
+       redef fun create_inherit_nblock(v: ContractsVisitor, n_conditions: Array[AExpr], super_args: Array[AExpr]): ABlockExpr
        do
-               var tid = new TId.init_tk(v.current_location)
-               tid.text = "{contract_name}"
-               # Creating the assert expression with the new condition
-               var assert_block = v.ast_builder.make_assert(tid,n_condition,null)
-               # Creating the super call to the contract
-               var super_call = v.ast_builder.make_super_call(args,null)
                # Define contract block
                var n_block = v.ast_builder.make_block
-               # Adding the expressions to the block
+
+               var super_call = v.ast_builder.make_super_call(super_args)
+
                n_block.add super_call
-               n_block.add assert_block
+               for n_condition in n_conditions do
+                       var tid = new TId.init_tk(n_condition.location)
+                       tid.text = "{n_condition.location.text}"
+                       # Creating the assert expression with the new condition
+                       var n_assert = v.ast_builder.make_assert(tid, n_condition)
+                       n_assert.location = n_condition.location
+                       n_block.add n_assert
+               end
                return n_block
        end
 
-       # Inject the result variable in the `n_block` of the given `n_mpropdef`.
+       # Inject the `result` variable into the `n_block` of the given n_mpropdef`.
+       #
+       # The purpose of the variable is to capture return values to use it in contracts.
        private fun inject_result(v: ContractsVisitor, n_mpropdef: AMethPropdef, ret_type: MType): Variable
+       is
+               expect(n_mpropdef.n_signature.n_type != null)
        do
                var actual_block = n_mpropdef.n_block
                # never happen. If it's the case the problem is in the contract facet building
                assert actual_block isa ABlockExpr
 
-               var return_var: nullable Variable = null
-
                var return_expr = actual_block.n_expr.last.as(AReturnExpr)
 
                var returned_expr = return_expr.n_expr
                # The return node has no returned expression
                assert returned_expr != null
 
-               # Check if the result variable already exit
-               if returned_expr isa AVarExpr then
-                       if returned_expr.variable.name == "result" then
-                               return_var = returned_expr.variable
-                       end
-               end
-
-               return_var = new Variable("result")
+               var return_var = new Variable("result")
                # Creating a new variable to keep the old return of the method
                var assign_result = v.ast_builder.make_var_assign(return_var, returned_expr)
                # Remove the actual return
@@ -435,13 +506,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
-
-       # Define the name of the contract
-       redef fun contract_name: String do return "ensure"
+redef class MEnsure
 
        redef fun adapt_specific_msignature(m_signature: MSignature): MSignature
        do
@@ -453,14 +518,12 @@ class MEnsure
                return n_signature.adapt_to_ensurecondition
        end
 
-       redef fun adapt_block_to_contract(v: ContractsVisitor, n_mpropdef: AMethPropdef)
+       redef fun adapt_method_to_contract(v: ContractsVisitor, mfacet: MFacet, n_mpropdef: AMethPropdef)
        do
                var callsite = v.ast_builder.create_callsite(v.toolcontext.modelbuilder, n_mpropdef, self, true)
                var n_self = new ASelfExpr
                # argument to call the contract method
                var args = n_mpropdef.n_signature.make_parameter_read(v.ast_builder)
-               # Inject the variable result
-               # The cast is always safe because the online adapted method is the contract facet
 
                var actual_block = n_mpropdef.n_block
                # never happen. If it's the case the problem is in the contract facet building
@@ -468,164 +531,120 @@ class MEnsure
 
                var ret_type = n_mpropdef.mpropdef.mproperty.intro.msignature.return_mtype
                if ret_type != null then
+                       # Inject the variable result
                        var result_var = inject_result(v, n_mpropdef, ret_type)
                        # Expr to read the result variable
                        var read_result = v.ast_builder.make_var_read(result_var, ret_type)
                        var return_expr = actual_block.n_expr.pop
                        # Adding the read return to argument
                        args.add(read_result)
-                       var n_callcontract = v.ast_builder.make_call(n_self,callsite,args)
-                       actual_block.add_all([n_callcontract,return_expr])
+                       var n_call_contract = v.ast_builder.make_call(n_self, callsite, args)
+                       actual_block.add_all([v.encapsulated_contract_call(n_mpropdef, [n_call_contract]), return_expr])
                else
                        # build the call to the contract method
-                       var n_callcontract = v.ast_builder.make_call(n_self,callsite,args)
-                       actual_block.add n_callcontract
+                       var n_call_contract = v.ast_builder.make_call(n_self, callsite, args)
+                       actual_block.add v.encapsulated_contract_call(n_mpropdef, [n_call_contract])
                end
-       end
-end
-
-redef class MClass
-
-       # This method create an abstract method representation with this MMethodDef an this AMethoddef
-       private fun create_abstract_method(v: ContractsVisitor, mproperty: MMethod, mclassdef: MClassDef, msignature: nullable MSignature, n_signature: ASignature): AMethPropdef
-       do
-               # new methoddef definition
-               var m_def = new MMethodDef(mclassdef, mproperty, v.current_location)
-               # set the signature
-               if msignature != null then m_def.msignature = msignature.clone
-               # set the abstract flag
-               m_def.is_abstract = true
-               # Build the new node method
-               var n_def = v.ast_builder.make_method(null,null,m_def,n_signature,null,null,null,null)
-               # Define the location of the new method for corresponding of the actual method
-               n_def.location = v.current_location
-               # Association new npropdef to mpropdef
-               v.toolcontext.modelbuilder.unsafe_add_mpropdef2npropdef(m_def,n_def)
-               return n_def
-       end
-
-       # Create method with an empty block
-       # the `mproperty` i.e the global property definition. The mclassdef to set where the method is declared and it's model `msignature` and ast `n_signature` signature
-       private fun create_empty_method(v: ContractsVisitor, mproperty: MMethod, mclassdef: MClassDef, msignature: nullable MSignature, n_signature: ASignature): AMethPropdef
-       do
-               var n_def = create_abstract_method(v, mproperty, mclassdef, msignature, n_signature)
-               n_def.mpropdef.is_abstract = false
-               n_def.n_block = v.ast_builder.make_block
-               return n_def
+               n_mpropdef.do_all(v.toolcontext)
+               mfacet.has_applied_ensure = true
        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)
-               if exist_contract_facet and exist_contract then return
-
-               var contract_facet: AMethPropdef
+       # Define contract facet for MMethod in the given mclassdef. The facet represents the entry point with contracts (expect, ensure) of the method.
+       # If a contract is given adapt the contract facet.
+       #
+       # `classdef`: Indicates the class where we want to introduce our facet
+       # `exist_contract`: Indicates if it is necessary to define a new facet for the contract. If `exist_contract_facet and exist_contract` it's not necessary to add a facet.
+       #
+       # Exemple:
+       # ~~~nitish
+       # from:
+       #       classe A
+       #               i :Int
+       #               fun add_one is ensure(old(i) + 1 == i)
+       #       end
+       # to:
+       #       classe A
+       #               fun add_one is ensure(old(i) + 1 == i)
+       #
+       #               # The contract facet
+       #               fun contract_add_one do
+       #                       add_one
+       #                       ensure_add_one(old_add_one)
+       #               end
+       #       end
+       # ~~
+       private fun define_contract_facet(v: ContractsVisitor, classdef: MClassDef, mcontract: nullable MContract)
+       do
+               var exist_contract_facet = has_contract_facet
+               var contract_facet = build_contract_facet
+               # Do nothing the contract and the contract facet already exist
+               if mcontract != null and mcontract.is_already_applied(contract_facet) then return
+
+               var n_contract_facet: AMethPropdef
                if not exist_contract_facet then
                        # If has no contract facet in intro just create it
-                       if classdef != mproperty.intro_mclassdef then create_contract_facet(v, mproperty.intro_mclassdef, n_signature)
-                       # If has no contract facet just create it
-                       contract_facet = create_contract_facet(v, classdef, n_signature)
+                       if classdef != intro_mclassdef then
+                               var n_intro_face = create_facet(v, intro_mclassdef, contract_facet, self)
+                               n_intro_face.location = self.intro.location
+                               n_intro_face.do_all(v.toolcontext)
+                       end
+                       n_contract_facet = create_facet(v, classdef, contract_facet, self)
                else
                        # Check if the contract facet already exist in this context (in this classdef)
-                       if classdef.mpropdefs_by_property.has_key(mproperty.mcontract_facet) then
-                               # get the define
-                               contract_facet = v.toolcontext.modelbuilder.mpropdef2node(classdef.mpropdefs_by_property[mproperty.mcontract_facet]).as(AMethPropdef)
+                       if classdef.mpropdefs_by_property.has_key(contract_facet) then
+                               # get the definition
+                               n_contract_facet = v.toolcontext.modelbuilder.mpropdef2node(classdef.mpropdefs_by_property[contract_facet]).as(AMethPropdef)
                        else
                                # create a new contract facet definition
-                               contract_facet = create_contract_facet(v, classdef, n_signature)
+                               n_contract_facet = create_facet(v, classdef, contract_facet, self)
                                var block = v.ast_builder.make_block
                                # super call to the contract facet
-                               var n_super_call = v.ast_builder.make_super_call(n_signature.make_parameter_read(v.ast_builder), null)
+                               var args = n_contract_facet.n_signature.make_parameter_read(v.ast_builder)
+                               var n_super_call = v.ast_builder.make_super_call(args)
                                # verification for add a return or not
-                               if contract_facet.mpropdef.msignature.return_mtype != null then
+                               if self.intro.msignature.return_mtype != null then
                                        block.add(v.ast_builder.make_return(n_super_call))
                                else
                                        block.add(n_super_call)
                                end
-                               contract_facet.n_block = block
+                               n_contract_facet.n_block = block
                        end
                end
-               contract_facet.adapt_block_to_contract(v, mcontract, contract_facet)
-               contract_facet.location = v.current_location
-               contract_facet.do_all(v.toolcontext)
-       end
+               if mcontract != null then mcontract.adapt_method_to_contract(v, contract_facet, n_contract_facet)
 
-       # 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
-               # 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
-
-               # check if the method has an `msignature` to copy it.
-               var m_signature: nullable MSignature = null
-               if mproperty.intro.msignature != null then m_signature = mproperty.intro.msignature.clone
+               n_contract_facet.location = v.current_location
+               n_contract_facet.do_all(v.toolcontext)
+       end
 
-               var n_contractdef = classdef.mclass.create_empty_method(v, contract_facet, classdef, m_signature, n_signature)
+       # Method to create a facet of the method.
+       # See `define_contract_facet` for more information about two types of facets.
+       #
+       # `called` : is the property to call in this facet.
+       private fun create_facet(v: ContractsVisitor, classdef: MClassDef, facet: MFacet, called: MMethod): AMethPropdef
+       is
+               expect( called.is_same_instance(self) or called.is_same_instance(self.mcontract_facet) )
+       do
+               # Defines the contract facet is an init or not
+               # it is necessary to use the contracts with in a constructor
+               facet.is_init = is_init
+               var n_contractdef = v.toolcontext.modelbuilder.create_method_from_property(facet, classdef, false, self.intro.msignature)
                # FIXME set the location because the callsite creation need the node location
                n_contractdef.location = v.current_location
                n_contractdef.validate
 
                var block = v.ast_builder.make_block
-               var n_self = new ASelfExpr
-               var args = n_contractdef.n_signature.make_parameter_read(v.ast_builder)
-               var callsite = v.ast_builder.create_callsite(v.toolcontext.modelbuilder, n_contractdef, mproperty, true)
-               var n_call = v.ast_builder.make_call(n_self, callsite, args)
 
-               if m_signature.return_mtype == null then
+               # Arguments to call the `called` property
+               var args: Array[AExpr]
+               args = n_contractdef.n_signature.make_parameter_read(v.ast_builder)
+
+               var callsite = v.ast_builder.create_callsite(v.toolcontext.modelbuilder, n_contractdef, called, true)
+               var n_call = v.ast_builder.make_call(new ASelfExpr, callsite, args)
+
+               if self.intro.msignature.return_mtype == null then
                        block.add(n_call)
                else
                        block.add(v.ast_builder.make_return(n_call))
@@ -635,150 +654,138 @@ redef class MMethodDef
                n_contractdef.do_all(v.toolcontext)
                return n_contractdef
        end
+end
+
+redef class MMethodDef
 
        # Entry point to build contract (define the contract facet and define the contract method verification)
-       private fun construct_contract(v: ContractsVisitor, n_signature: ASignature, n_annotation: AAnnotation, mcontract: MContract, exist_contract: Bool)
+       private fun construct_contract(v: ContractsVisitor, n_signature: ASignature, n_annotations: Array[AAnnotation], mcontract: MContract, exist_contract: Bool)
        do
-               if check_same_contract(v, n_annotation, mcontract) then return
-               if not exist_contract and not is_intro then no_intro_contract(v, n_signature, mcontract, n_annotation)
                v.define_signature(mcontract, n_signature, mproperty.intro.msignature)
-
-               var conditiondef = v.build_contract(n_annotation, mcontract, mclassdef)
-               check_contract_facet(v, n_signature.clone, mclassdef, mcontract, exist_contract)
-               has_contract = true
+               if not exist_contract and not is_intro then no_intro_contract(v, mcontract, n_annotations)
+               v.build_contract(n_annotations, mcontract, mclassdef)
+               # Check if the contract must be called to know if it's needed to construct the facet
+               if mcontract.is_called(v, self) then mproperty.define_contract_facet(v, mclassdef, mcontract)
        end
 
        # Create a contract on the introduction classdef of the property.
        # Display an warning message if necessary
-       private fun no_intro_contract(v: ContractsVisitor, n_signature: ASignature, mcontract: MContract, n_annotation: AAnnotation)
+       private fun no_intro_contract(v: ContractsVisitor, mcontract: MContract, n_annotations: Array[AAnnotation])
        do
-               mcontract.create_empty_contract(v, mcontract.intro_mclassdef, mcontract.adapt_msignature(self.mproperty.intro.msignature), mcontract.adapt_nsignature(n_signature))
-               mcontract.no_intro_contract(v, n_annotation)
-               mproperty.intro.has_contract = true
+               v.toolcontext.modelbuilder.create_method_from_property(mcontract, mcontract.intro_mclassdef, false, v.m_signature)
+               mcontract.no_intro_contract(v, n_annotations)
        end
 
-       # Is the contract already defined in the context
-       #
-       # Exemple :
-       # fun foo is expect([...]), expect([...])
-       #
-       # Here `check_same_contract` display an error when the second expect is processed
-       private fun check_same_contract(v: ContractsVisitor, n_annotation: AAnnotation ,mcontract: MContract): Bool
+       # Apply the `no_contract` annotation to the contract. This method removes the inheritance by adding an empty contract method.
+       # Display a warning if the annotation is not needed
+       private fun no_contract_apply(v: ContractsVisitor, n_signature: ASignature)
        do
-               if self.mclassdef.mpropdefs_by_property.has_key(mcontract) then
-                       v.toolcontext.error(n_annotation.location, "The method already has a defined `{mcontract.contract_name}` contract at line {self.mclassdef.mpropdefs_by_property[mcontract].location.line_start}")
-                       return true
+               var mensure = mproperty.mensure
+               var mexpect = mproperty.mexpect
+               if mensure == null and mexpect == null then
+                       v.toolcontext.warning(location, "useless_nocontract", "Useless `no_contract`, no contract was declared for `{name}`. Remove the `no_contract`")
+               end
+               if mensure != null then
+                       # Add an empty ensure method to replace the actual definition
+                       v.toolcontext.modelbuilder.create_method_from_property(mensure, mclassdef, false, mensure.intro.msignature)
+               end
+               if mexpect != null then
+                       # Add an empty expect method to replace the actual definition
+                       v.toolcontext.modelbuilder.create_method_from_property(mexpect, mclassdef, false, mexpect.intro.msignature)
                end
-               return false
        end
 end
 
-redef class MPropDef
-       # flag to indicate is the `MPropDef` has a contract
-       var has_contract = false
-end
-
 redef class APropdef
        redef fun check_callsite(v)
        do
-               v.visited_method = self
+               v.visited_propdef = self
        end
 end
 
 redef class AMethPropdef
 
-       # Execute all method verification scope flow and typing.
-       # It also execute an ast validation to define all parents and all locations
-       private fun do_all(toolcontext: ToolContext)
-       do
-               self.validate
-               # FIXME: The `do_` usage it is maybe to much (verification...). Solution: Cut the `do_` methods into simpler parts
-               self.do_scope(toolcontext)
-               self.do_flow(toolcontext)
-               self.do_typing(toolcontext.modelbuilder)
-       end
-
        # Entry point to create a contract (verification of inheritance, or new contract).
        redef fun create_contracts(v)
        do
                v.ast_builder.check_mmodule(mpropdef.mclassdef.mmodule)
-
                v.current_location = self.location
                v.is_intro_contract = mpropdef.is_intro
+               check_annotation(v)
+               if not mpropdef.is_intro then check_redef(v)
+       end
 
-               if n_annotations != null then
-                       for n_annotation in n_annotations.n_items do
-                               check_annotation(v,n_annotation)
-                       end
+       # Verification of the annotation to know if it is a contract annotation.
+       # If this is the case, we built the appropriate contract.
+       private fun check_annotation(v: ContractsVisitor)
+       do
+               var annotations_expect = get_annotations("expect")
+               var annotations_ensure = get_annotations("ensure")
+               var annotation_no_contract = get_annotations("no_contract")
+
+               if (not annotations_expect.is_empty or not annotations_ensure.is_empty) and not annotation_no_contract.is_empty then
+                       v.toolcontext.error(location, "The new contract definition is not correct when using `no_contract`. Remove the contract definition or the `no_contract`")
+                       return
                end
 
-               if not mpropdef.is_intro and not v.find_no_contract then
-                       self.check_redef(v)
+               var nsignature = n_signature or else new ASignature
+
+               if not annotation_no_contract.is_empty then
+                       mpropdef.no_contract_apply(v, nsignature.clone)
+                       return
                end
 
-               # reset the flag
-               v.find_no_contract = false
-       end
+               if not annotations_expect.is_empty then
+                       var exist_contract = mpropdef.mproperty.has_expect
+                       mpropdef.construct_contract(v, nsignature.clone, annotations_expect, mpropdef.mproperty.build_expect, exist_contract)
+               end
 
-       # Verification of the annotation to know if it is a contract annotation.
-       # If this is the case, we built the appropriate contract.
-       private fun check_annotation(v: ContractsVisitor, n_annotation: AAnnotation)
-       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)
-               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)
-               else if n_annotation.name == "no_contract" then
-                       # no_contract found set the flag to true
-                       v.find_no_contract = true
+               if not annotations_ensure.is_empty then
+                       var exist_contract = mpropdef.mproperty.has_ensure
+                       mpropdef.construct_contract(v, nsignature.clone, annotations_ensure, mpropdef.mproperty.build_ensure, exist_contract)
                end
        end
 
        # Verification if the method have an inherited contract to apply it.
        private fun check_redef(v: ContractsVisitor)
        do
-               # Check if the method has an attached contract
-               if not mpropdef.has_contract then
-                       if mpropdef.mproperty.intro.has_contract then
-                               mpropdef.has_contract = true
-                       end
-               end
-       end
+               var mexpect = mpropdef.mproperty.mexpect
+               var mensure = mpropdef.mproperty.mensure
+               var mcontract_facet = mpropdef.mproperty.mcontract_facet
 
-       # Adapt the block to use the contracts
-       private fun adapt_block_to_contract(v: ContractsVisitor, contract: MContract, n_mpropdef: AMethPropdef)
-       do
-               contract.adapt_block_to_contract(v, n_mpropdef)
-               mpropdef.has_contract = true
-               n_mpropdef.do_all(v.toolcontext)
+               if mexpect != null then
+                       if mcontract_facet != null and mcontract_facet.has_applied_expect then return
+                       if mexpect.is_called(v, mpropdef.as(not null)) then mpropdef.mproperty.define_contract_facet(v, mpropdef.mclassdef, mexpect)
+               end
+               if mensure != null then
+                       if mcontract_facet != null and mcontract_facet.has_applied_ensure then return
+                       if mensure.is_called(v, mpropdef.as(not null)) then mpropdef.mproperty.define_contract_facet(v, mpropdef.mclassdef, mensure)
+               end
        end
 end
 
 redef class MSignature
 
-       # Adapt signature for a expect condition
-       # Removed the return type is it not necessary
-       private fun adapt_to_condition: MSignature do return new MSignature(mparameters.to_a, null)
+       # Adapt signature for an contract
+       #
+       # The returned `MSignature` is the copy of `self` without return type.
+       private fun adapt_to_contract: MSignature do return new MSignature(mparameters.to_a, null)
 
-       # Adapt signature for a ensure condition
+       # Adapt signature for a ensure contract
        #
-       # Create new parameter with the return type
+       # The returned `MSignature` is the copy of `self` without return type.
+       # The return type is replaced by a new parameter `result`
        private fun adapt_to_ensurecondition: MSignature
        do
                var rtype = return_mtype
-               var msignature = adapt_to_condition
+               var msignature = adapt_to_contract
                if rtype != null then
                        msignature.mparameters.add(new MParameter("result", rtype, false))
                end
                return msignature
        end
 
-       # Adapt signature for a expect condition
-       # Removed the return type is it not necessary
+       # The returned `MSignature` is the exact copy of `self`.
        private fun clone: MSignature do return new MSignature(mparameters.to_a, return_mtype)
 end
 
@@ -798,26 +805,26 @@ redef class ASignature
                return args
        end
 
-       # Return a copy of self adapted for the expect condition
-       # npropdef it is use to define the parent of the parameters
-       private fun adapt_to_condition(return_type: nullable AType): ASignature
+       # Create a new ASignature adapted for contract
+       #
+       # The returned `ASignature` is the copy of `self` without return type.
+       private fun adapt_to_contract: ASignature
        do
                var adapt_nsignature = self.clone
-               adapt_nsignature.n_type = return_type
+               if adapt_nsignature.n_type != null then adapt_nsignature.n_type.detach
                return adapt_nsignature
        end
 
-       # Return a copy of self adapted for postcondition on npropdef
+       # Create a new ASignature adapted for ensure
+       #
+       # The returned `ASignature` is the copy of `self` without return type.
+       # The return type is replaced by a new parameter `result`
        private fun adapt_to_ensurecondition: ASignature do
-               var nsignature = adapt_to_condition(null)
+               var nsignature = adapt_to_contract
                if ret_type != null then
-                       var n_id = new TId
-                       n_id.text = "result"
-                       var new_param = new AParam
-                       new_param.n_id = n_id
-                       new_param.variable = new Variable(n_id.text)
-                       new_param.variable.declared_type = ret_type
-                       nsignature.n_params.add new_param
+                       var variable = new Variable("result")
+                       variable.declared_type = ret_type
+                       nsignature.n_params.add new AParam.make(variable, ret_type.create_ast_representation)
                end
                return nsignature
        end
@@ -828,7 +835,9 @@ redef class ASendExpr
        do
                var actual_callsite = callsite
                if actual_callsite != null then
-                       callsite = v.drive_method_contract(actual_callsite)
+                       callsite = v.drive_callsite_to_contract(actual_callsite)
+                       # Set the signature mapping with the old value, this avoids having to re-check the callsite.
+                       callsite.signaturemap = actual_callsite.signaturemap
                end
        end
 end
@@ -838,7 +847,9 @@ redef class ANewExpr
        do
                var actual_callsite = callsite
                if actual_callsite != null then
-                       callsite = v.drive_method_contract(actual_callsite)
+                       callsite = v.drive_callsite_to_contract(actual_callsite)
+                       # Set the signature mapping with the old value, this avoids having to re-check the callsite
+                       callsite.signaturemap = actual_callsite.signaturemap
                end
        end
 end
index 98a4412..2c8f1c5 100644 (file)
@@ -16,7 +16,7 @@
 module mclassdef_collect
 
 # We usualy need specific phases
-# NOTE: `frontend` is sufficent in most case (it is often too much)
+# NOTE: `frontend` is sufficent in most cases (it is often too much)
 import frontend
 import model_collect
 
index bb0612f..95b4ca0 100644 (file)
@@ -16,7 +16,7 @@
 module method_analyze_metrics
 
 # We usualy need specific phases
-# NOTE: `frontend` is sufficent in most case (it is often too much)
+# NOTE: `frontend` is sufficent in most cases (it is often too much)
 import nitsmell_toolcontext
 import mclassdef_collect
 
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
index be6c665..6441b1a 100644 (file)
@@ -75,6 +75,7 @@ else
 end
 
 modelbuilder.run_phases
+toolcontext.run_global_phases(modelbuilder.parsed_modules)
 
 if toolcontext.opt_only_metamodel.value then toolcontext.quit
 
index cd300d4..11b1451 100644 (file)
@@ -21,7 +21,7 @@ module test_test_phase
 import test_phase
 
 # We usualy need specific phases
-# NOTE: `frontend` is sufficient in most case (it is often too much)
+# NOTE: `frontend` is sufficient in most cases (it is often too much)
 import frontend
 
 # The body of the specific work.
diff --git a/tests/contracts_null_parameter.nit b/tests/contracts_null_parameter.nit
new file mode 100644 (file)
index 0000000..da7c073
--- /dev/null
@@ -0,0 +1,31 @@
+# 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.
+
+class A
+
+       var null_attribut: nullable Int
+
+       fun set_null_attribut(i: nullable Int)
+       is
+               ensure(null_attribut == i)
+       do
+               null_attribut = i
+       end
+end
+
+
+var a = new A
+a.set_null_attribut
+a.set_null_attribut(10)
+a.set_null_attribut
index fe6b723..c9b0553 100644 (file)
@@ -1 +1 @@
-Runtime error: Assert 'expect' failed (contracts.nit:31)
+Runtime error: Assert 'expect(not bool)' failed (contracts.nit:31)
index 5f6178c..738f3f0 100644 (file)
@@ -1 +1 @@
-Runtime error: Assert 'ensure' failed (contracts_abstract.nit:26)
+Runtime error: Assert 'ensure(y <= 10.0, y == 42.0)' failed (contracts_abstract.nit:26)
index a353fc9..6d21df2 100644 (file)
@@ -1,2 +1,2 @@
 contracts_add.nit:46,3--16: Useless contract: No contract defined at the introduction of the method
-Runtime error: Assert 'ensure' failed (contracts_add.nit:39)
+Runtime error: Assert 'ensure(x == 0)' failed (contracts_add.nit:39)
index f0801df..94dfe03 100644 (file)
@@ -1 +1 @@
-Runtime error: Assert 'expect' failed (contracts_constructor.nit:20)
+Runtime error: Assert 'expect(test > 10)' failed (contracts_constructor.nit:20)
index 5e3bffa..34f0938 100644 (file)
@@ -1 +1 @@
-Runtime error: Assert 'ensure' failed (contracts_ensures.nit:29)
+Runtime error: Assert 'ensure(not bool)' failed (contracts_ensures.nit:29)
index c947107..698c7dc 100644 (file)
@@ -1,3 +1,3 @@
-Runtime error: Assert 'ensure' failed (contracts_ensures_1.nit:20)
+Runtime error: Assert 'ensure(x > 0)' failed (contracts_ensures_1.nit:20)
 Good
 Fail
index 982613a..213d864 100644 (file)
@@ -1,4 +1,4 @@
-Runtime error: Assert 'ensure' failed (contracts_ensures_2.nit:31)
+Runtime error: Assert 'ensure(y == 1.2)' failed (contracts_ensures_2.nit:31)
 Good
 Good
 Good
index 11ebcc5..06c56eb 100644 (file)
@@ -1 +1 @@
-Runtime error: Assert 'ensure' failed (contracts_ensures_3.nit:20)
+Runtime error: Assert 'ensure(result > 0)' failed (contracts_ensures_3.nit:20)
index e602695..6c8805e 100644 (file)
@@ -1 +1 @@
-Runtime error: Assert 'ensure' failed (contracts_ensures_4.nit:31)
+Runtime error: Assert 'ensure(not result)' failed (contracts_ensures_4.nit:31)
index 3cdcc71..b62c05a 100644 (file)
@@ -1 +1 @@
-Runtime error: Assert 'ensure' failed (contracts_ensures_sequence.nit:18)
+Runtime error: Assert 'ensure(x > 2)' failed (contracts_ensures_sequence.nit:18)
index 45e60a6..3847129 100644 (file)
@@ -1,2 +1,2 @@
-contracts_error.nit:23,10--22: Error: expected an expression.
-contracts_error.nit:24,10--22: Error: expected an expression.
+contracts_error.nit:23,3--23: Error: expected an expression.
+contracts_error.nit:24,3--23: Error: expected an expression.
index c265d14..555a497 100644 (file)
@@ -1 +1 @@
-Runtime error: Assert 'expect' failed (contracts_expects_1.nit:20)
+Runtime error: Assert 'expect(x > 0)' failed (contracts_expects_1.nit:20)
index 9c7f782..6d36851 100644 (file)
@@ -1 +1 @@
-Runtime error: Assert 'expect' failed (contracts_generic_type.nit:33)
+Runtime error: Assert 'expect(x.length != 0)' failed (contracts_generic_type.nit:33)
index 0abeba3..5736913 100644 (file)
@@ -1,5 +1,5 @@
 contracts_inheritance.nit:58,6--9: Warning: conflicting property definitions for property `toto` in `MySubArray`: contracts_inheritance$MyArrayInt$toto contracts_inheritance$MyArrayInt2$toto
-Runtime error: Assert 'ensure' failed (contracts_inheritance.nit:32)
+Runtime error: Assert 'ensure(e == 12)' failed (contracts_inheritance.nit:32)
 toto MyArrayInt2
 toto MyArrayInt
 toto ArrayInt
index 54afbe1..e69de29 100644 (file)
@@ -1 +0,0 @@
-contracts_same_contract.nit:22,3--17: The method already has a defined `expect` contract at line 21
index 95b94d6..445cb2e 100644 (file)
@@ -1,2 +1,2 @@
-Runtime error: Assert 'ensure' failed (contracts_static.nit:29)
+Runtime error: Assert 'ensure(x > 10)' failed (contracts_static.nit:29)
 Error
index 616e1d0..ada2d2b 100644 (file)
@@ -1 +1 @@
-Runtime error: Assert 'expect' failed (contracts_virtual_type.nit:23)
+Runtime error: Assert 'expect(x == 1)' failed (contracts_virtual_type.nit:23)
index 1a3a40c..4181eb7 100644 (file)
@@ -16,6 +16,7 @@
 \e[0;33mtest_keep_going.nit:44,18--21\e[0m: Error: method `fail` does not exists in `Sys`.
                var a = new Sys.\e[1;31mfail\e[0m
                                ^
+Errors: 6. Warnings: 0.
 1
 2
 3