Browse Source

[macro] port expr + position printer to Haxe

Simon Krajewski 6 years ago
parent
commit
48435a8542
1 changed files with 140 additions and 0 deletions
  1. 140 0
      std/haxe/macro/Printer.hx

+ 140 - 0
std/haxe/macro/Printer.hx

@@ -335,4 +335,144 @@ class Printer {
 	}
 
 	function opt<T>(v:T, f:T->String, prefix = "") return v == null ? "" : (prefix + f(v));
+
+	public function printExprWithPositions(e:Expr) {
+		var buffer = new StringBuf();
+		function format4(i:Int) {
+			return StringTools.lpad(Std.string(i), " ", 4);
+		}
+		function loop(tabs:String, e:Expr) {
+			function add(s:String, ?p = null) {
+				if (p == null) {
+					p = e.pos;
+				}
+				var p = #if macro haxe.macro.Context.getPosInfos(p) #else e.pos #end;
+				buffer.add('${format4(p.min)}-${format4(p.max)} $tabs$s\n');
+			}
+			function loopI(e:Expr) loop(tabs + tabString, e);
+			switch (e.expr) {
+				case EConst(c): add(printConstant(c));
+				case EArray(e1, e2):
+					add("EArray");
+					loopI(e1);
+					loopI(e2);
+				case EBinop(op, e1, e2):
+					add("EBinop " + printBinop(op));
+					loopI(e1);
+					loopI(e2);
+				case EField(e, field):
+					add("EField " + field);
+					loopI(e);
+				case EParenthesis(e):
+					add("EParenthesis");
+					loopI(e);
+				case EObjectDecl(fields):
+					add("EObjectDecl");
+					for (field in fields) {
+						add(field.field); // TODO: we don't have the field pos?
+						loopI(field.expr);
+					}
+				case EArrayDecl(values):
+					add("EArrayDecl");
+					values.iter(loopI);
+				case ECall(e, params):
+					add("ECall");
+					loopI(e);
+					params.iter(loopI);
+				case ENew(tp, params):
+					add("ENew " + printTypePath(tp));
+					params.iter(loopI);
+				case EUnop(op, postFix, e):
+					add("EUnop " + printUnop(op));
+					loopI(e);
+				case EVars(vars):
+					add("EVars");
+					for (v in vars) {
+						if (v.expr != null) {
+							add(v.name);
+							loopI(v.expr);
+						}
+					}
+				case EFunction(name, f):
+					add("EFunction");
+					if (f.expr != null) {
+						loopI(f.expr);
+					}
+				case EBlock(exprs):
+					add("EBlock");
+					exprs.iter(loopI);
+				case EFor(it, expr):
+					add("EFor");
+					loopI(it);
+					loopI(expr);
+				case EIf(econd, eif, eelse):
+					add("EIf");
+					loopI(econd);
+					loopI(eif);
+					if (eelse != null) {
+						loopI(eelse);
+					}
+				case EWhile(econd, e, normalWhile):
+					add("EWhile");
+					loopI(econd);
+					loopI(e);
+				case ESwitch(e, cases, edef):
+					add("ESwitch");
+					loopI(e);
+					for (c in cases) {
+						for (pat in c.values) {
+							loop(tabs + tabString + tabString, pat);
+						}
+						if (c.expr != null) {
+							loop(tabs + tabString + tabString + tabString, c.expr);
+						}
+					}
+					if (edef != null) {
+						loop(tabs + tabString + tabString + tabString, edef);
+					}
+				case ETry(e, catches):
+					add("ETry");
+					loopI(e);
+					for (c in catches) {
+						loop(tabs + tabString + tabString, c.expr);
+					}
+				case EReturn(e):
+					add("EReturn");
+					if (e != null) {
+						loopI(e);
+					}
+				case EBreak:
+					add("EBreak");
+				case EContinue:
+					add("EContinue");
+				case EUntyped(e):
+					add("EUntyped");
+					loopI(e);
+				case EThrow(e):
+					add("EThrow");
+					loopI(e);
+				case ECast(e, t):
+					add("ECast");
+					loopI(e);
+				case EDisplay(e, displayKind):
+					add("EDisplay");
+					loopI(e);
+				case EDisplayNew(t):
+					add("EDisplayNew");
+				case ETernary(econd, eif, eelse):
+					add("ETernary");
+					loopI(econd);
+					loopI(eif);
+					loopI(eelse);
+				case ECheckType(e, t):
+					add("ECheckType");
+					loopI(e);
+				case EMeta(s, e):
+					add("EMeta " + printMetadata(s));
+					loopI(e);
+			}
+		}
+		loop("", e);
+		return buffer.toString();
+	}
 }