====== iCODE ====== {{tools:wwwLogo.png?250x150 }} Interactive Curry Observation DEbugger (**iCODE**) is a tool to support programmers stepping on the lazy evaluation order of expressions at the source code level. Every executed expression is covered in a layout of the source code and its runtime value can be represented to the user. ===== Installation ===== To run **iCODE**, you need the Curry development environment [[implementations:pakcs]]. After installing [[implementations:pakcs]], you should [[http://www-ps.informatik.uni-kiel.de/~phsa/icode.zip|download iCODE]] and follow the installation instructions: 1. GO to the directory containing your files. 2. Type: make 3. Run iCODE by the command: icode e.g. icode Test "reverse [1,2,3]" If you want only to see the executed parts of the program without running the debugger, you can write this command: cutter e.g. cutter Test main "reverse main" ===== Starting ===== After running **iCODE**, the source code and a tree representation of the whole program expressions are displayd in a graphical user interface (Browser). Follow the three steps represented in the image. {{ tools:mainwindow.png }} ===== Tools ===== You have access to three different sub-tools: - **CUrry TesTER (//CUTTER//)** - **Curry Object Observation Interactive SYstem (//COOiSY//)** - **Curry trACEr (//C-Ace//)** ==== CUTTER ==== This tool covers executed parts of the program by highlighting executed expressions with two methods: * Covering function definitions in the original source code. * Covering program expressions in a tree representation of the program. Switching between the above methods is possible by selecting an option in the Browser. {{ tools:optionmenu.png }} The tool also represents the number of function calls to help the user locating a non-terminating computation. === Example (Non-Terminating Computation) === As an example, we consider the Fibonacci sequence that can be produced by the following simple function in a program: fib n | n==0 = 1 | otherwise = n * fib n It supposed that the program has a failure. In the second Guard, we have written //fib n// instead of //fib (n-1)//. Executing the program on a number (larger than zero) generates a non-terminating computation. To test the program, we select //fib// as a single unit and activate **CUTTER** in the browser . The test case is supposed to be //fib 10// .The result is represented in the viewer by pressing the forward button. It shows that the function //fib// is executed 1657 times while the program execution is not yet completed. Every time we press the forward button, the number of function calls increased. There is a nonterminated computation in the program. {{ tools:fibnonterminate.png }} Now we select the appropriate option to see the executed subexpressions of the program in a tree representation. The following figure displays the executed expressions of the selected unit. The last executed expression (in this step) is highlighted red and other ones green. {{ tools:fibnonterminatetree.png }} As we see, the right-hand side of the first Guard is not executed and only the second Guard is highlighted completely. That means, the loop is generated by the second Guard. ==== COOiSY ==== Using this tool, the user can see how the evaluation of selected expressions proceeds. Every runtime value of selected expressions is represented with a textual visualisation, which could be: * **_** : non-evaluated argument * **!** : evaluated argument / undefined result * **?** : logical variable * **?/v** : logical variable bound to value v * **{\LHS->RHS}** : Functional value * value === Example (No Results) === Consider the following faulty program: maxList :: [Int] -> Int maxList = foldl max 0 where max :: Int -> Int -> Int max x y | x > y = x | x < y = y The program is written to compute the largest element in a given list. The program returns //No more solutions// when the test case is //maxList [2,1,2]//, because there is no Guards for equal numbers in //max//. To see the behavior of the function //max//, we should select //max// as a single expression and activate **COOiSY**. The runtime values of //max// is represented in the following figure. {{ tools:maxlistviewer.png }} The function //max// is called three times. In the third function call //{\2 2 -> !}//, it takes //2// and //2// as the inputs and returns //!// as the result. The exclamation mark represents that the evaluation is started but not completed. //max// returns true results for every given list, if we correct for example the first Guard to //x >= y = x//. ==== C-Ace ==== The run-time tracer is implemented as a combination of the two above sub-tools CUTTER and COOiSY.The tool allows the user following the order of evaluations in selected units, with two methods: * Following the evaluation order of function definitions in the original source code. * Following the evaluation order of all right-hand side subexpressions in a tree representation of the program. === Example (Unexpected Result) === As an example we consider the following program. The program is written to compute the reverse of two combined lists. For example by giving two lists //[1,2]// and //[3,4]//, the program should generate //[4,3,2,1]// as the result. reverse :: [Int] -> [Int] reverse [] = [] reverse (x:xs) = reverse xs ++ [x] append :: [Int] -> [Int] -> [Int] append xs ys = reverse ys ++ reverse ys Suppose that we have written an incorrect variable in the program. The second call of the function //reverse// in the right-hand side of //append// is applicated on //ys// instead of //xs//. Generating the test case //append [1] [2]// offers as unexpected result //[2,2]//. To locate the failure we select //reverse// and //append// as two units and activate **Run-Time Tracer**. The following figure displays an intermediate step of the evaluations. The figure shows that the function //append// is being executed and offers a list of numbers as the result. The first element of the list is //2// and the evaluation of the second element is started which is shown by an exclamation mark. {{ tools:append.png }} The computation of the second list element needs a function call on //reverse//. The following figure represents two sequence steps of the evaluations when the function //reverse// is being executed. In viewer <2>: The first application of //reverse// has offered a list with one element (//[2]//) and in the second call of this function, the evaluation of the first list element is started //(!:_)//. In viewer <3>: After completing the execution of the first element, it is evaluated to //2//. {{ tools:reverse.png }} The bug is located. The second call of the function //reverse// should be an application on the given list (//[1]//), but it is applicated on a list with //2// as an element. ===== Stepper ===== Activating COOiSY or Run-Time Tracer opens a small stepper window. You should select one of the stepping methods and press the forward button to see the evaluation order of program expressions in the viewer. {{ tools:stepwindow.png }}