key: cord-0059306-ijyfzghm authors: Lidström, Christian; Gurov, Dilian title: An Abstract Contract Theory for Programs with Procedures date: 2021-02-24 journal: Fundamental Approaches to Software Engineering DOI: 10.1007/978-3-030-71500-7_8 sha: 878fe008ad22db3e24216455dae235736bd0f251 doc_id: 59306 cord_uid: ijyfzghm When developing complex software and systems, contracts provide a means for controlling the complexity by dividing the responsibilities among the components of the system in a hierarchical fashion. In specific application areas, dedicated contract theories formalise the notion of contract and the operations on contracts in a manner that supports best the development of systems in that area. At the other end, contract meta-theories attempt to provide a systematic view on the various contract theories by axiomatising their desired properties. However, there exists a noticeable gap between the most well-known contract meta-theory of Benveniste et al. [5], which focuses on the design of embedded and cyber-physical systems, and the established way of using contracts when developing general software, following Meyer’s design-by-contract methodology [18]. At the core of this gap appears to be the notion of procedure: while it is a central unit of composition in software development, the meta-theory does not suggest an obvious way of treating procedures as components. In this paper, we provide a first step towards a contract theory that takes procedures as the basic building block, and is at the same time an instantiation of the meta-theory. To this end, we propose an abstract contract theory for sequential programming languages with procedures, based on denotational semantics. We show that, on the one hand, the specification of contracts of procedures in Hoare logic, and their procedure-modular verification, can be cast naturally in the framework of our abstract contract theory. On the other hand, we also show our contract theory to fulfil the axioms of the meta-theory. In this way, we give further evidence for the utility of the meta-theory, and prepare the ground for combining our instantiation with other, already existing instantiations. Contracts. Loosely speaking, a contract for a software or system component is a means of specifying that the component obliges itself to guarantee a certain behaviour or result, provided that the user (or client) of the component obliges itself to fulfil certain constraints on how it interacts with the component. dure is a central unit of composition in software development, the meta-theory does not suggest an obvious way of treating procedures as components. This situation is not fully satisfactory, since the software components of most embedded systems are implemented with the help of procedures (a typical C-module, for instance, would consist of a main function and a number of helper functions), and their development should ideally follow the same design flow as that of the embedded system as a whole. In this paper we provide a first step towards a contract theory that takes procedures as the basic building block, and at the same time respects the axioms of the meta-theory. Our contract theory is abstract, so that it can be instantiated to any procedural language, and similarly to the meta-theory, is presented at the semantics level only. Then, in the context of a simplistic imperative programming language with procedures and its denotational semantics, we show that the specification of contracts of procedures in Hoare logic, and their procedure-modular verification, can be cast in the framework of our abstract contract theory. We also show that our contract theory is an instance of the meta-theory of Benveniste et al. With this we expect to contribute to the bridging of the gap mentioned above, and to give a formal justification of the design methodology supported by the meta-theory, when applied to the software components of embedded systems. Several existing contract theories have already been shown to instantiate the meta-theory. In providing a contract theory for procedural programs that also instantiates it, we increase the value of the metatheory by providing further evidence for its universality. In addition, we prepare the theoretical ground for combining our instantiation with other instantiations, which may target components not to be implemented in software. Our theoretical development should be seen as a proof-of-concept. In future work it will need to be extended to cover more programming language features, such as object orientation, multi-threading, and exceptions. Related Work. Software contracts and operations on contracts have long been an area of intensive research, as evidenced, e.g., by [1] . We briefly mention some works related to our theory, in addition to the already mentioned ones. Reasoning from multiple Hoare triples is studied in [21] , in the context of unavailable source code, where new properties cannot be derived by re-verification. In particular, it is found that two Hoare-style rules, the standard rule of consequence and a generalised normalisation rule, are sufficient to infer, from a set of existing contracts for a procedure, any contract that is semantically entailed. Often-changing source code is a problem for contract-based reasoning and contract reuse. In [13] , abstract method calls are introduced to alleviate this problem. Fully abstract contracts are then introduced in [7] , allowing reasoning about software to be decoupled from contract applicability checks, in a way that not all verification effort is invalidated by changes in a specification. The relation between behavioural specifications and assume/guarantee-style contracts for modal transition systems is studied in [2] , which shows how to build a contract framework from any specification theory supporting composition and refinement. This work is built on in [9] , where a formal contract framework based on temporal logic is presented, allowing verification of correctness of contract refinement relative to a specific decomposition. A survey of behavioural specification languages [14] found that existing languages are well-suited for expressing properties of software components, but it is a challenge to express how components interact, making it difficult to reason about system and architectural level properties from detailed design specifications. This provides additional evidence for the gap between contracts used in software verification and contracts as used in system design. Structure. The paper is organised as follows. Section 2 recalls the concept of contract based design and the contract meta-theory considered in the present paper. In Section 3 we present a denotational semantics for programs with procedures, including a semantics for contracts for use in procedure-modular verification. Next, Section 4 presents our abstract contract theory for sequential programs with procedures. Then, we show in Section 5 that our contract theory fulfils the axioms of the meta-theory, while in Section 6 we show how the specification of contracts of procedures in Hoare logic and their procedure-modular verification can be cast in the framework of our abstract contract theory. We conclude with Section 7. This section describes the concept of contract based design, and motivates its use in cyber-physical systems development. We then recall the contract meta-theory by Benveniste et al. [5] . Contract based design is an approach to systems design, where the system is developed in a top-down manner through the use of contracts for components, which are incrementally assembled so that they preserve the desired system-wide properties. Contracts are typically described by a set of assumptions the component makes on its environment, and a set of guarantees on the component's behaviour, given that it operates in an environment adhering to the assumptions [5] . Present-day cyber-physical systems, such as those found in the automotive, avionics and other industries, are extremely complex. Products assembled by Original Equipment Manufacturers (OEMs) often consist of components from a number of different suppliers, all using their own specialised design processes, system architectures, development platforms, and tools. This is also true inside the OEMs, where there are different teams with different viewpoints of the system, and their own design processes and tools. In addition, the system itself has several different aspects that need to be managed, such as the architecture, safety and security requirements, functional behaviour, and so on. Thus, a rigorous design framework is called for that can solve these design-chain management issues. Contract based design addresses these challenges through the principles, at the specification level, of refinement and abstraction, which are processes for managing the design flow between different layers of abstraction, and composition and decomposition, which manage the flow at the same level of abstraction. Generally, when designing a system, at the top level of abstraction there will be an overall system specification (or contract). This top-level contract is then refined, to provide a more concrete contract for the system, and decomposed, in order to obtain contracts for the sub-systems, and to separate the different viewpoints of the system. A system design typically iterates the decompositionand-refinement process, resulting in several layers of abstraction, until contracts are obtained that can be directly implemented, or for which implementations already exist. An important requirement on this methodology of hierarchical decomposition and refinement of contracts is that it must guarantee that when the low-level components implement their concrete contracts, and are combined to form the overall system, then the top-level, abstract, contract shall hold. Furthermore, a contract framework in particular needs to support independent development and component reuse. That is, specifications for components, and their operations, must allow for components and specifications to be independently designed and implemented, and to be used in different parts of the system, each with their own assumptions on how the other components, the environment, behave. This is achieved through the principle operations on contracts: refinement, composition, and conjunction. Refinement allows one to extract a contract at the appropriate level of abstraction. A desired property of refinement is that components which have been designed with reference to the more abstract (i.e., weaker) contract do not need to be re-designed after the refinement step. That is, in the early stages of development an OEM may have provided a weak contract for some subsystem to an external supplier, which implemented a component relying on this contract. As development of the system progresses, and the contract is refined, the component supplied externally should still operate according to its guarantees without needing to be changed, when instead assuming the new, refined, contract. Composition enables one to combine contracts of different components into a contract for the larger subsystem obtained when combining the components. Again, a desirable property is that other components relying on one or more of the individual contracts, can, after composition of the contracts, assume the new contract and still perform its guarantees, without being re-designed, thus ensuring that subsystems can be independently implemented. Finally, contract conjunction is another way of combining contracts, but now for the different viewpoints of a single component. This allows one to separate a contract into several different, finer contracts for the same component, revealing just enough information for each particular system that depends on it, so that it can be reused in different parts of the system, or in entirely different systems. We consider the meta-theory described in [5] . The stated purpose of the metatheory has been to distil the notion of a contract to its essence, so that it can be used in system design methodologies without ambiguities. In particular, the meta-theory has been developed to give support for design-chain management, and to allow component reuse and independent development. It has been shown that a number of concrete contract theories instantiate it, including assume/guarantee-contracts, synchronous Moore interfaces, and interface theories. To our knowledge, this is the only meta-theory of its purpose and scope. We now present the formal definitions of the concepts defined in the metatheory, and the properties that they entail. The meta-theory is defined only in terms of semantics, and it is up to particular concrete instantiations to provide a syntax. Components. The most basic concept in the meta-theory is that of a component, which represents any concrete part of the system. Thus, we have an abstract component universe M with components m ∈ M. Over pairs of components, we have a composition operation ×. This operation is partially defined, and two components m 1 and m 2 are called composable when m 1 × m 2 is defined. In such cases, we call m 1 an environment for m 2 , and vice versa. In addition, component composition must be both commutative and associative, in order to ensure that different components can be combined in any order. Typically, components are open, in the sense that they contain functionality provided by other components, i.e., their environment. The environment in which a component is to be placed is often unknown at development time, and although a component cannot restrict it, it is designed for a certain context. In the meta-theory, the notion of contract is defined in terms of sets of components. The contract universe C def = 2 M × 2 M consists of contracts C = (E, M ), where E and M are the sets of environments and implementations of C, respectively. Importantly, each pair (m 1 , m 2 ) ∈ E ×M must be composable. This definition is intentionally abstract. The intuition is that contracts separate the responsibilities of a component from the expectations on its environment. Moreover, contracts are best seen as weak specifications of components: they should expose just enough information to be adequate for their purpose. For a component m and a contract C = (E, M ), we shall sometimes write m |= E C for m ∈ E, and m |= M C for m ∈ M . A contract C is said to be consistent if it has at least one implementation, and compatible if it has at least one environment. As an axiom of the meta-theory, it is required that the greatest lower bound with respect to refinement exists, for all subsets of C. Table 1 summarises the important properties of refinement and the other operations on contracts that a concrete Refinement. When C1 C2, every implementation of C1 is also an implementation of C2. 2 Shared refinement. Any contract refining C1 ∧ C2 also refines C1 and C2. Any implementation of C1 ∧ C2 is a shared implementation of C1 and C2. Any environment for C1 and C2 is an environment for C1 ∧ C2. 3 Independent implementability. Compatible contracts can be independently implemented. 4 Independent refinement. For all contracts Ci and Commutativity, sub-associativity. For any finite sets of contracts Ci, i = 1, . . . , n, C1 ⊗ C2 = C2 ⊗ C1 and 1≤i≤n Ci ( 1≤i