shithub: libmujs

Download patch

ref: 52f78c568760d8157e0f4dd780f7ffe6c521bc65
parent: dceb42044791bacd56bcf5017c865ff13bb68d7c
author: Tor Andersson <tor.andersson@artifex.com>
date: Sun Jan 12 10:31:43 EST 2014

Compile sub-functions.

--- a/jscompile.c
+++ b/jscompile.c
@@ -8,17 +8,27 @@
 
 #define JF js_State *J, js_Function *F
 
+static js_Function *newfun(js_State *J, js_Ast *name, js_Ast *params, js_Ast *body);
+
 static void cexp(JF, js_Ast *exp);
 static void cstmlist(JF, js_Ast *list);
 
+static int listlen(js_Ast *list)
+{
+	int n = 0;
+	while (list) {
+		n++;
+		list = list->b;
+	}
+	return n;
+}
+
 static int consteq(js_Value a, js_Value b)
 {
-	if (a.type != b.type)
-		return 0;
-	if (a.type == JS_TNUMBER)
-		return a.u.number == b.u.number;
-	else
-		return a.u.p == b.u.p;
+	if (a.type != b.type) return 0;
+	if (a.type == JS_TNUMBER) return a.u.number == b.u.number;
+	if (a.type == JS_TSTRING) return a.u.string == b.u.string;
+	return a.u.p == b.u.p;
 }
 
 static int addconst(JF, js_Value v)
@@ -50,6 +60,15 @@
 	F->code[F->len++] = value;
 }
 
+static void emitfunction(JF, int opcode, js_Function *fun)
+{
+	js_Value v;
+	v.type = JS_TFUNCTION;
+	v.u.function = fun;
+	emit(J, F, opcode);
+	emit(J, F, addconst(J, F, v));
+}
+
 static void emitnumber(JF, int opcode, double n)
 {
 	js_Value v;
@@ -236,6 +255,10 @@
 		emit(J, F, n);
 		break;
 
+	case EXP_FUNC:
+		emitfunction(J, F, OP_FUNEXP, newfun(J, exp->a, exp->b, exp->c));
+		break;
+
 	case EXP_DELETE:
 		clval(J, F, exp->a);
 		emit(J, F, OP_DELETE);
@@ -361,6 +384,10 @@
 	int then, end;
 
 	switch (stm->type) {
+	case STM_FUNC:
+		emitfunction(J, F, OP_FUNDEC, newfun(J, stm->a, stm->b, stm->c));
+		break;
+
 	case STM_BLOCK:
 		cstmlist(J, F, stm->a);
 		break;
@@ -432,10 +459,13 @@
 	}
 }
 
-static js_Function *newfun(js_State *J)
+static js_Function *newfun(js_State *J, js_Ast *name, js_Ast *params, js_Ast *body)
 {
 	js_Function *F = malloc(sizeof(js_Function));
 
+	F->name = name ? name->string : "<anonymous>";
+	F->numparams = listlen(params);
+
 	F->cap = 256;
 	F->len = 0;
 	F->code = malloc(F->cap);
@@ -447,6 +477,12 @@
 	F->next = J->fun;
 	J->fun = F;
 
+	cstmlist(J, F, body);
+	if (F->len == 0 || F->code[F->len - 1] != OP_RETURN) {
+		emit(J, F, OP_UNDEF);
+		emit(J, F, OP_RETURN);
+	}
+
 	return F;
 }
 
@@ -491,13 +527,8 @@
 		return NULL;
 	}
 
-	F = newfun(J);
-	cstmlist(J, F, prog);
+	F = newfun(J, NULL, NULL, prog);
 
-	emit(J, F, OP_UNDEF);
-	emit(J, F, OP_RETURN);
-
 	J->fun = NULL;
 	return F;
 }
-
--- a/jscompile.h
+++ b/jscompile.h
@@ -87,6 +87,9 @@
 
 struct js_Function
 {
+	const char *name;
+	int numparams;
+
 	unsigned char *code;
 	int cap, len;
 
@@ -99,6 +102,7 @@
 js_Function *jsC_compile(js_State *J, js_Ast *prog);
 void jsC_freecompile(js_State *J);
 int jsC_error(js_State *J, js_Ast *node, const char *fmt, ...);
+
 void jsC_dumpvalue(js_State *J, js_Value v);
 void jsC_dumpfunction(js_State *J, js_Function *fun);
 
--- a/jsdump.c
+++ b/jsdump.c
@@ -15,7 +15,7 @@
 	"ushr", "add", "sub", "mul", "div", "mod", "cond", "ass", "ass_mul",
 	"ass_div", "ass_mod", "ass_add", "ass_sub", "ass_shl", "ass_shr",
 	"ass_ushr", "ass_bitand", "ass_bitxor", "ass_bitor", "comma",
-	"var-init", "block", "fundec", "nop", "var", "if", "do-while", "while",
+	"var-init", "fundec", "block", "nop", "var", "if", "do-while", "while",
 	"for", "for-var", "for-in", "for-in-var", "continue", "break",
 	"return", "with", "switch", "throw", "try", "debugger", "label",
 	"case", "default",
@@ -594,7 +594,7 @@
 	case JS_TREGEXP: printf("<regexp %p>", v.u.p); break;
 	case JS_TOBJECT: printf("<object %p>", v.u.p); break;
 
-	case JS_TFUNCTION: printf("<function %p>", v.u.p); break;
+	case JS_TFUNCTION: printf("<function %p>", v.u.function); break;
 	case JS_TCFUNCTION: printf("<cfunction %p>", v.u.p); break;
 	case JS_TCLOSURE: printf("<closure %p>", v.u.p); break;
 	case JS_TARGUMENTS: printf("<arguments %p>", v.u.p); break;
@@ -607,9 +607,10 @@
 {
 	unsigned char *p = fun->code;
 	unsigned char *end = fun->code + fun->len;
-	int dest;
+	int i, dest;
 
-	printf("function with %d constants\n", fun->klen);
+	printf("function %p, %s, %d parameters, %d constants\n",
+		fun, fun->name, fun->numparams, fun->klen);
 
 	while (p < end) {
 		int c = *p++;
@@ -625,6 +626,8 @@
 		case OP_LOADMEMBER:
 		case OP_AVAR:
 		case OP_AMEMBER:
+		case OP_FUNDEC:
+		case OP_FUNEXP:
 			pc(' ');
 			jsC_dumpvalue(J, fun->klist[*p++]);
 			break;
@@ -643,5 +646,12 @@
 		}
 
 		nl();
+	}
+
+	for (i = 0; i < fun->klen; i++) {
+		if (fun->klist[i].type == JS_TFUNCTION) {
+			nl();
+			jsC_dumpfunction(J, fun->klist[i].u.function);
+		}
 	}
 }
--- a/jsparse.h
+++ b/jsparse.h
@@ -96,8 +96,8 @@
 	EXP_VAR, /* var initializer */
 
 	/* statements */
-	STM_BLOCK,
 	STM_FUNC, /* function declaration */
+	STM_BLOCK,
 	STM_NOP,
 	STM_VAR,
 	STM_IF,
--- a/jsrun.h
+++ b/jsrun.h
@@ -24,6 +24,7 @@
 		double number;
 		const char *string;
 		int boolean;
+		js_Function *function;
 		void *p;
 	} u;
 	int flag;