shithub: libmujs

Download patch

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;
 }