diff --git a/js.h b/js.h index 7080792..9b71634 100644 --- a/js.h +++ b/js.h @@ -41,8 +41,10 @@ void js_close(js_State *J); int js_error(js_State *J, const char *fmt, ...); -int js_loadstring(js_State *J, const char *s); +int js_loadstring(js_State *J, const char *source); int js_loadfile(js_State *J, const char *filename); +int js_dostring(js_State *J, const char *source); +int js_dofile(js_State *J, const char *filename); /* binding API: TODO: move from jsrun.h */ diff --git a/jscompile.c b/jscompile.c index cabe489..7147bc3 100644 --- a/jscompile.c +++ b/jscompile.c @@ -7,6 +7,8 @@ #define JF js_State *J, js_Function *F +JS_NORETURN int jsC_error(js_State *J, js_Ast *node, const char *fmt, ...); + static void cfunbody(JF, js_Ast *name, js_Ast *params, js_Ast *body); static void cexp(JF, js_Ast *exp); static void cstmlist(JF, js_Ast *list); @@ -754,7 +756,7 @@ int jsC_error(js_State *J, js_Ast *node, const char *fmt, ...) longjmp(J->jb, 1); } -void jsC_freecompile(js_State *J) +static void jsC_freecompile(js_State *J) { js_Function *F = J->fun; while (F) { diff --git a/jscompile.h b/jscompile.h index 5aa8483..85645b8 100644 --- a/jscompile.h +++ b/jscompile.h @@ -109,8 +109,6 @@ struct js_Function }; js_Function *jsC_compile(js_State *J, js_Ast *prog); -void jsC_freecompile(js_State *J); -JS_NORETURN int jsC_error(js_State *J, js_Ast *node, const char *fmt, ...); void jsC_dumpfunction(js_State *J, js_Function *fun); diff --git a/jsload.c b/jsload.c deleted file mode 100644 index 1dbf78f..0000000 --- a/jsload.c +++ /dev/null @@ -1,70 +0,0 @@ -#include "js.h" -#include "jsparse.h" -#include "jscompile.h" -#include "jsobject.h" -#include "jsrun.h" - -static int jsP_loadstring(js_State *J, const char *filename, const char *source) -{ - js_Ast *prog = jsP_parse(J, filename, source); - if (prog) { - js_Function *fun; - jsP_optimize(J, prog); - //jsP_dumpsyntax(J, prog); - //jsP_dumplist(J, prog); - fun = jsC_compile(J, prog); - if (fun) { - jsC_dumpfunction(J, fun); - jsR_runfunction(J, fun); - } - jsC_freecompile(J); - jsP_freeparse(J); - return 0; - } - return 1; -} - -int js_loadstring(js_State *J, const char *source) -{ - return jsP_loadstring(J, "(string)", source); -} - -int js_loadfile(js_State *J, const char *filename) -{ - FILE *f; - char *s; - int n, t; - - f = fopen(filename, "r"); - if (!f) { - return js_error(J, "cannot open file: '%s'", filename); - } - - if (fseek(f, 0, SEEK_END) < 0) { - fclose(f); - return js_error(J, "cannot seek in file: '%s'", filename); - } - n = ftell(f); - fseek(f, 0, SEEK_SET); - - s = malloc(n + 1); /* add space for string terminator */ - if (!s) { - fclose(f); - return js_error(J, "cannot allocate storage for file contents: '%s'", filename); - } - - t = fread(s, 1, n, f); - if (t != n) { - free(s); - fclose(f); - return js_error(J, "cannot read data from file: '%s'", filename); - } - - s[n] = 0; /* zero-terminate string containing file data */ - - t = jsP_loadstring(J, filename, s); - - free(s); - fclose(f); - return t; -} diff --git a/jsrun.c b/jsrun.c index 57fef50..c6638e1 100644 --- a/jsrun.c +++ b/jsrun.c @@ -1,5 +1,6 @@ #include "js.h" #include "jsobject.h" +#include "jsparse.h" #include "jscompile.h" #include "jsrun.h" #include "jsstate.h" @@ -88,7 +89,7 @@ void js_pushstring(js_State *J, const char *v) ++top; } -void jsR_pushliteral(js_State *J, const char *v) +void js_pushliteral(js_State *J, const char *v) { stack[top].type = JS_TSTRING; stack[top].u.string = v; @@ -102,6 +103,11 @@ void js_pushobject(js_State *J, js_Object *v) ++top; } +void js_pushglobal(js_State *J) +{ + js_pushobject(J, J->G); +} + void js_newobject(js_State *J) { js_pushobject(J, jsR_newobject(J, JS_COBJECT)); @@ -298,7 +304,7 @@ static void jsR_run(js_State *J, js_Function *F, js_Environment *E) case OP_NUMBER_1: js_pushnumber(J, 1); break; case OP_NUMBER_X: js_pushnumber(J, *pc++); break; case OP_NUMBER: js_pushnumber(J, NT[*pc++]); break; - case OP_STRING: jsR_pushliteral(J, ST[*pc++]); break; + case OP_STRING: js_pushliteral(J, ST[*pc++]); break; case OP_CLOSURE: js_pushobject(J, jsR_newfunction(J, FT[*pc++], E)); break; case OP_NEWOBJECT: js_newobject(J); break; @@ -378,7 +384,7 @@ static void jsR_run(js_State *J, js_Function *F, js_Environment *E) ref = jsR_nextproperty(J, obj, js_tostring(J, -1)); if (ref) { js_pop(J, 1); - jsR_pushliteral(J, ref->name); + js_pushliteral(J, ref->name); js_pushboolean(J, 1); } else { js_pop(J, 2); @@ -583,6 +589,24 @@ js_Environment *jsR_newenvironment(js_State *J, js_Object *vars, js_Environment return E; } +int jsR_loadstring(js_State *J, const char *filename, const char *source, js_Environment *E) +{ + js_Ast *P; + js_Function *F; + + // TODO: push exception stack + + P = jsP_parse(J, filename, source); + if (!P) return 1; + jsP_optimize(J, P); + F = jsC_compile(J, P); + jsP_freeparse(J); + if (!F) return 1; + + js_pushobject(J, jsR_newfunction(J, F, E)); + return 0; +} + void js_setglobal(js_State *J, const char *name) { js_Property *ref = jsR_setproperty(J, J->G, name); @@ -631,17 +655,3 @@ void jsR_error(js_State *J, const char *fmt, ...) longjmp(J->jb, 1); } - -void jsR_runfunction(js_State *J, js_Function *F) -{ - if (setjmp(J->jb)) { - js_dumpobject(J, J->G); - return; - } - - js_pushobject(J, J->G); /* initial "this" */ - jsR_run(J, F, J->GE); - - js_dumpobject(J, J->G); - js_dumpstack(J); -} diff --git a/jsrun.h b/jsrun.h index 199811c..9edb339 100644 --- a/jsrun.h +++ b/jsrun.h @@ -14,8 +14,13 @@ js_Property *js_decvar(js_State *J, js_Environment *E, const char *name); js_Property *js_getvar(js_State *J, js_Environment *E, const char *name); js_Property *js_setvar(js_State *J, js_Environment *E, const char *name); +int jsR_loadstring(js_State *J, const char *filename, const char *source, js_Environment *E); + void jsR_runfunction(js_State *J, js_Function *F); +void js_call(js_State *J, int n); + +void js_pushglobal(js_State *J); void js_pushundefined(js_State *J); void js_pushnull(js_State *J); void js_pushboolean(js_State *J, int v); diff --git a/jsstate.c b/jsstate.c index 0871cba..cb38a3d 100644 --- a/jsstate.c +++ b/jsstate.c @@ -3,6 +3,77 @@ #include "jsrun.h" #include "jsstate.h" +int js_loadstring(js_State *J, const char *source) +{ + return jsR_loadstring(J, "(string)", source, J->GE); +} + +int js_loadfile(js_State *J, const char *filename) +{ + FILE *f; + char *s; + int n, t; + + f = fopen(filename, "r"); + if (!f) { + return js_error(J, "cannot open file: '%s'", filename); + } + + if (fseek(f, 0, SEEK_END) < 0) { + fclose(f); + return js_error(J, "cannot seek in file: '%s'", filename); + } + n = ftell(f); + fseek(f, 0, SEEK_SET); + + s = malloc(n + 1); /* add space for string terminator */ + if (!s) { + fclose(f); + return js_error(J, "cannot allocate storage for file contents: '%s'", filename); + } + + t = fread(s, 1, n, f); + if (t != n) { + free(s); + fclose(f); + return js_error(J, "cannot read data from file: '%s'", filename); + } + + s[n] = 0; /* zero-terminate string containing file data */ + + t = jsR_loadstring(J, filename, s, J->GE); + + free(s); + fclose(f); + return t; +} + +int js_dostring(js_State *J, const char *source) +{ + int rv = js_loadstring(J, source); + if (!rv) { + if (setjmp(J->jb)) + return 1; + js_pushglobal(J); + js_call(J, 0); + js_pop(J, 1); + } + return rv; +} + +int js_dofile(js_State *J, const char *filename) +{ + int rv = js_loadfile(J, filename); + if (!rv) { + if (setjmp(J->jb)) + return 1; + js_pushglobal(J); + js_call(J, 0); + js_pop(J, 1); + } + return rv; +} + static int jsB_print(js_State *J, int argc) { int i; @@ -15,6 +86,22 @@ static int jsB_print(js_State *J, int argc) return 0; } +static int jsB_eval(js_State *J, int argc) +{ + const char *s; + if (!js_isstring(J, -1)) + return 1; + + // FIXME: need the real environment! + s = js_tostring(J, -1); + if (jsR_loadstring(J, "(eval)", s, J->GE)) + jsR_error(J, "SyntaxError (eval)"); + + js_pushglobal(J); + js_call(J, 0); + return 1; +} + js_State *js_newstate(void) { js_State *J = malloc(sizeof *J); @@ -23,6 +110,9 @@ js_State *js_newstate(void) J->G = jsR_newobject(J, JS_COBJECT); J->GE = jsR_newenvironment(J, J->G, NULL); + js_pushcfunction(J, jsB_eval); + js_setglobal(J, "eval"); + js_pushcfunction(J, jsB_print); js_setglobal(J, "print"); diff --git a/main.c b/main.c index 140dda3..20f623f 100644 --- a/main.c +++ b/main.c @@ -8,10 +8,8 @@ main(int argc, char **argv) J = js_newstate(); - for (i = 1; i < argc; ++i) { - js_loadfile(J, argv[i]); - // js_run(J); - } + for (i = 1; i < argc; ++i) + js_dofile(J, argv[i]); js_close(J);