Skip to content

Instantly share code, notes, and snippets.

@koistya
Created April 8, 2012 12:22
Show Gist options
  • Select an option

  • Save koistya/2336959 to your computer and use it in GitHub Desktop.

Select an option

Save koistya/2336959 to your computer and use it in GitHub Desktop.
New programming language + self-interpreter
/* 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