Doorspace

From Esolang
Jump to navigation Jump to search

Doorspace (or "Qugord") is an Esoteric programming language by user:David.werecat where the program is a series of doors and everything is stored in arrays.

Introduction

Doorspace is a language that describes a series of doors, where each line is a different door. Therefore, it has object oriented properties even though it executes on a purely functional basis. Its intent is to explore new types of control structures while maintaining a level of verbosity that ensures that the code is mostly readable to even non-programmers. The current version of Doorspace is "Doorspace 1.0". Any interpreters or compilers for Doorspace should at least implement the "Doorspace 1.0" standard as outlined in this document.

Language Basics

Doors

As already mentioned, each line of code is a definition of a door. The doors are read from line by line from the top and are put from left to right into doorspace. All doors have two states, open and closed. When the program is loaded, all doors are created in the closed state. The program begins at the first door. At each door the program visits, the code attached to the door is executed and the program moves on to the next door. If the door is closed, the door directly to the right (the line below the current line in the source code) is visited next. However if the door is open, the program will step through the door and end up at the location that the door is mapped to. All doors are mapped by default to the door directly to the right, however doors can be remapped in the code to map to other doors. Also note that doors can be mapped to themselves or to the END door (the END door is known as "-1"). Execution finishes whenever the program steps outside of doorspace or ends up at the END door. For convenience's sake, doors may also be given names in the source code so that they can be easily referenced anywhere in the code.

Transient Value array

Instead of using variables, data is stored in an array known as the transient value array. The array contains an infinite amount of integers which are indexed by number, starting at zero. Interpreters should initialize the array with no elements and expand it as is required. Conceptually the array only exists in doorspace, so when the program exits the values are lost. When an integer overflows or underflows, it wraps around to the opposite end of the integer range. The values in the transient value array can be accessed through their index or using another value within the array as an index (accessing values using another value limits the number of possible values you can access to two billion). Any attempts to access indices under zero will instead access the value at index zero.

Value Groups

During execution, tags can be produced which represent a subset of values in the transient value array, known as group tags. Each group tag has a name, a start index, an end index, and a per value. The group is made up of the indices from the start index to the end index, affecting each perth element. Value groups can be iterated through, allowing high level emulation of arrays and strings.

Space Stack

The space stack is the only other way of storing data aside from the transient value array. The space stack provides an infinite amount of integer storage and is accessed through a few basic commands described later.

Input and Output

Input and output functionality is also provided through arrays. The input array contains all data that has been read from the console since the start of the program. New data is requested when the input array is attempted to be read at a location that has not been filled with input yet. In this case, data is read until the location attempted to be read is filled and stops directly afterwards. The input array starts at a size of zero, and is indexed from zero onwards. Note that the zeroth element of the input array is not read immediately and represents the first character of input. The output array is similar, although does not store all output data history. When the output array is wrote to, the data is not immediately output. A command is provided to write all data from the output array to the console, although this also clears the output array. As with the input array, the output array grows when an index outside of the array is attempted to be accessed. Note that both the input and output arrays act as the transient value array in that any attempts to access indices under zero will instead access the value at index zero.

Instructions

Code Style

Each line is interpreted after removing all whitespace from the front and the back of the line. Lines are separated with newline characters or with pipe (|) symbols. Note that a pipe symbol will break a line even when encountered inside quotes. Each line can be one of three types of lines: a named door definition, a generic door definition or a comment. Comments are not included as door definitions and are defined as lines beginning with an exclamation mark (!) or lines that are empty. Comments cannot appear mid-line, as they will be interpreted as part of the code of that line. Lines defining generic doors (doors with no name) are defined as lines starting with a tilde (~) character. The code to be executed at that door is put after the tilde character on the same line. Note that generic doors cannot be functionally accessed, and so should only represent purely sequential code. Lines defining named doors are defined as any line that isn't a generic door definition or a comment. Each line defining a named door must start with a door name followed by a whitespace character or a colon (:) and further followed by the code to execute at that door. All door names are case sensitive, as well as no two doors may share the same name.

All door definitions must have code defined with them. Each line of code is a series of statements or statement constructs separated by whitespace characters or colons. In statement constructs that have multiple words/values, each word or value is also separated by whitespace characters or colons. To group a series of characters into a single word/value even if they contain whitespace characters or colons, the characters must be quoted with either single quotes ('), or double quotes ("). Quotes are not interpreted as part of the code, rather as separators. To include a quote in a section of code, it must be between two quotes of the opposite type (eg. "Th'is has a word with a single quote in it"). Lines are interpreted from left to right. Each line can be divided into one or more subsections. The statements also, choose and each splits the subsection in which they reside into two subsections: one for statements on the left side and one for statements on the right side. These statements will be discussed in greater depth in the statement reference section.

Each subsection has a temporary value that is present only while the subsection is being executed. The temporary value is initialized to zero before executing the subsection. At the end of the subsection, if the at statement appeared in the subsection, the temporary value will be written into the transient array at the index specified by the at statement. This is explained in the statement reference section. The temporary value is changed by statements which are described as emiting values. The temporary value is not changed by statements that are not explicitly specified to emit a value.

When a subsection is to be skipped, all subsections of that subsection are skipped as well. If a subsection is to be repeated, all subsections of that subsections are repeated as well. Subsections may contain any number of subsections or statements per subsection.

Note that most statements will not raise errors. Everything will be attempted to be executed and invalid syntax or operations can cause parts of lines to fail to execute or undefined behavior when they do execute. How the parser and interpreter handle errors in the code or during execution is implementation defined.

Statement Reference

In all these examples, the case of the statements do not matter; however literal values, door names and group tags are all case sensitive. The following notations are used while outlining the syntax of various statements:

  • A hash (#) represents the name of a door.
  • A dollar sign ($) represents a numeric value to be read. A numeric value represents the literal value of the number when the number if prefixed with a percent sign (%). If the number is not prefixed, it represents the value of the transient array value at the specified index. Lastly, a numeric value can also represent the value of the transient array value at the index of the value of the transient array value specified by the number when the number is prefixed with an AT symbol (@). This last type of numeric value is equivalent to pointer dereferencing in C.
  • An ampersand (&) represents the index of the transient array value to be written. Literal numeric values represent the index, whereas numeric values prefixed with an AT symbol represent the index of the transient array value of which to retrieve the index from.
  • A power symbol (^) represents a group tag.
  • A triple underscore (___) represents a literal value.
Statement/Construct Syntax Description
also Divides the current subsection of the line into two more subsections, each of which are executed separately and sequentially.
kill Throws a hard error from within the interpreter and exits the program immediately with an error message.
open # Changes the state of the specified door to open.
close # Changes the state of the specified door to closed.
switch # Changes the state of the specified door to the reverse of what is was.
check # Emits the value 1 if the specified door is open, otherwise emits the value 0.
map # to # Maps the door specified in the first parameter to the door specified by the second parameter.
map # to # with # Maps the door specified in the first parameter to the door specified by the second parameter, forcing the execution of the code at the door specified in the third parameter during transit between them.
at & Causes the last emited value in the current subsection to be written to a transient array value at the end of the current subsection.
choose full $ Executes the following subsection of code only if the value in the first parameter is not zero.
choose empty $ Executes the following subsection of code only if the value in the first parameter is zero.
learn $ Emits the value read the input array at the index specified by the value of the first parameter.
give $ to $ Writes the value of the first parameter into the output array at the index specified by the value of the second parameter.
publish Writes all data in the output array to the console and empties the output array.
make & into $ Writes the value of the second parameter to a transient array value.
pile $ Pushes the value of the first parameter onto the space stack.
grab Emits the value of the element popped from the space stack.
size Emits the value of the size of the space stack.
join $ and $ Emits the value of the value of the first parameter plus the value of the second parameter.
differ $ and $ Emits the value of the value of the first parameter minus the value of the second parameter.
clones $ and $ Emits the value of the value of the first parameter times the value of the second parameter.
fits $ and $ Emits the value of the value of the first parameter divided by the value of the second parameter.
produce $ and $ Emits the value of the value of the first parameter to the power of the value of the second parameter.
similar $ and $ Emits the value of the value of the first parameter bitwise AND the value of the second parameter.
either $ and $ Emits the value of the value of the first parameter bitwise OR the value of the second parameter.
change $ and $ Emits the value of the value of the first parameter bitwise XOR the value of the second parameter.
back $ by $ Emits the value of the value of the first parameter bitwise shifted left the value of the second parameter.
forth $ by $ Emits the value of the value of the first parameter bitwise shifted right the value of the second parameter.
anti $ Emits the value of the bitwise NOT of the value of the first parameter.
more $ than $ Emits the value 1 if the value of the first parameter is greater than the value of the second parameter.
less $ than $ Emits the value 1 if the value of the first parameter is less than the value of the second parameter.
same $ as $ Emits the value 1 if the value of the first parameter is the same as the value of the second parameter.
shape ___ Emits the literal integer in the first parameter.
group ^ from $ to $ Creates a group with the tag specified by the first parameter from the transient value array index specified by the value of the first parameter to the transient value array index specified by the value of the second parameter. Each element in the specified range is counted ("per 1").
group ^ from $ to $ per $ Creates a group with the tag specified by the first parameter from the transient value array index specified by the value of the first parameter to the transient value array index specified by the value of the second parameter, affecting only one element per the number of elements specified by the value of the third parameter.
split ^ Destroys a group tag. The elements in the group are not changed.
affect ^ into ___ Copies each character from the literal string in the second parameter into the group at the tag specified by the first parameter. The copy is bounded both by the size of the string and the size of the group.
each ^ into & task Iterates through each element in the group specified by the tag specified by the first parameter, writing the value of the current element into the transient value specified by the second parameter and executing the subsection following it once per element.

Sample Programs

CAT Program

init map run2 to run1 also map run1 to -1 also open run2 also at 4 shape 1
run1 at 0 learn 1 also at 1 join 1 and 4 also at 2 less 0 than 3 also choose full 2 open run1
run2 give 0 to 3 also publish

Hello, world!

~group hello from %2 to %14 also affect hello into "Hello, world!" also each hello into 0 task give 0 to 1 also at 1 join 1 and %1
~publish also split hello

Fibonacci Sequence

~shape 0 at 0 also at 1 shape 1
~map chk to top also open chk
top at 2 join 0 and 1
~make 0 into 1 also make 1 into 2
~at 3 shape "0"
~make 4 into 0
~at 5 more 0 than %999999 also choose full 5 at 6 fits 4 and %1000000 also at 7 clones 6 and %1000000 also at 4 differ 4 and 7 also at 6 join 6 and %48 also give 6 to 3 also at 3 join 3 and %1
~at 5 more 0 than %99999 also choose full 5 at 6 fits 4 and %100000 also at 7 clones 6 and %100000 also at 4 differ 4 and 7 also at 6 join 6 and %48 also give 6 to 3 also at 3 join 3 and %1
~at 5 more 0 than %9999 also choose full 5 at 6 fits 4 and %10000 also at 7 clones 6 and %10000 also at 4 differ 4 and 7 also at 6 join 6 and %48 also give 6 to 3 also at 3 join 3 and %1
~at 5 more 0 than %999 also choose full 5 at 6 fits 4 and %1000 also at 7 clones 6 and %1000 also at 4 differ 4 and 7 also at 6 join 6 and %48 also give 6 to 3 also at 3 join 3 and %1
~at 5 more 0 than %99 also choose full 5 at 6 fits 4 and %100 also at 7 clones 6 and %100 also at 4 differ 4 and 7 also at 6 join 6 and %48 also give 6 to 3 also at 3 join 3 and %1
~at 5 more 0 than %9 also choose full 5 at 6 fits 4 and %10 also at 7 clones 6 and %10 also at 4 differ 4 and 7 also at 6 join 6 and %48 also give 6 to 3 also at 3 join 3 and %1
~at 5 more 0 than %-1 also choose full 5 at 6 fits 4 and %1 also at 7 clones 6 and %1 also at 4 differ 4 and 7 also at 6 join 6 and %48 also give 6 to 3 also at 3 join 3 and %1
~give %10 to 3 also publish
chk at 3 less 0 than %1000000 also choose empty 3 close chk

Greeter Program

~group query from %10 to %28 also affect query into "What is your name? "
~group sayhi from %30 to %35 also affect sayhi into "Hello "
~at 0 shape 0 also each query into 1 task give 1 to 0 also at 0 join 0 and %1
~publish
~map iseof to readname also open iseof also at 0 shape 0
readname at 2 learn 0 also pile 2 also at 0 join 0 and %1
iseof at 2 same 2 as %10 also choose full 2 close iseof
~at 0 shape 0 also each sayhi into 1 task give 1 to 0 also at 0 join 0 and %1
~publish
~map isempty to writename also open isempty
writename at 2 grab also at 0 size also give 2 to 0
isempty at 0 same 0 as %0 also choose full 0 close isempty
~publish

Deadfish Interpreter

!Reads only one instruction per line
!The current character is put into 1 from the location at 2 and the current value is stored in 0
~map bottom to top also open bottom
~map chkout to skipout
~map chklf to skiplf
~map looplf to chklf also open looplf
top give %62 to %0 also give %62 to %1 also give %32 to %2 also publish
!Read input character into 1
~at 1 learn 2 also at 2 join 2 and %1
!Decrement instruction
~at 3 same 1 as %100 also choose full 3 at 0 differ 0 and %1
!Increment instruction
~at 3 same 1 as %105 also choose full 3 at 0 join 0 and %1
!Output instruction
chkout at 3 same 1 as %111 also choose empty 3 open chkout
	~at 3 shape 0 also make 4 into 0
	~at 5 more 0 than %999999999 also choose full 5 at 6 fits 4 and %1000000000 also at 7 clones 6 and %1000000000 also at 4 differ 4 and 7 also at 6 join 6 and %48 also give 6 to 3 also at 3 join 3 and %1
	~at 5 more 0 than %99999999 also choose full 5 at 6 fits 4 and %100000000 also at 7 clones 6 and %100000000 also at 4 differ 4 and 7 also at 6 join 6 and %48 also give 6 to 3 also at 3 join 3 and %1
	~at 5 more 0 than %9999999 also choose full 5 at 6 fits 4 and %10000000 also at 7 clones 6 and %10000000 also at 4 differ 4 and 7 also at 6 join 6 and %48 also give 6 to 3 also at 3 join 3 and %1
	~at 5 more 0 than %999999 also choose full 5 at 6 fits 4 and %1000000 also at 7 clones 6 and %1000000 also at 4 differ 4 and 7 also at 6 join 6 and %48 also give 6 to 3 also at 3 join 3 and %1
	~at 5 more 0 than %99999 also choose full 5 at 6 fits 4 and %100000 also at 7 clones 6 and %100000 also at 4 differ 4 and 7 also at 6 join 6 and %48 also give 6 to 3 also at 3 join 3 and %1
	~at 5 more 0 than %9999 also choose full 5 at 6 fits 4 and %10000 also at 7 clones 6 and %10000 also at 4 differ 4 and 7 also at 6 join 6 and %48 also give 6 to 3 also at 3 join 3 and %1
	~at 5 more 0 than %999 also choose full 5 at 6 fits 4 and %1000 also at 7 clones 6 and %1000 also at 4 differ 4 and 7 also at 6 join 6 and %48 also give 6 to 3 also at 3 join 3 and %1
	~at 5 more 0 than %99 also choose full 5 at 6 fits 4 and %100 also at 7 clones 6 and %100 also at 4 differ 4 and 7 also at 6 join 6 and %48 also give 6 to 3 also at 3 join 3 and %1
	~at 5 more 0 than %9 also choose full 5 at 6 fits 4 and %10 also at 7 clones 6 and %10 also at 4 differ 4 and 7 also at 6 join 6 and %48 also give 6 to 3 also at 3 join 3 and %1
	~at 5 more 0 than %-1 also choose full 5 at 6 fits 4 and %1 also at 7 clones 6 and %1 also at 4 differ 4 and 7 also at 6 join 6 and %48 also give 6 to 3 also at 3 join 3 and %1
	~give %10 to 3
	~publish
skipout close chkout
!Square instruction
~at 3 same 1 as %115 also choose full 3 at 0 clones 0 and 0
!Check for overflow/underflow
~at 3 same 0 as %256 also choose full 3 at 0 shape 0
~at 3 less 0 than %0 also choose full 3 at 0 shape 0
!Loop until a newline
chklf at 3 same 1 as %10 also choose full 3 open chklf
looplf at 1 learn 2 also at 2 join 2 and %1
skiplf close chklf
!Back to top
bottom also

Truth Machine

~map condition to -1 also map loop to top also open loop
~at 0 learn %0
condition at 1 same 0 as %49 also choose empty 1 give %48 to %0 also publish also open condition
top give %49 to %0
loop publish

About The Reference Interpreter

The reference interpreter included in the External resources section comes with all the above sample programs. It is fully compliant with the "Doorspace 1.0" standard. The interpreter is named after the alternate name of the language, Qugord. The reference interpreter is called from the command line and will display a help screen explaining its usage when it is called with no parameters. The warnings feature and the feature to flush output on program exit are not part of the standard, but are included for debugging purposes. The interpreter follows the Doorspace philosophy by suppressing errors, even when source files cannot be loaded.

External resources

Reference interpreter and sample programs, requires either the .NET framework on Windows or Mono on Linux to run