shithub: libmujs

Download patch

ref: effc3ae9ad351c53f4b3ecba8669464e4a97c8c2
parent: 3f564db259b89d87cf87ff6691c4ef0f47b55f09
author: Tor Andersson <tor@ccxvii.net>
date: Fri Jan 10 09:34:27 EST 2014

Add constant folding.

--- a/jsload.c
+++ b/jsload.c
@@ -5,6 +5,7 @@
 {
 	js_Ast *prog = jsP_parse(J, filename, source);
 	if (prog) {
+		jsP_foldconstants(J, prog);
 		jsP_pretty(J, prog);
 		jsP_freeparse(J);
 		return 0;
--- /dev/null
+++ b/jsoptim.c
@@ -1,0 +1,86 @@
+#include "js.h"
+#include "jsparse.h"
+
+static inline int i32(double d)
+{
+	double two32 = 4294967296.0;
+	double two31 = 2147483648.0;
+
+	if (!isfinite(d) || d == 0)
+		return 0;
+
+	d = fmod(d, two32);
+	d = d >= 0 ? floor(d) : ceil(d) + two32;
+	if (d >= two31)
+		return d - two32;
+	else
+		return d;
+}
+
+static inline unsigned int u32(double d)
+{
+	return i32(d);
+}
+
+static int N(js_Ast *node, double *r, double x)
+{
+	node->type = AST_NUMBER;
+	node->number = x;
+	node->a = node->b = node->c = node->d = NULL;
+	*r = x;
+	return 1;
+}
+
+static int foldnumber(js_Ast *node, double *r)
+{
+	double x, y, z, w;
+	int a, b;
+
+	a = node->a ? foldnumber(node->a, &x) : 0;
+	b = node->b ? foldnumber(node->b, &y) : 0;
+	if (node->c) foldnumber(node->c, &z);
+	if (node->d) foldnumber(node->d, &w);
+
+	if (node->type == AST_NUMBER) {
+		*r = node->number;
+		return 1;
+	}
+
+	/* not an expression */
+	if (node->c || node->d)
+		return 0;
+
+	/* binary */
+	if (a && b) {
+		switch (node->type) {
+		case EXP_MUL: return N(node, r, x * y);
+		case EXP_DIV: return N(node, r, x / y);
+		case EXP_MOD: return N(node, r, fmod(x, y));
+		case EXP_ADD: return N(node, r, x + y);
+		case EXP_SUB: return N(node, r, x - y);
+		case EXP_SHL: return N(node, r, i32(x) << (u32(y) & 0x1F));
+		case EXP_SHR: return N(node, r, i32(x) >> (u32(y) & 0x1F));
+		case EXP_USHR: return N(node, r, u32(x) >> (u32(y) & 0x1F));
+		case EXP_BITAND: return N(node, r, i32(x) & i32(y));
+		case EXP_BITXOR: return N(node, r, i32(x) ^ i32(y));
+		case EXP_BITOR: return N(node, r, i32(x) | i32(y));
+		}
+	}
+
+	/* unary */
+	else if (a) {
+		switch (node->type) {
+		case EXP_NEG: return N(node, r, -x);
+		case EXP_POS: return N(node, r, x);
+		case EXP_BITNOT: return N(node, r, ~i32(x));
+		}
+	}
+
+	return 0;
+}
+
+void jsP_foldconstants(js_State *J, js_Ast *prog)
+{
+	double x;
+	foldnumber(prog, &x);
+}
--- a/jsparse.c
+++ b/jsparse.c
@@ -34,8 +34,8 @@
 	node->b = b;
 	node->c = c;
 	node->d = d;
-	node->n = 0;
-	node->s = NULL;
+	node->number = 0;
+	node->string = NULL;
 
 	node->next = J->ast;
 	J->ast = node;
@@ -46,7 +46,7 @@
 js_Ast *jsP_newstrnode(js_State *J, int type, const char *s)
 {
 	js_Ast *node = jsP_newnode(J, type, 0, 0, 0, 0);
-	node->s = s;
+	node->string = s;
 	return node;
 }
 
@@ -53,7 +53,7 @@
 js_Ast *jsP_newnumnode(js_State *J, int type, double n)
 {
 	js_Ast *node = jsP_newnode(J, type, 0, 0, 0, 0);
-	node->n = n;
+	node->number = n;
 	return node;
 }
 
--- a/jsparse.h
+++ b/jsparse.h
@@ -8,8 +8,8 @@
 	int type;
 	int line;
 	js_Ast *a, *b, *c, *d;
-	double n;
-	const char *s;
+	double number;
+	const char *string;
 	js_Ast *next; /* next in alloc list */
 };
 
@@ -124,6 +124,7 @@
 js_Ast *jsP_parse(js_State *J, const char *filename, const char *source);
 void jsP_freeparse(js_State *J);
 
+void jsP_foldconstants(js_State *J, js_Ast *prog);
 void jsP_pretty(js_State *J, js_Ast *prog);
 
 #endif
--- a/jspretty.c
+++ b/jspretty.c
@@ -165,10 +165,10 @@
 static void printast(js_Ast *n, int level)
 {
 	switch (n->type) {
-	case AST_IDENTIFIER: printf("%s", n->s); return;
-	case AST_NUMBER: printf("%g", n->n); return;
-	case AST_STRING: printf("'%s'", n->s); return;
-	case AST_REGEXP: printf("/%s/", n->s); return;
+	case AST_IDENTIFIER: printf("%s", n->string); return;
+	case AST_NUMBER: printf("%g", n->number); return;
+	case AST_STRING: printf("'%s'", n->string); return;
+	case AST_REGEXP: printf("/%s/", n->string); return;
 	case AST_LIST:
 		putchar('[');
 		printlist(n, level, " ");