ref: f6c5c56b446123b1d3ee7865870091a060ddd7d1
parent: 2a027a1b21ace51301989dd4009f6a56d183df92
author: Tor Andersson <tor@ccxvii.net>
date: Fri Jan 17 09:58:03 EST 2014
Keep the current environment scope chain in the js_State struct. Create script (global/eval code) functions without a scope (they're not closures) and run them with js_eval so they can execute with the current scope chain. Normal functions still have a scope and are run with js_call.
--- a/jsrun.c
+++ b/jsrun.c
@@ -5,7 +5,7 @@
#include "jsrun.h"
#include "jsstate.h"
-static void jsR_run(js_State *J, js_Function *F, js_Environment *E);
+static void jsR_run(js_State *J, js_Function *F);
static js_Value stack[256];
static int top = 0;
@@ -296,13 +296,14 @@
return E;
}
-static js_Property *js_decvar(js_State *J, js_Environment *E, const char *name)
+static js_Property *js_decvar(js_State *J, const char *name)
{
- return jsR_setproperty(J, E->variables, name);
+ return jsR_setproperty(J, J->E->variables, name);
}
-static js_Property *js_getvar(js_State *J, js_Environment *E, const char *name)
+static js_Property *js_getvar(js_State *J, const char *name)
{
+ js_Environment *E = J->E;
do {
js_Property *ref = jsR_getproperty(J, E->variables, name);
if (ref)
@@ -312,8 +313,9 @@
return NULL;
}
-static js_Property *js_setvar(js_State *J, js_Environment *E, const char *name)
+static js_Property *js_setvar(js_State *J, const char *name)
{
+ js_Environment *E = J->E;
do {
js_Property *ref = jsR_getproperty(J, E->variables, name);
if (ref)
@@ -327,20 +329,23 @@
static void jsR_callfunction(js_State *J, int n, js_Function *F, js_Environment *scope)
{
- js_Environment *E;
+ js_Environment *saveE;
int i;
- E = jsR_newenvironment(J, jsR_newobject(J, JS_COBJECT), scope);
+ saveE = J->E;
+
+ J->E = jsR_newenvironment(J, jsR_newobject(J, JS_COBJECT), scope);
for (i = 0; i < n; i++) {
- js_Property *ref = js_decvar(J, E, F->params[i]);
+ js_Property *ref = js_decvar(J, F->params[i]);
if (i < n)
ref->value = js_tovalue(J, i + 1);
}
js_pop(J, n);
- jsR_run(J, F, E);
-
+ jsR_run(J, F);
js_rot3pop2(J);
+
+ J->E = saveE;
}
static void jsR_callcfunction(js_State *J, int n, js_CFunction F)
@@ -370,6 +375,20 @@
bot = savebot;
}
+void js_eval(js_State *J)
+{
+ js_Object *obj = js_toobject(J, -2);
+ int savebot = bot;
+ bot = top - 1;
+ if (obj->type == JS_CFUNCTION) {
+ jsR_run(J, obj->function);
+ js_rot3pop2(J);
+ }
+ else
+ jsR_error(J, "TypeError (not a script)");
+ bot = savebot;
+}
+
/* Main interpreter loop */
void js_dumpstack(js_State *J)
@@ -387,7 +406,7 @@
fprintf(stderr, "trap!\n");
}
-static void jsR_run(js_State *J, js_Function *F, js_Environment *E)
+static void jsR_run(js_State *J, js_Function *F)
{
js_Function **FT = F->funtab;
double *NT = F->numtab;
@@ -418,7 +437,7 @@
case OP_NUMBER: js_pushnumber(J, NT[*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_CLOSURE: js_pushobject(J, jsR_newfunction(J, FT[*pc++], J->E)); break;
case OP_NEWOBJECT: js_newobject(J); break;
case OP_NEWARRAY: js_newarray(J); break;
@@ -431,7 +450,7 @@
case OP_GLOBAL: js_pushobject(J, J->G); break;
case OP_FUNDEC:
- ref = js_decvar(J, E, ST[*pc++]);
+ ref = js_decvar(J, ST[*pc++]);
if (ref)
ref->value = js_tovalue(J, -1);
js_pop(J, 1);
@@ -438,12 +457,12 @@
break;
case OP_VARDEC:
- ref = js_decvar(J, E, ST[*pc++]);
+ ref = js_decvar(J, ST[*pc++]);
break;
case OP_GETVAR:
str = ST[*pc++];
- ref = js_getvar(J, E, str);
+ ref = js_getvar(J, str);
if (ref)
js_pushvalue(J, ref->value);
else
@@ -451,7 +470,7 @@
break;
case OP_SETVAR:
- ref = js_setvar(J, E, ST[*pc++]);
+ ref = js_setvar(J, ST[*pc++]);
if (ref)
ref->value = js_tovalue(J, -1);
break;
@@ -710,7 +729,7 @@
}
}
-int jsR_loadstring(js_State *J, const char *filename, const char *source, js_Environment *E)
+int jsR_loadscript(js_State *J, const char *filename, const char *source)
{
js_Ast *P;
js_Function *F;
@@ -724,7 +743,7 @@
jsP_freeparse(J);
if (!F) return 1;
- js_pushobject(J, jsR_newfunction(J, F, E));
+ js_pushobject(J, jsR_newfunction(J, F, NULL));
return 0;
}
--- a/jsrun.h
+++ b/jsrun.h
@@ -9,9 +9,10 @@
js_Environment *jsR_newenvironment(js_State *J, js_Object *variables, js_Environment *outer);
-int jsR_loadstring(js_State *J, const char *filename, const char *source, js_Environment *E);
+int jsR_loadscript(js_State *J, const char *filename, const char *source);
void js_call(js_State *J, int n);
+void js_eval(js_State *J);
void js_getglobal(js_State *J, const char *name);
void js_setglobal(js_State *J, const char *name);
--- a/jsstate.c
+++ b/jsstate.c
@@ -5,7 +5,7 @@
int js_loadstring(js_State *J, const char *source)
{
- return jsR_loadstring(J, "(string)", source, J->GE);
+ return jsR_loadscript(J, "(string)", source);
}
int js_loadfile(js_State *J, const char *filename)
@@ -41,7 +41,7 @@
s[n] = 0; /* zero-terminate string containing file data */
- t = jsR_loadstring(J, filename, s, J->GE);
+ t = jsR_loadscript(J, filename, s);
free(s);
fclose(f);
@@ -54,8 +54,8 @@
if (!rv) {
if (setjmp(J->jb))
return 1;
- js_pushglobal(J);
- js_call(J, 0);
+ js_dup(J, 0);
+ js_eval(J);
js_pop(J, 1);
}
return rv;
@@ -67,8 +67,8 @@
if (!rv) {
if (setjmp(J->jb))
return 1;
- js_pushglobal(J);
- js_call(J, 0);
+ js_dup(J, 0);
+ js_eval(J);
js_pop(J, 1);
}
return rv;
@@ -93,15 +93,14 @@
if (!js_isstring(J, -1))
return 1;
- // FIXME: use the real environment
// FIXME: return value if eval string is an expression
s = js_tostring(J, -1);
- if (jsR_loadstring(J, "(eval)", s, J->GE))
+ if (jsR_loadscript(J, "(eval)", s))
jsR_error(J, "SyntaxError (eval)");
- js_pushglobal(J);
- js_call(J, 0);
+ js_dup(J, 0); /* copy this */
+ js_eval(J); /* call with current scope chain */
return 1;
}
@@ -111,7 +110,7 @@
memset(J, 0, sizeof(*J));
J->G = jsR_newobject(J, JS_COBJECT);
- J->GE = jsR_newenvironment(J, J->G, NULL);
+ J->E = jsR_newenvironment(J, J->G, NULL);
js_pushcfunction(J, jsB_eval);
js_setglobal(J, "eval");
--- a/jsstate.h
+++ b/jsstate.h
@@ -30,7 +30,7 @@
/* runtime */
js_Object *G;
- js_Environment *GE;
+ js_Environment *E;
};
--- a/jsvalue.c
+++ b/jsvalue.c
@@ -5,7 +5,7 @@
{
js_Object *obj;
- if (v->type != JS_COBJECT)
+ if (v->type != JS_TOBJECT)
return *v;
obj = v->u.object;