Dark
Dark is an Esoteric programming language by user:David.werecat which is designed to be inherently evil.
Instructions
Introduction
Dark is a language based on manipulating entire worlds and dimensions to achieve goals and to build the best torturous reality possible. Each program is read as a series of commands to objects with the goal to twist each world as much as possible. Due to its poorly designed documentation, it's likely that even the descriptions of the language are inherently evil.
Language Basics
note: In all code examples, whenever {} brackets are used, they provide information about part of a command (eg. {objname}${function}
would denote a line containing an object name followed by a colon, followed by a function name; an example of such a line could be something$action
)
The language is based entirely on objects. At the start of every program, an object of type HELL must be declared (syntax: +{objname} hell
). This object allows the creation and manipulation of other objects, and is the basis for the program. An object is used by specifying the object name and the function to run on that object (syntax: {objname}${function} {parameters}
). All lines of the program with exception to the first line should be in this format, unless the line is either a blank line or a comment. Commented lines must start with a pipe symbol (|) and end with another pipe symbol. All object names are case sensitive.
Whenever a syntax error occurs, the program's sanity decreases by 1. The program's sanity starts at 100. If the program's sanity reaches zero, the interpreter goes insane. Whenever a general error occurs, the interpreter prints out the line "Murphy's Law is working correctly.".
When the program ends, any active objects will be dealt with and appropriate error messages will be output to the console detailing the cleanup process. As such it is recommended to destroy all objects before the program ends. Variables are also dealt with similarly.
Specifics
All objects are stored in a memory area known as the CONTROL_SPACE, separate from all variables. Variables are local to each manipulator and are stored in a memory location known as the WORLD_BLOCK. There is a global queue of strings known as the VOICELIST, which stores the values of signs.
Reference Interpreter
The reference interpreter is fully compliant with the Dark programming language. It accepts multiple source files are command line arguments. Each input file is interpreted separately and sequentially. Options may also be tweaked using the command line. Command line arguments only affect the source files after the argument. Possible arguments are:
Argument | Description |
---|---|
-wimpmode |
Turns on wimpmode. This is not part of the official specification and is off by default. In wimpmode variables don't accumulate corruption and default error handlers are replaced with meaningful error messages. |
-strict |
Turns off wimpmode. This ensures that the interpreter runs compliant to the full standard (except for the TRACE mode). |
-traceon |
Taking the advice of Emiya Shirou, you will see everything that happens inside the interpreter. All lines are printed as they are executed, and all error handlers are replaced as in wimpmode. This is off by default, and will be removed in future versions of the interpreter. |
-traceoff |
Turns off trace mode. |
-stripcode |
Allows the interpreter to remove comments and empty lines upon loading a source file. This is on by default, and will result in better performance. The actual source file is not modified. While in wimpmode, this will cause invalid line numbers to be printed with the error messages. |
-keepextra |
Forces the interpreter to keep all extra code, such as comments and empty lines. Only useful for debugging. |
-breakonerror |
Causes the interpreter to stop execution and wait for a keypress after each error message. Again, this is off by default and will only affect wimpmode. |
-continueonerror |
Does not stop when error messages are output. The default behavior of the interpreter. |
The reference interpreter also complies to undocumented parts of the Dark standard.
Object Types
HELL
The hell object is the base object of the program, declared in the first line of code. There may only be one HELL object per program. A HELL object accepts the following commands:
Syntax | Description |
---|---|
{object}$twist {objtype} {objname} |
Creates a new object. |
{object}$consume {objname} |
Destroys an object. |
{object}$empty |
Destroys all objects. |
{object}$break |
Throws an error to the interpreter. The reference interpreter will print a simple error message when this function is issued. |
{object}$break {errortext} |
Throws an error to the interpreter with customized error text. |
{object}$apocalypse |
Immediately ends the program. All active objects are destroyed as usual. |
MANIPULATOR
A manipulator is an object that allows the management of variables. A manipulator can hold a maximum of 1024 variables. When a variable is freed, it leaves decay behind. This decay must be cleared using the VOID function to reopen the variable spot to new variables. There are several variable mechanics. Variables with the same name as another variable in another manipulator can be defined, although when used can cause problems. A manipulator can only manipulate its own variables, therefore variable operations across manipulators must use a SIGN object as temporary storage. All variables are unsigned integers that can be either 8,16,32 or 64 bits long. When variables are not used for over 65536 cycles, they start to accumulate corruption. Corruption flips a single bit in the variable when it occurs. Each variable must have a disposition. If a variables with dispositions that are more than one apart are used in a function, they conflict and the variables are killed. Variables must also be defined as either a SERVANT or a MASTER. A servant must select a master variable. When the master dies, all servant variables attached to that master also die. This is useful for grouping and mass killing variables. A manipulator object accepts the following functions:
Syntax | Description |
---|---|
{object}$manufacture {varname} {disposition} {size} master |
Creates a new master variable. |
{object}$manufacture {varname} {disposition} {size} servant {mastername} |
Creates a new servant variable with a given master. The master can also be nonexistant, in which case the variable is considered lost and is treated as a master variable that cannot have servants. |
{object}$suicide {varname} |
Forces a variable to kill itself, freeing it (remember though that it will leave decay). |
{object}$kill {varname} |
Kills a variable. The same as the suicide function. |
{object}$void |
Cleans up all decay. This ensures that all open variable spots are usable. |
{object}$genocide {disposition} |
Kills all variables of a specified disposition. Remember, this only affects the variables directly under the manipulator's control and leaves decay just like all other functions. |
{object}$omnicide |
Kills all variables. Works like genocide. |
{object}$chaos {varname} |
Sets a variable to a random value. Uses the Global Chaos Generator. |
{object}$set {varname} {value} |
Sets a variable to a given value. The value may be another variable from the same manipulator or a number. |
{object}$add {varname} {val1} {val2} |
Sets a variable to the sum of two values. Once again, values may be either variables or numbers. |
{object}$subtract {varname} {val1} {val2} |
Sets a variable to the difference of two values. |
{object}$multiply {varname} {val1} {val2} |
Sets a variable to the product of two values. |
{object}$divide {varname} {val1} {val2} |
Sets a variable to the quotient of two values. |
ENTROPY
An entropy object allows program flow control. Labels may be nested, and will not be redefined inside other labels unless they are undefined. Choices may be nested, but each nested choice must be from a different entropy object. Accepted functions are:
Syntax | Description |
---|---|
{object}$choice {val1} {comparator} {val2} |
Compares two values and executes the enclosed block if the condition is true. Works like an IF in most programming languages. The values can be either variables or numeric values; the variables can come from any manipulator objects. Accepted comparators are: = == > < >= <= != <> .
|
{object}$balance |
Defines the code block to run if the choice condition is false. Works like an ELSE in most programming languages. |
{object}$reprogram |
Ends the previous choice or balance block. Works like an ENDIF in most programming languages. |
{object}$corpse {lblname} |
Defines a label. If a label is already defined, the previous definition is kept. Some interpreters may cause a general error if a label already exists, therefore it is good practice to undefine nested labels and redefine them each iteration. |
{object}$stumble {lblname} |
Causes execution to jump to a previously defined corpse (label). |
{object}$illusion {lblname} |
Undefines a corpse. The corpse then can be properly redefined later. |
STALKER
A stalker object controls all basic IO functions. A stalker starts uninitialized, it must be initialized using the stalk function. If a stalker is not initialized, any attempts to perform IO will result in depressing error messages to be written to the console. A stalker has two modes, DISTANT (default) and PERSONAL. While in distant mode, all output is written to a buffer and must be flushed to the console using the paracusia function. Switching modes will not cause the buffer to be flushed. When a stalker is in personal mode, all output is written to the console instantly.
Syntax | Description |
---|---|
{object}$stalk |
Starts the stalker. Required in order to use the other functions. |
{object}$control {varname} |
Causes the given variable to accept control, which sets the variable to the character code of the character read from the console. |
{object}$control # {varname} |
Causes the given variable to accept control, which sets the variable to the value of the typed number. Invalid typing will cause general errors. |
{object}$action {varname} |
Causes the given variable to take action, which causes a character with the character code equal to the value of the variable to be written to the console. |
{object}$action # {varname} |
Causes the given variable to take action, which causes the numeric value of the variable to be written to the console. |
{object}$echo |
Removes a value from the VOICELIST and writes it to the console. |
{object}$distant |
Switches the object to DISTANT mode. |
{object}$personal |
Switches the object to PERSONAL mode. |
{object}$paracusia |
Flushes the buffer to the console. The buffer is reset to an empty value. |
SIGN
Sign objects are containers for strings. A sign is a representation of a queue of character codes. Signs accept the following functions:
Syntax | Description |
---|---|
{object}$scrawl {varname} |
Appends the character value of a variable to the current message. |
{object}$scrawl # {varname} |
Appends the numerical value of a variable to the current message. |
{object}$scrawl " {string} |
Appends a literal string to the current message. |
{object}$tear |
Removes the first character from the message. |
{object}$tear {count} |
Removes the first {count} characters from the message. |
{object}$tear * |
Removes all characters from the message. |
{object}$observe {varname} |
Sets a variable to the value of the first character in the message. |
{object}$steal {varname} |
Sets a variable to the value of the first character in the message end erases the character from the message. |
{object}$read |
Enqueues the current message in the VOICELIST, then erases the current message. |
{object}$read ~ |
Enqueues the current message in the VOICELIST without erasing the current message. |
Sample Programs
CAT Program
+deadcat hell deadcat$twist stalker killer deadcat$twist manipulator person deadcat$twist entropy fate killer$stalk killer$personal person$manufacture weapon 0 8 master fate$corpse violence killer$control weapon killer$action weapon fate$stumble violence fate$illusion violence person$kill weapon deadcat$consume person deadcat$consume killer deadcat$consume fate deadcat$apocalypse
Hello, world!
+hello hell hello$twist sign hws hello$twist stalker io io$stalk io$personal hws$scrawl " Hello, world! hws$read io$echo hello$empty hello$apocalypse
Fibonacci Sequence
+fib hell fib$twist stalker creep fib$twist entropy cruelty fib$twist manipulator darkone creep$stalk creep$personal darkone$manufacture new 0 64 master darkone$manufacture this 0 64 servant new darkone$manufacture last 0 64 servant new darkone$manufacture ltr 0 8 master darkone$set this 1 cruelty$corpse fate darkone$add new last this darkone$set last this darkone$set this new creep$action # this cruelty$choice this <= 9223372036854775807 darkone$set ltr 44 creep$action ltr darkone$set ltr 32 creep$action ltr cruelty$stumble fate cruelty$reprogram darkone$omnicide darkone$void fib$empty fib$apocalypse
General Language/Interpreter Test
+test hell |Initialize objects| test$twist manipulator overseer test$twist manipulator leader test$twist entropy fate test$twist entropy path test$twist stalker spy test$twist sign bbs test$twist sign keep_out |Define a few variables| overseer$manufacture politician 0 64 master overseer$manufacture person1 0 32 servant politician overseer$manufacture person2 0 16 servant politician overseer$manufacture person3 0 8 servant none leader$manufacture person1 0 16 master leader$manufacture test1 0 32 servant politician leader$manufacture test2 0 32 servant test3 leader$manufacture test3 0 32 servant test2 leader$manufacture hater 5 8 master leader$manufacture hated 9 8 master |Check that stalker is not initialized| |Should give depressing errors| spy$action politician spy$control politician |Initialize stalker| spy$stalk |Test io modes with fibonacci series| |Should print Press any key to continue..., then will display the fibonacci series| spy$distant overseer$set person1 10 leader$set test1 0 leader$set test2 1 bbs$scrawl " , fate$corpse fibonacci_1 leader$add test3 test1 test2 leader$set test1 test2 leader$set test2 test3 spy$action # test1 bbs$read ~ spy$echo fate$choice test1 < 1000000 fate$stumble fibonacci_1 fate$reprogram fate$illusion fibonacci_1 bbs$tear * bbs$scrawl " Press any key to continue... bbs$read spy$personal spy$echo spy$action person1 spy$distant spy$control test1 spy$action person1 spy$paracusia |Test that choices work and nested choices are allowed| |Should display True,True,False,True,True,True,False| spy$personal bbs$scrawl " True bbs$scrawl person1 keep_out$scrawl " False keep_out$scrawl person1 fate$choice 0 = 0 bbs$read ~ spy$echo fate$reprogram fate$choice 0 = 0 bbs$read ~ spy$echo fate$balance keep_out$read ~ spy$echo fate$reprogram fate$choice 0 <> 0 bbs$read ~ spy$echo fate$balance keep_out$read ~ spy$echo fate$reprogram fate$choice person2 = person3 path$choice person2 = 0 bbs$read ~ bbs$read ~ spy$echo spy$echo path$balance bbs$read ~ keep_out$read ~ spy$echo spy$echo path$reprogram fate$balance path$choice person2 = 0 keep_out$read ~ bbs$read ~ spy$echo spy$echo path$balance keep_out$read ~ keep_out$read ~ spy$echo spy$echo path$reprogram fate$reprogram fate$choice person2 = person3 path$choice person2 = 1 bbs$read ~ bbs$read ~ spy$echo spy$echo path$balance bbs$read ~ keep_out$read ~ spy$echo spy$echo path$reprogram fate$balance path$choice person2 = 1 keep_out$read ~ bbs$read ~ spy$echo spy$echo path$balance keep_out$read ~ keep_out$read ~ spy$echo spy$echo path$reprogram fate$reprogram bbs$tear * keep_out$tear * |Test Randomization| overseer$chaos person2 spy$action # person2 spy$action person1 |Test getting rid of master variable| overseer$suicide politician |Test garbage collect| overseer$void |Test sign functionality| |Shoud output ello, world!,world!,w,orld!,orld!,| leader$set person1 10 bbs$tear * bbs$scrawl " Hello, world! bbs$scrawl person1 bbs$tear bbs$read ~ spy$echo bbs$tear 6 bbs$read ~ spy$echo bbs$observe test1 spy$action test1 spy$action person1 bbs$steal test1 bbs$read ~ spy$echo bbs$read spy$echo bbs$read spy$echo |Test disposition conflict| leader$set hater hated |Test murphy's law| spy$action /THIS/IS/NOT/A/VALID/VARIABLE/NAME |Cleanup| test$twist manipulator final final$manufacture temporary 0 8 master final$empty test$consume final test$consume spy test$consume fate test$consume keep_out leader$suicide test3 |Should show overseer melting person3, overseer dying, leader melting person1 test1 test2, leader dying, path, bbs|