Advertisement
NovaYoshi

NSFalse

Aug 9th, 2011
239
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.13 KB | None | 0 0
  1. /*
  2.   NovaYoshi's FALSE interpreter - first release
  3.  ------------------------------------------------------------------------------
  4.   It's different from PortableFalse in that:
  5.   - It's NOT strongly typed. You can push an integer to the stack and ! it
  6.   - The macro usage actually makes sense
  7.   - < is 'less than'
  8.   - ; and : work on both numeric addresses and variables
  9.   - I'm using ` as an escape code for more extensions
  10.   - `? is like ? except it takes an "else" block too (["true"]["false"]`?)
  11.   - `/ is modulo
  12.   - ^ is now XOR
  13.   - W,X,Y, and Z push the values of variables w,x,y, and z respectively
  14.   - Relies on GNU C features, some of which aren't in GNU C++ (function nesting)
  15.   - Programs have a time limit of two seconds (but it doesn't seem to work?)
  16.   - Everything's still all in one function but it's not main()
  17.   - Doesn't put additional main() arguments into variables
  18.   - Probably more stuff I forgot
  19.  
  20.   Some ideas taken from Ian Osgood's DUP and other FALSE-like stuff.
  21.  
  22.   ~~~ Nova Storm the Yoshifox
  23. */
  24.  
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include <ctype.h>
  28. #include <time.h>
  29. #define DEBUG 0
  30. #define LOAD_FROM_FILE 1
  31.  
  32. typedef unsigned long u32;
  33. typedef signed long s32;
  34.  
  35. int NSFalse(char *Program) {
  36.   __label__ hell; // We can goto out of a nested function if we define the label first
  37.  
  38.   u32 PC = 0;                     // Program counter
  39.   // Index 0 is the stack pointer
  40.   s32 DST[50]={1};                // Data stack
  41.   u32 RST[50]={1};                // Return stack
  42.   s32 Mem[256]={[0 ... 255] = 0}; // Memory for variables
  43.   u32 PrgEnd = strlen(Program);   // Ending that we can check against
  44.   char TempText[60];              // a little text buffer
  45.   char *ErrMsg;                   // what error message to show
  46.   unsigned int TimeStarted = (unsigned)time(NULL);
  47.  
  48.   #if !LOAD_FROM_FILE
  49.   printf("%s \n", Program);
  50.   #endif
  51.  
  52.   #define Pop(Var, Stack) { \
  53.     Stack[0]--; \
  54.     if((Stack[0] < 1) || (Stack[0] > 100)) { \
  55.       ErrMsg = "Stack underflow"; goto hell; \
  56.     } \
  57.     *Var = Stack[Stack[0]]; \
  58.   }
  59.   #define Push(Var, Stack) { \
  60.     Stack[Stack[0]]=Var; \
  61.     Stack[0]++; \
  62.     if((Stack[0] < 1) || (Stack[0] > 100)) { \
  63.       ErrMsg = "Stack overflow"; goto hell; \
  64.     } \
  65.   }
  66.  
  67.   // Checks an index to see if it's inside the ranges
  68.   void CheckIndex(int Index, int Min, int Max) {
  69.     if(Index > Max || Index < Min) {
  70.       ErrMsg = "CheckIndex() failed somewhere";
  71.       goto hell;
  72.     }
  73.   }
  74.  
  75.   // Call a FALSE subroutine
  76.   void Run(StartingAt) {
  77.     s32 a,b,c; // Scratch registers
  78.  
  79.     #if DEBUG
  80.       printf("\n-- %i to %i\n", PC, StartingAt);
  81.     #endif
  82.     Push(PC,RST);
  83.     PC = StartingAt;
  84.     if(!(PC>=0 && PC<PrgEnd)) {
  85.       ErrMsg = "Trying to call to some place outside the program";
  86.       goto hell;
  87.     }
  88.     while(PC>=0 && PC<PrgEnd) {
  89.       if(TimeStarted+3<((unsigned)time(NULL))) {
  90.         ErrMsg = "Program exceeded the time limit"; goto hell;}
  91.       #if DEBUG
  92.       putchar('\n');
  93.       for(a=0;a<PC;a++)
  94.         putchar(' ');
  95.       putchar(Program[PC]);
  96.       //putchar('^');
  97.       for(a=1;a<DST[0];a++)
  98.         printf(" %i", DST[a]);
  99.       putchar('-');
  100.       #endif
  101.  
  102.       switch(Program[PC]) {
  103.         case ' ': case '\r': case '\n': case '\t': case -1: break;
  104.         case '+':Pop(&b,DST);Pop(&a,DST);Push(a+b,DST);break;
  105.         case '-':Pop(&b,DST);Pop(&a,DST);Push(a-b,DST);break;
  106.         case '*':Pop(&b,DST);Pop(&a,DST);Push(a*b,DST);break;
  107.         case '/':Pop(&b,DST);Pop(&a,DST);Push(a/b,DST);break;
  108.         case '|':Pop(&b,DST);Pop(&a,DST);Push(a|b,DST);break;
  109.         case '&':Pop(&b,DST);Pop(&a,DST);Push(a&b,DST);break;
  110.         case '^':Pop(&b,DST);Pop(&a,DST);Push(a^b,DST);break;
  111.         case '<':Pop(&b,DST);Pop(&a,DST);Push(-(a<b),DST);break;
  112.         case '=':Pop(&b,DST);Pop(&a,DST);Push(-(a==b),DST);break;
  113.         case '>':Pop(&b,DST);Pop(&a,DST);Push(-(a>b),DST);break;
  114.         case '_':Pop(&a,DST);Push(-a,DST);break;
  115.         case '~':Pop(&a,DST);Push(~a,DST);break;
  116.         case '%':Pop(&a,DST);break;
  117.         case 'W':Push(Mem['w'-'a'],DST);break;
  118.         case 'X':Push(Mem['x'-'a'],DST);break;
  119.         case 'Y':Push(Mem['y'-'a'],DST);break;
  120.         case 'Z':Push(Mem['z'-'a'],DST);break;
  121.         case '$':Pop(&a,DST);Push(a,DST);Push(a,DST);break;
  122.         case '\\':Pop(&a,DST);Pop(&b,DST);Push(a,DST);Push(b,DST);break;
  123.         case '@':Pop(&a,DST);Pop(&b,DST);Pop(&c,DST);Push(b,DST);Push(a,DST);Push(c,DST);break;
  124.         case 'O':Pop(&a,DST);CheckIndex(DST[0]-a,1,49);Push(DST[DST[0]-a],DST);break; // ?
  125.         case ':':Pop(&a,DST);CheckIndex(a,0,255);Pop(&b,DST);Mem[a]=b;break;
  126.         case ';':Pop(&a,DST);CheckIndex(a,0,255);Push(Mem[a],DST);break;
  127.         case '.':Pop(&a,DST);printf("%i",(int)a);break;
  128.         case ',':Pop(&a,DST);putchar(a);break;
  129.         case 'B':fflush(stdout);fflush(stdin);break;
  130.         case '\"':while(Program[++PC]!='\"' && PC<PrgEnd)putchar(Program[PC]);break;
  131.         case '{':while(Program[++PC]!='}' && PC<PrgEnd);break;
  132.         case '\'':Push(Program[++PC],DST);break;
  133.         case '[':Push(++PC,DST);
  134.           int Level=1; PC++;
  135.           while(Level!=0) {
  136.             if(PC>PrgEnd){ ErrMsg="[ not closed"; goto hell;}
  137.             if(Program[PC++]=='[') Level++;
  138.             if(Program[PC]  ==']') Level--;
  139.           }
  140.           break;
  141.         case ']':Pop(&PC,RST);return;
  142.         case '!':Pop(&a,DST);Run(a);break;
  143.         case '?':Pop(&a,DST);Pop(&b,DST);if(b)Run(a);break;
  144.         case '#':
  145.           Pop(&a,DST); // pop the 'do' block
  146.           Pop(&b,DST); // 'condition' block
  147.           while(1) {
  148.             Run(b);
  149.             Pop(&c,DST);
  150.             if(!c)
  151.               break;
  152.             Run(a);
  153.           }
  154.           break;
  155.         case '`': // ` doesn't serve a purpose in FALSE anymore, so I'll make
  156.                   //  it my escape code for stupid extensions to FALSE
  157.           switch(Program[++PC]) {
  158.             case '/':Pop(&b,DST);Pop(&a,DST);Push(a%b,DST);break;
  159.             case '?': // extended 'if' with an 'else'
  160.               Pop(&a,DST);Pop(&b,DST);Pop(&c,DST);if(c)Run(b);else Run(a);break;
  161.             case '%': // delete everything
  162.               DST[0]=1;break;
  163.             default:
  164.               sprintf(TempText,"Unrecognized extended symbol (%c)",Program[PC]);
  165.               ErrMsg = TempText; goto hell;
  166.           }
  167.           break;
  168.         default:
  169.           if(isdigit(Program[PC])) {
  170.             Push(strtol(Program+PC,NULL,10),DST);
  171.             while(isdigit(Program[PC])) PC++;
  172.             PC--; // PC gets incremented soon after this.
  173.           }
  174.           else if(Program[PC]>='a'&&Program[PC]<='z') {
  175.             Push(Program[PC]-'a',DST);
  176.           }
  177.           else {
  178.             sprintf(TempText,"Unrecognized symbol (%c)",Program[PC]);
  179.             ErrMsg = TempText; goto hell;
  180.           }
  181.           break;
  182.       }
  183.       PC++;
  184.     }
  185.     Pop(&PC,RST);
  186.   }
  187.   Run(0);
  188.   return(1);
  189.  
  190. hell: // Jumps here when there's an error
  191.   printf("\nError at %i: %s \n", PC,ErrMsg);
  192.   return(-1);
  193. }
  194.  
  195. int main(int argc, char **argv) {
  196.   char Program[8192];
  197.   int i=0;
  198.  
  199.   #if LOAD_FROM_FILE
  200.   if(argc < 2) {
  201.     printf("Syntax: %s file.f\n", argv[0]);
  202.     return -1;
  203.   }
  204.   FILE *MyFile = fopen(argv[1],"r");
  205.   if(MyFile == NULL) {
  206.     printf("Wasn't able to open %s\n",argv[1]);
  207.     return -2;
  208.   }
  209.   while(!feof(MyFile)) {
  210.     int j = fgetc(MyFile);
  211.     Program[i++]=j;
  212.   }
  213.   Program[i]=0;
  214.   fclose(MyFile);
  215.   return(NSFalse(Program));
  216.  
  217.   #else
  218.   // just do sample programs then
  219.                   NSFalse("5.");
  220.   printf("\n\n"); NSFalse("\"hello!\"");
  221.   printf("\n\n"); NSFalse("[\"hello!\" ]w:W!");
  222.   printf("\n\n"); NSFalse("0[\"hello!\"]?");
  223.   printf("\n\n"); NSFalse("1[\"hello!\"]?");
  224.   printf("\n\n"); NSFalse("0[\"true\"][\"false\"]`?");
  225.   printf("\n\n"); NSFalse("1[\"true\"][\"false\"]`?");
  226.   printf("\n\n"); NSFalse("5w:W.");
  227.   printf("\n\n"); NSFalse("1[$10<][$.1+' ,]#%");
  228.   printf("\n\n"); NSFalse("1i:[10i;>][i;$.1+i:' ,]#");
  229.   printf("\n\n"); NSFalse("8.1a:[10a;>][a;1+a:'=,]#'D,");
  230.   printf("\n\n"); NSFalse("0a:1b:1n:[17n;>][n;1+n:a;$.' ,b;+c:b;a:c;b:]#");
  231.   printf("\n");
  232.   return 1;
  233.   #endif
  234. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement