Wordy

From Esolang
Jump to navigation Jump to search

Wordy is a wip esoteric programming language inspired by .Gertrude and designed at 3am the week before finals.

The language is designed such that any set of period, question-mark or excamation-point separated sentences is valid source code. Each sentence mapping to one of a couple dozen instructions. The instruction that a sentence represents is found by finding the average word length in that sentence (rounded to the nearest integer) and then counting the number of words above and below that average. The ratio [words above average]/[words below average] is looked up in the below table. 2/3 maps to the same instruction as 4/9 (VALUE) and any ratio not explicitly mapped to an instruction is a NOP.

ratio command ratio command
13/7 ASSIGN 7/3 LESS?
2/3 VALUE 9/5 GREATER?
0/1 LITERAL 11/17 OR
2/1 LABEL 13/3 AND
1/1 GOTO 5/13 NOT
1/2 ADD 4/7 INNUM
5/9 SUBTRACT 5/2 INCHAR
3/4 MULTIPLY 15/14 OUTNUM
4/1 DIVIDE 3/7 OUTCHAR
1/4 MODULO 1/0 RAND
2/9 ABS 5/3 EXIT
1/5 EQUAL? --- NOP

These ratios are not final as I would like to do some analysis on text to see what common and uncommon ratios are so I can map more important instructions (like GOTO) to the more common ratios.

Walking through steps to interpret some text

Say this was the source being interpreted:

I'd just like to interject for a moment. What you're referring to as Linux, is
in fact, GNU/Linux, or as I've recently taken to calling it, GNU plus Linux.
Linux is not an operating system unto itself, but rather another free component
of a fully functioning GNU system made useful by the GNU corelibs, shell
utilities and vital system components comprising a full OS as defined by POSIX.

For each sentence, count the size of each word (ignore punctuation like ' / - " . so "I'd" is length two and "GNU/Linux" is length 8)

2 4 4 2 9 3 1 6.
4 5 9 2 2 5 2 2 4 8 2 2 3 8 5 2 7 2 3 4 5.
5 2 3 2 9 6 4 6 3 6 7 4 9 2 1 5 11 3 6 4 6 2 3 3 8 5 9 3 5 6 10 10 1 4 2 2 7 2 5.

For each sentence, find the average word length (round to nearest integer), count the number of words with length above, below, and equal to the average.

avg 4, above 2, below 4, exact 2.
avg 4, above 8, below 10, exact 3.
avg 5, above 15, below 19, exact 5.

To translate this into instructions now, just find the ratio of above/below for each sentence.

2/4 8/10 15/19

2/4 maps to the ADD instruction (1/2). 8/10 and 15/19 both map to NOP since they don't map exactly to another instruction.

ADD NOP NOP

ADD takes two arguments. NOP takes no arguments and results in 0.

ADD 0 0

0 + 0 is 0

0

Using this method, any text could be interpreted with Wordy and would produce a valid program. One of the core ideas in designing Wordy was to make it as safe as possible. Part of the spec is that any undefined behavior, while left up to the implementer, must not crash or create errors during interpretation. Every possible program is valid.

Built in functions

Here's the expected (BNF-like) syntax for the pseudocode/wimpmode:

<wordy-program> ::= <expression>*

<expression> ::= <zero-arg-op> 
<zero-arg-op> ::= "NOP" | "INNUM" | "INCHAR" | "EXIT"

<expression> ::= <one-arg-op> <expression> 
<one-arg-op> ::= "VALUE" | "LABEL" | "GOTO" | "ABS" | "OUTNUM" | "OUTCHAR" | "RAND" 

<expression> ::= <two-arg-op> <expression> <expression> 
<two-arg-op> ::= "ASSIGN" | "ADD" | "SUBTRACT" | "MULTIPLY" | "DIVIDE" | "MODULO" | "EQUAL?" | "LESS?" | "GREATER?" | "OR" | "AND" | "NOT" 

<expression> ::= "LITERAL" <integer>
<integer> ::= ("-" | "+" | "")<digit>+
<digit> ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
  • ASSIGN VAR_ID VALUE: sets variable VAR_ID to VALUE, creates variable VAR_ID if necessary, results in VALUE
  • VALUE VAR_ID: Results in the value of variable VAR_ID. If there is no variable VAR_ID, NOP
  • LITERAL VALUE: Results in the literal value following this instruction. This value is parsed differently from other sentences. Instead of the value being the ratio of [larger than average words]/[smaller than average words], this value is the number of words of average length. Note that it is not possible to have a literal negative.
  • LABEL ID: A label with id ID is defined. A label with the same ID as a previously defined label overwrites the previous one. Putting a label in the middle of an expression is completely valid (for example: ADD LABEL LITERAL 1 OR VALUE NOP GOTO LITERAL 1). For a label to become defined, execution must reach the LABEL instruction. Results in 1.
  • GOTO ID: Jump to label with id ID. If there is no label ID, NOP
  • ADD VALUE1 VALUE2: Results in VALUE1 + VALUE2
  • SUBTRACT VALUE1 VALUE2: Results in VALUE1 - VALUE2
  • MULTIPLY VALUE1 VALUE2: Results in VALUE1 * VALUE2
  • DIVIDE VALUE1 VALUE2: Results in VALUE1 / VALUE2 (integer division)
  • MODULO VALUE1 VALUE2: Results in VALUE1 % VALUE2
  • ABS VALUE: Results in the absuloute value of VALUE
  • EQUAL? VALUE1 VALUE2: Results in VALUE1 == VALUE2 (0: false, 1: true)
  • LESS? VALUE1 VALUE2: Results in VALUE1 < VALUE2
  • GREATER? VALUE1 VALUE2: Results in VALUE1 > VALUE2
  • OR VALUE1 VALUE2: VALUE1 || VALUE2 (true: 1 or greater, false: 0 or less). results in VALUE1 if VALUE1 is 1 or greater, otherwise results in VALUE2
  • AND VALUE1 VALUE2: VALUE1 && VALUE2. results in VALUE1 if VALUE1 is 0 or less, otherwise results in VALUE2
  • NOT VALUE: !VALUE. 0 if VALUE is 1 or greater, 1 otherwise
  • INNUM: reads a number from stdin (prefix '-' indicates negative value). what happens when it encounters a non-number on stdin is undefined however it definitely won't crash.
  • INCHAR: reads a single character from stdin, value of INCHAR is unicode id of character read. results in 0 if eof read
  • OUTNUM VALUE: outputs value as a number to stdout, results in the value output
  • OUTCHAR VALUE: outputs value as a unicide character with VALUE as unicode id to stdout, results in the value output
  • RAND VALUE: results in a random number range [0 VALUE] inclusive (a range [0 -5] is equilivant to the range [-5 0])
  • EXIT: stops program execution
  • NOP: any ratio other than those that map to instructions or a GOTO to a non-existent label. results in 0

Notes

  • Note that LITERAL is the only way to specify a literal value either in variable names or as LABELs or as targets for GOTOs, everything that takes arguments--aside from LITERAL--takes the argument in the form of the result of another expression. This is especially useful in LABELs and GOTOs as the expression GOTO RAND INCHAR is perfectly valid (goto the label with the id matching a random integer from 0 to the value of an input character).
  • Whether 0/0 results in RAND, LITERAL, GOTO, or NOP is undefined.
  • A GOTO as an argument to another instruction results in either 0 of there is no LABEL with the correct ID to go to (as if it were a NOP) or in the value of the label jumped to (1). If a GOTO is the first argument to an instruction that takes more than one argument, the second argument is the next expression after the LABEL jumped to.
  • If program execution reaches the end of the last sentence, there is an implicit EXIT.
  • There is no need for conditionals like IF as these could be built using OR and AND. IF COND1 THEN E1 ELSE E2 can be expressed as OR AND COND1 E1 E2 if E1 will always evaluate to true,or OR AND COND1 OR E1 LITERAL 1 E2 if E1 might evaluate to false.

Example cat program

Honestly this is very easy, much more simple than some.  
It is named after the Unix command cat, although this command is actually more powerful.
"I know what it means well enough when I find a thing," said the Duck, "it's generally a frog or a worm."
In both cases the manufacturer is one and the same Jew.
In the beginning there was no sense of heuristic algorithms with which they wrote.
Weirdly thruvian melodics are not terribly complex.
This is harder than I thought.
We particularly cannot permit any individual State within the nation, and the Reich which represents it, sovereign power and independent State rank.
It dried up any trickle of pity for him that may have remained in the pirates infuriated breast.
Cats are fluffy but don't fuck with them unless you're ready for the consequences.

The pseudocode for this is:

LABEL NOP ASSIGN NOP OUTCHAR INCHAR GOTO NOT VALUE NOP

This program takes advantage of NOP resulting in 0 by using it as shorthand for LITERAL 0.

Here is a hello world program and fizzbuzz.

Brainfuck to Wordy

The following rules will translate a brainfuck program into Wordy pseudocode:

start of file -> LABEL LITERAL 0

> -> AND VALUE LITERAL 0 ASSIGN LITERAL 0 ADD VALUE LITERAL 0 LITERAL 1
< -> AND VALUE LITERAL 0 ASSIGN LITERAL 0 SUBTRACT VALUE LITERAL 0 LITERAL 1
+ -> AND VALUE LITERAL 0 ASSIGN VALUE LITERAL 0 ADD VALUE VALUE LITERAL 0 LITERAL 1
- -> AND VALUE LITERAL 0 ASSIGN VALUE LITERAL 0 SUBTRACT VALUE VALUE LITERAL 0 LITERAL 1
. -> AND VALUE LITERAL 0 OUTCHAR VALUE VALUE LITERAL 0
, -> AND VALUE LITERAL 0 ASSIGN VALUE LITERAL 0 INCHAR
[ -> AND VALUE LITERAL 0 OR VALUE VALUE LITERAL 0 GOTO LITERAL x
     OR VALUE LITERAL 0 LABEL SUBTRACT LITERAL 0 LITERAL x
] -> AND VALUE LITERAL 0 AND VALUE VALUE LITERAL 0 GOTO SUBTRACT LITERAL 0 LITERAL x
     OR VALUE LITERAL 0 LABEL LITERAL x
     (where 'x' is 1 for the first [] pair, 2 for the second, etc)

end of file -> AND VALUE LITERAL 0 EXIT
               ASSIGN LITERAL 0 LITERAL 1
               GOTO LITERAL 0

This is a right-infinite tape version of brainfuck where reading in eof results in 0. And it shows that Wordy is Turing Complete as restricting brainfuck to a right-infinite tape does not affect its computational class.

External resources