 Hi, hello and welcome to the program analysis course. In this lecture we will look at program slicing, which is a technique that given a potentially large program extracts an interesting subset of that program. We will see what interesting really means here in this context and we'll then look at a couple of techniques that do this program slicing. Here's a rough outline of the lecture. So this lecture will consist of four parts that each have a video on their own. We're now here in this first part where I'll give an introduction into this problem of program slicing and an overview of techniques that exist. Then we look into one set of these techniques, namely static slicing, so techniques that do not execute a program but rather analyze its source code in order to extract a slice of a program. Then we'll have a brief look at the so-called thin slicing, which is a technique that specifically cares about what developers do with the slice and how you can interactively create the slice that you really want. And finally we look into dynamic slicing techniques that execute a program and then from this execution extract an interesting fragment of the larger program. Most of what I'm talking about here is based on these four papers, which you should look at if you're interested in more details or if something is not clear from the lecture. Let's get started by defining what program slicing actually tries to achieve. Given a potentially large program, slicing tries to extract an executable subset of this program that affects the values that exist at a particular program location. So given something called a slicing criterion, which is essentially a point in the program, so the program location, antiparticular variable or maybe particular memory location that you really care about, slicing wants to extract that subset of the program that is responsible for computing the value of that variable at this particular program location. And the idea is that once the slice has been executed, an observer of this program, be it someone who looks at the code or be it someone who executes the code, should not be able to distinguish the full program from the slice if that observer is only interested in the slicing criterion. So essentially for the observer, the slice and the full program look the same as long as that observer is only interested in a particular location and the value that a particular variable has at this location. Let's illustrate this idea using a simple example. So here you see a few lines of JavaScript code that get some input. So n has a value that we statically do not really know. Then there are a couple of other variables, some loop counter variable i, something that we will use to produce the sum of values and something that we will use to produce the product of values. And then here in this loop where we iterate n times, we are basically adding or multiplying what we already have in sum or broad with i. And we also increment this loop variable. And then at the end, we have these two print statements that print the sum and the product that has been computed. Now, this is not a particularly complex program. In practice, you can, of course, just look at it and you see what it's doing. But let's use this as an example of how slicing can further reduce this full program into something that is relevant for a particular slicing criterion. So let's say our slicing criterion is that we care about the value of sum at this code location. So which parts of the program are relevant for that? Well, it's basically these statements. So everything that is not really highlighted anymore could be removed from the program. And you can still observe exactly the same value of sum at this line here. So basically what we still need is this code that reads n and then initializes i and sum. We still need the loop, but we do not do anything about this broad variable because this is not really relevant for the value of sum here at the end. Now, of course, we could also have a different slicing criterion. So for example, we could care about the value of broad at the last line of code. And then the slice looks different because now we can ignore everything that is related to the sum variable and how it gets computed. But instead, we just look at everything relevant for this broad variable. And of course, this could not only be done for things that are eventually printed, but we can pick any variable also in the middle of the program. For example, we could ask, well, what actually determines the value of n at this location here and then the slice is very, very simple because it only consists of this first statement that reads n from this read input method. And then the loop because of course this loop is needed in order to get a program that is complete and can compile and can execute. So now you might say, well, okay, that's a nice idea. You can reduce a large program to a small program, but why do we actually need this? Well, slicing has a lot of interesting applications. And here I just list four of them to give you a feel for what one could do with slicing. One, and that's maybe the most obvious one, is for debugging. So if you're interested in a particular misbehavior of your program, some bug, then you want to know which parts of the program influence what you are seeing. So say you know that at a particular point in the program, some variable has the wrong value. Then the question you're typically asking is, hey, which parts of the program influence the value of that variable that I'm seeing here. And slicing can help you to answer that question by basically focusing your attention on those parts of the program that are relevant for this bug. Another more general application is program understanding. So irrespective of whether there's a bug or not, you may just want to know which statements are actually influencing some other statements and the values that they are computed on. And slicing can help you by doing this. You can start from one statement and then either slice backward or forward and see how this statement gets influenced or influences future statements. A third application is so-called change impact analysis. So what is that? It means that when a program is evolving, so when the code is changing, then at some point you want to know which parts of the code are affected by a particular change. For example, this is interesting to know if you want to decide which parts of a program should be retested or maybe tested at all after a code change. Because typically you do not have to retest everything after you change something, but only those parts of the program that are affected by a change. And which parts of a program are affected by a change? That's something you can compute with the help of slicing. And finally, a third application of slicing is in parallelization. So if you have a program that is sequential, but you would like to run it in parallel to speed up the execution, then you need some way to determine which parts of the program can be computed independently of each other. And because slicing tells you about the dependencies of different statements and parts of your program, it can also help you to basically compute individual slices that are independent of each other. And then you can run these slices in parallel because they anyway do not influence each other. So as you can see, there are a couple of interesting applications. And actually there are many more that are not covering here that all rely on this underlying pretty fundamental technique of slicing. So now, before looking into particular techniques to address the slicing problem, which we will do in the remaining three videos in this lecture, let me just give you a very broad overview of the kinds of techniques that exist. One dimension to distinguish different techniques is based on whether they compute a forward or a backward slice. I've already very briefly mentioned these two terms on the previous slide. So the basic idea of a backward slice is that starting from a slicing criterion, we're interested in the statements that influence the slicing criterion. So it's basically about which other statements make us have this particular value at this particular location in the code. This backward slicing will also be the main focus of this lecture. In contrast, there's also the idea of forward slicing where starting at a particular slicing criterion to a particular statement with a variable that has some value, we are asking the question, which other statements are influenced by this slicing criterion? It's kind of a related problem because both forward and backward slicing reason about program dependencies and very similar techniques can be used. So if you know a lot about backward slicing, you also know a lot about forward slicing. And because of that, we just focus on one of them, namely, backward slicing here in the lecture. The other dimension in which we can distinguish different kinds of techniques and this is basically the same as for any program analysis problem is that there's static and dynamic techniques. A static slicing algorithm basically looks at the source code and tries to compute a slice just by looking at the code without executing it. And as for most interesting program analysis problems, computing exactly the result that we would like to have is undecidable in general. Specifically, this here means that statically computing a minimum slice is undecidable. So most or basically all static slicing algorithms cannot guarantee to only contain statements that are really needed to compute or to influence the slicing criteria, but they basically aim at getting a small but not necessarily minimal slice. The other kind of algorithm that the dynamic slicing approaches compute a slice by focusing on a particular execution that is driven by a particular input. So basically, these approaches look at the execution of a program and all the statements that are executed and then select those statements out of this larger set of statements that are really relevant for the value of a particular variable at a particular program location. And then this is the dynamically computed slice. All right, so this is already the end of the first video in this lecture. So you hopefully now know what slicing is and have a rough idea of what kinds of approaches exist in that space. And now on the remaining three videos, we will look at some of these approaches in some more detail. Thank you very much for listening and see you next time.