Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions basic.c
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
#include <stdio.h>
#include "basic.h"

PRINTS_() { puts((char*)*sp++); STEP; }
int PRINTS_() { puts((char*)*sp++); STEP; }

kwdhook_(char *msg) {
int kwdhook_(char *msg) {
if (!strcmp(msg,"PRINTS"))
expr(), emit(PRINTS_);
else return 0;
return 1;
}

main(int argc, char **argv) {
int main(int argc, char **argv) {
FILE *sf=stdin;
initbasic(0);
kwdhook=kwdhook_;
if (argv[1])
if (sf=fopen(argv[1],"r"))
if (argv[1]) {
if ((sf=fopen(argv[1],"r")) != NULL)
compile++;
else {
printf("CANNOT OPEN: %s\n", argv[1]);
return 255;
}
}
return interp(sf);
}
106 changes: 57 additions & 49 deletions basic.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#include <ctype.h>
#include <setjmp.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#define SYMSZ 16 /* SYMBOL SIZE */
#define PRGSZ 65536 /* PROGRAM SIZE */
#define STKSZ 256 /* STACK SIZE */
Expand All @@ -13,6 +15,9 @@
typedef ptrdiff_t Val; /* SIGNED INT/POINTER */
typedef int (*Code)(); /* BYTE-CODE */

int err(char *msg);
int expr(void);

enum { NAME=1,NUMBER,STRING,LP,RP,COMMA,ADD,SUBS,MUL,DIV,MOD,
EQ,LT,GT, NE,LE,GE,AND,OR,FORMAT,SUB,END,RETURN,LOCAL,
WHILE,FOR,TO,IF,ELSE,THEN,DIM,UBOUND,BYE,BREAK,RESUME };
Expand All @@ -21,7 +26,8 @@ char *kwd[]={ "AND","OR","FORMAT","SUB","END","RETURN","LOCAL","WHILE",

char lbuf[256],tokn[SYMSZ],*lp; /* LEXER STATE */
int lnum,tok,tokv,ungot; /* LEXER STATE */
int (*prg[PRGSZ])(),(**pc)(),cpc,lmap[PRGSZ]; /* COMPILED PROGRAM */
int (*prg[PRGSZ])(),(**pc)(); /* COMPILED PROGRAM */
intptr_t cpc,lmap[PRGSZ]; /* COMPILED PROGRAM */
Val stk[STKSZ],*sp; /* RUN-TIME STACK */
Val value[VARS]; /* VARIABLE VALUES */
char name[VARS][SYMSZ]; /* VARIABLE NAMES */
Expand All @@ -44,70 +50,72 @@ Val *bound(Val *mem, int n) { if (n<1 || n>*mem) err("BOUNDS"); return mem+n; }
int (*kwdhook)(char *kwd); /* KEYWORD HOOK */
int (*funhook)(char *kwd, int n); /* FUNCTION CALL HOOK */

initbasic(int comp) { pc=prg; sp=stk+STKSZ; csp=cstk+STKSZ; stabp=stab; compile=comp; }
bad(char *msg) { printf("ERROR %d: %s\n", lnum, msg); longjmp(trap,1); }
err(char *msg) { printf("ERROR %d: %s\n",lmap[pc-prg-1],msg); longjmp(trap,2); }
emit(int opcode()) { lmap[cpc]=lnum; prg[cpc++]=opcode; }
inst(int opcode(), Val x) { emit(opcode); emit((Code)x); }
BYE_() { longjmp(trap,4); }
BREAK_() { longjmp(trap,3); }
RESUME_() { pc=opc? opc:pc; opc=pc; cpc=ipc; STEP; }
NUMBER_() { *--sp=PCV; STEP; }
LOAD_() { *--sp=value[PCV]; STEP; }
STORE_() { value[PCV]=*sp++; STEP; }
ECHO_() { printf("%d\n",*sp++); }
FORMAT_() { char *f; Val n=PCV, *ap=(sp+=n)-1;
void initbasic(int comp) { pc=prg; sp=stk+STKSZ; csp=cstk+STKSZ; stabp=stab; compile=comp; }
int bad(char *msg) { printf("ERROR %d: %s\n", lnum, msg); longjmp(trap,1); return 0; }
int err(char *msg) { printf("ERROR %d: %s\n",(int)lmap[pc-prg-1],msg); longjmp(trap,2); return 0;}
void emit(int opcode()) { lmap[cpc]=lnum; prg[cpc++]=opcode; }
void inst(int opcode(), Val x) { emit(opcode); emit((Code)x); }
int BYE_(void) { longjmp(trap,4); return 0; }
int BREAK_(void) { longjmp(trap,3); return 0; }
int RESUME_(void) { pc=opc? opc:pc; opc=pc; cpc=ipc; STEP; }
int NUMBER_(void) { *--sp=PCV; STEP; }
int LOAD_(void) { *--sp=value[PCV]; STEP; }
int STORE_(void) { value[PCV]=*sp++; STEP; }

int ECHO_(void) { printf("%td\n",*sp++); STEP; }
int FORMAT_(void) { char *f; Val n=PCV, *ap=(sp+=n)-1;
for (f=stab + *sp++; *f; f++)
if (*f=='%') printf("%d", (int)*ap--);
else if (*f=='$') printf("%s", (char*)*ap--);
else putchar(*f);
putchar('\n'); STEP;
}
ADD_() { A+=B; sp++; STEP; };
SUBS_() { A-=B; sp++; STEP; };
MUL_() { A*=B; sp++; STEP; };
DIV_() { if (!B) sp+=2,err("DIVISION BY ZERO"); A/=B; sp++; STEP; };
MOD_() { if (!B) sp+=2,err("MODULUS OF ZERO"); A%=B; sp++; STEP; };
EQ_() { A=(A==B)? -1: 0; sp++; STEP; };
LT_() { A=(A<B)? -1: 0; sp++; STEP; };
GT_() { A=(A>B)? -1: 0; sp++; STEP; };
NE_() { A=(A!=B)? -1: 0; sp++; STEP; };
LE_() { A=(A<=B)? -1: 0; sp++; STEP; };
GE_() { A=(A>=B)? -1: 0; sp++; STEP; };
AND_() { A&=B; sp++; STEP; };
OR_() { A|=B; sp++; STEP; };
JMP_() { pc=prg+(int)*pc; STEP; }
FALSE_() { if (*sp++) pc++; else pc=prg+(int)*pc; STEP; }
FOR_() { if (value[PCV] >= *sp) pc=prg+(int)*pc, sp++; else PCV; STEP; }
NEXT_() { value[PCV]++; STEP; }
CALL_() { Val v=PCV, n=sub[v][1], x, *ap=sp;
int ADD_(void) { A+=B; sp++; STEP; };
int SUBS_(void) { A-=B; sp++; STEP; };
int MUL_(void) { A*=B; sp++; STEP; };
int DIV_(void) { if (!B) sp+=2,err("DIVISION BY ZERO"); A/=B; sp++; STEP; };
int MOD_(void) { if (!B) sp+=2,err("MODULUS OF ZERO"); A%=B; sp++; STEP; };
int EQ_(void) { A=(A==B)? -1: 0; sp++; STEP; };
int LT_(void) { A=(A<B)? -1: 0; sp++; STEP; };
int GT_(void) { A=(A>B)? -1: 0; sp++; STEP; };
int NE_(void) { A=(A!=B)? -1: 0; sp++; STEP; };
int LE_(void) { A=(A<=B)? -1: 0; sp++; STEP; };
int GE_(void) { A=(A>=B)? -1: 0; sp++; STEP; };
int AND_(void) { A&=B; sp++; STEP; };
int OR_(void) { A|=B; sp++; STEP; };
int JMP_(void) { pc=prg+(intptr_t)*pc; STEP; }
int FALSE_(void) { if (*sp++) pc++; else pc=prg+(intptr_t)*pc; STEP; }
int FOR_(void) { if (value[PCV] >= *sp) pc=prg+(intptr_t)*pc, sp++; else PCV; STEP; }
int NEXT_(void) { value[PCV]++; STEP; }
int CALL_(void) { Val v=PCV, n=sub[v][1], x, *ap=sp;
while (n--) { x=LOC(n); LOC(n)=*ap; *ap++=x; }
for (n=sub[v][1]; n<sub[v][0]; n++) *--sp=LOC(n);
*--sp=pc-prg;
pc=prg+value[v];
STEP;
}
RETURN_() { int v=PCV, n=sub[v][0];
int RETURN_(void) { int v=PCV, n=sub[v][0];
pc=prg+*sp++;
while (n--) LOC(n)=*sp++;
STEP;
}
SETRET_() { ret=*sp++; STEP; }
RV_() { *--sp=ret; STEP; }
DROP_() { sp+=PCV; STEP; }
DIM_() { int v=PCV, n=*sp++; Val *mem=calloc(sizeof(Val),n+1);
int SETRET_(void) { ret=*sp++; STEP; }
int RV_(void) { *--sp=ret; STEP; }
int DROP_(void) { sp+=PCV; STEP; }
int DIM_(void) { int v=PCV, n=*sp++; Val *mem=calloc(sizeof(Val),n+1);
mem[0]=n; value[v]=(Val)mem;
return 0;
}
LOADI_() { Val x=*sp++; x=*bound((Val*)value[PCV],x); *--sp=x; STEP; }
STOREI_() { Val x=*sp++, i=*sp++; *bound((Val*)value[PCV],i)=x; STEP; }
UBOUND_() { *--sp=*(Val*)value[PCV]; STEP; }
find(char *var) {
int LOADI_(void) { Val x=*sp++; x=*bound((Val*)value[PCV],x); *--sp=x; STEP; }
int STOREI_(void) { Val x=*sp++, i=*sp++; *bound((Val*)value[PCV],i)=x; STEP; }
int UBOUND_(void) { *--sp=*(Val*)value[PCV]; STEP; }
int find(char *var) {
int i;
for (i=0; i<nvar && strcmp(var,name[i]); i++);
if (i==nvar) strcpy(name[nvar++], var);
return i;
}
read() { /* READ TOKEN */
int read(void) { /* READ TOKEN */
char *p,*d,**k, *pun="(),+-*/\\=<>", *dub="<><==>";
if (ungot) return ungot=0, tok; /* UNGOT PREVIOUS */
while (isspace(*lp)) lp++; /* SKIP SPACE */
Expand All @@ -128,10 +136,10 @@ read() { /* READ TOKEN */
return *stabp++=0, lp++, tokv=p-stab, tok=STRING;
} else return bad("BAD TOKEN");
}
want(int type) { return !(ungot=read()!=type); }
need(int type) { if (!want(type)) bad("SYNTAX ERROR"); }
int want(int type) { return !(ungot=read()!=type); }
void need(int type) { if (!want(type)) bad("SYNTAX ERROR"); }
#define LIST(BODY) if (!want(0)) do {BODY;} while (want(COMMA))
base() { /* BASIC EXPRESSION */
void base(void) { /* BASIC EXPRESSION */
int neg=want(SUBS)? (inst(NUMBER_,0),1): 0;
if (want(NUMBER)) inst(NUMBER_, tokv);
else if (want(STRING)) inst(NUMBER_, (Val)(stab+tokv));
Expand All @@ -158,7 +166,7 @@ base() { /* BASIC EXPRESSION */
if (neg) emit(SUBS_); /* NEGATE */
}
int (*bin[])()={ADD_,SUBS_,MUL_,DIV_,MOD_,EQ_,LT_,GT_, NE_,LE_,GE_,AND_,OR_};
#define BIN(NAME,LO,HI,ELEM) NAME() { int (*o)(); \
#define BIN(NAME,LO,HI,ELEM) int NAME(void) { int (*o)(); \
ELEM(); \
while (want(0), LO<=tok && tok<=HI) \
o=bin[tok-ADD], read(), ELEM(), emit(o); \
Expand All @@ -167,7 +175,7 @@ BIN(factor,MUL,MOD,base)
BIN(addition,ADD,SUBS,factor)
BIN(relation,EQ,GE,addition)
BIN(expr,AND,OR,relation)
stmt() { /* STATEMENT */
void stmt(void) { /* STATEMENT */
int n,var;
switch (read()) {
case FORMAT:
Expand Down Expand Up @@ -235,7 +243,7 @@ stmt() { /* STATEMENT */
} else if (csp[-1]==IF) {
for (n=*csp++; n--; ) /* PATCH BLOCK ENDS */
prg[*csp++]=(Code)cpc;
if (n=*csp++) prg[n]=(Code)cpc; /* PATCH "ELSE" */
if ((n=*csp++) != 0) prg[n]=(Code)cpc; /* PATCH "ELSE" */
}
break;
case NAME:
Expand Down Expand Up @@ -264,7 +272,7 @@ stmt() { /* STATEMENT */
}
if (!want(0)) bad("TOKENS AFTER STATEMENT");
}
interp(FILE *sf) { /* INTERPRETER LOOP */
int interp(FILE *sf) { /* INTERPRETER LOOP */
for (;;) {
int code=setjmp(trap); /* RETURN ON ERROR */
if (code==1 && sf!=stdin) return 1; /* FILE SYNTAX ERROR */
Expand Down