Getchl

Getchl is an esoteric shell designed for WalrusOS that uses getch() as its primary form of input. Every time a keystroke occurs, Getchl executes a command. This makes it an esoteric shell in that it uses irregular forms of user interaction, coupled with the esoteric programming language used (which is really just a standard stack-based golfing language).
==Data Model==
In one of my favorite data model families, the model behind Getchl is a both-sides-infinite tape of byte stacks with a scalar accumulator.
==Terminology==
Term 	Meaning
Stack 	LIFO queuing mechanism
Queue 	FIFO queuing mechanism
Tape 	A right-infinite array with an index
Pop 	Take the value off the top of the stack and return it
Push 	Put a value on the stack
Accumulator 	A scalar that holds a value
0gnirts 	A null-terminated string on the stack (alternatively, if no null terminator is present, the entire stack as a string) (first character of string at top of stack for technical reasons)
Mode 	Alternative interpreter modes
Default mode	The standard interpreter mode
String mode 	The mode where commands are ord()ed and pushed on the stack
Block mode 	The mode where commands are saved to a block instead of executed (used for evaluating groups of commands later)
Prime mode 	The mode where commands are slightly different for control purposes
Safe mode 	The mode where commands do not execute when the stack is too short, instead returning 0
All values are modulo 256 (or not, for a unicode implementation).
==Command List==
All commands are subject to change. Feel free to suggest such changes yourself.
Hex	Ch 	Name 	Meaning
20 	' ' 	NOP 	Do absolutely nothing
21 	! 	NOT 	Push the logical inversion of a popped value
22 	" 	STR 	Enter string mode
23 	# 	DEFINE 	Pop a value, map it to the previous command (or block)
24 	$ 	DROP 	Pop a value and discard it
25 	% 	MOD 	Pop a, pop b, push b%a
26 	% 	MOD 	Pop a, pop b, push b%a
27 	' 	PRIME 	Enter prime mode for the following character
28 	( 	START BLOCK 	Start forming a block
29 	) 	END BLOCK 	Terminate a block
2A 	* 	MULT 	Pop a, pop b, push b*a
2B 	+ 	ADD 	Pop a, pop b, push b+a
2C 	, 	INP 	Get a single character as input and pop its ASCII value on the stack (fail if EOF)
2D 	- 	SUB 	Pop a, pop b, push b-a
2E 	. 	PRINT 	Print the character whose ascii value is on the ToS
2F 	/ 	DIV 	Pop a, pop b, push b//a
30 	0 	ZERO 	Push 0
31 	1 	ONE 	Push 1
32 	2 	TWO 	Push 2
33 	3 	THREE 	Push 3
34 	4 	FOUR 	Push 4
35 	5 	FIVE 	Push 5
36 	6 	SIX 	Push 6
37 	7 	SEVEN 	Push 7
38 	8 	EIGHT 	Push 8
39 	9 	NINE 	Push 9
3A 	: 	DUP 	Pop a, push a, push a
3B 	; 	TERMINATE 	End session
3C 	< 	LT 	Pop a, pop b, push 1 if b<a, else push 0
3D 	= 	EQ 	Pop a, pop b, push 1 if b=a, else push 0
3E 	> 	GT 	Pop a, pop b, push 1 if b>a, else push 0
3F 	? 	IF 	Pop a, pop b, pop c, if a!=0 push b, else push c.
40 	@ 	REDUCE 	Repeat the previous instruction (or block) until it fails
41 	A 	A 	Push 10
42 	B 	B 	Push 11
43 	C 	C 	Push 12
44 	D 	D 	Push 13
45 	E 	E 	Push 14
46 	F 	F 	Push 15
47 	G 	GLOBAL 	Create a variable (pop v, pop 0gnirts name, map name to v)
48 	H 	 	
49 	I 	INVERT 	Invert the stack
 st2 = Stack()
 while len(stack) > 0:
 st2.push(st.pop())
 st = st2
4A 	J 	TAPE RELATIVE JUMP 	Pop n, go n-127 cells to the left on the tape
4B 	K 	 	
4C 	L 	LEFT 	Go left on the tape
4D 	M 	MAXIMIZE 	Pop a, set maximum stack size to a (pushes fail when len(stack) = stack.max) (extraneous elements dropped) (0 means no bound)
4E 	N 	 	
4F 	O 	 	
50 	P 	 	
51 	Q 	QUEUE 	Toggle queuing mode (all PUSHes become ENQUEUEs, all POPs become DEQUEUEs)
52 	R 	RIGHT 	Go right on the tape
53 	S 	 	
54 	T 	 	
55 	U 	 	
56 	V 	 	
57 	W 	 	
58 	X 	 	
59 	Y 	 	
5A 	Z 	 	
5B 	[ 	ROT 	Pop a, pop b, pop c, push a, push c, push b
5C 	SWAP	Pop a, pop b, push a, push b	
5D 	] 	ROTCC 	Pop a, pop b, pop c, push b, push a, push c
5E 	^ 	ACCUMULATE 	Pop a and put it in the accumulator
5F 	_ 	DECCUMULATE 	Push value in the accumulator
60 	` 	APPLY/ EVAL 	Pop a value and evaluate it as ASCII
61 	a 	 	
62 	b 	 	
63 	c 	 	
64 	d 	DIR 	Change the current working directory (pop a 0gnirts s, cd to s)
65 	e 	 	
66 	f 	FIND 	Pop tf, Repeatedly pop a until a==tf, push a
67 	g 	GET 	Inverse of G: Pop a 0gnirts, push the global with that name
68 	h 	 	
69 	i 	IDENTITY 	Pop a value and push it (NOP normally, but equivalent to ROLL in queueing mode)
6A 	j 	JUMP 	Pop a 0gnirts, jump back to that location and reexecute to the current point
6B 	k 	 	
6C 	l 	LABEL 	Get a 0gnirts, label this location as a jumpback location
6D 	m 	 	
6E 	n 	 	
6F 	o 	OPEN 	Pop a, get 0gnirts s from the stack, open the file s and associate it with value a
70 	p 	 	
71 	q 	 	
72 	r 	READ 	Pop a, read the content of the file associated with a
73 	s 	REPLACE 	Pop three strings off the stack, replace s[1] with s[2] in s[0], push s[0] onto the stack
74 	t 	 	
75 	u 	 	
76 	v 	 	
77 	w 	WRITE 	Pop a, pop 0gnirts s, write s to the file associated with a
78 	x 	 	
79 	y 	 	
7A 	z 	 	
7B 	{ 	COMMENT 	Stop executing commands (??? do I need this for a shell?)
7C 	 	OR 	a
7D 	} 	DECOMMENT 	Resume executing commands
7E 	~ 	SAFE 	Toggle safemode
===Prime Mode Commands===
Prime mode is an interpreter mode where commands are executed with alternative meanings. Unless otherwise specified, the interpreter returns to default mode after execution.
Character	Name 	Meaning
'@ 	CONDITIONAL REDUCE 	Pop value, negate it, execute previous command (or block) until a certain type of failure, fail if it fails on another failure (complicated, I know)
'? 	CONDITIONAL EXECUTE	Pop a, execute the previous instruction (or block) if a != 0
'; 	FAIL 	Pop a value and fail with its negated value
'` 	RUN 	Pop a value and execute the function defined to it
'( 	CONTINUED PRIME 	Enter continued prime mode (terminates on \)). All commands are interpreted as prime (e.g. '(abc) is equivalent to 'a'b'c).
'' 	DOUBLE PRIME 	Enter double-prime mode (currently does nothing)
'G 	GLOBAL STRING 	Pop a 0gnirts name, pop a 0gnirts s, map name to string s
'g 	GET STRING 	Pop a 0gnirts, push the 0gnirts it's mapped to
'L 	RELATIVE LEFT JUMP 	Pop n, go n cells to the left on the tape
'R 	RELATIVE RIGHT JUMP	Pop n, go n cells to the right on the tape
 	XOR 	Pop a, pop b, push b^a
==Failure Codes==
Some commands can return failure codes when executed under certain conditions. Failure codes do not terminate the script. All failure codes are negative.
Value	Meaning
-1 	Not enough values on stack
-2 	Attempted to push onto full stack
-3 	Divide or modulo by 0
-4 	No previous command (start of script or block)
-5 	No input character
-6 	Attempt to print null character
-7 	Invalid varname
-8 	Invalid filename
-9 	Invalid label
Useful Constructs and Mnemonics
Construct 	Meaning
<op>@ 	
,@ 	Get an input string, terminated by EOF
.@ 	Print a 0gnirts
$@ 	Clear the stack
`@ 	Eval a 0gnirts
&! 	NAND
! 	NOR
! 	XNOR
<n>:@ 	Fill the remainder of the stack with value n (exclude n for existing ToS) (Make sure the stack has a max, or it will hang forever)
<n>(<coms>1-0\/$)@ [I think this is right]	Execute coms n times (Push n on stack, then execute coms and push 1 and subtract 1 from n, push 1, swap, and divide it by n and drop. This means it fails when n is equal to 0, thus terminating the loop) (note that coms must not change the stack, or at least must bury their values under the values.)
 
== See Also ==
* The spec: https://docs.google.com/document/d/1IVBYW2CSDgvspkCl0nYTy-FQPUwozYdkX2H-cZGwALo/edit?usp=sharing