shithub: libmujs

Download patch

ref: 96667d99b197808927bad6c1231296f040812df7
parent: d949e161184d8eeddd0d92edb68e617cb692c94f
author: Tor Andersson <tor@ccxvii.net>
date: Mon Feb 3 07:49:54 EST 2014

Use precedence table when pretty-printing syntax.

--- a/jsdump.c
+++ b/jsdump.c
@@ -41,6 +41,105 @@
 	return opname[opcode];
 }
 
+static int prec(js_AstType type)
+{
+	switch (type) {
+	case AST_IDENTIFIER:
+	case AST_NUMBER:
+	case AST_STRING:
+	case AST_REGEXP:
+	case EXP_UNDEF:
+	case EXP_NULL:
+	case EXP_TRUE:
+	case EXP_FALSE:
+	case EXP_THIS:
+	case EXP_ARRAY:
+	case EXP_OBJECT:
+		return 170;
+
+	case EXP_FUN:
+	case EXP_INDEX:
+	case EXP_MEMBER:
+	case EXP_CALL:
+	case EXP_NEW:
+		return 160;
+
+	case EXP_POSTINC:
+	case EXP_POSTDEC:
+		return 150;
+
+	case EXP_DELETE:
+	case EXP_VOID:
+	case EXP_TYPEOF:
+	case EXP_PREINC:
+	case EXP_PREDEC:
+	case EXP_POS:
+	case EXP_NEG:
+	case EXP_BITNOT:
+	case EXP_LOGNOT:
+		return 140;
+
+	case EXP_MOD:
+	case EXP_DIV:
+	case EXP_MUL:
+		return 130;
+
+	case EXP_SUB:
+	case EXP_ADD:
+		return 120;
+
+	case EXP_USHR:
+	case EXP_SHR:
+	case EXP_SHL:
+		return 110;
+
+	case EXP_IN:
+	case EXP_INSTANCEOF:
+	case EXP_GE:
+	case EXP_LE:
+	case EXP_GT:
+	case EXP_LT:
+		return 100;
+
+	case EXP_STRICTNE:
+	case EXP_STRICTEQ:
+	case EXP_NE:
+	case EXP_EQ:
+		return 90;
+
+	case EXP_BITAND: return 80;
+	case EXP_BITXOR: return 70;
+	case EXP_BITOR: return 60;
+	case EXP_LOGAND: return 50;
+	case EXP_LOGOR: return 40;
+
+	case EXP_COND:
+		return 30;
+
+	case EXP_ASS:
+	case EXP_ASS_MUL:
+	case EXP_ASS_DIV:
+	case EXP_ASS_MOD:
+	case EXP_ASS_ADD:
+	case EXP_ASS_SUB:
+	case EXP_ASS_SHL:
+	case EXP_ASS_SHR:
+	case EXP_ASS_USHR:
+	case EXP_ASS_BITAND:
+	case EXP_ASS_BITXOR:
+	case EXP_ASS_BITOR:
+		return 20;
+
+#define COMMA 15
+
+	case EXP_COMMA:
+		return 10;
+
+	default:
+		return 0;
+	}
+}
+
 static inline void pc(int c)
 {
 	putchar(c);
@@ -74,7 +173,7 @@
 {
 	while (list) {
 		assert(list->type == AST_LIST);
-		pexpi(d, 0, list->a);
+		pexpi(d, COMMA, list->a);
 		list = list->b;
 		if (list)
 			ps(", ");
@@ -86,7 +185,7 @@
 	ps("[");
 	while (list) {
 		assert(list->type == AST_LIST);
-		pexpi(d, 0, list->a);
+		pexpi(d, COMMA, list->a);
 		list = list->b;
 		if (list)
 			ps(", ");
@@ -102,13 +201,13 @@
 		assert(list->type == AST_LIST);
 		switch (kv->type) {
 		case EXP_PROP_VAL:
-			pexpi(d, 0, kv->a);
+			pexpi(d, COMMA, kv->a);
 			ps(": ");
-			pexpi(d, 0, kv->b);
+			pexpi(d, COMMA, kv->b);
 			break;
 		case EXP_PROP_GET:
 			ps("get ");
-			pexpi(d, 0, kv->a);
+			pexpi(d, COMMA, kv->a);
 			ps("() {\n");
 			pstmlist(d, kv->b);
 			in(d); ps("}");
@@ -115,9 +214,9 @@
 			break;
 		case EXP_PROP_SET:
 			ps("set ");
-			pexpi(d, 0, kv->a);
+			pexpi(d, COMMA, kv->a);
 			ps("(");
-			pexpi(d, 0, kv->b);
+			pexpi(d, COMMA, kv->b);
 			ps(") {\n");
 			pstmlist(d, kv->c);
 			in(d); ps("}");
@@ -155,26 +254,30 @@
 	if (flags & JS_REGEXP_M) pc('m');
 }
 
-static void pbin(int d, int i, js_Ast *exp, const char *op)
+static void pbin(int d, int p, js_Ast *exp, const char *op)
 {
-	if (i) pc('(');
-	pexpi(d, 1, exp->a);
+	pexpi(d, p, exp->a);
 	ps(op);
-	pexpi(d, 1, exp->b);
-	if (i) pc(')');
+	pexpi(d, p, exp->b);
 }
 
-static void puna(int d, int i, js_Ast *exp, const char *pre, const char *suf)
+static void puna(int d, int p, js_Ast *exp, const char *pre, const char *suf)
 {
-	if (i) pc('(');
 	ps(pre);
-	pexpi(d, 1, exp->a);
+	pexpi(d, p, exp->a);
 	ps(suf);
-	if (i) pc(')');
 }
 
-static void pexpi(int d, int i, js_Ast *exp)
+static void pexpi(int d, int p, js_Ast *exp)
 {
+	int tp = prec(exp->type);
+	int paren = 0;
+	if (tp < p) {
+		pc('(');
+		paren = 1;
+	}
+	p = tp;
+
 	switch (exp->type) {
 	case AST_IDENTIFIER: ps(exp->string); break;
 	case AST_NUMBER: printf("%.9g", exp->number); break;
@@ -190,105 +293,95 @@
 	case EXP_OBJECT: pobject(d, exp->a); break;
 	case EXP_ARRAY: parray(d, exp->a); break;
 
-	case EXP_DELETE: puna(d, i, exp, "delete ", ""); break;
-	case EXP_VOID: puna(d, i, exp, "void ", ""); break;
-	case EXP_TYPEOF: puna(d, i, exp, "typeof ", ""); break;
-	case EXP_PREINC: puna(d, i, exp, "++", ""); break;
-	case EXP_PREDEC: puna(d, i, exp, "--", ""); break;
-	case EXP_POSTINC: puna(d, i, exp, "", "++"); break;
-	case EXP_POSTDEC: puna(d, i, exp, "", "--"); break;
-	case EXP_POS: puna(d, i, exp, "+", ""); break;
-	case EXP_NEG: puna(d, i, exp, "-", ""); break;
-	case EXP_BITNOT: puna(d, i, exp, "~", ""); break;
-	case EXP_LOGNOT: puna(d, i, exp, "!", ""); break;
+	case EXP_DELETE: puna(d, p, exp, "delete ", ""); break;
+	case EXP_VOID: puna(d, p, exp, "void ", ""); break;
+	case EXP_TYPEOF: puna(d, p, exp, "typeof ", ""); break;
+	case EXP_PREINC: puna(d, p, exp, "++", ""); break;
+	case EXP_PREDEC: puna(d, p, exp, "--", ""); break;
+	case EXP_POSTINC: puna(d, p, exp, "", "++"); break;
+	case EXP_POSTDEC: puna(d, p, exp, "", "--"); break;
+	case EXP_POS: puna(d, p, exp, "+", ""); break;
+	case EXP_NEG: puna(d, p, exp, "-", ""); break;
+	case EXP_BITNOT: puna(d, p, exp, "~", ""); break;
+	case EXP_LOGNOT: puna(d, p, exp, "!", ""); break;
 
-	case EXP_LOGOR: pbin(d, i, exp, " || "); break;
-	case EXP_LOGAND: pbin(d, i, exp, " && "); break;
-	case EXP_BITOR: pbin(d, i, exp, " | "); break;
-	case EXP_BITXOR: pbin(d, i, exp, " ^ "); break;
-	case EXP_BITAND: pbin(d, i, exp, " & "); break;
-	case EXP_EQ: pbin(d, i, exp, " == "); break;
-	case EXP_NE: pbin(d, i, exp, " != "); break;
-	case EXP_STRICTEQ: pbin(d, i, exp, " === "); break;
-	case EXP_STRICTNE: pbin(d, i, exp, " !== "); break;
-	case EXP_LT: pbin(d, i, exp, " < "); break;
-	case EXP_GT: pbin(d, i, exp, " > "); break;
-	case EXP_LE: pbin(d, i, exp, " <= "); break;
-	case EXP_GE: pbin(d, i, exp, " >= "); break;
-	case EXP_INSTANCEOF: pbin(d, i, exp, " instanceof "); break;
-	case EXP_IN: pbin(d, i, exp, " in "); break;
-	case EXP_SHL: pbin(d, i, exp, " << "); break;
-	case EXP_SHR: pbin(d, i, exp, " >> "); break;
-	case EXP_USHR: pbin(d, i, exp, " >>> "); break;
-	case EXP_ADD: pbin(d, i, exp, " + "); break;
-	case EXP_SUB: pbin(d, i, exp, " - "); break;
-	case EXP_MUL: pbin(d, i, exp, " * "); break;
-	case EXP_DIV: pbin(d, i, exp, " / "); break;
-	case EXP_MOD: pbin(d, i, exp, " % "); break;
-	case EXP_ASS: pbin(d, i, exp, " = "); break;
-	case EXP_ASS_MUL: pbin(d, i, exp, " *= "); break;
-	case EXP_ASS_DIV: pbin(d, i, exp, " /= "); break;
-	case EXP_ASS_MOD: pbin(d, i, exp, " %= "); break;
-	case EXP_ASS_ADD: pbin(d, i, exp, " += "); break;
-	case EXP_ASS_SUB: pbin(d, i, exp, " -= "); break;
-	case EXP_ASS_SHL: pbin(d, i, exp, " <<= "); break;
-	case EXP_ASS_SHR: pbin(d, i, exp, " >>= "); break;
-	case EXP_ASS_USHR: pbin(d, i, exp, " >>>= "); break;
-	case EXP_ASS_BITAND: pbin(d, i, exp, " &= "); break;
-	case EXP_ASS_BITXOR: pbin(d, i, exp, " ^= "); break;
-	case EXP_ASS_BITOR: pbin(d, i, exp, " |= "); break;
+	case EXP_LOGOR: pbin(d, p, exp, " || "); break;
+	case EXP_LOGAND: pbin(d, p, exp, " && "); break;
+	case EXP_BITOR: pbin(d, p, exp, " | "); break;
+	case EXP_BITXOR: pbin(d, p, exp, " ^ "); break;
+	case EXP_BITAND: pbin(d, p, exp, " & "); break;
+	case EXP_EQ: pbin(d, p, exp, " == "); break;
+	case EXP_NE: pbin(d, p, exp, " != "); break;
+	case EXP_STRICTEQ: pbin(d, p, exp, " === "); break;
+	case EXP_STRICTNE: pbin(d, p, exp, " !== "); break;
+	case EXP_LT: pbin(d, p, exp, " < "); break;
+	case EXP_GT: pbin(d, p, exp, " > "); break;
+	case EXP_LE: pbin(d, p, exp, " <= "); break;
+	case EXP_GE: pbin(d, p, exp, " >= "); break;
+	case EXP_INSTANCEOF: pbin(d, p, exp, " instanceof "); break;
+	case EXP_IN: pbin(d, p, exp, " in "); break;
+	case EXP_SHL: pbin(d, p, exp, " << "); break;
+	case EXP_SHR: pbin(d, p, exp, " >> "); break;
+	case EXP_USHR: pbin(d, p, exp, " >>> "); break;
+	case EXP_ADD: pbin(d, p, exp, " + "); break;
+	case EXP_SUB: pbin(d, p, exp, " - "); break;
+	case EXP_MUL: pbin(d, p, exp, " * "); break;
+	case EXP_DIV: pbin(d, p, exp, " / "); break;
+	case EXP_MOD: pbin(d, p, exp, " % "); break;
+	case EXP_ASS: pbin(d, p, exp, " = "); break;
+	case EXP_ASS_MUL: pbin(d, p, exp, " *= "); break;
+	case EXP_ASS_DIV: pbin(d, p, exp, " /= "); break;
+	case EXP_ASS_MOD: pbin(d, p, exp, " %= "); break;
+	case EXP_ASS_ADD: pbin(d, p, exp, " += "); break;
+	case EXP_ASS_SUB: pbin(d, p, exp, " -= "); break;
+	case EXP_ASS_SHL: pbin(d, p, exp, " <<= "); break;
+	case EXP_ASS_SHR: pbin(d, p, exp, " >>= "); break;
+	case EXP_ASS_USHR: pbin(d, p, exp, " >>>= "); break;
+	case EXP_ASS_BITAND: pbin(d, p, exp, " &= "); break;
+	case EXP_ASS_BITXOR: pbin(d, p, exp, " ^= "); break;
+	case EXP_ASS_BITOR: pbin(d, p, exp, " |= "); break;
 
-	case EXP_COMMA: pbin(d, 1, exp, ", "); break;
+	case EXP_COMMA: pbin(d, p, exp, ", "); break;
 
 	case EXP_COND:
-		if (i) pc('(');
-		pexpi(d, 1, exp->a);
+		pexpi(d, p, exp->a);
 		ps(" ? ");
-		pexpi(d, 1, exp->b);
+		pexpi(d, p, exp->b);
 		ps(" : ");
-		pexpi(d, 1, exp->c);
-		if (i) pc(')');
+		pexpi(d, p, exp->c);
 		break;
 
 	case EXP_INDEX:
-		if (i) pc('(');
-		pexpi(d, 1, exp->a);
+		pexpi(d, p, exp->a);
 		pc('[');
 		pexpi(d, 0, exp->b);
 		pc(']');
-		if (i) pc(')');
 		break;
 
 	case EXP_MEMBER:
-		if (i) pc('(');
-		pexpi(d, 1, exp->a);
+		pexpi(d, p, exp->a);
 		pc('.');
-		pexpi(d, 1, exp->b);
-		if (i) pc(')');
+		pexpi(d, p, exp->b);
 		break;
 
 	case EXP_CALL:
-		if (i) pc('(');
-		pexpi(d, 1, exp->a);
+		pexpi(d, p, exp->a);
 		pc('(');
 		pargs(d, exp->b);
 		pc(')');
-		if (i) pc(')');
 		break;
 
 	case EXP_NEW:
-		if (i) pc('(');
 		ps("new ");
-		pexpi(d, 1, exp->a);
+		pexpi(d, p, exp->a);
 		pc('(');
 		pargs(d, exp->b);
 		pc(')');
-		if (i) pc(')');
 		break;
 
 	case EXP_FUN:
 		ps("(function ");
-		if (exp->a) pexpi(d, 1, exp->a);
+		if (exp->a) pexpi(d, 0, exp->a);
 		pc('(');
 		pargs(d, exp->b);
 		ps(") {\n");
@@ -300,6 +393,8 @@
 		ps("<UNKNOWN>");
 		break;
 	}
+
+	if (paren) pc(')');
 }
 
 static void pexp(int d, js_Ast *exp)
@@ -372,7 +467,7 @@
 	switch (stm->type) {
 	case AST_FUNDEC:
 		ps("function ");
-		pexpi(d, 1, stm->a);
+		pexp(d, stm->a);
 		pc('(');
 		pargs(d, stm->b);
 		ps(")\n");
--- a/jsparse.h
+++ b/jsparse.h
@@ -20,8 +20,6 @@
 	EXP_FALSE,
 	EXP_THIS,
 
-	EXP_FUN,
-
 	EXP_ARRAY,
 	EXP_OBJECT,
 	EXP_PROP_VAL,
@@ -28,6 +26,8 @@
 	EXP_PROP_GET,
 	EXP_PROP_SET,
 
+	EXP_FUN,
+
 	/* expressions */
 	EXP_INDEX,
 	EXP_MEMBER,
@@ -34,41 +34,42 @@
 	EXP_CALL,
 	EXP_NEW,
 
+	EXP_POSTINC,
+	EXP_POSTDEC,
+
 	EXP_DELETE,
 	EXP_VOID,
 	EXP_TYPEOF,
 	EXP_PREINC,
 	EXP_PREDEC,
-	EXP_POSTINC,
-	EXP_POSTDEC,
 	EXP_POS,
 	EXP_NEG,
 	EXP_BITNOT,
 	EXP_LOGNOT,
 
-	EXP_LOGOR,
-	EXP_LOGAND,
-	EXP_BITOR,
-	EXP_BITXOR,
-	EXP_BITAND,
-	EXP_EQ,
-	EXP_NE,
-	EXP_STRICTEQ,
-	EXP_STRICTNE,
-	EXP_LT,
-	EXP_GT,
-	EXP_LE,
-	EXP_GE,
-	EXP_INSTANCEOF,
-	EXP_IN,
-	EXP_SHL,
-	EXP_SHR,
-	EXP_USHR,
-	EXP_ADD,
-	EXP_SUB,
-	EXP_MUL,
-	EXP_DIV,
 	EXP_MOD,
+	EXP_DIV,
+	EXP_MUL,
+	EXP_SUB,
+	EXP_ADD,
+	EXP_USHR,
+	EXP_SHR,
+	EXP_SHL,
+	EXP_IN,
+	EXP_INSTANCEOF,
+	EXP_GE,
+	EXP_LE,
+	EXP_GT,
+	EXP_LT,
+	EXP_STRICTNE,
+	EXP_STRICTEQ,
+	EXP_NE,
+	EXP_EQ,
+	EXP_BITAND,
+	EXP_BITXOR,
+	EXP_BITOR,
+	EXP_LOGAND,
+	EXP_LOGOR,
 
 	EXP_COND,
 
--- a/main.c
+++ b/main.c
@@ -41,7 +41,7 @@
 	if (argc > 1) {
 		for (i = 1; i < argc; ++i) {
 			js_dofile(J, argv[i]);
-			js_gc(J, 1);
+			js_gc(J, 0);
 		}
 	} else {
 		fputs(PS1, stdout);