OGEL

From Esolang
Jump to: navigation, search

OGEL stands for Open Grid Execution Language (the fact that, backwards, it happens to spell the name of a certain famous manufacturer of coloured blocks (LEGO®) is a complete coincidence). It was designed by GreyKnight in August of 2006.

Elements of an OGEL program

An OGEL program consists of a grid-like arena, each cell of which can contain a stack of coloured blocks. Processors wander this grid, climbing up certain stacks and executing their contents as code.

The regular blocks are coloured black(K), red(R), yellow(Y), green(G), blue(B), and white(W). There is also a glass(s) block used as a separator.

Each processor has an associated stack somewhere on the arena on which it can keep data. Processors can also be instructed to address one other stack on the arena and manipulate it, although the commands for doing so are not quite as numerous. These "processor stacks" are not protected specially, and can be executed and manipulated just like any other.

Stacks as data

When reading an addressed stack, or a processor stack, the contents are interpreted as integers or the special nil value in the following manner. First, the number of glass (s) blocks which separate a number from the previous one is examined. If it is an odd number, a positive (or zero) number is being described; if an even number, a negative number (or nil) is present. The first item on a stack can optionally leave out its leading s blocks and start directly on a colour, in which case the value is assumed to be positive. Values are specified in base-6, with the following digits:

K (black) 0
R (red) 1
Y (yellow) 2
G (green) 3
B (blue) 4
W (white) 5

If you specify a negative number and a value of zero, the item will be interpreted as "nil". This is used as the boolean false value, and often used to signal errors. Any non-nil value (including 0) is boolean true.

For instance, a stack containing the values (1, 2, 12, -12, nil, 27) could be represented:

RsYsYKssYKssKsBG

The "top" of the stack

Values that are popped from a stack are taken from the bottom, and pushed values also appear on the bottom. Note that this is upside-down from the usual visualization of a stack. Unless otherwise specified, in this article the phrase "top of the stack" will refer to the point where push/popping takes place; that is, its physical bottom.

Processors

Each processor, upon arriving in an arena cell, will begin executing any stack found there from the bottom up; if there is no stack, it will idle in the cell until given further instructions. Upon reaching the top of the stack, or exiting it by some other means, it will pop an x and y offset from its processor stack and move by that amount to a new cell. If either value popped is nil then the processor will not move anywhere, but idle in the current cell. If an offset of <0, 0> was popped, the current stack is executed again from the bottom.

Niceness

Processors can have different "niceness" values (a priority), in which the lowest-niceness processor gets the highest share of actual execution time. Specifically, the niceness indicates the number of clock ticks the processor waits between steps. A niceness of 0 means that the processor executes a step every tick. All processors created at the start of the execution have the default niceness of 8.

Instructions

Instructions are sequences of coloured blocks separated by s blocks. The number of s blocks used to separate one instruction from the next is not normally significant (exceptions are noted below). Any value not recognized as a valid instruction will be treated as a "no-operation" instruction; however, when you wish to explicitly insert a no-op, you should use the instruction reserved for this use: (5)WWWWWK

Notation

Instructions are separated into tiers by the number of W blocks in their prefix. For clarity, the sequence WWWWK could be written as (4)WWWWK, or even shortened to (4)WK or (4)K. This is easier to read than long strings of Ws.

Tier-0 Instructions

mnemonic sequence action
push K Skip next item in program and push it onto the processor stack
jump R Pop $n from proc stack and jump to $nth next program item ($n==1 => move to next as normal); jumps out if too few remaining
add Y Pop $a, $b from processor stack, then push $a+$b
mul G Pop $a, $b from processor stack, then push $a*$b
ina B Read in a single character from the user and push its Unicode value to the proc stack
n/a W <prefix for tier 1>

Tier-1 Instructions

mnemonic sequence action
pop (1)WK Pop frame from processor stack
jumpb (1)WR Jump over next $n glass blocks; is equal to R if there are no extraneous s blocks
sub (1)WY Pop $a, $b from processor stack, then push $a-$b
div (1)WG Pop $a, $b from processor stack, then push $a/$b
outa (1)WB Print a single character from its popped Unicode value
n/a (1)WW <prefix for tier 2>

Tier-2 Instructions

mnemonic sequence action
dupl (2)WWK Duplicate the item on the top of the proc stack
jumpout (2)WWR Jump out of this command stack prematurely
not (2)WWY Pop $a from proc stack and push the bitwise not $a
mod (2)WWG Pop $a, $b from processor stack, then push $a mod $b
inn (2)WWB Read in an integer from the user and push it
n/a (2)WWW <prefix for tier 3>

Tier-3 Instructions

mnemonic sequence action
roll (3)WWWK Rotate the top $b stack elements ($a mod $b) times
daddr (3)WWWR Address the stack at co-ordinates <$a, $b> (default none, nil addresses none)
or (3)WWWY Pop $a, $b from processor stack, then push bitwise $a or $b
and (3)WWWG Pop $a, $b from processor stack, then push bitwise $a and $b
outn (3)WWWB Pop an integer and print it
n/a (3)WWWW <prefix for tier 4>

Tier-4 Instructions

mnemonic sequence action
dpush (4)WWWWK Push a frame onto the addressed stack, popped from the proc stack.
dpop (4)WWWWR Pop a frame from the addressed stack and push it onto the proc stack.
ddupl (4)WWWWY Duplicate the top frame on the addressed stack
droll (4)WWWWG Roll the top $b stack elements ($a mod $b) times ($a,$b from proc stack)
dcord (4)WWWWB Push the addressed stack's co-ordinates onto the proc stack.
n/a (4)WWWWW <prefix for tier 5>

Tier-5 Instructions

mnemonic sequence action
morep (5)WWWWWK Pop $a,$b from proc stack and push the boolean ($a>$b) (1 for true, nil for false)
equalp (5)WWWWWR Pop $a,$b from proc stack and push the boolean ($a==$b) (1 for true, nil for false)
fork (5)WWWWWY Fork the current processor. The new proc stack will be allocated in the first free cell after the parent's stack in the x-direction. The child's proc stack has a 0 pushed onto it; the parent's has the child's processor ID pushed (or nil on failure).
kill (5)WWWWWG Pop a value from the stack; if nil, destroys the processor but leaves the proc stack as data. If non-nil, also destroys the proc stack.
system (5)WWWWWB Pop $a, $n, then $n more items; execute system call $a with the $n arguments. See below for system call list.
n/a (5)WWWWWW <prefix for tier 6>

Tier-6 Instructions

mnemonic sequence action
nop (6)WWWWWWK Reserved no-operation instruction
n/a (6)WWWWWWR <reserved>
n/a (6)WWWWWWY <reserved>
n/a (6)WWWWWWG <reserved>
n/a (6)WWWWWWB <reserved>
n/a (6)WWWWWWW <reserved from here on>

System Calls

For use with (5)WWWWWB. If too few arguments are specified, the remaining are set to nil. If too many, the excess are thrown away. On error, the call returns its usual number of arguments, but all set to nil.

Arguments after ';' in the argument lists shown below have default values and can be unspecified if you wish; unless otherwise stated, the default is 'nil'.

call number number (base 6) mnemonic arguments return description
0 K EXIT 1 ($code) 0 Stops all processors and terminates execution, returning $code in an appropriate manner.
1 R NPROCS 0 () 1 Pushes the number of processors currently alive.
2 Y PID 0 () 1 Pushes the processor ID of the calling processor.
3 G PKILL 2 ($pid; $s) 1 Kills processor #$pid; if $s, also destroys its stack. Pushes success (true/false)
4 B TIME 0 () 1 Pushes the number of seconds since the UNIX epoch (1970 Jan 1st, 00:00:00)
5 W PROCSTAT 1 ($pid) 4 Pushes $sy,$sx, $py,$px (positions of proc stack and processor for proc #$pid)
6 RK PROCTELL 5 ($pid,$px,$py; $sx,$sy) 1 Tells processor #$pid to go to <$px,$py> and use <$sx,$sy> as its proc stack. Default for <$sx,$sy> is current stack. Pushes success (true/false).
7 RR HEIGHTB 2 ($x, $y) 1 Push the height of the stack at <$x,$y> in blocks.
8 RY HEIGHT 2 ($x, $y) 1 Push the height of the stack at <$x,$y> in functional units (between 's' separators).
9 RG GETNICE 1 ($pid) 1 Pushes the "niceness" (number of clock ticks between execution steps) of #$pid.
10 RB SETNICE 2 ($pid, $nice) 1 Resets the "niceness" of #$pid (nil sets to the default of 8). Pushes new actual niceness, or nil on error.
11 RW FOPEN 4 ($nx,$ny, $mode; $flags) 1 Read the stack at <$nx,$ny> as a string pathname to open and push a file handle.
$mode: {1=read, 2=write, 3=readwrite}
$flags: {1=append, 2=truncate, 4=create, 8=binarymode, 16=xcreate}
In read mode, flags defaults to 0; in write mode, 6; in readwrite, 4. With the xcreate flag, fails if file already exists.
12 YK FOPENTEMP 2 (;$mode, $flags) 1 Pushes a handle for a temporary file; $mode defaults to 3 (readwrite). The tempfile will be removed automatically after use.
13 YR FCLOSE 1 ($file) 1 Closes $file and pushes true on success.
14 YY FSEEK 3 ($file, $pos; $whence) 1 Moves pointer of $file to [$whence]+$pos. $whence defaults to '0' (start), and can also be '1' (current pos), or '2' (end of file). Pushes new location.
15 YG FREAD 4 ($file, $x,$y; $n) 1 Read $n (default: all) bytes and store them as a stack at <$x,$y>. Push amount read.
16 YB FWRITE 4 ($file, $x,$y; $n) 1 Write $n (default: all) bytes read from <$x,$y> and push success.
17 YW FREADCH 1 ($file) 1 Reads a single byte from $file and pushes it.
18 GK FWRITECH 2 ($file, $char) 1 Writes $char to file and pushes $char on success.
19 GR FREADLINE 4 ($file, $x,$y; $n) 1 As FREAD, but stops when it hits any line break (then skips past the break)
20 GY FWRITELINE 4 ($file, $x,$y; $n) 2 As FWRITE, but writes a line break afterwards.
21 GG FLOCK 2 ($file; $unlock) 1 Either lock or unlock the file (depending on $unlock) for access by this processor. Pushes success; if false, file is already locked.
22 GB FFLUSH 1 ($file) 1 For writeable files, matches the disk representation to that in memory. Push success.
23 GW <reserved> n/a n/a <reserved>
24 BK <reserved> n/a n/a <reserved>
25 BR REVERSEB 2 ($x, $y) 1 Reverses the stack at <$x, $y> by blocks and pushes numblocks on success.
26 BY REVERSE 2 ($x, $y) 1 Reverses the stack at <$x, $y> by units and pushes numunits on success.
27 BG SLEEP 1 ($secs) 0 Sleeps for at least $secs seconds. When there are many processors, may overshoot.
28 BB EXECUTE 2 ($x, $y) 1 Executes a string stored in stack <$x,$y> in the OS shell and pushes the return code.
29 BW PEXECUTE 4 ($x,$y, $ox,$oy) 1 As EXECUTE, but stores any command output at <$ox,$oy>
30 WK GETENV 4 ($x,$y, $ox,$oy) 1 Gets the value of an environment variable, pushes success.
31 WR GETARG 3 ($n, $x,$y) 1 Stores command-line argument $n at <$x,$y>, push success. If $n is nil, push number of arguments and store nothing.
32 WY PPID 0 () 1 Pushes the processor ID of the calling processor.
33 WG <reserved> n/a n/a <reserved>
34 WB <reserved> n/a n/a <reserved>
35 WW <reserved> n/a n/a <reserved>
36 RKK EDITSTACK 4 ($x,$y; $z,$v) 1 If $z nil, push length of stack. If $v nil, push blockvalue at $z position (0 is bottom-most block); else set $z position to $v blockvalue and return $v. Blockvalues are as for digits, and '6' represents an 's' block. Other blockvalues are erroneous. You can set the block just above the top one, but no higher.
{0=black, 1=red, 2=yellow, 3=green, 4=blue, 5=white, 6=glass}

Resources