**A Semantic Framework for the Declarative Debugging of Wrong and Missing Answers in Declarative Constraint Programming**

Rafael del Vado Vírseda and Fernando Pérez Morente *Universidad Complutense de Madrid Spain*

## **1. Introduction**

22 Will-be-set-by-IN-TECH

120 Semantics – Advances in Theories and Mathematical Models

Scott, D.S. (1970). Outline of a mathematical theory of computation, *Proceedings of 4th Annual*

Scott, D.S. (1982). Domains for denotational semantics. *Lecture Notes in Computer Science*, Vol.

York), March 1970.

140, 577– 613.

*Princeton Conference on Information Science and Systems*, pp. 169-176, Princeton (New

Debugging tools are a practical need for helping programmers to understand why their programs do not work as intended. Declarative programming paradigms involving complex operational details, such as constraint solving and lazy evaluation, do not fit well to traditional debugging techniques relying on the inspection of low-level computation traces. As a solution to this problem, and following a seminal idea by Shapiro (Shapiro, 1982), *declarative debugging* (a.k.a. *declarative diagnosis* or *algorithmic debugging*) uses *Computation Trees* (shortly, *CT*s) in place of traces. *CT*s are built *a posteriori* to represent the structure of a computation whose top-level outcome is regarded as a *symptom* of the unexpected behavior by the user. Each node in a *CT* represents the computation of some observable result, depending on the results of its children nodes, using a program fragment also attached to the node. Declarative diagnosis explores a *CT* looking for a so-called *buggy node* which computes an unexpected result from children whose results are all expected. Each buggy node points to a program fragment responsible for the unexpected behavior. The search for a buggy node can be implemented with the help of an external *oracle* (usually the user with some semiautomatic support) who has a reliable declarative knowledge of the expected program semantics, the so-called *intended interpretation*.

The generic description of declarative diagnosis in the previous paragraph follows (Naish, 1997). Declarative diagnosis was first proposed in the field of *Logic Programming* (*LP*) (Ferrand, 1987; Lloyd, 1987; Shapiro, 1982), and it has been successfully extended to other declarative programming paradigms, including (lazy) *Functional Programming* (*FP*) (Nilsson, 2001; Nilsson & Sparud, 1997; Pope, 2006; Pope & Naish, 2003), *Constraint Logic Programming* (*CLP*) (Boye et al., 1997; Ferrand et al., 2003; Tessier & Ferrand, 2000), and *Functional-Logic Programming* (*FLP*) (Caballero & Rodríguez, 2004; Naish & Barbour, 1995). The nature of unexpected results differs according to the programming paradigm. Unexpected results in *FP* are mainly *incorrect values*, while in *CLP* and *FLP* an unexpected result can be either a single computed answer regarded as *incorrect*, or a set of computed answers (for one and the same goal with a finite search space) regarded as *incomplete*. These two possibilities give rise to the declarative debugging of *wrong* and *missing* computed answers, respectively. The case of unexpected *finite failure* of a goal is a particular symptom of missing answers with special relevance. However, diagnosis methods must consider the most general case, since finite

computed answers, as well as the results ensuring the logical correctness of the diagnosis. Section 7 presents a prototype debugger for diagnosing missing answers. Section 8 concludes

<sup>123</sup> A Semantic Framework for the Declarative Debugging

As a motivation for our declarative debugging method of wrong answers in the *CFLP*(D) scheme, we consider the following program fragment written in T OY (López & Sánchez, 1999), a programming system which supports several instances of the *CFLP*(D) scheme:

rect (X,Y) LX LY (X',Y') = (X' >= X)&& (X' <= X+LX)&& (**Y'** <= **Y**)&& (Y'<=Y+LY)

In this example (see Fig. 1), T OY is used to implement the instance *CFLP*(R) of the *CFLP*(D) scheme, with the parameter D replaced by the real numbers domain R, which provides real numbers, arithmetic operations and various arithmetic constraints, including equalities, disequalities and inequalities. The type figure is intended to represent geometric figures as boolean functions, the function rect is intended to represent rectangles (more precisely, (rect (X,Y) LX LY) is intended to represent a rectangle with leftmost-bottom vertex (X,Y) and rightmost-upper vertex (X+LX,Y+LY)); and the function ladder is intended to build an infinite list of rectangles in the shape of a ladder. Although the text of the program seems to include no constraints, it uses arithmetic and comparison operators that give rise to constraint solving in

5

20

40 45

5 20 35 70

and points to some plans for future work.

**Example 1. (Debugging Wrong Answers in** T OY**)**

of Wrong and Missing Answers in Declarative Constraint Programming

(&&) :: bool –> bool –> bool

**2. Motivating examples**

infixr 40 &&

false && Y = false true && Y = Y

head :: [A] –> A head [X|Xs] = <sup>X</sup>

Fig. 1. Building ladders in T OY

type point = (real,real) type figure = point –> bool

rect :: point –> real –> real –> figure

intersect :: figure –> figure –> figure intersect F1 F2 P = F1 P && F2 P

ladder :: point –> real –> real –> [figure]

% This program rule is incorrect. It should be: **(Y'** >= **Y)**...

execution time. More precisely, consider the following session in T OY:

ladder (X,Y) LX LY = [rect (X,Y) LX LY | ladder (X+LX, Y+LY) LX LY]

failure of a goal is often caused by non-failing subgoals that do not compute all the expected answers.

In contrast to recent approaches to error diagnosis using *abstract interpretation* (e.g., (Alpuente et al., 2003; Comini et al., 1999; Hermenegildo, 2002), and some of the approaches described in (Deransart et al., 2000)), declarative diagnosis often involves complex queries to the user. This problem has been tackled by means of various techniques, such as user-given partial specifications of the program's semantics (Boye et al., 1997), safe inference of information from answers previously given by the user (Caballero & Rodríguez, 2004), or *CT*s tailored to the needs of a particular debugging problem over a particular computation domain (Ferrand et al., 2003). Another practical problem with declarative diagnosis is that the size of *CT*s can cause excessive overhead in the case of computations that demand a big amount of computer storage. As a remedy, techniques for piecemeal construction of *CT*s have been considered; see (Pope, 2006) for a recent proposal in the *FP* field. However, current research in declarative diagnosis has still to face many challenges regarding both the foundations and the development of practical tools.

In spite of the above mentioned difficulties, we are confident that declarative diagnosis methods can be useful for detecting programming bugs by observing computations whose demand of computer storage is modest. The aim of this chapter is to present a logical and semantic framework for diagnosing wrong and missing computed answers in *CFLP*(D) (López et al., 2006), a newly proposed generic programming scheme for lazy *Constraint Functional-Logic Programming* which can be instantiated by any constraint domain D given as parameter, and supports a powerful combination of functional and constraint logic programming over D. Sound and complete goal solving procedures for the *CFLP*(D) scheme have been obtained (López et al., 2004). Moreover, useful instances of this scheme have been implemented in the T OY system (López & Sánchez, 1999) and tested in practical applications (Fernández et al., 2007). Borrowing ideas from *CFLP*(D) declarative semantics we obtain a suitable notion of *intended interpretation*, as well as a kind of abridged *proof trees* with a sound logical meaning to play the role of *CT*s. Our aim is to achieve a natural combination of previous approaches that were independently developed for the *CLP*(D) scheme (Tessier & Ferrand, 2000) and for lazy functional-logic languages (Caballero & Rodríguez, 2004). We give theoretical results showing that the proposed debugging method is logically correct for any sound *CFLP*(D)-system whose computed answers are logical consequences of the program in the sense of *CFLP*(D) semantics. We also present a practical debugger called DDT , developed as an extension of previously existing but less powerful tools (Caballero, 2005; Caballero & Rodríguez, 2004). DDT implements the proposed diagnosis method for *CFLP*(R)-programming in the T OY system (López & Sánchez, 1999) using the domain R of arithmetic constraints over the real numbers.

The rest of the chapter is organized as follows: Section 2 motivates our approach by presenting debugging examples which are used as illustration of the main features of our diagnosis method. Section 3 recalls the *CFLP*(D) scheme from (López et al., 2006) to the extent needed for understanding the theoretical results in this chapter. Section 4 presents a correct method for the declarative diagnosis of wrong computed answers in any soundly implemented *CFLP*(D)-system. Section 5 describes the debugging tool DDT for wrong answers. Section 6 presents the abbreviated proof trees used as *CT*s in our method for debugging missing computed answers, as well as the results ensuring the logical correctness of the diagnosis. Section 7 presents a prototype debugger for diagnosing missing answers. Section 8 concludes and points to some plans for future work.
