Twocode

From Esolang
Jump to navigation Jump to search
Twocode
Paradigm(s) imperative
Designed by User:Fergusq
Appeared in 2014
Dimensions two-dimensional
Computational class Turing complete
Reference implementation Doublecode
Influenced by Befunge, SNUSP
File extension(s) .dcode

Twocode is a one-dimensional esoteric language with two-dimensional control structures. It was created by User:Fergusq in 2014. Language belongs to the category of visual programming languages and was designed to offer an alternative, visual GOTO statement.

Twocode

Twocode is a two-dimensional language like SNUSP. It contains two-dimensional instruction series and onecode blocks. It is used to implement flow-control.

Instruction Meaning
/ If going to north, go east, if to east, go north. If going to south, go west, if to west, go south.
\ If going to south, go east, if to east, go south. If going to north, go west, if to west, go south.
v Go south.
^ Go north.
> Go east.
< Go west.
Z If accumulator contains 0 continue forward, otherwise works like /.
S If accumulator contains 0 continue forward, otherwise works like \.
# Halt.

Debug commands:

Command Meaning
n Prints accumulator as a number.
c Prints accumulator as a character.
f Flushes output stream.

Example: an infinite loop

>===v
|   |
^===<

Twocode and gotos

Twocode is used in simillar manner to the GOTO statement. For example, a simle truth-machine like the following:

{getc()='0'}=S={putc('0')}=#
             |
             >={putc('1')}=\
             \=============/

... can be translated to Onecode+Goto code:

if(getc()='0') goto L2; else goto L1;
L1:
putc('0');
halt();
L2:
putc('1');
goto L2;

If debug commands are ignored, paths just connect program start, halt and onecode blocks. They can contain conditions, if something then come here otherwise go there. They are just like GOTOs.

Onecode blocks

Onecode blocks are blocks of onecode code inside twocode. A block begins with { and ends with }. The code must always be between the brackets. An onecode line starts with : and ends with ; (except the first and the last one, see examples). Colons are optional when the execution direction is left-to-right. After the block is executed its valeu is placed to the accumulator.

Acceptable blocks (<= and => show the direction, area which is parsed as onecode highlighted):

=>{ code;
    smth else }=>
=>{ code ;
  : code ;
  : code }=>
<={ code      ;
  : more code }<=
=>{ stmt \
  : continues }=>

Inacceptable blocks

=>{ code ; code }

Error: statements cannot share a line

=>{ code
    code }

Error: no colons or semicolons.

{ code ;
  code }<=
{ code \
  code }<=

Error: no colon.

{ long line;
: code }<=

Error: long line is not fully between the brackets.

Onecode

Main article: Onecode (Fergusq)

Onecode is used to do anything else but flow control.

Variables

A value can be assigned to a variable using operator ~.

i~0;
a~3;
b~c~5;
x~a+b+c;

Pointers

i~1;
*i~'H';
*(i+1)~'i';
putc(*i);
putc(*(i+1));

Lists

List syntax can be used to write a few numbers to the memory.

*i~[1,2,3];

Is same as:

*i~1;
*(i+1)~2;
*(i+2)~3;

Strings work like list and have always a null terminator.

*s~"abc";
*s~['a','b','c',0];

Boolean values

0 is false, everything else is true.

Examples

Hello world

{ i~0;                 /={i~i+1}============\
  *i~"Hello world\n" }=>={putc(*i)}={!*i}=S=/
                                          #
{ putc('H');
  putc('e');
  putc('l');
  putc('l');
  putc('o');
  putc(32);
  putc('w');
  putc('o');
  putc('r');
  putc('l');
  putc('d');
  putc(10) }#

Factorial

>=={ x~7 }===\   calculate !7
             |
/=={ n~1   ; |   initialization
|  : t~1   ; |
|  : x~x+1 }=/
|
v==============\
\=={ n~n*t ;   | main loop
   : t~t+1 }=\ |
/============/ |
\=={ !(t=x) }==Z=={putn(n)}#

Short version using debug command to print the answer:

>{x~7}==v  {n}n#
v{x~x+1}<  |
>{t~1}{n~1}+===v
>====={t=x}Z===v
^{t~t+1}{n~n*t}<

99 bottles of beer

>={i~99}==\
    /=====/
/===|===========\
|/==>={!(i=2)}S=/
||  /=========/
||  { putn(i);
||    s~0;
||    *s~" bottles of beer on the wall,\n" }=\
|| /=========================================/
|| | /={s~s+1}============\
|| \=>={putc(*s)}={!*s}=S=/
||  /==================f/
||  { putn(i);
||    s~0;
||    *s~" bottles of beer\n" }=\
|| /============================/
|| | /={s~s+1}============\
|| \=>={putc(*s)}={!*s}=S=/
||  /==================f/
||  { s~0;
||    *s~"Take one down, pass it around\n" }=\
|| /=========================================/
|| | /={s~s+1}============\
|| \=>={putc(*s)}={!*s}=S=/
||  /==================f/
||  { i~i-1;
||    putn(i);
||    s~0;
||    *s~" bottles of beer\n\n" }=\
|| /==============================/
|| | /={s~s+1}============\
|| \=>={putc(*s)}={!*s}=S=/
|\=====================f/
|
\==={ s~0;
      *s~"2 bottles of beer on the wall,\n2 bottles of beer\nTake one down, pass it around\n1 bottle of beer on the wall\n\n" }=\
   /============================================================================================================================/
   | /={s~s+1}============\
   \=>={putc(*s)}={!*s}=S=/
    /==================f/
    { s~0;
      *s~"1 bottle of beer on the wall,\n1 bottle of beer\nTake one down, pass it around\nNo more bottles of beer on the wall\n\n" }=\
   /=================================================================================================================================/
   | /={s~s+1}============\
   \=>={putc(*s)}={!*s}=S=/
    /==================f/
    { s~0;
      *s~"No more bottles of beer on the wall,\nno more bottle of beer\nTake one down, pass it around\n99 bottles of beer on the wall\n\n" }=\
   /=========================================================================================================================================/
   | /={s~s+1}============\
   \=>={putc(*s)}={!*s}=S=/
    /==================f/
    #

Minsky machine

v
| Minsky machine interpreter
| 
| Program code structure in memory
| op reg addr1 addr2
| 
| op = 1 if INC
| reg = memory address
| addr1 = next instruction address in memory
| addr2 = second instruction address, used with DEC
|
>={i~0}=\ instruction pointer = 0
        |
        |        INC             If *p != 0 decrement
/=======>========{*i=1}=S========{!(**(i+1)=0)}=S====\
| /={**(i+1)~**(i+1)+1}=/ /={**(i+1)~**(i+1)-1}=/    |
| \={i~*(i+2)}=\          \={i~*(i+2)}=\             |
\=Z={i=0-1}====<=======================<=={i~*(i+3)}=/ otherwise jump
  |
  \=# Halt