ref: 7228ec51c423cd57413c2c1c9b65b288d0189f5b
parent: 288eef80e136441fe00bc618b523139cb6bb5bca
author: Tor Andersson <tor@ccxvii.net>
date: Thu Jan 16 12:04:29 EST 2014
Handle "this" by always keeping it in stack[0].
--- a/jscompile.c
+++ b/jscompile.c
@@ -357,12 +357,12 @@
break;
default:
cexp(J, F, fun);
- emit(J, F, OP_THIS);
+ emit(J, F, OP_GLOBAL);
break;
}
n = cargs(J, F, args);
emit(J, F, OP_CALL);
- emit(J, F, 1 + n);
+ emit(J, F, n);
}
static void cexp(JF, js_Ast *exp)
--- a/jscompile.h
+++ b/jscompile.h
@@ -26,6 +26,7 @@
OP_TRUE,
OP_FALSE,
OP_THIS,
+ OP_GLOBAL,
OP_FUNDEC, /* <closure> -S- */
OP_VARDEC, /* -S- */
--- a/jsdump.c
+++ b/jsdump.c
@@ -666,7 +666,18 @@
case JS_TBOOLEAN: printf(v.u.boolean ? "true" : "false"); break;
case JS_TNUMBER: printf("%.9g", v.u.number); break;
case JS_TSTRING: printf("'%s'", v.u.string); break;
- case JS_TOBJECT: printf("<object %p>", v.u.object); break;
+ case JS_TOBJECT:
+ switch (v.u.object->type) {
+ case JS_COBJECT: printf("object(%p)", v.u.object); break;
+ case JS_CARRAY: printf("array(%p)", v.u.object); break;
+ case JS_CFUNCTION: printf("function(%s)", v.u.object->function->name); break;
+ case JS_CCFUNCTION: printf("cfunction(%p)", v.u.object->cfunction); break;
+ case JS_CBOOLEAN: printf("boolean(%d)", v.u.object->primitive.boolean); break;
+ case JS_CNUMBER: printf("number(%g)", v.u.object->primitive.number); break;
+ case JS_CSTRING: printf("string('%s')", v.u.object->primitive.string); break;
+ default: printf("<unknown %p>", v.u.object); break;
+ }
+ break;
}
}
--- a/jsrun.c
+++ b/jsrun.c
@@ -8,7 +8,7 @@
static int top = 0;
static int bot = 0;
-static void js_call(js_State *J, int argc);
+static void jsR_run(js_State *J, js_Function *F, js_Environment *E);
static void js_dumpstack(js_State *J)
{
@@ -220,11 +220,57 @@
void js_trap(js_State *J)
{
+ fprintf(stderr, "trap!\n");
js_dumpstack(J);
}
-static void runfun(js_State *J, js_Function *F, js_Environment *E)
+static void jsR_callfunction(js_State *J, int n, js_Function *F, js_Environment *scope)
{
+ js_Environment *E;
+ int i;
+
+ 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]);
+ if (i < n)
+ ref->value = js_tovalue(J, i + 1);
+ }
+ js_pop(J, n);
+
+ jsR_run(J, F, E);
+
+ js_rot3pop2(J);
+}
+
+static void jsR_callcfunction(js_State *J, int n, js_CFunction F)
+{
+ int rv = F(J, n + 1);
+ if (rv) {
+ js_Value v = js_tovalue(J, -1);
+ js_pop(J, top - bot + 1);
+ js_pushvalue(J, v);
+ } else {
+ js_pop(J, top - bot + 1);
+ js_pushundefined(J);
+ }
+}
+
+void js_call(js_State *J, int n)
+{
+ js_Object *obj = js_toobject(J, -n - 2);
+ int savebot = bot;
+ bot = top - n - 1;
+ if (obj->type == JS_CFUNCTION)
+ jsR_callfunction(J, n, obj->function, obj->scope);
+ else if (obj->type == JS_CCFUNCTION)
+ jsR_callcfunction(J, n, obj->cfunction);
+ else
+ jsR_error(J, "TypeError (not a function)");
+ bot = savebot;
+}
+
+static void jsR_run(js_State *J, js_Function *F, js_Environment *E)
+{
js_Function **FT = F->funtab;
double *NT = F->numtab;
const char **ST = F->strtab;
@@ -263,7 +309,8 @@
case OP_TRUE: js_pushboolean(J, 1); break;
case OP_FALSE: js_pushboolean(J, 0); break;
- case OP_THIS: js_pushnull(J); break;
+ case OP_THIS: js_pushobject(J, js_toobject(J, 0)); break;
+ case OP_GLOBAL: js_pushobject(J, J->G); break;
case OP_FUNDEC:
ref = js_decvar(J, E, ST[*pc++]);
@@ -528,47 +575,6 @@
}
}
-static void js_call(js_State *J, int argc)
-{
- js_Environment *E;
- js_Property *ref;
- js_Function *F;
- js_Object *obj;
- int i;
- int savebot = bot;
-
- bot = top - argc;
-
- obj = js_toobject(J, -argc - 1);
-
- F = obj->function;
- if (F) {
- E = jsR_newenvironment(J, jsR_newobject(J, JS_COBJECT), obj->scope);
-
- for (i = 0; i < F->numparams; ++i) {
- ref = js_decvar(J, E, F->params[i]);
- if (i + 1 < argc)
- ref->value = js_tovalue(J, i + 1);
- }
- js_pop(J, argc + 1);
-
- runfun(J, F, E);
- } else {
- js_CFunction CF = obj->cfunction;
- i = CF(J, argc);
- if (i) {
- js_Value v = js_tovalue(J, -1);
- js_pop(J, top - bot + 1);
- js_pushvalue(J, v);
- } else {
- js_pop(J, top - bot + 1);
- js_pushundefined(J);
- }
- }
-
- bot = savebot;
-}
-
js_Environment *jsR_newenvironment(js_State *J, js_Object *vars, js_Environment *outer)
{
js_Environment *E = malloc(sizeof *E);
@@ -633,7 +639,8 @@
return;
}
- runfun(J, F, J->GE);
+ js_pushobject(J, J->G); /* initial "this" */
+ jsR_run(J, F, J->GE);
js_dumpobject(J, J->G);
js_dumpstack(J);