Formal Whirl Program Definition

The execution model of a Whirl program ("Whirl program" is a term that means either the execution model or the sequence of instructions which is a composition of "0" and "1" symbols) depend on the instructions themselves as well as two levels of state: one state level determines which table to use to determine the instruction's command (these tables are called the "ops ring" and the "math ring"), the other state level determines for that table a set of conditions that determine which command with which argument (if any) is to be selected for execution. A Whirl program also contains "memory" of an indeterminate number of mutable cells, each cell contains a numeric value initialized to 0.

Program

The above description can be summarized precisely by the following tuple equivalence:

PWhirl = { Ring-typeactive, Hist, Rings, MemHT(indexed), InstHT(indexed) }
 where:
 
PWhirl is the execution model of this Whirl Program ("the program")
Ring-typeactive one-of([ops, math]) indicates which ring is currently active
Histhist(State, last_instruction(Inst)) the results of interpretation of the previous instruction
 where: 
 
Stateone-of([quescient, executed]) was a command selected for execution?
 'quescient' means a command was not selected for execution
 'executed' means a command was selected and executed
Instone-of(["0", "1"]) the last interpreted instruction
Rings { Ringops, Ringmath } the current state of each ring (rings described below)
MemHT(indexed) is A list of memory cells (described below); current active one at the head
InstHT(indexed) is Indexed (unsorted) program instructions; current active one at the head (structure described below).

Instructions

Semantics

Whirl has two instructions "0", and "1". The meanings of these instructions are captured here:
1

Rotate the currently active ring in its indicated direction and set the history to "hist(quescient, last_instruction(1))"

ex 1:
GIVEN the current ring is "ops"
 and its direction is "clockwise spin"
 and the currectly selected command is "3 - zero"
THEN the ops ring's newly selected command is "4 - load"
ex 2:
GIVEN the current ring is "math"
 and its direction is "counterclockwise spin"
 and the currectly selected command is "0 - noop"
THEN the math ring's newly selected command is "11 - neg"
0
First, Reverse the spin of the currently active ring
And then, perform the test:
 
IF the last instruction was "0",
 and the last instruction did not result in a command execution,
  (i.e.: the command history is "hist(quescient, last_instruction(0))")
THEN execute the currently selected command
 and activate the inactive ring and deactivate this one (i.e.: switch rings)
 and set the history to "hist(executed, last_instruction(0))"
OTHERWISE set the history to "hist(quescient, last_instruction(0))"
ex 1: 
 
GIVEN the current ring is "math"
 and its direction is "counterclockwise spin"
 and the command history is "hist(executed, last_instruction(0))"
THEN the math ring's new direction is "clockwise spin"
 and the command history is set to "hist(quescient, last_instruction(0))"
ex 2: 
 
GIVEN the current ring is "ops"
 and its direction is "clockwise spin"
 and the currently selected command is "2 - one"
 and the command history is "hist(quescient, last_instruction(0))"
THEN the ops ring's new direction is "counterclockwise spin"
 and the "one" command is executed
  (i.e.: the ops Accumulator is set to 1)
 and the ops ring is deactivated; the math ring, activated
 and the command history is set to "hist(executed, last_instruction(0))"
ex 3: 
 
GIVEN the current ring is "math"
 and its direction is "clockwise spin"
 and the command history is "hist(quescient, last_instruction(1))"
THEN the math ring's new direction is "counterclockwise spin"
 and the command history is set to "hist(quescient, last_instruction(0))"

Traversal

Whirl instructions are executed in sequence (a padd command alters the sequence by a relative amount for the next instruction to be executed), and to enforce this discipline, we store the sequence of instructions decorated with an index (such storage is normally referred to as an "array", but such a term has a grossly overloaded meaning (particularly when it comes to element access) in the software engineering field). Individual elements are of the form:

{ Index, Instruction }

where: 
 Index indicates this instruction is ith in the program source
 Instruction is one-of(["0", "1"])

These elements are stored in a list with the only ordering being that the current instruction is at the head of the list. The next instruction is obtained by incrementing the Index by an offset (the offset is either 1 or the amount in the ops accumulator if the command executed is a 'padd') and then moving that corresponding element to the head of the list.

Program Termination

The program will terminate when any of the following conditions are met:

Rings

Whirl programs interact with two rings, the "ops" ring and the "math" ring. Each ring has its own (not necessarily orthogonal) set of commands, a selector pointing to the command to be executed, an accumulator, and a (reversible) direction of spin. The general structure of each ring is as follows:

RingType = { CommandsHT, Direction, Accumulator }
 where:
 
Typeone-of([ops, math])which ring this tuple represents
CommandsHT isList of indexed (unsorted) commands; the command at the head is considered selected for execution
Directionone-of([clockwise spin, counterclockwise spin]) the direction in which the ring rotations for next command selection
Accumulatorvalue(Number) Number is initially 0 and changes when commands are executed
The indexed commands for the ops ring are: The indexed commands for the math ring are:
0-noop 4-load 8-logic
1-exit 5-store 9-if
2-one 6-padd 10-intIO
3-zero 7-dadd 11-ascIO
0-noop 4-mult 8->
1-load 5-div 9-=
2-store 6-zero 10-not
3-add 7-< 11-neg

Ring Command Semantics

Not only is command selection dependent on a dual state layer from the instruction, but also the command itself may have meaning dependent on the state. The commands are described as follows:

IndexCommandPreconditionsEffect
Ops Ring
0noopn/a(no effect)
1exitn/aprogram halts
2oneAccumulator = any valueAccumulator = 1
3zeroAccumulator = any valueAccumulator = 0
4load Accumulator = any value; Current Memory cell = NumAccumulator = Num
5store Accumulator = Num; Current Memory cell = any valueCurrent Memory cell = Num
6padd Accumulator = Num1; program index = Num2 program index = Num1 + Num2
(relative jump)
7dadd Accumulator = Num1; memory index = Num2 memory index = Num1 + Num2
(relative access)
8logic
current memory index = 0
otherwise (Accumulator = Val)
Accumulator = 0
Accumulator = Val & 1
9if
current memory index = 0
otherwise
noop
padd
10intIO
Accumulator = 0
otherwise
current memory value = input integer
current memory value printed as an integer
11ascIO
Accumulator = 0
otherwise
current memory value = input ASCII character
current memory value printed as an ASCII character
Math Ring
0noop n/a(no effect)
1load Accumulator = any value; Current Memory cell = Num Accumulator = Num
2store Accumulator = Num; Current Memory cell = any value Current Memory cell = Num
3add Accumulator = A; Current Memory cell = B Accumulator = A + B
4mult Accumulator = A; Current Memory cell = B Accumulator = AB
5div Accumulator = A; Current Memory cell = B Accumulator = A / B
6zero Accumulator = any valueAccumulator = 0
7<
Accumulator < current memory value
otherwise
Accumulator = 1
Accumulator = 0
8>
Accumulator > current memory value
otherwise
Accumulator = 1
Accumulator = 0
9=
Accumulator = current memory value
otherwise
Accumulator = 1
Accumulator = 0
10not
Accumulator = 0
otherwise
Accumulator = 1
Accumulator = 0
11neg Accumulator = NumAccumulator = -Num

Memory

The Whirl specification states that Whirl program memory is infinite; we obey by accumulating memory on an as-needed basis ("lazily"). Memory follows a similar structural and allocation scheme as with program instruction storage: decorated with an index when the head element being the currently selected one.

The difference with memory is that:

  1. instructions are of the binary form "0" or "1", but memory may store any (Rational) numeric value; and,
  2. it starts initially with one tuple: { 0, 0.0 }; and,
  3. when another element is selected (with dadd) that is not present, that element is added to the memory store, initialized to { Index, 0.0 }

It is implementation-dependent as to how memory values are converted to integral or to (ASCII) character near-equivalents.


author:Douglas M. Auclair
date:November 28, 2005
whirl@ http://www.bigzaphod.org/whirl