Noobinary

From Esolang
Jump to navigation Jump to search

Noobinary is an esoteric language designed by user Batmanifestdestiny to resemble Binary, but be easier to learn.

The specifications are as follows:

NOOBINARY: BINARY FOR NOOBS

noobinary specifications:

1 is instruction symbol.
0 is also an instruction symbol.
The only whitespace is newline.

commands(command - description)

1 - push 1 on to the stack
11 - pops the top two stack values and adds them
111 - pops the top two stack values and subtracts them
1111 - pops the top two stack values and multiplies them
11111 - pops the top two stack values and divides them
111111 - copies the top stack value
1111111 - pops top stack value and outputs an integer
11111111 - pops top stack value and outputs a UTF-32 character
111111111 - accept input
1111111111 - terminate program

0 - nop for distinguishing between different 1 commands
00 - loop tag
000 - if top stack value = 0, then continue.  If not, then go back to previous loop tag or beginning of the program, whichever comes later in the code
0000 - if top stack value != 0, then continue.  If not, then go back to previous loop tag or beginning of the program, whichever comes later in the code
00000 - like 000, but takes the stack value and goes that many tags backward.
000000 - pops the top value off of the stack


This language is similar in stack usage to Befunge and Piet, though handles code flow vastly differently, since Befunge and Piet are both 2D, and Noobinary is strictly 1D, left-to-right, with the occasional jump backwards.


Shown below is a standard "Hello World" program based entirely on adding values up to the UTF-32 equivalents of the letters and symbols:

   101011011111101101111110111111011111101111110
   111101111011011011111101111111101010110111111
   011011111101011011111101111011110101101111110
   111111110101011011111101101111110110110101110
   111111011111101111111101111111101010101101101
   101111111101010110111111011011111101111110110
   111101111111101010110111111011011111101111010
   111011011111111010101101111110111111011110111
   101011101010110111111011011111101111011110101
   110111111011111101111111101010101101101101111
   111101010101101101110111111011111111010101101
   111110111111011011110111011111111010101101111
   110110111111011111101101111010110111111110101
   011011111101101011011111101101111111101111111
   111


Here's an example of loop usage, to count down from 100:

101011010110101101011010110101101011010110101101111110111100101110111111011111110001111111111


In this language, the only whitespace allowed is the carriage return. All comments must be after the termination command, so to refer to specific parts of the code, one would say something like "(3,15) output an integer."


Implementation

Written by User:rdebath

Assumptions:

  • Stack type is C integer (from number print command)
  • Order of operands in SUB and DIV (original hello world)
  • Jump/branch instructions leave the stack untouched (peek the stack) from loop example.
  • Number print is a "wimp mode" and so has a trailing newline (loop example).
  • "UTF-32" is actually supposed to be "UTF-8".
  • Interpretation of the computed goto value.
  • Stops at end of program rather than looping to start as may be implied by termination command.
  • Stack has limited (small) size.
  • Input is bytes (perhaps should be getwchar())


 #include <stdio.h>
 
 void do_one(int cmd);
 void do_zero(int cmd);
 void do_trace(char * cmd);
 
 char * header =
         "#include <stdio.h>"
 "\n"    "#define one *sp++ = 1;"
 "\n"    "#define add sp--; sp[-1] += *sp;"
 "\n"    "#define sub sp--; sp[-1] -= *sp;"
 "\n"    "#define mul sp--; sp[-1] *= *sp;"
 "\n"    "#define div sp--; sp[-1] /= *sp;"
 "\n"    "#define dup *sp = sp[-1]; sp++;"
 "\n"    "#define num printf(\"%d\\n\", *--sp);"
 "\n"    "#define out printf(\"%lc\", *--sp);"
 "\n"    "#define inp *sp++ = getchar();"
 "\n"    "#define end exit(0);"
 "\n"    "#define loop(x) case x:"
 "\n"    "#define bne(x) if (*sp != 0) { j=(x); break; }"
 "\n"    "#define beq(x) if (*sp == 0) { j=(x); break; }"
 "\n"    "#define jmp(x) if (*sp != 0) { j=(x) - sp[-1]; break; }"
 "\n"    "#define pop --sp;"
 "\n"    "int main(void) {"
 "\n"    "int stack[1024], *sp = stack;"
 "\n"    "int j = 0;"
 "\n"    "while(j>=0) switch(j) {"
 "\n"    "case 0:";
 
 char * cmd1[] = {"err", "one", "add", "sub", "mul", "div", "dup", "num", "out", "inp", "end"};
 char * cmd0[] = {"err", "err", "loop(%d)\n", "bne(%d)\n", "beq(%d)\n", "jmp(%d)\n", "pop"};
 
 char * footer =
         "default: j = -1; break;"
 "\n"    "}"
 "\n"    "return 0;"
 "\n"    "}";
 
 int loopid = 0;
 int tron = 0;
 
 int
 main(int argc, char ** argv)
 {
     FILE * fp;
     int ch, ones = 0, zeros = 0;
     if (argc>1 && !strcmp(argv[1], "-t")) {argc--; argv++; tron++;}
     fp = argc>1?fopen(argv[1], "r"):stdin;
     if (!fp) {perror(argv[1]); exit(1);}
     puts(header);
     while((ch = fgetc(fp)) != EOF) {
         if (ch == '\n' || ch == ' ' || ch == '\t') continue;
 
         if (ch == '1') {
             if (zeros) do_zero(zeros);
             zeros = 0;
             ones++;
         } else if (ch == '0') {
             if (ones) do_one(ones);
             ones = 0;
             zeros++;
         } else {
             fprintf(stderr, "Bad chararacter\n");
             exit(1);
         }
 
     }
     if (ones) do_one(ones);
     if (zeros) do_zero(zeros);
     puts(footer);
 }
 
 void do_one(int cmd)
 {
     if (cmd < 1 || cmd > 10) {
         fprintf(stderr, "Too many ones in a row\n");
         exit(1);
     }
     printf("%s\n", cmd1[cmd]);
     do_trace(cmd1[cmd]);
 }
 
 void do_zero(int cmd)
 {
     if (cmd < 1 || cmd > 6) {
         fprintf(stderr, "Too many zeros in a row\n");
         exit(1);
     }
 
     switch(cmd) {
     case 1: break;
     case 2:
         printf(cmd0[cmd], ++loopid); break;
     case 3:
     case 4:
     case 5:
         printf(cmd0[cmd], loopid); break;
     case 6:
         printf("%s\n", cmd0[cmd]); break;
     }
     if(cmd != 1) do_trace(cmd0[cmd]);
 }
 
 void do_trace(char * cmd)
 {
     if(!tron) return;
     printf("puts(\"\\ncmd: %s\");\n", cmd);
     printf("printf(\"STACK\");\n");
     printf("{int *p; for(p=stack; p<sp; p++) printf(\" %%d\", *p);}\n");
     printf("puts(\"\");\n");
 }