Noobinary

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  void do_one(int cmd); void do_zero(int cmd); void do_trace(char * cmd); char * header = "#include " "\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"); }