Noobinary

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");
 }
Category:Languages
Category:Implemented
Category:Unknown computational class