Fix the shape of the outer API a bit. Implement eval.

This commit is contained in:
Tor Andersson
2014-01-16 21:36:54 +01:00
parent e01b4d02c0
commit 56042de82b
8 changed files with 130 additions and 95 deletions
+3 -1
View File
@@ -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 */
+3 -1
View File
@@ -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) {
-2
View File
@@ -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);
-70
View File
@@ -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;
}
+27 -17
View File
@@ -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);
}
+5
View File
@@ -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);
+90
View File
@@ -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");
+2 -4
View File
@@ -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);