contracts a mystery function
play

Contracts A Mystery Function 1 The Story Your first task at your - PowerPoint PPT Presentation

Contracts A Mystery Function 1 The Story Your first task at your new job is to debug this code written by your predecessor, who was fired for being a poor programmer. int f(int x, int y) { int r = 1; while (y > 1) { if (y % 2 == 1) { r


  1. Contracts

  2. A Mystery Function 1

  3. The Story Your first task at your new job is to debug this code written by your predecessor, who was fired for being a poor programmer. int f(int x, int y) { int r = 1; while (y > 1) { if (y % 2 == 1) { r = x * r; } x = x * x; y = y / 2; This is all you } return r * x; are given } How do you go about this “friendly” challenge? 2

  4. The Language  This code is written in C0 int f(int x, int y) { int r = 1; o The language we will use for most while (y > 1) { of this course if (y % 2 == 1) { r = x * r; }  This is also valid C code x = x * x; o For the most part, C0 programs y = y / 2; } are valid C programs return r * x; o We will use C0 as a gentler } language to  learn to write complex code that is correct  learn to write code in C itself  But what does this function do? 3

  5. The Programmer  Is this good code? int f(int x, int y) { int r = 1; o there are no comments while (y > 1) { o the names are non-descript if (y % 2 == 1) { r = x * r;  the function is called f }  the variables are called x, y, r x = x * x;  No! y = y / 2; } return r * x;  No wonder your predecessor } was fired as a programmer!  But what does this function do? 4

  6. The Function  But what does this function do?  We can run experiments o call f with various inputs and observe the outputs  We do so by loading it in the C0 interpreter – coin The command for The file where we the C0 interpreter saved the function Linux Terminal # coin mystery.c0 C0 interpreter (coin) 0.3.3 'Nickel' (r590, Mon Aug 29 12:04:13 UTC 2016) Type `#help' for help or `#quit' to exit. --> The coin prompt 5

  7. Running Experiments  Call f with various inputs and observe the outputs Linux Terminal We are calling f with # coin mystery.c0 inputs 7 and 12 C0 interpreter (coin) … … The result is 956385313 --> f(7, 12); 956385313 (int) --> f(3, 17); 129140163 (int) --> The result has type int  These are not very good experiments o they don’t help us understand what f does 6

  8. Running Experiments  Call f with various inputs and observe the outputs o we are better off calling f with small inputs o and vary them by just a little bit so we can spot a pattern Linux Terminal Much better! --> f(2, 3); 8 (int) --> f(2, 4); o It looks like f(x, y) computes x y 16 (int) --> f(2, 5); o Let’s confirm with more 32 (int) experiments --> f(2, 6); 64 (int) --> 7

  9. Confirming the Hypothesis  It looks like f(x, y) computes x y  Let’s confirm with more experiments Linux Terminal Yep! That’s x y --> f(2, 2); 4 (int) --> f(3, 2); 9 (int) o We find a secret memo in a --> f(4, 2); hidden drawer 16 (int) --> f(5, 2); Power not working. 25 (int) Fix by tonight or you’re out --> Not the friendliest of work places!  Let’s run a few more experiments to identify the problem 8

  10. Discovering the Bug  f(x, y) is meant to computes x y o but it doesn’t  Let’s find where it fails with more experiments Linux Terminal --> f(-2, 3); It seems to work for It seems to work for -8 (int) negative values of x negative values of x --> f(-2, 2); 4(int) --> f(2, 1); 1 (int) --> f(2, 0); That’s not 2 0 2 (int) --> f(2, -1); That’s definitely not 2 -1 2 (int) -->  Now we have something to chew on 9

  11. Preconditions 10

  12. The Power Function  What does it mean to be the power function x y ? o x * …. * x y times  Yes, but that’s not very precise  Let’s write a mathematical definition x 0 = 1 o x y = x y-1 * x This is a recursive definition and this is its base case 11

  13. The Power Function  What does it mean to be the power function x y ? x 0 = 1 x y = x y-1 * x o What happens if y is negative?  we never reach the base case …  The power function x y on integers is undefined if y < 0 x 0 = 1 This defines x y for y ≥ 0 only This defines x y for y ≥ 0 only x y = x y-1 * x if y > 0 12

  14. int f(int x, int y) { int r = 1; The Power Function while (y > 1) { if (y % 2 == 1) { r = x * r; } x = x * x;  What does it mean to be the power function x y ? y = y / 2; } return r * x; x 0 = 1 } x y = x y-1 * x if y > 0  To implement the power function, f must disallow negative exponents We need to test y. o It can raise an error This would slow f down a bit. o It can tell the caller that the exponent should be ≥ 0 Better! no need to test y 13

  15. Preconditions  Disallow negative exponents o by telling the caller that the exponent should be ≥ 0  A restriction on the admissible inputs to a function is called a precondition o We need to impose // y must be greater than or equal to 0 int f(int x, int y) { a precondition on f int r = 1; o In most languages, while (y > 1) { we are limited to if (y % 2 == 1) { r = x * r; writing a comment }  and hope the caller x = x * x; reads it y = y / 2; This is how we } would write a return r * x; precondition in C } 14

  16. Preconditions in C0  We need to impose a precondition on f o to tell the caller that y should be ≥ 0  In C0 we can write an executable contract directive //@requires y >= 0; int f(int x, int y) //@requires y >= 0; C0 keyword to specify a precondition C0 keyword to specify a precondition { • written between the function header and the body • written between the function header and the body • before the first “{“ • before the first “{“ int r = 1; while (y > 1) { o We check contracts by invoking coin if (y % 2 == 1) { with the -d flag r = x * r; }  “dynamic checking” x = x * x;  but everybody understands it as debug mode y = y / 2; o without the -d flag, contracts are } treated as comments return r * x; } 15

  17. Using Contract Running with contracts disabled Running with contracts enabled Linux Terminal Linux Terminal # coin mystery.c0 # coin -d mystery.c0 C0 interpreter (coin) … C0 interpreter (coin) … --> f(2, 3); --> f(2, 3); 8 (int) 8 (int) --> f(2, -1); --> f(2, -1); 2 (int) mystery.c0:2.4-2.20: @requires annotation failed --> Last position: mystery.c0:2.4-2.20 f from <stdio>:1.1-1.9 --> Contracts are treated as comments Line number where contract failed Contracts are executed File where cc0, the C0 compiler, • if true , execution proceeds normally contract failed works the same way • if false , execution aborts 16

  18. Safety  If we call f(x,y) with a negative y o with -d , execution aborts o without -d , f can return an arbitrary result  there is no right value it could return  Calling a function with inputs that cause a precondition to fail is unsafe o execution will never do the right thing  either abort  or compute a wrong result  The caller must make sure that the call is safe  that y ≥ 0 17

  19. Postconditions 18

  20. Contracts about Function Outcomes  Preconditions are checked before the function starts executing pre  A contract that is checked after it is done function executing could tell us if the function did body the right thing  check that the output is what we expect post o This is a postcondition 19

  21. Postconditions in C0  In C0, the contract directive int f(int x, int y) //@ensures <some_condition> ; //@requires y >= 0; //@ensures …; { C0 keyword to specify a precondition C0 keyword to specify a postcondition • written between the function header and the body • written between the function header and the body int r = 1; • before the first “{“ • after the preconditions (by convention) while (y > 1) { • before the first “{“ if (y % 2 == 1) { allows us to write a postcondition r = x * r; } o <some_condition> can mention the x = x * x; y = y / 2; contract-only variable \result }  what the function returns return r * x;  can only be used with //@ensures } 20

  22. Writing a Postcondition  The postcondition we want to write is //@ensures \result == x**y; o but x**y is not defined in C0 That’s how we write x y in Python  C0 has no primitive power function!  What do we do? o transcribe the mathematical definition into a C0 function int POW(int x, int y) //@requires y >= 0; x 0 = 1 { if (y == 0) return 1; x y = x y-1 * x if y > 0 return POW(x, y-1) * x; } 21

  23. Writing a Postcondition int POW(int x, int y) //@requires y >= 0;  Then our postcondition is { if (y == 0) return 1; //@ensures \result == POW(x, y); return POW(x, y-1) * x; } right? … almost int f(int x, int y) //@requires y >= 0; Linux Terminal //@ensures \result == POW(x,y); # coin -d mystery.c0 { mystery.c0:18.5-18.6:error:cannot assign to int r = 1; while (y > 1) { variable 'x' used in @ensures annotation if (y % 2 == 1) { x = x * x; r = x * r; ~ } Unable to load files, exiting... x = x * x; y = y / 2; o The function modifies x (and y) } return r * y;  Which values of x and y should C0 evaluate the } postcondition with?  We want the initial values, but it is checked when returning … o To avoid confusion, C0 disallows modified variables in postconditions 22

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend