courses.pgbovine.net

Code Annotation Assignments

As we are studying the internals of the CPython interpreter, your assignments will be to annotate parts of the CPython source code with comments explaining how you think they work in your own words. The general workflow is that we dissect parts of the CPython source code together in class, and then you must annotate related parts of the code that we did not cover in class.

Annotation format

You will directly annotate a copy of the source files from the Python 2.7.8 source code.

Your annotations will take the form of C code comments in one of the following formats:

// CSC253: write short inline annotations like this

or ...

/** CSC253

write multi-line annotations
like this for longer explanations

*/

Just remember to use the exact comment headers // CSC253 for single-line annotations and /** CSC253 for multi-line annotations.

Make sure you are using a text editor that preserves line endings so that the diffs between the original and your annotated source code consist of only your annotations. Do not modify the files in any other way. In other words, if the staff diffs your code against the original, we should see only your annotations. Run a diff before submitting your assignments to double-check.

Annotation writing style

Write your code annotations as though you are giving a tutorial to teach a student about the CPython code base. You should be guiding the reader through relevant parts of the source files in a logical flow as though you are walking them through an informal code review.

One recommended technique is to label each annotation using a unique identifier (without spaces) so that a reader can easily follow the order of annotations and jump between them. Here is a trivial toy example:

#include  // CSC253: import to get printf

void foo() { // CSC253: S2 - enter then call S3
  bar();
}

void bar() { // CSC253: S3 - prints hello then exits
  printf("Hello world\n");
}


/** CSC253
  S1 - execution starts here, then jumps to S2
*/
int main() {
  foo();
}

Note how S1, S2, and S3 are unique labels that allow annotations to cross-reference one another. To show ordering, we recommend using numbers prepended with a letter (e.g., S1, S2, S3, etc.) so that they are easily searchable. (Searching for numbers alone will yield false positives.)

Logistics

You can either work on each assignment alone or in a group of 2 students. Since we do not grant extensions, we strongly encourage working in a group to decrease the chance of missing the submission deadline. Include both group members' names if you are working in a group.

Submit one copy of each assignment on Blackboard in the CSC 253 "Course Materials" section by attaching a single zip file containing all of the source code files that you have annotated. For instance, if you are asked to annotate parts of ceval.c and object.h, do not submit two separate files on Blackboard. Compress both into a single zip file and submit that file. The default "create a compressed folder" option on Windows and Mac OS will produce a standard zip file. Do not use any other formats. And do not paste your source code as a text submission. Use "Attach File" on Blackboard to attach a single zip file.

When you submit your zip file in Blackboard, put all of your group members' names in the filename so that the staff can easily identify the creator by glancing at the filename. e.g., if your group is John Smith and Jane Doe, then you can turn in a file named "Assignment 1 - John Smith and Jane Doe.zip"

Also, put a comment at the very top of each annotated source code file with all of your group member's names on it.

And finally, do not rename any files. e.g., ceval.c should remain as ceval.c, not renamed to anything else.

In-class discussions

Part of your assignment grade comes from Professor Guo asking you questions about it during the class right after its due date. So be prepared to explain what you have written to the class.


Code annotation assignment 1 due at 6pm on Sep 12

Your assignment is to trace all possible executions of the following code through the PyEval_EvalFrameEx() main interpreter loop function starting on line 693 of Python/ceval.c:

if x < y:
    z = x
elif True:
    z = y
else:
    z = 100

Assume x and y are both integers, and that this code does not throw any exceptions. (If you try to directly run this code, then it will throw an exception since x and y have not been defined yet. For this assignment, assume x and y are defined elsewhere but unknown to you, so you need to trace execution through all possible paths.)

For your reference, here is the disassembled Python bytecode in Python 2.7.8:

$ python -m dis assignment1.py 
  1           0 LOAD_NAME                0 (x)
              3 LOAD_NAME                1 (y)
              6 COMPARE_OP               0 (<)
              9 POP_JUMP_IF_FALSE       21

  2          12 LOAD_NAME                0 (x)
             15 STORE_NAME               2 (z)
             18 JUMP_FORWARD            21 (to 42)

  3     >>   21 LOAD_NAME                3 (True)
             24 POP_JUMP_IF_FALSE       36

  4          27 LOAD_NAME                1 (y)
             30 STORE_NAME               2 (z)
             33 JUMP_FORWARD             6 (to 42)

  6     >>   36 LOAD_CONST               0 (100)
             39 STORE_NAME               2 (z)
        >>   42 LOAD_CONST               1 (None)
             45 RETURN_VALUE        

Annotate all of the relevant code in the PyEval_EvalFrameEx() function to walk a reader through the process of executing all of the above bytecode instructions that could possibly get executed in any path, and concluding by exiting PyEval_EvalFrameEx(). You can ignore the extra profiling and timing-related code and just focus on the essence of the bytecode execution loop. The Python 2 opcode reference might be helpful.

You don't need to annotate every single line of code, but strive for an appropriate level of detail required to give a meaningful code walkthrough like you see in CSC 253 lecture.

Professor Guo will ask you to explain parts of your annotations in class. Good luck, and please post your questions to Piazza.


Code annotation assignment 2 due at 6pm on Sep 26

Your assignment is to trace the (single) execution path of the following code through the PyEval_EvalFrameEx() main interpreter loop function starting on line 693 of Python/ceval.c, and diving into detail in Objects/abstract.c, Objects/intobject.c, and Objects/tupleobject.c as necessary.

x = 12
y = 12345
z = (x*2, y/2)
w = z + z

For your reference, here is the disassembled Python bytecode in Python 2.7.8:

  1           0 LOAD_CONST               0 (12)
              3 STORE_NAME               0 (x)

  2           6 LOAD_CONST               1 (12345)
              9 STORE_NAME               1 (y)

  3          12 LOAD_NAME                0 (x)
             15 LOAD_CONST               2 (2)
             18 BINARY_MULTIPLY     
             19 LOAD_NAME                1 (y)
             22 LOAD_CONST               2 (2)
             25 BINARY_DIVIDE       
             26 BUILD_TUPLE              2
             29 STORE_NAME               2 (z)

  4          32 LOAD_NAME                2 (z)
             35 LOAD_NAME                2 (z)
             38 BINARY_ADD          
             39 STORE_NAME               3 (w)
             42 LOAD_CONST               3 (None)
             45 RETURN_VALUE

You don't need to annotate every single line of code, but strive for an appropriate level of detail required to give a meaningful code walkthrough like you see in CSC 253 lecture. Focus in particular on the operations involving integer and tuple objects.

Also, avoid making trivial comments that simply reiterate what each line of code does verbatim without adding any insights. An example of a trivial comment is:

Py_INCREF(x); // CSC253: increase reference count by 1

Professor Guo will ask you to explain parts of your annotations in class. Good luck, and please post your questions to Piazza.

Finally, remember to download a fresh copy of the Python 2.7.8 source code so that your annotations for this assignment do not get mixed up with ones from prior assignments.


Code annotation assignment 3 due at 6pm on Oct 10

Your assignment is to trace the (single) execution path of the following code through the PyEval_EvalFrameEx() main interpreter loop function starting on line 693 of Python/ceval.c, and diving into detail in any other .c files as necessary. (Use reasonable judgment as to how much detail you dive into in other files, and focus on the concepts of iterators and user-defined classes and objects like you learned in lecture.)

class Counter:
    def __init__(self, low, high):
        self.current = low
        self.high = high

    def __iter__(self):
        return self

    def next(self):
        if self.current > self.high:
            raise StopIteration
        else:
            self.current += 1
            return self.current - 1

c = Counter(5, 7)
for elt in c:
    print elt

For your reference, here is the disassembled Python bytecode in Python 2.7.8:

  1           0 LOAD_CONST               0 ('Counter')
              3 LOAD_CONST               5 (())
              6 LOAD_CONST               1 (<code object Counter at 0x100510230, file "test.py", line 1>)
              9 MAKE_FUNCTION            0
             12 CALL_FUNCTION            0
             15 BUILD_CLASS
             16 STORE_NAME               0 (Counter)

 16          19 LOAD_NAME                0 (Counter)
             22 LOAD_CONST               2 (5)
             25 LOAD_CONST               3 (7)
             28 CALL_FUNCTION            2
             31 STORE_NAME               1 (c)

 17          34 SETUP_LOOP              19 (to 56)
             37 LOAD_NAME                1 (c)
             40 GET_ITER
        >>   41 FOR_ITER                11 (to 55)
             44 STORE_NAME               2 (elt)

 18          47 LOAD_NAME                2 (elt)
             50 PRINT_ITEM
             51 PRINT_NEWLINE
             52 JUMP_ABSOLUTE           41
        >>   55 POP_BLOCK
        >>   56 LOAD_CONST               4 (None)
             59 RETURN_VALUE

For simplicity, ignore all of the bytecodes corresponding to Lines 1 and 16 in the source code, so you should start executing at line 17 (the SETUP_LOOP opcode at address 34). Just focus on lines 17 and 18 in the source code, which correspond to addresses 34 to 59 in the bytecode. You also do not need to trace execution through the bytecodes of the individual methods (functions) within the Counter class.

Professor Guo will ask you to explain parts of your annotations in class. Good luck, and please post your questions to Piazza.

Finally, remember to download a fresh copy of the Python 2.7.8 source code so that your annotations for this assignment do not get mixed up with ones from prior assignments.