= = = GRAY SNAIL COMPILER = = =
Language and Javascript by Jack Eisenmann

Enter Gray Snail code here:



Program input:


Program output:



= DESCRIPTION OF GRAY SNAIL =

For an iPad JavaScript implementation, please go to this page.

Gray Snail is a fiendishly simple programming language which only has support for the string data type. It is an imperative language, with no built in support for procedural programming. There are 2 commands (4 including I/O):

POP (Var1) (Var2) (String): Pops the first character from the string, stores that character in one variable, and stores the rest of the string in the other variable.

GOTO (Label) (String1) (String2): If the strings are the same, execution skips to the given label.

INPUT (Var): Halts the program, and stores an input string in the given variable.

OUTPUT (String): Prints a string in the output box.

Each command is written on its own line, and commands are executed in sequential order (unless a GOTO command is invoked). If a command is not one of the four listed above, it is interpreted as a label.

If an argument (or label name) contains a space, it must be enclosed in quotes.

A substitution may occur in an argument (but NOT a label or command name) by inserting a variable name enclosed in brackets.

= EXAMPLE PROGRAMS =

To run each program, copy and paste the code into the code box above, then compile the code and execute it. To give input, enter text into the input box and press the "Set Input" button.

This program asks for the user's name, then responds with a greeting:

OUTPUT "WHAT IS YOUR NAME?"
INPUT NAME
OUTPUT "HELLO, [NAME]!"

The program below accepts an input string and reverses its characters:

OUTPUT "ENTER A STRING TO REVERSE."
INPUT INPUT
POP A OUTPUT A
LABEL1
POP CHAR INPUT [INPUT]
POP A OUTPUT A[CHAR][OUTPUT]
GOTO LABEL2 "" [INPUT]
GOTO LABEL1 A A
LABEL2
OUTPUT [OUTPUT]

The program below sets up a procedural structure. This structure supports both embedded and recursive procedure calls. The lines preceeded by a "#" are comments (in reality, they are actually labels, but the compiler doesn't mind this). When the program is executed, it will ask the user for 2 digits, and it will report their sum. As an example, try entering "54" as the input.

# Initializes the procedure stack.
POP A "PROC STACK" A
OUTPUT "ENTER TWO DIGITS TO ADD"
INPUT "INPUT DIGIT 2"
# Sets the arguments of the procedure to be called.
POP "PROC ARG 1" "PROC ARG 2" "[INPUT DIGIT 2]"
# Adds the return label to the stack.
POP A "PROC STACK" "AMAIN LABEL 1,[PROC STACK]"
# Calls the procedure.
GOTO "DIGITS ADD" A A
# The return label itself.
"MAIN LABEL 1"
# Display the output.
OUTPUT "THE ANSWER IS [PROC RETURN VALUE]"
# End the program by going to the end.
GOTO "MAIN LABEL END" A A

# Declares a procedure.
"DIGITS ADD"
# Stores the sequence of ones digits and tens digits.
POP A "VAR A 1" A0123456789012345678
POP A "VAR A 2" A0000000000111111111
# Truncates each of these sequences until the first
# digit has been reached.
"DIGITS ADD LABEL 1"
POP "VAR A 3" "VAR A 1" "[VAR A 1]"
POP "VAR A 6" "VAR A 2" "[VAR A 2]"
GOTO "DIGITS ADD LABEL 2" "[VAR A 3]" "[PROC ARG 1]"
GOTO "DIGITS ADD LABEL 1" A A
"DIGITS ADD LABEL 2"
# Stores another digit sequence, but only 0 through 9.
POP A "VAR A 4" A0123456789
# Declares var A 5, the output 1's digit.
POP A "VAR A 5" "A[VAR A 3]"
# Truncates var A 4 until the second digit has been
# reached, and truncate var A 1 and 2 as well.
"DIGITS ADD LABEL 3"
POP "VAR A 3" "VAR A 4" "[VAR A 4]"
GOTO "DIGITS ADD LABEL 4" "[VAR A 3]" "[PROC ARG 2]"
POP "VAR A 5" "VAR A 1" "[VAR A 1]"
POP "VAR A 6" "VAR A 2" "[VAR A 2]"
GOTO "DIGITS ADD LABEL 3" A A
"DIGITS ADD LABEL 4"
# Returns the ones and tens digits.
POP A "PROC RETURN VALUE" "A[VAR A 6][VAR A 5]"
# Invokes the procedure return function.
GOTO "PROC RETURN FUNC" A A

# Defines the procedure return function.
"PROC RETURN FUNC"
# Declares the return label as a blank string.
POP A "PROC RETURN LABEL" A
# Loops through the stack to extract the return label.
"PROC RETURN FUNC LABEL 1"
POP "VAR A 1" "PROC STACK" "[PROC STACK]"
GOTO "PROC RETURN FUNC LABEL 2" "[VAR A 1]" ","
POP A "PROC RETURN LABEL" "A[PROC RETURN LABEL][VAR A 1]"
GOTO "PROC RETURN FUNC LABEL 1" A A
"PROC RETURN FUNC LABEL 2"
# Goes to the return label.
GOTO "[PROC RETURN LABEL]" A A

# The end of the program.
"MAIN LABEL END"

Lastly, here is a proof for the Turing completeness of Gray Snail. The program below can execute Smallf**k code without limit; since Smallf**k is Turing complete, Gray Snail must also be Turing complete. (Note: this implementation uses parenthesis instead of brackets to perform loops in Smallf**k, since this Gray Snail compiler does not have support for using brackets as characters.)

OUTPUT "INPUT A SMALLFK PROGRAM."
INPUT "INSTRUCTION TAPE RIGHT"
POP A "INSTRUCTION TAPE LEFT" A
POP A "MEMORY TAPE RIGHT" A0
POP A "MEMORY TAPE LEFT" A
POP A "MACHINE STATE" AEXECUTE
POP A "MACHINE DIRECTION" ARIGHT
POP A "MACHINE STACK" A

"CYCLE START"

OUTPUT "[MEMORY TAPE LEFT] / [MEMORY TAPE RIGHT] [INSTRUCTION TAPE LEFT] / [INSTRUCTION TAPE RIGHT] [MACHINE STACK] [MACHINE DIRECTION] [MACHINE STATE]"
INPUT A

GOTO "MOVE LEFT" LEFT "[MACHINE DIRECTION]"
POP COMMAND "INSTRUCTION TAPE RIGHT" "[INSTRUCTION TAPE RIGHT]"
POP A "INSTRUCTION TAPE LEFT" "A[COMMAND][INSTRUCTION TAPE LEFT]"
GOTO "MOVE END" A A
"MOVE LEFT"
POP COMMAND "INSTRUCTION TAPE LEFT" "[INSTRUCTION TAPE LEFT]"
POP A "INSTRUCTION TAPE RIGHT" "A[COMMAND][INSTRUCTION TAPE RIGHT]"
"MOVE END"

GOTO "IGNORE PROCESS" IGNORE "[MACHINE STATE]"
GOTO "MEMORY MOVE RIGHT" > [COMMAND]
GOTO "MEMORY MOVE LEFT" < [COMMAND]
GOTO "MEMORY CHANGE" * [COMMAND]
GOTO "LOOP START" ( [COMMAND]
GOTO "LOOP END" ) [COMMAND]

"IGNORE PROCESS"
GOTO "LOOP START PASS" ( [COMMAND]
GOTO "LOOP END PASS" ) [COMMAND]
GOTO "CYCLE START" A A
"LOOP START PASS"
GOTO "MACHINE STACK ADD" RIGHT "[MACHINE DIRECTION]"
GOTO "MACHINE STACK SUBTRACT" A A
"LOOP END PASS"
GOTO "MACHINE STACK ADD" LEFT "[MACHINE DIRECTION]"
GOTO "MACHINE STACK SUBTRACT" A A
GOTO "CYCLE START" A A
"MACHINE STACK ADD"
POP A "MACHINE STACK" "A1[MACHINE STACK]"
GOTO "CYCLE START" A A
"MACHINE STACK SUBTRACT"
POP A "MACHINE STACK" "[MACHINE STACK]"
GOTO "EXECUTION RESUME" "" "[MACHINE STACK]"
GOTO "CYCLE START" A A
"EXECUTION RESUME"
POP A "MACHINE DIRECTION" ARIGHT
POP A "MACHINE STATE" AEXECUTE
GOTO "CYCLE START" A A

"MEMORY MOVE RIGHT"
POP CHAR "MEMORY TAPE RIGHT" "[MEMORY TAPE RIGHT]"
POP A "MEMORY TAPE LEFT" "A[CHAR][MEMORY TAPE LEFT]"
GOTO "MEMORY EOF" "" "[MEMORY TAPE RIGHT]"
GOTO "CYCLE START" A A
"MEMORY EOF"
POP A "MEMORY TAPE RIGHT" A0
GOTO "CYCLE START" A A

"MEMORY MOVE LEFT"
POP CHAR "MEMORY TAPE LEFT" "[MEMORY TAPE LEFT]"
POP A "MEMORY TAPE RIGHT" "A[CHAR][MEMORY TAPE RIGHT]"
GOTO "CYCLE START" A A

"MEMORY CHANGE"
POP CHAR "MEMORY TAPE RIGHT" "[MEMORY TAPE RIGHT]"
GOTO "MEMORY IS 1" 1 [CHAR]
POP A CHAR A1
GOTO "MEMORY WRITE" A A
"MEMORY IS 1"
POP A CHAR A0
"MEMORY WRITE"
POP A "MEMORY TAPE RIGHT" "A[CHAR][MEMORY TAPE RIGHT]"
GOTO "CYCLE START" A A

"LOOP START"
POP CHAR A "[MEMORY TAPE RIGHT]"
GOTO "CYCLE START" 1 [CHAR]
POP A "MACHINE STACK" "A1[MACHINE STACK]"
POP A "MACHINE STATE" AIGNORE
GOTO "CYCLE START" A A

"LOOP END"
POP A "MACHINE STACK" A
POP A "MACHINE STATE" AIGNORE
POP A "MACHINE DIRECTION" ALEFT
GOTO "CYCLE START" A A

Return to the Ostracod Pond