Created
April 8, 2012 12:22
-
-
Save koistya/2336959 to your computer and use it in GitHub Desktop.
New programming language + self-interpreter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* Bootstrap interpreter (program is bad, it can segfault) */ | |
| /* Written in: C */ | |
| /* From: Stack */ | |
| /* To: N/A (interpreter) */ | |
| /* Stack 0 - Output */ | |
| /* Stack 1 - Program */ | |
| /* Stack 2 - Working stack */ | |
| /* Other stacks - Whatever you want */ | |
| /* | |
| * Self-interpreter | |
| * Written in: Stack | |
| * From: Stack | |
| * To: N/A (interpreter) | |
| * | |
| * Human-readable: | |
| * .3o d..=[.3o.4u] d.u=[.4ot.3u .4o.3u .3o.3o u] d.o=[.4oto.4u] d.d=[.4od.4u.4u] d.==[.4o.4o=.4u] d.[=.0=[.1.4u].4o.0=[.3<] d.<=[.4ot<] .t=[.4ot.4u] | |
| * | |
| * Short: | |
| * .3od..=[.3o.4u]d.u=[.4ot.3u.4o.3u.3o.3ou]d.o=[.4oto.4u]d.d=[.4od.4u.4u]d.==[.4o.4o=.4u]d.[=.0=[.1.4u].4o.0=[.3<]d.<=[.4ot<].t=[.4ot.4u] | |
| * | |
| * Len: 135 | |
| */ | |
| /* | |
| * Example: | |
| * | |
| * $ gcc -std=c99 stack-interpr.c -o /tmp/si | |
| * $ A=".3od..=[.3o.4u]d.u=[.4ot.3u.4o.3u.3o.3ou]d.o=[.4oto.4u]d.d=[.4od.4u.4u]d.==[.4o.4o=.4u]d.[=.0=[.1.4u].4o.0=[.3<]d.<=[.4ot<].t=[.4ot.4u]" | |
| * $ B="$(for((I = 0; I != 135; ++I)){ echo "$A"; })" | |
| * $ /tmp/si "$B" "" "$A$A$A" "" ".a.0u" | |
| */ | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #define STACK_COUNT 10 | |
| #define STACK_SIZE 65536 | |
| char stack[STACK_COUNT][STACK_SIZE]; | |
| char *top[STACK_COUNT]; | |
| char c; | |
| void push(int st, char what){ | |
| if(st == 0){ | |
| putchar(what); | |
| return; | |
| } | |
| if(top[st] == stack[st] + STACK_SIZE){ | |
| fprintf(stderr, "%c: stack %d: stack overflow\n", c, st); | |
| exit(EXIT_FAILURE); | |
| } | |
| *top[st] = what; | |
| ++top[st]; | |
| } | |
| char pop_no_check(int st){ | |
| if(st == 0){ | |
| fprintf(stderr, "%c: cannot pop stdout\n", c, st); | |
| exit(EXIT_FAILURE); | |
| } | |
| --top[st]; | |
| return *top[st]; | |
| } | |
| char pop(int st){ | |
| if(top[st] == stack[st]){ | |
| fprintf(stderr, "%c: stack %d: stack underflow\n", c, st); | |
| exit(EXIT_FAILURE); | |
| } | |
| return pop_no_check(st); | |
| } | |
| void eat(int st){ | |
| do{ | |
| c = pop_no_check(st); | |
| if(c == 0){ | |
| fprintf(stderr, "`]' expected\n"); | |
| exit(EXIT_FAILURE); | |
| } | |
| }while(c != ']'); | |
| } | |
| /* В том числе для gdb */ | |
| extern void dump(void){ | |
| for(int i = 1; i != STACK_COUNT; ++i){ | |
| printf("%d: ", i); | |
| for(char *jj = stack[i]; jj != top[i]; ++jj){ | |
| putchar(*jj); | |
| } | |
| putchar('\n'); | |
| } | |
| putchar('\n'); | |
| } | |
| int main(int argc, char *argv[]){ | |
| int debug = 0; | |
| if(strcmp(argv[1], "-d") == 0){ | |
| debug = 1; | |
| ++argv; | |
| --argc; | |
| } | |
| if(argc > STACK_COUNT){ | |
| fprintf(stderr, "Too many stacks\n"); | |
| exit(EXIT_FAILURE); | |
| } | |
| for(int i = 1; i != argc; ++i){ | |
| int len = strlen(argv[i]); | |
| if(len > STACK_SIZE){ | |
| fprintf(stderr, "Stack %d is too big\n", i); | |
| exit(EXIT_FAILURE); | |
| } | |
| top[i] = stack[i] + len; | |
| for(int j = 0; j != len; ++j){ | |
| top[i][-j - 1] = argv[i][j]; | |
| } | |
| } | |
| for(int i = argc; i != STACK_COUNT; ++i){ | |
| top[i] = stack[i]; | |
| } | |
| for(;;){ | |
| if(debug){ | |
| dump(); | |
| } | |
| c = pop_no_check(1); | |
| switch(c){ | |
| case 0: | |
| putchar('\n'); | |
| exit(EXIT_SUCCESS); | |
| case '.': /* escape */ | |
| c = pop_no_check(1); | |
| if(c == 0){ | |
| fprintf(stderr, "end of string after `.'\n"); | |
| exit(EXIT_FAILURE); | |
| } | |
| push(2, c); | |
| break; | |
| case 'u': /* pUsh */ | |
| { | |
| int st = pop(2) - '0'; | |
| char what = pop(2); | |
| push(st, what); | |
| } | |
| break; | |
| case 'o': /* pOp */ | |
| push(2, pop(pop(2) - '0')); | |
| break; | |
| case 'd': /* Duplicate */ | |
| { | |
| char what = pop(2); | |
| push(2, what); | |
| push(2, what); | |
| } | |
| break; | |
| case '=': /* equal */ | |
| if(pop(2) == pop(2)){ | |
| push(2, '1'); | |
| }else{ | |
| push(2, '0'); | |
| } | |
| break; | |
| case '[': /* if */ | |
| if(pop(2) != '1'){ | |
| eat(1); | |
| } | |
| break; | |
| case ']': | |
| case ' ': | |
| case '\t': | |
| case '\n': | |
| break; | |
| case '<': /* eat (packman :) */ | |
| eat(pop(2) - '0'); | |
| break; | |
| case 't': | |
| { | |
| int what = pop(2); | |
| if(what != '0'){ | |
| what += 2; | |
| } | |
| push(2, what); | |
| } | |
| break; | |
| default: | |
| fprintf(stderr, "%c: unknown command\n", c); | |
| exit(EXIT_FAILURE); | |
| } | |
| } | |
| /* Not reached */ | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment