mirror of
https://github.com/antirez/aocla
synced 2025-01-13 20:01:40 +01:00
Run program from file.
This commit is contained in:
parent
54807bb9fc
commit
58b779f2ef
1 changed files with 100 additions and 8 deletions
108
aocla.c
108
aocla.c
|
@ -157,7 +157,7 @@ int issymbol(int c) {
|
||||||
* of parse error, it is possible to pass NULL.
|
* of parse error, it is possible to pass NULL.
|
||||||
*
|
*
|
||||||
* Returned object has a ref count of 1. */
|
* Returned object has a ref count of 1. */
|
||||||
obj *newList(aoclactx *ctx, const char *s, const char **next) {
|
obj *parseObject(aoclactx *ctx, const char *s, const char **next) {
|
||||||
obj *o = myalloc(sizeof(*o));
|
obj *o = myalloc(sizeof(*o));
|
||||||
o->refcount = 1;
|
o->refcount = 1;
|
||||||
while(isspace(s[0])) s++;
|
while(isspace(s[0])) s++;
|
||||||
|
@ -189,7 +189,7 @@ obj *newList(aoclactx *ctx, const char *s, const char **next) {
|
||||||
|
|
||||||
/* Parse the current sub-element recursively. */
|
/* Parse the current sub-element recursively. */
|
||||||
const char *nextptr;
|
const char *nextptr;
|
||||||
obj *element = newList(ctx,s,&nextptr);
|
obj *element = parseObject(ctx,s,&nextptr);
|
||||||
if (element == NULL) {
|
if (element == NULL) {
|
||||||
release(o);
|
release(o);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -613,7 +613,7 @@ void addProc(aoclactx *ctx, const char *name, int(*cproc)(aoclactx *), obj *list
|
||||||
/* Add a procedure represented by the Aocla code 'prog', that must
|
/* Add a procedure represented by the Aocla code 'prog', that must
|
||||||
* be a valid list. On error (not valid list) 1 is returned, otherwise 0. */
|
* be a valid list. On error (not valid list) 1 is returned, otherwise 0. */
|
||||||
int addProcString(aoclactx *ctx, const char *name, const char *prog) {
|
int addProcString(aoclactx *ctx, const char *name, const char *prog) {
|
||||||
obj *list = newList(NULL,prog,NULL);
|
obj *list = parseObject(NULL,prog,NULL);
|
||||||
if (prog == NULL) return 1;
|
if (prog == NULL) return 1;
|
||||||
addProc(ctx,name,NULL,list);
|
addProc(ctx,name,NULL,list);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -640,8 +640,8 @@ int procBasicMath(aoclactx *ctx) {
|
||||||
/* Implements ==, >=, <=, !=. */
|
/* Implements ==, >=, <=, !=. */
|
||||||
int procCompare(aoclactx *ctx) {
|
int procCompare(aoclactx *ctx) {
|
||||||
if (checkStackLen(ctx,2)) return 1;
|
if (checkStackLen(ctx,2)) return 1;
|
||||||
obj *a = stackPop(ctx);
|
|
||||||
obj *b = stackPop(ctx);
|
obj *b = stackPop(ctx);
|
||||||
|
obj *a = stackPop(ctx);
|
||||||
int cmp = compare(a,b);
|
int cmp = compare(a,b);
|
||||||
if (cmp == COMPARE_TYPE_MISMATCH) {
|
if (cmp == COMPARE_TYPE_MISMATCH) {
|
||||||
stackPush(ctx,b);
|
stackPush(ctx,b);
|
||||||
|
@ -692,6 +692,45 @@ int procDef(aoclactx *ctx) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* if and ifelse. */
|
||||||
|
int procIf(aoclactx *ctx) {
|
||||||
|
int e = ctx->frame->curproc->name[2] == 'e'; /* ifelse? */
|
||||||
|
if (e) {
|
||||||
|
if (checkStackType(ctx,3,OBJ_TYPE_LIST,OBJ_TYPE_LIST,OBJ_TYPE_LIST))
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
if (checkStackType(ctx,2,OBJ_TYPE_LIST,OBJ_TYPE_LIST))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj *elsebranch, *ifbranch, *cond;
|
||||||
|
elsebranch = e ? stackPop(ctx) : NULL;
|
||||||
|
ifbranch = stackPop(ctx);
|
||||||
|
cond = stackPop(ctx);
|
||||||
|
|
||||||
|
/* Evaluate the conditional program. */
|
||||||
|
if (eval(ctx,cond)) goto rterr;
|
||||||
|
if (checkStackType(ctx,1,OBJ_TYPE_BOOL)) goto rterr;
|
||||||
|
obj *condres = stackPop(ctx);
|
||||||
|
int res = condres->istrue;
|
||||||
|
release(condres);
|
||||||
|
|
||||||
|
/* Now eval the true or false branch depending on the
|
||||||
|
* result. */
|
||||||
|
if (res) {
|
||||||
|
if (eval(ctx,ifbranch)) goto rterr;
|
||||||
|
} else if (e) {
|
||||||
|
if (eval(ctx,elsebranch)) goto rterr;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
rterr: /* Run time error. */
|
||||||
|
release(cond);
|
||||||
|
release(ifbranch);
|
||||||
|
release(elsebranch);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
void loadLibrary(aoclactx *ctx) {
|
void loadLibrary(aoclactx *ctx) {
|
||||||
addProc(ctx,"+",procBasicMath,NULL);
|
addProc(ctx,"+",procBasicMath,NULL);
|
||||||
addProc(ctx,"-",procBasicMath,NULL);
|
addProc(ctx,"-",procBasicMath,NULL);
|
||||||
|
@ -705,6 +744,8 @@ void loadLibrary(aoclactx *ctx) {
|
||||||
addProc(ctx,"!=",procCompare,NULL);
|
addProc(ctx,"!=",procCompare,NULL);
|
||||||
addProc(ctx,"sort",procSortList,NULL);
|
addProc(ctx,"sort",procSortList,NULL);
|
||||||
addProc(ctx,"def",procDef,NULL);
|
addProc(ctx,"def",procDef,NULL);
|
||||||
|
addProc(ctx,"if",procIf,NULL);
|
||||||
|
addProc(ctx,"ifelse",procIf,NULL);
|
||||||
addProcString(ctx,"dup","[(x) $x $x]");
|
addProcString(ctx,"dup","[(x) $x $x]");
|
||||||
addProcString(ctx,"swap","[(x y) $y $x]");
|
addProcString(ctx,"swap","[(x y) $y $x]");
|
||||||
addProcString(ctx,"drop","[(_)]");
|
addProcString(ctx,"drop","[(_)]");
|
||||||
|
@ -732,9 +773,9 @@ void repl(void) {
|
||||||
buf[l] = ']';
|
buf[l] = ']';
|
||||||
buf[l+1] = 0;
|
buf[l+1] = 0;
|
||||||
|
|
||||||
obj *list = newList(ctx,buf,NULL);
|
obj *list = parseObject(ctx,buf,NULL);
|
||||||
if (!list) {
|
if (!list) {
|
||||||
printf("Parsing string: %s\n", ctx->errstr);
|
printf("Parsing program: %s\n", ctx->errstr);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (eval(ctx,list)) {
|
if (eval(ctx,list)) {
|
||||||
|
@ -746,14 +787,65 @@ void repl(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void evalFile(const char *filename, char **argv, int argc) {
|
/* Execute the program contained in the specified filename.
|
||||||
|
* Return 1 on error, 0 otherwise. */
|
||||||
|
int evalFile(const char *filename, char **argv, int argc) {
|
||||||
|
FILE *fp = fopen(filename,"r");
|
||||||
|
if (!fp) {
|
||||||
|
perror("Opening file");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read file into buffer. */
|
||||||
|
int incrlen = 1024; /* How much to allocate when we are out of buffer. */
|
||||||
|
char *buf = myalloc(incrlen);
|
||||||
|
size_t buflen = 1, nread;
|
||||||
|
size_t leftspace = incrlen-buflen;
|
||||||
|
buf[0] = '[';
|
||||||
|
while((nread = fread(buf+buflen,1,leftspace,fp)) > 0) {
|
||||||
|
buflen += nread;
|
||||||
|
leftspace -= nread;
|
||||||
|
if (leftspace == 0) {
|
||||||
|
buf = myrealloc(buf,buflen+incrlen);
|
||||||
|
leftspace += incrlen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (leftspace < 2) buf = myrealloc(buf,buflen+2);
|
||||||
|
buf[buflen++] = ']';
|
||||||
|
buf[buflen++] = 0;
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
/* Parse the program before eval(). */
|
||||||
|
aoclactx *ctx = newInterpreter();
|
||||||
|
obj *o = parseObject(ctx,buf,NULL);
|
||||||
|
free(buf);
|
||||||
|
if (!o) {
|
||||||
|
printf("Parsing program: %s\n", ctx->errstr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Before evaluating the program, let's push on the arguments
|
||||||
|
* we received on the stack. */
|
||||||
|
for (int j = 0; j < argc; j++) {
|
||||||
|
o = parseObject(NULL,argv[j],NULL);
|
||||||
|
if (!o) {
|
||||||
|
printf("Parsing command line argument: %s\n", ctx->errstr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
stackPush(ctx,o);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Run the program. */
|
||||||
|
int retval = eval(ctx,o);
|
||||||
|
release(o);
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
if (argc == 1) {
|
if (argc == 1) {
|
||||||
repl();
|
repl();
|
||||||
} else if (argc >= 2) {
|
} else if (argc >= 2) {
|
||||||
evalFile(argv[1],argv+1,argc-1);
|
if (evalFile(argv[1],argv+1,argc-1)) return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue