Comp 210 Lab 10: JAM; for-Loops and Structures in C

Table of Contents

  • Scheme in Batch Mode
  • Running the JAM machine
  • for loops
  • Structures in C
  • Running Scheme in Batch Mode

    Before starting this lab, cp ~comp210/setup/.mzschemerc ~ so that mzscheme will work correctly.

    It is possible to run Scheme without starting up the graphical interface, drscheme. Instead, from the UNIX prompt, type mzscheme. (Do not put an ampersand after this command.) You should see

    Welcome to MzScheme version 44, Copyright (c) 1995-96 Matthew Flatt
    |-
    
    where the > is the prompt, waiting for you to type in some Scheme code, just like the |- prompt from Dr. Scheme's lower window. (In fact, that lower window was practically the program mzscheme, with the doctor presenting the input/output a bit differently -- highlighting errors, etc.) For instance, try typing (+ 2 3 4), and the printed result should be no surprise to you.

    Suppose you type in a long function definition, and have a mistake in it? Unlike in Dr. Scheme, there is no nice easy way to go back and fix what you just typed. Instead, you usually use a batch method: Using a text editor (like emacs or even drscheme), you create your file prog.ss. Then, you typically start up mzscheme and type

    (load "prog.ss")
    
    This just causes mzscheme to read in the contents of prog.ss as if you'd just typed them at the keyboard veryveryquickly. It's reminiscent of pressing the Evaluate button in Dr. Scheme (except that previous definitions aren't discarded).

    Running the Jam2000 Machine

    Setup: Before continuing, you'll need your own copy of the source code for the Jam2000 simulator. (For hw10, you'll get to individualize this copy!) Something like
    owl%  cd ~/comp210
    owl%  mkdir jam
    owl%  cd jam
    owl%  cp ~comp210/Project/Jam/* .
    owl%  ls
    
    (Remember to include that trailing dot, meaning "copy all these specified files to the current directory.) Among other things, you'll find a file REFERENCE.ps, which is a one-page summary of the tables in Chapter 21, which you can either print, or remove if you need the 35k of disc quota. Continue this example from inside this directory.

    You can run a simulator for the Jam2000 from inside mzscheme as follows. Start up mzscheme, and type in (load "jam.ss").

    You must do this from the same directory where you copied all the Jam2000 files to. If you get an error define: illegal use (not at top-level), then you didn't cp ~comp210/setup/.mzscheme ~ just right.

    This loads the simulator, and starts it running as well. You'll see:

    [00000]:  00000000 (halt) %
    
    The first number in brackets is the bucket-number (0 in this case). The next number is the contents of the bucket (initially 0). If this corresponds to an encoded instruction, then the decoded (assembly) version follows in parentheses. Finally, the % is the prompt for the Jam2000 simulator.

    Here is a short Jam2000 program as seen in lecture, with comments.

    +00000749      ; Store  +8 into registor 4
    +00001439      ; Store +14 into register 3
     00043510      ; R5 <- R4 + R3
    
    Type each of these three encoded instructions in response to a prompt. You can omit leading zeroes and the +. Notice how the display updates. Type ? for a list of further Jam commands. Press s to see the state of the PC and registers, and try x for "execute". Nothing seemed to happen (even after looking at the status again). Well, one small change, the program counter stepped from 4 (instruction "halt") to 5. Aha! Try setting the PC to 0 (see the help screen), and then execute.

    To quit the simulator, type q, and you will be back at the mzscheme prompt. If you want to leave mzscheme, type ^D to signal the end-of-input.

    for-Loops in C

    Here is a simple for loop in C:
    for ( int i = 0;  i < 10;  i = i + 1 ) {
      printf( "i is now %d.\n" );
      }
    
    The above code uses a for loop. Here's what the code on the right-hand side means:
    1. Initially, set i to have the value 0.
    2. if i < 10, then perform the body of loop (inside the braces), and
    3. do i = i+1. Now go back to Step 2.
    Whenever, in Step 2, the condition i < 10 is false, we leave the loop. Note that as written, the scope of the placeholder i is inside the loop only.

    Using for loops with vectors

    Let's write a for loop which calculates the sum of the elements of a vector vec, which has size elements (where size is just a placeholder).
    // define some data:
    int vec[] = { 8, 9, 10 };
    int const size = 3;
    
    
    int sum = 0;
    for ( int i = 0;  i < size;  i = i + 1 ) {
      sum = sum + vec[i];
      }
    
    Exercise: Hand-evaluate this loop.
    Exercise: Transliterate this code into Scheme -- that is, don't just calculate the same answer, but calculate it using the same steps. (Don't use the fori= from lecture.)
    Hint I: What does sum become in the Scheme version?
    Hint II: Your answer should be tail-recursive! Remember how the fori= was tail-recursive? Not a coincidence. In general, loop constructs are a special, restricted form of recursion that compilers can implement efficiently.

    Once you have the C code working for summing the elements of one particular vector, it's possible to build on that to create a C function that takes a vector as a parameter .

    Syntax of C's for

    The general syntax of a for statement is:
    for ( init; test; end-of-loop-update )
       action
    moreCode...
    
    1. init is performed just once, before anything else in the for loop.
    2. if test is false, we're done; exit the loop and continue with moreCode.... But if test is true, then perform action, and
    3. do the end-of-loop-update. Go back to Step 2.
    A couple of notes: Yes, you must have exactly two semicolons in the for statement, separating the three parts.
    The action can either be:
  • a single statement followed by a semicolon, or
  • an open-brace, {, followed by many statements followed by } (but no semicolon after the close-brace). Think of it as a begin. It doesn't hurt to always include the curly-braces even when you have only statement inside.
  • (This specification for an action also applies to the bodies of while loops, if expressions, etc.)

    Structures in C

    The Scheme structure
    (define-structure (vehicle idNum numWheels price))  
    
    (define rig (make-vehicle 4713  18  9999.99))    
    
    translates into C as follows.
    struct vehicle_s {
        int idNum;
        int numWheels;
        float price;
        };
    
    int main() {
      struct vehicle_s* rig = new (struct vehicle_s);
      rig->idNum = 4713;
      rig->numWheels = 18;
      rig->price = 9999.99;
    
      return 0;
      }
    
    The first statement, starting
    struct vehicle_s { ...
    is analagous to Scheme's define-structure. It creates a new type, which has the two-word name "struct vechicle_s". The _s is only our convention to remind ourselves that the word struct is part of the type's name.

    Let's dissect the second part of this, which happens to be inside the function main().

    1. struct vehicle_s* rig
      This declares the placeholder rig, which is of type struct vehicle_s *. Hey, what is that star doing there? Think of it as telling C "this is something that gets treated with those special hat-variables, when evaluating". So using the star makes structures behave in C the same way they did in Scheme. Include the star only when defining placeholders (or giving them as formal parameters), not when you use the placeholder rig anywhere else! (And as in the example, don't use the star in the new statement, next.)
    2. ...rig = new (struct vehicle_s);
      The new operator actually creates the structure, and we assign that value to the placeholder rig

    3. rig->idNum
      is the idNum field inside the structure referred to by rig. It is the analog of (vehicle-idNum rig)

    4. rig->idNum = 4713;
      When on the left hand side of the "gets" operator =, this changes the value of rig->idNum. So the line here is actually the analog of set-vehicle-idNum.
    Task: Copy this code into your own program, and use printf to print out the rig's price.

    A word of caution: if declaring several placeholders to hold structures, you must use a star when defining each one:

    struct vehicle_s *rig = new( struct vehicle_s ), *trike = new( struct vehicle_s );
    trike->numWheels = 3;
    rig->numWheels   = 6 * trike->numWheels;  // this star just means multiply!
    ...
    

    Okay, what about the following? struct vehicle_s *trike = new( struct vehicle_s ); struct vehicle_s *rig; rig = trike; trike->numWheels = 3; rig->numWheels = 6 * trike->numWheels; // this star just means multiply!

    What is the value of rig->numWheels?
    trike->numWheels?
    (Recall the example showing difference between set!
    and set-bik-location!.  This is exactly analagous.)
    

    For Lazy People Only: typedef

    You may have noticed that using the name "struct vehicle_s"; is a bit unwieldy; really we'd like to be able to just have a type "vehicle" like we did in Scheme. Whaddya know, C indeed has a device for giving an additional name to any already-existing type:
    typedef existing-type-name new-type-name;
    
    (This syntax is reminiscent of the syntax for declaring a variable, as in int x; in that the already-known-to-C part (int) comes first, and the part you're defining (x) comes second.) So in our case, we could add a typdef line like this:
    typedef  struct vehicle_s   vehicle;
    
    After doing this, vehicle and struct vehicle_s are synonumous -- you can use either one.

    (Perhaps you are asking yourself, why not include the star in the typedef, as in typedef (struct vehicle_s *) vehicle;. Not a bad idea, but ... what do you put in the new statement in the program?)

    Exercise: Add this typedef to your program, and use it to simplify how the program reads.

    In practice, every time a structure is defined, it is also given an easier name with typedef. This idiom is so common that there is even a way to combine typedef and a struct definition.


    Back to Lab 10
    Back to Comp 210 Home