mirror of
https://github.com/ccxvii/mujs.git
synced 2026-09-25 19:23:34 +08:00
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).
This commit is contained in:
@@ -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;
|
||||
|
||||
+5
-3
@@ -376,21 +376,23 @@ static void ccall(JF, js_Ast *fun, js_Ast *args)
|
||||
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);
|
||||
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 @@ static void cstm(JF, js_Ast *stm)
|
||||
label(J, F, end);
|
||||
break;
|
||||
|
||||
// label
|
||||
// break
|
||||
// continue
|
||||
|
||||
@@ -687,7 +690,6 @@ static void cstm(JF, js_Ast *stm)
|
||||
break;
|
||||
|
||||
// try
|
||||
// label
|
||||
|
||||
case STM_DEBUGGER:
|
||||
emit(J, F, OP_DEBUGGER);
|
||||
|
||||
+2
-1
@@ -6,6 +6,7 @@ enum
|
||||
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 @@ enum
|
||||
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,
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ struct js_Value
|
||||
const char *string;
|
||||
js_Object *object;
|
||||
js_Closure *closure;
|
||||
js_CFunction *cfunction;
|
||||
js_CFunction cfunction;
|
||||
} u;
|
||||
js_ValueType type;
|
||||
};
|
||||
|
||||
@@ -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 @@ void js_pushobject(js_State *J, js_Object *v)
|
||||
++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 @@ int js_toboolean(js_State *J, int idx)
|
||||
{
|
||||
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 @@ int js_toboolean(js_State *J, int idx)
|
||||
|
||||
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 @@ double js_tointeger(js_State *J, int idx)
|
||||
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 @@ const char *js_tostring(js_State *J, int idx)
|
||||
|
||||
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 @@ void js_dup2(js_State *J)
|
||||
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 @@ static void runfun(js_State *J, js_Function *F, js_Object *E)
|
||||
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,7 +268,8 @@ static void runfun(js_State *J, js_Function *F, js_Object *E)
|
||||
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 @@ static void runfun(js_State *J, js_Function *F, js_Object *E)
|
||||
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_error(js_State *J, const char *message)
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user