Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- NovaYoshi's FALSE interpreter - first release
- ------------------------------------------------------------------------------
- It's different from PortableFalse in that:
- - It's NOT strongly typed. You can push an integer to the stack and ! it
- - The macro usage actually makes sense
- - < is 'less than'
- - ; and : work on both numeric addresses and variables
- - I'm using ` as an escape code for more extensions
- - `? is like ? except it takes an "else" block too (["true"]["false"]`?)
- - `/ is modulo
- - ^ is now XOR
- - W,X,Y, and Z push the values of variables w,x,y, and z respectively
- - Relies on GNU C features, some of which aren't in GNU C++ (function nesting)
- - Programs have a time limit of two seconds (but it doesn't seem to work?)
- - Everything's still all in one function but it's not main()
- - Doesn't put additional main() arguments into variables
- - Probably more stuff I forgot
- Some ideas taken from Ian Osgood's DUP and other FALSE-like stuff.
- ~~~ Nova Storm the Yoshifox
- */
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #include <time.h>
- #define DEBUG 0
- #define LOAD_FROM_FILE 1
- typedef unsigned long u32;
- typedef signed long s32;
- int NSFalse(char *Program) {
- __label__ hell; // We can goto out of a nested function if we define the label first
- u32 PC = 0; // Program counter
- // Index 0 is the stack pointer
- s32 DST[50]={1}; // Data stack
- u32 RST[50]={1}; // Return stack
- s32 Mem[256]={[0 ... 255] = 0}; // Memory for variables
- u32 PrgEnd = strlen(Program); // Ending that we can check against
- char TempText[60]; // a little text buffer
- char *ErrMsg; // what error message to show
- unsigned int TimeStarted = (unsigned)time(NULL);
- #if !LOAD_FROM_FILE
- printf("%s \n", Program);
- #endif
- #define Pop(Var, Stack) { \
- Stack[0]--; \
- if((Stack[0] < 1) || (Stack[0] > 100)) { \
- ErrMsg = "Stack underflow"; goto hell; \
- } \
- *Var = Stack[Stack[0]]; \
- }
- #define Push(Var, Stack) { \
- Stack[Stack[0]]=Var; \
- Stack[0]++; \
- if((Stack[0] < 1) || (Stack[0] > 100)) { \
- ErrMsg = "Stack overflow"; goto hell; \
- } \
- }
- // Checks an index to see if it's inside the ranges
- void CheckIndex(int Index, int Min, int Max) {
- if(Index > Max || Index < Min) {
- ErrMsg = "CheckIndex() failed somewhere";
- goto hell;
- }
- }
- // Call a FALSE subroutine
- void Run(StartingAt) {
- s32 a,b,c; // Scratch registers
- #if DEBUG
- printf("\n-- %i to %i\n", PC, StartingAt);
- #endif
- Push(PC,RST);
- PC = StartingAt;
- if(!(PC>=0 && PC<PrgEnd)) {
- ErrMsg = "Trying to call to some place outside the program";
- goto hell;
- }
- while(PC>=0 && PC<PrgEnd) {
- if(TimeStarted+3<((unsigned)time(NULL))) {
- ErrMsg = "Program exceeded the time limit"; goto hell;}
- #if DEBUG
- putchar('\n');
- for(a=0;a<PC;a++)
- putchar(' ');
- putchar(Program[PC]);
- //putchar('^');
- for(a=1;a<DST[0];a++)
- printf(" %i", DST[a]);
- putchar('-');
- #endif
- switch(Program[PC]) {
- case ' ': case '\r': case '\n': case '\t': case -1: break;
- case '+':Pop(&b,DST);Pop(&a,DST);Push(a+b,DST);break;
- case '-':Pop(&b,DST);Pop(&a,DST);Push(a-b,DST);break;
- case '*':Pop(&b,DST);Pop(&a,DST);Push(a*b,DST);break;
- case '/':Pop(&b,DST);Pop(&a,DST);Push(a/b,DST);break;
- case '|':Pop(&b,DST);Pop(&a,DST);Push(a|b,DST);break;
- case '&':Pop(&b,DST);Pop(&a,DST);Push(a&b,DST);break;
- case '^':Pop(&b,DST);Pop(&a,DST);Push(a^b,DST);break;
- case '<':Pop(&b,DST);Pop(&a,DST);Push(-(a<b),DST);break;
- case '=':Pop(&b,DST);Pop(&a,DST);Push(-(a==b),DST);break;
- case '>':Pop(&b,DST);Pop(&a,DST);Push(-(a>b),DST);break;
- case '_':Pop(&a,DST);Push(-a,DST);break;
- case '~':Pop(&a,DST);Push(~a,DST);break;
- case '%':Pop(&a,DST);break;
- case 'W':Push(Mem['w'-'a'],DST);break;
- case 'X':Push(Mem['x'-'a'],DST);break;
- case 'Y':Push(Mem['y'-'a'],DST);break;
- case 'Z':Push(Mem['z'-'a'],DST);break;
- case '$':Pop(&a,DST);Push(a,DST);Push(a,DST);break;
- case '\\':Pop(&a,DST);Pop(&b,DST);Push(a,DST);Push(b,DST);break;
- case '@':Pop(&a,DST);Pop(&b,DST);Pop(&c,DST);Push(b,DST);Push(a,DST);Push(c,DST);break;
- case 'O':Pop(&a,DST);CheckIndex(DST[0]-a,1,49);Push(DST[DST[0]-a],DST);break; // ?
- case ':':Pop(&a,DST);CheckIndex(a,0,255);Pop(&b,DST);Mem[a]=b;break;
- case ';':Pop(&a,DST);CheckIndex(a,0,255);Push(Mem[a],DST);break;
- case '.':Pop(&a,DST);printf("%i",(int)a);break;
- case ',':Pop(&a,DST);putchar(a);break;
- case 'B':fflush(stdout);fflush(stdin);break;
- case '\"':while(Program[++PC]!='\"' && PC<PrgEnd)putchar(Program[PC]);break;
- case '{':while(Program[++PC]!='}' && PC<PrgEnd);break;
- case '\'':Push(Program[++PC],DST);break;
- case '[':Push(++PC,DST);
- int Level=1; PC++;
- while(Level!=0) {
- if(PC>PrgEnd){ ErrMsg="[ not closed"; goto hell;}
- if(Program[PC++]=='[') Level++;
- if(Program[PC] ==']') Level--;
- }
- break;
- case ']':Pop(&PC,RST);return;
- case '!':Pop(&a,DST);Run(a);break;
- case '?':Pop(&a,DST);Pop(&b,DST);if(b)Run(a);break;
- case '#':
- Pop(&a,DST); // pop the 'do' block
- Pop(&b,DST); // 'condition' block
- while(1) {
- Run(b);
- Pop(&c,DST);
- if(!c)
- break;
- Run(a);
- }
- break;
- case '`': // ` doesn't serve a purpose in FALSE anymore, so I'll make
- // it my escape code for stupid extensions to FALSE
- switch(Program[++PC]) {
- case '/':Pop(&b,DST);Pop(&a,DST);Push(a%b,DST);break;
- case '?': // extended 'if' with an 'else'
- Pop(&a,DST);Pop(&b,DST);Pop(&c,DST);if(c)Run(b);else Run(a);break;
- case '%': // delete everything
- DST[0]=1;break;
- default:
- sprintf(TempText,"Unrecognized extended symbol (%c)",Program[PC]);
- ErrMsg = TempText; goto hell;
- }
- break;
- default:
- if(isdigit(Program[PC])) {
- Push(strtol(Program+PC,NULL,10),DST);
- while(isdigit(Program[PC])) PC++;
- PC--; // PC gets incremented soon after this.
- }
- else if(Program[PC]>='a'&&Program[PC]<='z') {
- Push(Program[PC]-'a',DST);
- }
- else {
- sprintf(TempText,"Unrecognized symbol (%c)",Program[PC]);
- ErrMsg = TempText; goto hell;
- }
- break;
- }
- PC++;
- }
- Pop(&PC,RST);
- }
- Run(0);
- return(1);
- hell: // Jumps here when there's an error
- printf("\nError at %i: %s \n", PC,ErrMsg);
- return(-1);
- }
- int main(int argc, char **argv) {
- char Program[8192];
- int i=0;
- #if LOAD_FROM_FILE
- if(argc < 2) {
- printf("Syntax: %s file.f\n", argv[0]);
- return -1;
- }
- FILE *MyFile = fopen(argv[1],"r");
- if(MyFile == NULL) {
- printf("Wasn't able to open %s\n",argv[1]);
- return -2;
- }
- while(!feof(MyFile)) {
- int j = fgetc(MyFile);
- Program[i++]=j;
- }
- Program[i]=0;
- fclose(MyFile);
- return(NSFalse(Program));
- #else
- // just do sample programs then
- NSFalse("5.");
- printf("\n\n"); NSFalse("\"hello!\"");
- printf("\n\n"); NSFalse("[\"hello!\" ]w:W!");
- printf("\n\n"); NSFalse("0[\"hello!\"]?");
- printf("\n\n"); NSFalse("1[\"hello!\"]?");
- printf("\n\n"); NSFalse("0[\"true\"][\"false\"]`?");
- printf("\n\n"); NSFalse("1[\"true\"][\"false\"]`?");
- printf("\n\n"); NSFalse("5w:W.");
- printf("\n\n"); NSFalse("1[$10<][$.1+' ,]#%");
- printf("\n\n"); NSFalse("1i:[10i;>][i;$.1+i:' ,]#");
- printf("\n\n"); NSFalse("8.1a:[10a;>][a;1+a:'=,]#'D,");
- printf("\n\n"); NSFalse("0a:1b:1n:[17n;>][n;1+n:a;$.' ,b;+c:b;a:c;b:]#");
- printf("\n");
- return 1;
- #endif
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement