ref: 0f87d01184d3eee0c5b4b41b765ef5d11093f0c4
parent: 18b192b8aa8dd3779d33ead2b5d8531a43389cd4
author: Tor Andersson <tor@ccxvii.net>
date: Wed Jan 15 21:13:34 EST 2014
Add callable CFunctions and a print() function.
--- 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_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);
--- a/jsrun.c
+++ b/jsrun.c
@@ -567,18 +567,38 @@
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, ...)
--- 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;
}