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"); }