Cycle

From Esolang
Jump to navigation Jump to search

Cycle is a stack-based programming language designed by User:EZ132. It was designed to be extremely simple, having only two types of commands, yet easy to program in.

Overview

Cycle programs consist of a list of statements and code blocks. When a program is executed, its statements and code blocks are put onto a main cycle. It then starts from the beginning and goes around and around the cycle and executing statements when it encounters them. It stops either when there are no statements in the cycle or when an error occurs.

Cycle is based on three fundamental elements.

* Statements and code blocks
* Stacks and stack-like objects
* Numbers

Statements and code blocks are executable elements, that is, they can be run. These are the building blocks of Cycle. A statement simply consists of a direction to execute followed by a semicolon. A code block is an array of statements enclosed by curly brackets. An example of a statement is NUMIO->MEM;, while an example of a code block is

{
  NUMIO->ADD;
  NUMIO->ADD;
  ADD->NUMIO;
}

Statements can also be marked onetime by prefixing with a single quote, which will cause it to be deleted after running for the first time. However, statements inside code blocks cannot be marked onetime.

When Cycle encounters a statement, it executes it, but when it encounters a code block, it will not. However, code blocks are executable in different ways, and they can be pretty useful.

Stacks and stack-like objects should be familiar from other esolangs. Basically, they can be pushed and popped from. Cycle only provides one "true" stack, MEM, but there are a lot of other useful "pseudo-stacks" as well. Here is a table of all stacks and their behaviors:

Stack name Behavior on push Behavior on pop
MAIN Writes pushed code block/statement before the current statement. Errors on numbers Deletes and returns next statement
BLOCKS Pushed onto it normally and code blocks are pushed onto it when encountered in the program. Errors on numbers Popped normally and returned
MEM Pushed normally Popped normally and returned. Errors if empty
ADD Added to the stored value. Errors on statements and code blocks Stored value is returned and reset to 0
SUB If the stored value is RESET, then set the stored value to the pushed value. Otherwise, subtract the pushed value from the stored value. Errors on statements and code blocks Stored value is returned and set to RESET. If stored value is RESET, it errors
MUL Multiplied to the stored value. Errors on statements and code blocks Stored value is returned and reset to 1
DIV If the stored value is RESET, then set the stored value to the pushed value. Otherwise, divide the stored value by the pushed value. Errors on statements and code blocks Stored value is returned and set to RESET. If stored value is RESET, it errors
MOD If the stored value is RESET, then set the stored value to the pushed value. Otherwise, take the remainder of the stored value by the pushed value. Note that mod always returns a positive number. Errors on statements and code blocks Stored value is returned and set to RESET. If stored value is RESET, it errors
NEG Sets stored value to the negative of the pushed value. Errors on statements and code blocks Stored value is returned
ABS Sets stored value to the absolute value of the pushed value. Errors on statements and code blocks Stored value is returned
NUMIO Prints out pushed value as a number. Errors on statements and code blocks Gets numeric input from user, terminated by the first non-numeric inputted character.. Errors if input is not a number
TEXTIO Prints out pushed value an an ASCII character. Errors on statements and code blocks Inputs a character from user
EXEC Executes pushed statement/code block. Errors on numbers, and if the statement/code block errors. Errors
IF If the pushed value is a number, it will execute the next code blocks until the next number if it is nonzero Returns the last pushed number, and errors if there isn't one
IFZ If the pushed value is a number, it will execute the next code blocks until the next number if it is zero Returns the last pushed number, and errors if there isn't one
LOOP If the pushed value is a number, it will execute the next code blocks until the next number that many times Returns the last pushed number, and errors if there isn't one
WHILE If the pushed value is a statement/code block, it will repeatedly execute it until the statement/code block pushes a number onto `WHILE` Errors

Some of the stacks reference stored values. MEM starts off as an empty stack. ADD and MUL start as 0 and 1, respectively. SUB, DIV, and MOD start as RESET. NEG starts with the value 0.

Numbers are simple, and can be written by number literals like 0, 10, -21.

As mentioned before, Cycle programs consist of statements and code blocks, and code blocks are made out of statements. Statements themselves have the form STACK1->STACK2, where STACK1 and STACK2 are valid stack names. This will pop the last value off of STACK1, or do whatever happens when STACK1 is popped from, and push that onto STACK2, or do whatever happens on push. When the stack pop returns multiple values, they will be pushed onto the new stack in reverse order. In addition, numbers can be directly treated as stacks. The syntax is (number)->STACK. This will take number and push its value onto STACK. For example, the statement (123)->NUMIO; will push the number 123 onto the stack NUMIO, which will cause it to print 123. Another example is NUMIO->MEM;, which will get an input number and push it onto the memory stack.

A # sign will make Cycle ignore the rest of the line, so it can be used to make comments.

Sample programs

Prints out about 20 Fibonacci numbers before stopping.

# Fibonacci number caluculator
# Initialize the values
'(1)->MEM;
'(1)->MEM;
'(1)->NUMIO;
'(32)->TEXTIO;
'(1)->NUMIO;
'(20)->MEM;
(32)->TEXTIO; # Print out seperating space
MEM->SUB; # Move counter and prepare to decrement
# Just caluculate the next term and remove the oldest term
MEM->NEG;
NEG->NEG;
MEM->ADD;
NEG->ADD;
NEG->MEM;
ADD->NEG;
NEG->NEG;
NEG->MEM;
NEG->NUMIO; # Print out next term
(1)->SUB; # Decrement counter
SUB->NEG;
NEG->NEG;
{
    WHILE->MEM; # Intentionally error
}
# If counter reaches zero, exit, else, push the updated counter onto MEM
NEG->IFZ;
BLOCKS->IFZ;
NEG->MEM;

99 bottles

# Prints out the 99 bottles of beer on the wall song
# Very long since the text has to be printed character by character
'(99)->MEM;
MEM->NEG;
NEG->NEG;
NEG->NUMIO;
(32)->TEXTIO; (98)->TEXTIO; (111)->TEXTIO; (116)->TEXTIO; (116)->TEXTIO; (108)->TEXTIO; (101)->TEXTIO; (115)->TEXTIO; (32)->TEXTIO; (111)->TEXTIO; (102)->TEXTIO; (32)->TEXTIO; (98)->TEXTIO; (101)->TEXTIO; (101)->TEXTIO; (114)->TEXTIO; (32)->TEXTIO; (111)->TEXTIO; (110)->TEXTIO; (32)->TEXTIO; (116)->TEXTIO; (104)->TEXTIO; (101)->TEXTIO; (32)->TEXTIO; (119)->TEXTIO; (97)->TEXTIO; (108)->TEXTIO; (108)->TEXTIO; (44)->TEXTIO; (10)->TEXTIO;
NEG->NUMIO;
(32)->TEXTIO; (98)->TEXTIO; (111)->TEXTIO; (116)->TEXTIO; (116)->TEXTIO; (108)->TEXTIO; (101)->TEXTIO; (115)->TEXTIO; (32)->TEXTIO; (111)->TEXTIO; (102)->TEXTIO; (32)->TEXTIO; (98)->TEXTIO; (101)->TEXTIO; (101)->TEXTIO; (114)->TEXTIO; (46)->TEXTIO; (10)->TEXTIO; (84)->TEXTIO; (97)->TEXTIO; (107)->TEXTIO; (101)->TEXTIO; (32)->TEXTIO; (111)->TEXTIO; (110)->TEXTIO; (101)->TEXTIO; (32)->TEXTIO; (100)->TEXTIO; (111)->TEXTIO; (119)->TEXTIO; (110)->TEXTIO; (44)->TEXTIO; (32)->TEXTIO; (112)->TEXTIO; (97)->TEXTIO; (115)->TEXTIO; (115)->TEXTIO; (32)->TEXTIO; (105)->TEXTIO; (116)->TEXTIO; (32)->TEXTIO; (97)->TEXTIO; (114)->TEXTIO; (111)->TEXTIO; (117)->TEXTIO; (110)->TEXTIO; (100)->TEXTIO; (44)->TEXTIO; (10)->TEXTIO;
NEG->SUB;
(1)->SUB;
SUB->NEG;
NEG->NEG;
NEG->MEM;
NEG->NUMIO;
(32)->TEXTIO; (98)->TEXTIO; (111)->TEXTIO; (116)->TEXTIO; (116)->TEXTIO; (108)->TEXTIO; (101)->TEXTIO; (115)->TEXTIO; (32)->TEXTIO; (111)->TEXTIO; (102)->TEXTIO; (32)->TEXTIO; (98)->TEXTIO; (101)->TEXTIO; (101)->TEXTIO; (114)->TEXTIO; (32)->TEXTIO; (111)->TEXTIO; (110)->TEXTIO; (32)->TEXTIO; (116)->TEXTIO; (104)->TEXTIO; (101)->TEXTIO; (32)->TEXTIO; (119)->TEXTIO; (97)->TEXTIO; (108)->TEXTIO; (108)->TEXTIO; (46)->TEXTIO; (10)->TEXTIO; (10)->TEXTIO;
{
    WHILE->MEM; # Intentional error
}
NEG->IFZ;
BLOCKS->IFZ;