shithub: libmujs

Download patch

ref: 56042de82bbb4f4cee4fbb1e352a45d3acf134b2
parent: e01b4d02c0312f6ddc5b03adb78ed806d1eb22bb
author: Tor Andersson <tor@ccxvii.net>
date: Thu Jan 16 16:36:54 EST 2014

Fix the shape of the outer API a bit. Implement eval.

--- a/js.h
+++ b/js.h
@@ -41,8 +41,10 @@
 
 int js_error(js_State *J, const char *fmt, ...);
 
-int js_loadstring(js_State *J, const char *s);
+int js_loadstring(js_State *J, const char *source);
 int js_loadfile(js_State *J, const char *filename);
+int js_dostring(js_State *J, const char *source);
+int js_dofile(js_State *J, const char *filename);
 
 /* binding API: TODO: move from jsrun.h */
 
--- a/jscompile.c
+++ b/jscompile.c
@@ -7,6 +7,8 @@
 
 #define JF js_State *J, js_Function *F
 
+JS_NORETURN int jsC_error(js_State *J, js_Ast *node, const char *fmt, ...);
+
 static void cfunbody(JF, js_Ast *name, js_Ast *params, js_Ast *body);
 static void cexp(JF, js_Ast *exp);
 static void cstmlist(JF, js_Ast *list);
@@ -754,7 +756,7 @@
 	longjmp(J->jb, 1);
 }
 
-void jsC_freecompile(js_State *J)
+static void jsC_freecompile(js_State *J)
 {
 	js_Function *F = J->fun;
 	while (F) {
--- a/jscompile.h
+++ b/jscompile.h
@@ -109,8 +109,6 @@
 };
 
 js_Function *jsC_compile(js_State *J, js_Ast *prog);
-void jsC_freecompile(js_State *J);
-JS_NORETURN int jsC_error(js_State *J, js_Ast *node, const char *fmt, ...);
 
 void jsC_dumpfunction(js_State *J, js_Function *fun);
 
--- a/jsload.c
+++ /dev/null
@@ -1,70 +1,0 @@
-#include "js.h"
-#include "jsparse.h"
-#include "jscompile.h"
-#include "jsobject.h"
-#include "jsrun.h"
-
-static int jsP_loadstring(js_State *J, const char *filename, const char *source)
-{
-	js_Ast *prog = jsP_parse(J, filename, source);
-	if (prog) {
-		js_Function *fun;
-		jsP_optimize(J, prog);
-		//jsP_dumpsyntax(J, prog);
-		//jsP_dumplist(J, prog);
-		fun = jsC_compile(J, prog);
-		if (fun) {
-			jsC_dumpfunction(J, fun);
-			jsR_runfunction(J, fun);
-		}
-		jsC_freecompile(J);
-		jsP_freeparse(J);
-		return 0;
-	}
-	return 1;
-}
-
-int js_loadstring(js_State *J, const char *source)
-{
-	return jsP_loadstring(J, "(string)", source);
-}
-
-int js_loadfile(js_State *J, const char *filename)
-{
-	FILE *f;
-	char *s;
-	int n, t;
-
-	f = fopen(filename, "r");
-	if (!f) {
-		return js_error(J, "cannot open file: '%s'", filename);
-	}
-
-	if (fseek(f, 0, SEEK_END) < 0) {
-		fclose(f);
-		return js_error(J, "cannot seek in file: '%s'", filename);
-	}
-	n = ftell(f);
-	fseek(f, 0, SEEK_SET);
-
-	s = malloc(n + 1); /* add space for string terminator */
-	if (!s) {
-		fclose(f);
-		return js_error(J, "cannot allocate storage for file contents: '%s'", filename);
-	}
-
-	t = fread(s, 1, n, f);
-	if (t != n) {
-		free(s);
-		fclose(f);
-		return js_error(J, "cannot read data from file: '%s'", filename);
-	}
-
-	s[n] = 0; /* zero-terminate string containing file data */
-
-	t = jsP_loadstring(J, filename, s);
-
-	free(s);
-	fclose(f);
-	return t;
-}
--- a/jsrun.c
+++ b/jsrun.c
@@ -1,5 +1,6 @@
 #include "js.h"
 #include "jsobject.h"
+#include "jsparse.h"
 #include "jscompile.h"
 #include "jsrun.h"
 #include "jsstate.h"
@@ -88,7 +89,7 @@
 	++top;
 }
 
-void jsR_pushliteral(js_State *J, const char *v)
+void js_pushliteral(js_State *J, const char *v)
 {
 	stack[top].type = JS_TSTRING;
 	stack[top].u.string = v;
@@ -102,6 +103,11 @@
 	++top;
 }
 
+void js_pushglobal(js_State *J)
+{
+	js_pushobject(J, J->G);
+}
+
 void js_newobject(js_State *J)
 {
 	js_pushobject(J, jsR_newobject(J, JS_COBJECT));
@@ -298,7 +304,7 @@
 		case OP_NUMBER_1: js_pushnumber(J, 1); break;
 		case OP_NUMBER_X: js_pushnumber(J, *pc++); break;
 		case OP_NUMBER: js_pushnumber(J, NT[*pc++]); break;
-		case OP_STRING: jsR_pushliteral(J, ST[*pc++]); break;
+		case OP_STRING: js_pushliteral(J, ST[*pc++]); break;
 
 		case OP_CLOSURE: js_pushobject(J, jsR_newfunction(J, FT[*pc++], E)); break;
 		case OP_NEWOBJECT: js_newobject(J); break;
@@ -378,7 +384,7 @@
 				ref = jsR_nextproperty(J, obj, js_tostring(J, -1));
 			if (ref) {
 				js_pop(J, 1);
-				jsR_pushliteral(J, ref->name);
+				js_pushliteral(J, ref->name);
 				js_pushboolean(J, 1);
 			} else {
 				js_pop(J, 2);
@@ -583,6 +589,24 @@
 	return E;
 }
 
+int jsR_loadstring(js_State *J, const char *filename, const char *source, js_Environment *E)
+{
+	js_Ast *P;
+	js_Function *F;
+
+	// TODO: push exception stack
+
+	P = jsP_parse(J, filename, source);
+	if (!P) return 1;
+	jsP_optimize(J, P);
+	F = jsC_compile(J, P);
+	jsP_freeparse(J);
+	if (!F) return 1;
+
+	js_pushobject(J, jsR_newfunction(J, F, E));
+	return 0;
+}
+
 void js_setglobal(js_State *J, const char *name)
 {
 	js_Property *ref = jsR_setproperty(J, J->G, name);
@@ -630,18 +654,4 @@
 	fprintf(stderr, "\n");
 
 	longjmp(J->jb, 1);
-}
-
-void jsR_runfunction(js_State *J, js_Function *F)
-{
-	if (setjmp(J->jb)) {
-		js_dumpobject(J, J->G);
-		return;
-	}
-
-	js_pushobject(J, J->G); /* initial "this" */
-	jsR_run(J, F, J->GE);
-
-	js_dumpobject(J, J->G);
-	js_dumpstack(J);
 }
--- a/jsrun.h
+++ b/jsrun.h
@@ -14,8 +14,13 @@
 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_pushglobal(js_State *J);
 void js_pushundefined(js_State *J);
 void js_pushnull(js_State *J);
 void js_pushboolean(js_State *J, int v);
--- a/jsstate.c
+++ b/jsstate.c
@@ -3,6 +3,77 @@
 #include "jsrun.h"
 #include "jsstate.h"
 
+int js_loadstring(js_State *J, const char *source)
+{
+	return jsR_loadstring(J, "(string)", source, J->GE);
+}
+
+int js_loadfile(js_State *J, const char *filename)
+{
+	FILE *f;
+	char *s;
+	int n, t;
+
+	f = fopen(filename, "r");
+	if (!f) {
+		return js_error(J, "cannot open file: '%s'", filename);
+	}
+
+	if (fseek(f, 0, SEEK_END) < 0) {
+		fclose(f);
+		return js_error(J, "cannot seek in file: '%s'", filename);
+	}
+	n = ftell(f);
+	fseek(f, 0, SEEK_SET);
+
+	s = malloc(n + 1); /* add space for string terminator */
+	if (!s) {
+		fclose(f);
+		return js_error(J, "cannot allocate storage for file contents: '%s'", filename);
+	}
+
+	t = fread(s, 1, n, f);
+	if (t != n) {
+		free(s);
+		fclose(f);
+		return js_error(J, "cannot read data from file: '%s'", filename);
+	}
+
+	s[n] = 0; /* zero-terminate string containing file data */
+
+	t = jsR_loadstring(J, filename, s, J->GE);
+
+	free(s);
+	fclose(f);
+	return t;
+}
+
+int js_dostring(js_State *J, const char *source)
+{
+	int rv = js_loadstring(J, source);
+	if (!rv) {
+		if (setjmp(J->jb))
+			return 1;
+		js_pushglobal(J);
+		js_call(J, 0);
+		js_pop(J, 1);
+	}
+	return rv;
+}
+
+int js_dofile(js_State *J, const char *filename)
+{
+	int rv = js_loadfile(J, filename);
+	if (!rv) {
+		if (setjmp(J->jb))
+			return 1;
+		js_pushglobal(J);
+		js_call(J, 0);
+		js_pop(J, 1);
+	}
+	return rv;
+}
+
 static int jsB_print(js_State *J, int argc)
 {
 	int i;
@@ -15,6 +86,22 @@
 	return 0;
 }
 
+static int jsB_eval(js_State *J, int argc)
+{
+	const char *s;
+	if (!js_isstring(J, -1))
+		return 1;
+
+	// FIXME: need the real environment!
+	s = js_tostring(J, -1);
+	if (jsR_loadstring(J, "(eval)", s, J->GE))
+		jsR_error(J, "SyntaxError (eval)");
+
+	js_pushglobal(J);
+	js_call(J, 0);
+	return 1;
+}
+
 js_State *js_newstate(void)
 {
 	js_State *J = malloc(sizeof *J);
@@ -22,6 +109,9 @@
 
 	J->G = jsR_newobject(J, JS_COBJECT);
 	J->GE = jsR_newenvironment(J, J->G, NULL);
+
+	js_pushcfunction(J, jsB_eval);
+	js_setglobal(J, "eval");
 
 	js_pushcfunction(J, jsB_print);
 	js_setglobal(J, "print");
--- a/main.c
+++ b/main.c
@@ -8,10 +8,8 @@
 
 	J = js_newstate();
 
-	for (i = 1; i < argc; ++i) {
-		js_loadfile(J, argv[i]);
-		// js_run(J);
-	}
+	for (i = 1; i < argc; ++i)
+		js_dofile(J, argv[i]);
 
 	js_close(J);