Add object property accessor functions to public API.

This commit is contained in:
Tor Andersson
2014-01-17 03:03:10 +01:00
parent 56042de82b
commit b595422da9
6 changed files with 166 additions and 83 deletions
+1
View File
@@ -79,6 +79,7 @@ js_Object *jsR_toobject(js_State *J, const js_Value *v);
/* jsproperty.c */
js_Object *jsR_newobject(js_State *J, js_Class type);
js_Property *jsR_getownproperty(js_State *J, js_Object *obj, const char *name);
js_Property *jsR_getproperty(js_State *J, js_Object *obj, const char *name);
js_Property *jsR_setproperty(js_State *J, js_Object *obj, const char *name);
js_Property *jsR_nextproperty(js_State *J, js_Object *obj, const char *name);
+12 -1
View File
@@ -142,11 +142,22 @@ js_Object *jsR_newobject(js_State *J, js_Class type)
return obj;
}
js_Property *jsR_getproperty(js_State *J, js_Object *obj, const char *name)
js_Property *jsR_getownproperty(js_State *J, js_Object *obj, const char *name)
{
return lookup(obj->properties, name);
}
js_Property *jsR_getproperty(js_State *J, js_Object *obj, const char *name)
{
do {
js_Property *ref = lookup(obj->properties, name);
if (ref)
return ref;
obj = obj->prototype;
} while (obj);
return NULL;
}
js_Property *jsR_setproperty(js_State *J, js_Object *obj, const char *name)
{
js_Property *result;
+136 -71
View File
@@ -5,22 +5,12 @@
#include "jsrun.h"
#include "jsstate.h"
static void jsR_run(js_State *J, js_Function *F, js_Environment *E);
static js_Value stack[256];
static int top = 0;
static int bot = 0;
static void jsR_run(js_State *J, js_Function *F, js_Environment *E);
static void js_dumpstack(js_State *J)
{
int i;
for (i = 0; i < top; ++i) {
printf("stack %d: ", i);
js_dumpvalue(J, stack[i]);
putchar('\n');
}
}
static inline double tointeger(double n)
{
double sign = n < 0 ? -1 : 1;
@@ -50,6 +40,15 @@ static inline unsigned int touint32(double n)
return toint32(n);
}
/* Push and read stack values stack */
static int stackidx(js_State *J, int idx)
{
if (idx < 0)
return top + idx;
return bot + idx;
}
static void js_pushvalue(js_State *J, js_Value v)
{
stack[top] = v;
@@ -123,13 +122,6 @@ void js_pushcfunction(js_State *J, js_CFunction v)
js_pushobject(J, jsR_newcfunction(J, v));
}
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 = stackidx(J, idx);
@@ -172,14 +164,17 @@ js_Object *js_toobject(js_State *J, int idx)
return jsR_toobject(J, &stack[idx]);
}
/* Stack manipulation */
void js_pop(js_State *J, int n)
{
top -= n;
}
void js_dup(js_State *J)
void js_dup(js_State *J, int idx)
{
stack[top] = stack[top-1];
idx = stackidx(J, idx);
stack[top] = stack[idx];
++top;
}
@@ -224,12 +219,106 @@ void js_dup1rot4(js_State *J)
++top;
}
void js_trap(js_State *J)
/* Global and object property accessors */
void js_getglobal(js_State *J, const char *name)
{
fprintf(stderr, "trap!\n");
js_dumpstack(J);
js_Property *ref = jsR_getproperty(J, J->G, name);
if (ref)
js_pushvalue(J, ref->value);
else
js_pushundefined(J);
}
void js_setglobal(js_State *J, const char *name)
{
js_Property *ref = jsR_setproperty(J, J->G, name);
if (ref)
ref->value = js_tovalue(J, -1);
js_pop(J, 1);
}
void js_getownproperty(js_State *J, int idx, const char *name)
{
js_Object *obj = js_toobject(J, idx);
js_Property *ref = jsR_getownproperty(J, obj, name);
if (ref)
js_pushvalue(J, ref->value);
else
js_pushundefined(J);
}
void js_getproperty(js_State *J, int idx, const char *name)
{
js_Object *obj = js_toobject(J, idx);
js_Property *ref = jsR_getproperty(J, obj, name);
if (ref)
js_pushvalue(J, ref->value);
else
js_pushundefined(J);
}
void js_setproperty(js_State *J, int idx, const char *name)
{
js_Object *obj = js_toobject(J, idx);
js_Property *ref = jsR_setproperty(J, obj, name);
if (ref)
ref->value = js_tovalue(J, -1);
js_pop(J, 1);
}
int js_nextproperty(js_State *J, int idx)
{
js_Object *obj = js_toobject(J, idx);
js_Property *ref = jsR_nextproperty(J, obj, js_tostring(J, -1));
js_pop(J, 1);
if (ref) {
js_pushliteral(J, ref->name);
js_pushvalue(J, ref->value);
return 1;
}
return 0;
}
/* Environment records */
js_Environment *jsR_newenvironment(js_State *J, js_Object *vars, js_Environment *outer)
{
js_Environment *E = malloc(sizeof *E);
E->outer = outer;
E->variables = vars;
return E;
}
static js_Property *js_decvar(js_State *J, js_Environment *E, const char *name)
{
return jsR_setproperty(J, E->variables, name);
}
static js_Property *js_getvar(js_State *J, js_Environment *E, const char *name)
{
do {
js_Property *ref = jsR_getproperty(J, E->variables, name);
if (ref)
return ref;
E = E->outer;
} while (E);
return NULL;
}
static js_Property *js_setvar(js_State *J, js_Environment *E, const char *name)
{
do {
js_Property *ref = jsR_getproperty(J, E->variables, name);
if (ref)
return ref;
E = E->outer;
} while (E);
return jsR_setproperty(J, J->G, name);
}
/* Function calls */
static void jsR_callfunction(js_State *J, int n, js_Function *F, js_Environment *scope)
{
js_Environment *E;
@@ -275,6 +364,23 @@ void js_call(js_State *J, int n)
bot = savebot;
}
/* Main interpreter loop */
void js_dumpstack(js_State *J)
{
int i;
for (i = 0; i < top; ++i) {
printf("stack %d: ", i);
js_dumpvalue(J, stack[i]);
putchar('\n');
}
}
void js_trap(js_State *J)
{
fprintf(stderr, "trap!\n");
}
static void jsR_run(js_State *J, js_Function *F, js_Environment *E)
{
js_Function **FT = F->funtab;
@@ -294,7 +400,7 @@ static void jsR_run(js_State *J, js_Function *F, js_Environment *E)
opcode = *pc++;
switch (opcode) {
case OP_POP: js_pop(J, 1); break;
case OP_DUP: js_dup(J); break;
case OP_DUP: js_dup(J, -1); break;
case OP_DUP2: js_dup2(J); break;
case OP_ROT2: js_rot2(J); break;
case OP_ROT3: js_rot3(J); break;
@@ -315,7 +421,7 @@ static void jsR_run(js_State *J, js_Function *F, js_Environment *E)
case OP_TRUE: js_pushboolean(J, 1); break;
case OP_FALSE: js_pushboolean(J, 0); break;
case OP_THIS: js_pushobject(J, js_toobject(J, 0)); break;
case OP_THIS: js_dup(J, 0); break;
case OP_GLOBAL: js_pushobject(J, J->G); break;
case OP_FUNDEC:
@@ -355,8 +461,11 @@ static void jsR_run(js_State *J, js_Function *F, js_Environment *E)
break;
case OP_GETPROP:
obj = js_toobject(J, -2);
str = js_tostring(J, -1);
js_pop(J, 1);
js_getproperty(J, -1, str);
obj = js_toobject(J, -2);
ref = jsR_getproperty(J, obj, str);
js_pop(J, 2);
if (ref)
@@ -581,14 +690,6 @@ static void jsR_run(js_State *J, js_Function *F, js_Environment *E)
}
}
js_Environment *jsR_newenvironment(js_State *J, js_Object *vars, js_Environment *outer)
{
js_Environment *E = malloc(sizeof *E);
E->outer = outer;
E->variables = vars;
return E;
}
int jsR_loadstring(js_State *J, const char *filename, const char *source, js_Environment *E)
{
js_Ast *P;
@@ -607,42 +708,6 @@ int jsR_loadstring(js_State *J, const char *filename, const char *source, js_Env
return 0;
}
void js_setglobal(js_State *J, const char *name)
{
js_Property *ref = jsR_setproperty(J, J->G, name);
ref->value = js_tovalue(J, -1);
js_pop(J, 1);
}
js_Property *js_decvar(js_State *J, js_Environment *E, const char *name)
{
return jsR_setproperty(J, E->variables, name);
}
js_Property *js_getvar(js_State *J, js_Environment *E, const char *name)
{
while (E) {
js_Property *ref = jsR_getproperty(J, E->variables, name);
if (ref)
return ref;
E = E->outer;
}
return NULL;
}
js_Property *js_setvar(js_State *J, js_Environment *E, const char *name)
{
while (1) {
js_Property *ref = jsR_getproperty(J, E->variables, name);
if (ref)
return ref;
if (!E->outer)
break;
E = E->outer;
}
return jsR_setproperty(J, E->variables, name);
}
void jsR_error(js_State *J, const char *fmt, ...)
{
va_list ap;
+11 -8
View File
@@ -7,19 +7,19 @@ struct js_Environment
js_Object *variables;
};
void js_setglobal(js_State *J, const char *name);
js_Environment *jsR_newenvironment(js_State *J, js_Object *variables, js_Environment *outer);
js_Property *js_decvar(js_State *J, js_Environment *E, const char *name);
js_Property *js_getvar(js_State *J, js_Environment *E, const char *name);
js_Property *js_setvar(js_State *J, js_Environment *E, const char *name);
int jsR_loadstring(js_State *J, const char *filename, const char *source, js_Environment *E);
void jsR_runfunction(js_State *J, js_Function *F);
void js_call(js_State *J, int n);
void js_getglobal(js_State *J, const char *name);
void js_setglobal(js_State *J, const char *name);
void js_getownproperty(js_State *J, int idx, const char *name);
void js_getproperty(js_State *J, int idx, const char *name);
void js_setproperty(js_State *J, int idx, const char *name);
int js_nextproperty(js_State *J, int idx);
void js_pushglobal(js_State *J);
void js_pushundefined(js_State *J);
void js_pushnull(js_State *J);
@@ -29,13 +29,16 @@ void js_pushstring(js_State *J, const char *v);
void js_newobject(js_State *J);
void js_newarray(js_State *J);
void js_pushcfunction(js_State *J, js_CFunction v);
int js_isundefined(js_State *J, int idx);
int js_isstring(js_State *J, int idx);
int js_toboolean(js_State *J, int idx);
double js_tonumber(js_State *J, int idx);
double js_tointeger(js_State *J, int idx);
const char *js_tostring(js_State *J, int idx);
void js_pop(js_State *J, int n);
void js_dup(js_State *J);
void js_dup(js_State *J, int idx);
#endif
+4 -1
View File
@@ -89,10 +89,13 @@ static int jsB_print(js_State *J, int argc)
static int jsB_eval(js_State *J, int argc)
{
const char *s;
if (!js_isstring(J, -1))
return 1;
// FIXME: need the real environment!
// 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))
jsR_error(J, "SyntaxError (eval)");
+2 -2
View File
@@ -85,7 +85,7 @@ const char *jsR_tostring(js_State *J, const js_Value *v)
return jsR_tostring(J, &vv);
}
}
return NULL;
return "undefined";
}
js_Object *jsR_toobject(js_State *J, const js_Value *v)
@@ -98,5 +98,5 @@ js_Object *jsR_toobject(js_State *J, const js_Value *v)
case JS_TSTRING: return jsR_newstring(J, v->u.string);
case JS_TOBJECT: return v->u.object;
}
return NULL;
jsR_error(J, "TypeError (ToObject)");
}