shithub: libmujs

Download patch

ref: 47e88ac80569849e458b22b67341e19acd9af5a7
parent: 6b1906f3b53c3799dcef6e3e87e05a25ef7479c4
author: Tor Andersson <tor@ccxvii.net>
date: Tue Jan 14 20:34:30 EST 2014

Calculate stack index for both positive and negative numbers.

Call all functions with "this" as the first argument.

Negative indexes count from the top, positive indexes count from
the current function call frame (so arguments start at 0).

--- a/js.h
+++ b/js.h
@@ -12,7 +12,7 @@
 typedef struct js_State js_State;
 
 typedef enum js_ValueType js_ValueType;
-typedef int (*js_CFunction)(js_State *J);
+typedef int (*js_CFunction)(js_State *J, int n);
 typedef struct js_Ast js_Ast;
 typedef struct js_Closure js_Closure;
 typedef struct js_Function js_Function;
--- a/jscompile.c
+++ b/jscompile.c
@@ -376,6 +376,7 @@
 		emit(J, F, OP_DUP);
 		cexp(J, F, fun->b);
 		emit(J, F, OP_GETPROP);
+		emit(J, F, OP_ROT2);
 		break;
 	case EXP_MEMBER:
 		cexp(J, F, fun->a);
@@ -382,15 +383,16 @@
 		emit(J, F, OP_DUP);
 		emitstring(J, F, OP_STRING, fun->b->string);
 		emit(J, F, OP_GETPROP);
+		emit(J, F, OP_ROT2);
 		break;
 	default:
-		emit(J, F, OP_THIS);
 		cexp(J, F, fun);
+		emit(J, F, OP_THIS);
 		break;
 	}
 	n = cargs(J, F, args);
 	emit(J, F, OP_CALL);
-	emit(J, F, n);
+	emit(J, F, 1 + n);
 }
 
 static void cexp(JF, js_Ast *exp)
@@ -661,6 +663,7 @@
 		label(J, F, end);
 		break;
 
+	// label
 	// break
 	// continue
 
@@ -687,7 +690,6 @@
 		break;
 
 	// try
-	// label
 
 	case STM_DEBUGGER:
 		emit(J, F, OP_DEBUGGER);
--- a/jscompile.h
+++ b/jscompile.h
@@ -6,6 +6,7 @@
 	OP_POP,		/* A -- */
 	OP_DUP,		/* A -- A A */
 	OP_DUP2,	/* A B -- A B A B */
+	OP_ROT2,	/* A B -- B A */
 	OP_ROT3,	/* A B C -- C A B */
 	OP_DUP1ROT4,	/* A B C -- C A B C */
 
@@ -39,7 +40,7 @@
 	OP_DELPROP,	/* <obj> <name> -- <success> */
 	OP_NEXTPROP,	/* <obj> <name> -- <obj> <name+1> true || false */
 
-	OP_CALL,	/* <thisvalue> <closure> <args...> -(numargs)- <returnvalue> */
+	OP_CALL,	/* <closure> <this> <args...> -(numargs)- <returnvalue> */
 	OP_NEW,		/* <closure> <args...> -(numargs)- <returnvalue> */
 
 	OP_VOID,
--- a/jsobject.h
+++ b/jsobject.h
@@ -20,7 +20,7 @@
 		const char *string;
 		js_Object *object;
 		js_Closure *closure;
-		js_CFunction *cfunction;
+		js_CFunction cfunction;
 	} u;
 	js_ValueType type;
 };
--- a/jsrun.c
+++ b/jsrun.c
@@ -6,6 +6,7 @@
 
 static js_Value stack[256];
 static int top = 0;
+static int bot = 0;
 
 static inline double tointeger(double n)
 {
@@ -82,21 +83,34 @@
 	++top;
 }
 
+static int stackidx(js_State *J, int idx)
+{
+	if (idx < 0)
+		return top + idx;
+	return bot + idx;
+}
+
 int js_isundefined(js_State *J, int idx)
 {
-	idx += top;
+	idx = stackidx(J, idx);
 	return stack[idx].type == JS_TUNDEFINED;
 }
 
 int js_isstring(js_State *J, int idx)
 {
-	idx += top;
+	idx = stackidx(J, idx);
 	return stack[idx].type == JS_TSTRING;
 }
 
+int js_iscfunction(js_State *J, int idx)
+{
+	idx = stackidx(J, idx);
+	return stack[idx].type == JS_TCFUNCTION;
+}
+
 js_Value js_tovalue(js_State *J, int idx)
 {
-	idx += top;
+	idx = stackidx(J, idx);
 	return stack[idx];
 }
 
@@ -104,7 +118,7 @@
 {
 	const char *s;
 	double n;
-	idx += top;
+	idx = stackidx(J, idx);
 	switch (stack[idx].type) {
 	case JS_TUNDEFINED: return 0;
 	case JS_TNULL: return 0;
@@ -117,7 +131,7 @@
 
 double js_tonumber(js_State *J, int idx)
 {
-	idx += top;
+	idx = stackidx(J, idx);
 	switch (stack[idx].type) {
 	case JS_TUNDEFINED: return NAN;
 	case JS_TNULL: return 0;
@@ -133,20 +147,10 @@
 	return toint32(js_tonumber(J, idx));
 }
 
-int js_toint32(js_State *J, int idx)
-{
-	return toint32(js_tonumber(J, idx));
-}
-
-unsigned int js_touint32(js_State *J, int idx)
-{
-	return toint32(js_tonumber(J, idx));
-}
-
 const char *js_tostring(js_State *J, int idx)
 {
 	char buf[20];
-	idx += top;
+	idx = stackidx(J, idx);
 	switch (stack[idx].type) {
 	case JS_TUNDEFINED: return "undefined";
 	case JS_TNULL: return "null";
@@ -159,7 +163,7 @@
 
 js_Object *js_toobject(js_State *J, int idx)
 {
-	idx += top;
+	idx = stackidx(J, idx);
 	switch (stack[idx].type) {
 	case JS_TUNDEFINED: jsR_error(J, "TypeError");
 	case JS_TNULL: jsR_error(J, "TypeError");
@@ -190,6 +194,14 @@
 	top += 2;
 }
 
+void js_rot2(js_State *J)
+{
+	/* A B -> B A */
+	js_Value tmp = stack[top-1];	/* A B (B) */
+	stack[top-1] = stack[top-2];	/* A A */
+	stack[top-2] = tmp;		/* B A */
+}
+
 void js_rot3(js_State *J)
 {
 	/* A B C -> C A B */
@@ -241,6 +253,7 @@
 		case OP_POP: js_pop(J, 1); break;
 		case OP_DUP: js_dup(J); break;
 		case OP_DUP2: js_dup2(J); break;
+		case OP_ROT2: js_rot2(J); break;
 		case OP_ROT3: js_rot3(J); break;
 		case OP_DUP1ROT4: js_dup1rot4(J); break;
 
@@ -255,8 +268,9 @@
 		case OP_NULL: js_pushnull(J); break;
 		case OP_TRUE: js_pushboolean(J, 1); break;
 		case OP_FALSE: js_pushboolean(J, 0); break;
-		// case OP_THIS: break;
 
+		case OP_THIS: js_pushnull(J); break;
+
 		case OP_NEWOBJECT: js_pushobject(J, js_newobject(J)); break;
 		case OP_NEWARRAY: js_pushobject(J, js_newobject(J)); break;
 
@@ -323,7 +337,6 @@
 				ref = js_firstproperty(J, obj);
 			else
 				ref = js_nextproperty(J, obj, js_tostring(J, -1));
-			printf("nextprop -> %s\n", ref ? ref->name : "(end)");
 			if (ref) {
 				js_pop(J, 1);
 				js_pushstring(J, ref->name);
@@ -517,14 +530,14 @@
 
 void jsR_runfunction(js_State *J, js_Function *F)
 {
-	js_Object *varenv = js_newobject(J);
+	js_Object *E = js_newobject(J);
 
 	if (setjmp(J->jb)) {
-		js_dumpobject(J, varenv);
+		js_dumpobject(J, E);
 		return;
 	}
 
-	runfun(J, F, varenv);
+	runfun(J, F, E);
 
-	js_dumpobject(J, varenv);
+	js_dumpobject(J, E);
 }