Semantics
  1. Expressions.
    1. Precedence and associativity.
    2. Postfix notation used occasionally.
    3. Short-circuit evaluation.
      1. Used by most languages for and and or.
      2. Pascal often used regular.
      3. Ada has both
        1. Regular operators: and, or
        2. Short circuit: and then, or else
      4. Violates eval-arguments-first.
        May feel strange with functional notation.
        Lisp: (or (null? x) (= (car x) 0))
      5. Many languages have conditional expressions: a > b ? a : b Only evaluates the test and exactly one branch.
    4. Practical limits on data sizes — not like math
      1. Values can overflow: may make order matter more.
      2. Some scripting languages have unbounded integer types.
    5. Side-effects.
      1. Certain operators, like ++
      2. Function calls that update object or global data.
  2. State
    1. Collection of all variables and their values.
    2. Assigning a variable updates state.
  3. Assignments
    1. Variations
      1. Chained assignment: a = b = c = 0;
      2. Parallel assignment: a, b, c = 1, 2*y, 3+z;
        Usually all rhs values computed before any lhs variables set.
      3. Statement or expression
        1. Often assignment is a statement: Pascal, Ada, Python.
        2. Expression in C family. a = (b = 10) + 1.
          More common while(ch = getchar()) { . . . }
    2. Semantics
      1. Type transfer
        1. Statically-typed languages: r-value converted to target type. Types must conform, or the conversion must be legal.
        2. Dynamically-typed languages: both type and value are assigned.
      2. Copy v. reference: Assignment may copy the l-value or make the target a new reference to the l-value object.
        1. Reference assignment is typical of interpreted languages and object-oriented languages.
        2. Some language may use each on different types.
        3. Java uses reference semantics for objects, and copy semantics for base types like int. C++ uses copy semantics. For Instance.
  4. Control flow
    1. Sequence.
    2. Goto.
      1. Primary control structure in early languages.
      2. Algol and later languages provided an alternative.
      3. Eventually, goto considered a bad thing.
    3. Conditional.
      1. Algol, Pascal:
        if a < b then begin a := b; b := 0; end else a := -b;
        1. begin, end used to group multiple statements.
        2. Result is a compound statement.
        3. Optional when a branch contains only one statement.
      2. C, C++, Java, and gobs of others
        if (a < b) { a = b; b = 0; } else a = -b;
        Uses curly braces instead of begin, end keywords.
      3. Ada, some others:
        if a < b then a := b; b := 0; else a := -b; end if
        1. No separate grouping; part of the statement.
        2. Eliminates the option not to group a singleton (good idea).
        3. End has to say what it's closing. Reduces difficulty finding errors when you leave out a close.
      4. Python, all by itself:
        if a < b: a = b b = 0 else: a = -b
        1. Bracketing accomplished by indents. (If you don't indent properly, it won't compile.)
        2. No bracketing markers are used.
      5. Short-circuit evaluation is also a variety of control.
    4. Switch or case
      1. Earliest form was a computed goto:
        GO TO (80, 100, 10, 35), IDING - JBAT
      2. C, C++, Java: Cases must be broken.
        switch(x) { case 1: type = "control"; break; case 2: type = "data"; break; case 3: case 4: case 5: type = "attribute"; break; default: type = "error"; }
      3. The newer Go language keeps the C-like syntax, but does not require break.
        switch x { case 1: type = "control"; case 2: type = "data"; case 3,4,5: type = "attribute"; default: type = "error"; }
      4. Pascal, Ada, Ruby, others: Various syntax, but again no break is required (that's a C thing). Ada:
        case x is when 1 => type := "control"; when 2 => type := "data"; when 3|4|5 => type := "attribute"; when others => type := "error"; end case;
      5. Variations.
        1. In in C, and traditionally, the cases had to be constants, the type of the expression limited to integer or some other integral type, and cases could not be repeated. This allows a more efficient translation than the equivalent of if/else if/else if/...else
        2. Ada adds the requirement that you must cover all possible values of the case expression (using the default mark others takes care of this).
        3. Java follows C, but at some point allowed switching on String since it's so blasted convenient.
        4. In C, each case executes from its label to the end of the switch. That is why you need to use break at the end. Most languages outside the C family end each case at the beginning of the next.
        5. C's rules allow you to run one branch in several cases by stacking the case statements without a break. Languages that don't use break usually provide a range and/or list syntax to combine cases values for one branch.
        6. Some languages, including Go and many interpreted langauges, allow cases to have more general types, or to be expressions, or to be repeated (the first match wins). There is much variation.
    5. Loops
      1. While loop -- most general.
      2. Counted for loop (Pascal): for a := 1 to 10 do
      3. For-each style loops
        1. Go through some sort of list or collection.
        2. Started in interpreted and scripting languages; now entering compiled languages. Now very common. C++:
          int s = 0; for(int i: { 4, 9, 18, 3, 22, 17 }) { s += i; }
        3. Variations between language in syntax and the type of collection allowed.
      4. Break statement.
      5. Continue statement.
  5. I/O
    1. Binary or character.
      1. Binary: Data are written exactly as stored.
      2. Character: Data are written as character strings.
        1. Free format (unformatted)
        2. Formatted: Fixed-width fields
    2. Standard streams.
    3. Sequential or random access.
    4. Syntactic class
      1. Statement (FORTRAN)
      2. Library call (Most common).
      3. Privileged function call (Pascal).
    5. Error handling
      1. Pascal: aborts on bad conversions.
      2. Reporting through a return value (C).
      3. Current trend is to use exceptions.
        Some languages allow both
  6. Exceptions
    1. An error condition which the operation cannot handle itself.
    2. Opinions differ about what events are exceptions.
    3. Exception-less languages.
      1. Return an error value (typically -1 or nil). Perhaps an additional return value if the language permits.
      2. Extra output parameter describing success.
    4. Exception support.
      1. Program aborts can be thought of as uncatchable exceptions.
      2. Exception types.
        1. A type of its own (Ada).
        2. An object with a certain base class (Java Throwable).
        3. Any type (C++).
      3. Raising an exception transfers directly to a handler.
      4. Options
        1. How are handlers associated with exceptions?
          1. The try block is familiar.
          2. PL/I on statement assigns the block to the exception type.
          3. C signals are similar.
        2. Does the operation resume after the handler completes?
          1. No: Most languages today.
          2. Yes: PL/I used this. C signals likewise.
            1. Must somehow make the operation become legal after restart.
            2. Really tough for bad input.
            3. Handlers often jump away or exit program to prevent restart.
    5. Examples.
      1. I/O returning and throwing
      2. Ada
      3. Python
      4. Ruby
    6. Assert.
      1. A condition which must be true, else throws an exception.
      2. Some older languages have assertions which abort on failure.