diff --git a/js.h b/js.h index aa6e20f..38ca11b 100644 --- a/js.h +++ b/js.h @@ -11,7 +11,6 @@ typedef struct js_State js_State; -typedef int (*js_CFunction)(js_State *J, int argc); #define JS_REGEXP_G 1 #define JS_REGEXP_I 2 @@ -25,12 +24,38 @@ int js_error(js_State *J, const char *fmt, ...); int js_loadstring(js_State *J, const char *s); int js_loadfile(js_State *J, const char *filename); +/* binding API */ + +typedef int (*js_CFunction)(js_State *J, int argc); +typedef struct js_Object js_Object; + +void js_pushundefined(js_State *J); +void js_pushnull(js_State *J); +void js_pushboolean(js_State *J, int v); +void js_pushnumber(js_State *J, double v); +void js_pushlstring(js_State *J, const char *v); +void js_pushstring(js_State *J, const char *v); +void js_pushobject(js_State *J, js_Object *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); +js_Object *js_toobject(js_State *J, int idx); + +void js_pop(js_State *J, int n); +void js_dup(js_State *J); + +void js_setglobal(js_State *J, const char *name); + /* private */ typedef struct js_Ast js_Ast; typedef struct js_Environment js_Environment; typedef struct js_Function js_Function; -typedef struct js_Object js_Object; typedef struct js_StringNode js_StringNode; const char *js_intern(js_State *J, const char *s); diff --git a/jsrun.c b/jsrun.c index 8d39ece..5d07066 100644 --- a/jsrun.c +++ b/jsrun.c @@ -567,20 +567,40 @@ static void js_call(js_State *J, int argc) obj = js_toobject(J, -argc - 1); F = obj->function; - E = js_newenvironment(J, obj->scope, js_newobject(J, JS_COBJECT)); + if (F) { + E = js_newenvironment(J, obj->scope, js_newobject(J, JS_COBJECT)); - 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); + 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); + } } - js_pop(J, argc + 1); - - runfun(J, F, E); bot = savebot; } +void js_setglobal(js_State *J, const char *name) +{ + js_Property *ref = js_setproperty(J, J->E->variables, name); + ref->value = js_tovalue(J, -1); + js_pop(J, 1); +} + void jsR_error(js_State *J, const char *fmt, ...) { va_list ap; diff --git a/jsstate.c b/jsstate.c index ff33073..9f32194 100644 --- a/jsstate.c +++ b/jsstate.c @@ -2,12 +2,29 @@ #include "jsobject.h" #include "jsstate.h" +static int jsB_print(js_State *J, int argc) +{ + int i; + for (i = 1; i < argc; ++i) { + const char *s = js_tostring(J, i); + if (i > 1) putchar(' '); + fputs(s, stdout); + } + putchar('\n'); + return 0; +} + js_State *js_newstate(void) { js_State *J = malloc(sizeof *J); memset(J, 0, sizeof(*J)); + J->global = js_newobject(J, JS_COBJECT); J->E = js_newenvironment(J, NULL, J->global); + + js_pushobject(J, js_newcfunction(J, jsB_print)); + js_setglobal(J, "print"); + return J; }