tags:

views:

306

answers:

2

When have you found something that gave you pause and made you realize that more cooks in the kitchen is sometimes a good thing? Specifically, simple things you've seen that made you wonder why you never thought of them before.

+6  A: 

Working on a Half-Life 2 mod I recently found in the source a simple way of keeping track of how many items exist in an enumeration. This comes in handy when doing lookups in, for example, an array of entity relations to see if they are friendly or not.

"Oh, duh!"

#include <iostream>

using namespace std;

enum Robots
{
    Bender = 0,
    Boxy,
    Calculon,
    Flexo,
    Hedonismbot,
    ReverendPreacherbot,
    Roberto,
    RobotDevil,
    RobotMafia,
    RobotSanta,
    TinnyTim,

    // Always add new robots above this line
    NumRobots
};

void main()
{
    cout << "There are " << NumRobots << " robot types" << endl;
}
RobotCaleb
+5  A: 

When I saw the 1-page assembler and interpreter in "The Awk Programming Language". It was a revelation!

http://plan9.bell-labs.com/cm/cs/awkbook

First a sample assembler program

# print sum of input numbers (terminated by zero)

     ld    zero   # initialize sum to zero
     st    sum 
loop get          # read a number
     jz    done   # no more input if number is zero
     add   sum    # add in accumulated sum 
     st    sum    # store new value back in sum 
     j     loop   # go back and read another number

done ld    sum    # print sum 
     put 
     halt

zero const 0
sum  const

And the assembler and interpreter

# asm - assembler and interpreter for simple computer
#   usage: awk -f asm program-file data-files...

BEGIN {
    srcfile = ARGV[1]
    ARGV[1] = ""  # remaining files are data
    tempfile = "asm.temp"
    n = split("const get put ld st add sub jpos jz j halt", x)
    for (i = 1; i <= n; i++)   # create table of op codes
        op[x[i]] = i-1

# ASSEMBLER PASS 1
    FS = "[ \t]+"
    while (getline <srcfile > 0) {
        sub(/#.*/, "")         # strip comments
        symtab[$1] = nextmem   # remember label location
        if ($2 != "") {        # save op, addr if present
            print $2 "\t" $3 >tempfile
            nextmem++
        }
    }
    close(tempfile)

# ASSEMBLER PASS 2
    nextmem = 0
    while (getline <tempfile > 0) {
        if ($2 !~ /^[0-9]*$/)  # if symbolic addr,
            $2 = symtab[$2]    # replace by numeric value
        mem[nextmem++] = 1000 * op[$1] + $2  # pack into word
    }

# INTERPRETER
    for (pc = 0; pc >= 0; ) {
        addr = mem[pc] % 1000
        code = int(mem[pc++] / 1000)
        if      (code == op["get"])  { getline acc }
        else if (code == op["put"])  { print acc }
        else if (code == op["st"])   { mem[addr] = acc }
        else if (code == op["ld"])   { acc  = mem[addr] }
        else if (code == op["add"])  { acc += mem[addr] }
        else if (code == op["sub"])  { acc -= mem[addr] }
        else if (code == op["jpos"]) { if (acc >  0) pc = addr }
        else if (code == op["jz"])   { if (acc == 0) pc = addr }
        else if (code == op["j"])    { pc = addr }
        else if (code == op["halt"]) { pc = -1 }
        else                         { pc = -1 }
    }
}
Mark Harrison