This file's purpose is to document our code framework and process.



Section 1:  Coding in Java
--------------------------

This project is written in Java, an object-oriented language, and thus
we should use object-oriented structures as much as possible.  I've
collected here a bunch of the rules I use to "objectify" code that I
am writing.


* If you find yourself wanting to use the "instanceof" operator, think
twice.  Then think trice, and make sure that's the best way to write
that code.  Most of the time, you really want to create a method in a
base class or interface, and override it in the child classes for each
"instanceof" case.  For example, the lecture notes' example code for
destructure(n) is like:
  if n instanceof If
    // stuff
  else if n instanceof While
    // etc...
A better way to do it is to create a destructure() method in the base
class of If and While, and override it in the subclasses If and While.


* If you're implementing a function which you might do in C or
pseudocode as f(x) where x is an object, you probably really want to
write a method f() of the class of x and call x.f().  A good example
would be the destructure(n) function in the lecture notes (see
above).  When you want to implement a function of more than one
argument, say f(x,y,z), you should decide which of x, y, or z is the
one most "doing" the action, and make the function a method of that
class.  An example of that would be shortcircuit(n,t,f) from the
notes.  It's fairly clear that it should be a method shortcircuit(t,f)
of the class (HighInstruction) of n.


* If you ever find yourself wanting to use integer codes to separate
different "kinds" of objects, you probably really want subclasses.
For example, having an "opcode" field for binary operators is an
atrocity: having separate AddExpr, SubExpr, etc subclasses is much
better.


* Accessor methods are generally bad, though sometimes unavoidable.
Try to move the relevant code into the class of the object being
accessed.


Section 2:  Style Guide
-----------------------

General rules:
* No tabs; 2 spaces per indentation
* 80 columns
* Class names in StudlyCaps, all else lowercase_and_underscores.

Java code:
* Open brace ('{') should be the last thing on a line _unless_ the
  whole body of the block can fit on one line.  I.e.:
    if (foo) { bar; baz; }
  is OK, but
    if (foo) { // Comment
      bar;
      baz;
    }
  is not.  (Move the comment to the next line.)
* Close brace ('}') always goes on its own line _unless_ terminating
  a one-line block (see above).
* I prefer /* */ style comments to // ones (c-mode deals better), but
  use what works for you.
* I prefer cuddled elses and catches (i.e. '} else {',
  '} catch (Exception e) {', etc.), but again, do what works for you.
* For multi-block constructions (if/else, try/catch, etc.) I prefer
  to use braces around _all_ blocks and usually don't do things like
    try { foo; }
    catch (Exception e) { bar; }
  But do as you like.

Parser.cup rules:
* Name of target nonterminal at column 0
* For reduction rules, ::= or | begins at column 2 of next line
* For reduction actions, {: and :} begin at column 4 of next line
  * If action is more than one line, {: and :} go on lines of their
    own, and body of action is indented starting at column 6.
* Terminal ';' at column 0 of last line.
