shithub: libmujs

Download patch

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;