Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(539)

Unified Diff: lib/compiler/implementation/js/printer.dart

Issue 10825180: Add JavaScript AST. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: updated. Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: lib/compiler/implementation/js/printer.dart
diff --git a/lib/compiler/implementation/js/printer.dart b/lib/compiler/implementation/js/printer.dart
new file mode 100644
index 0000000000000000000000000000000000000000..b1d8b472ef23accc82dc6a9e87a453098c09227f
--- /dev/null
+++ b/lib/compiler/implementation/js/printer.dart
@@ -0,0 +1,792 @@
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Printer implements NodeVisitor {
+ final bool shouldCompressOutput = false;
+ Compiler compiler;
+ var positionElement;
+ CodeBuffer outBuffer;
+ int indentLevel = 0;
+ bool inForInit = false;
+ bool atStatementBegin = false;
+
+ Printer(this.compiler, this.positionElement) : outBuffer = new CodeBuffer();
+
+ void spaceOut() {
+ if (!shouldCompressOutput) out(" ");
+ }
+ void lineOut() {
+ if (!shouldCompressOutput) out("\n");
+ }
+ int lastCharCode = 0;
+ void out(String str) {
+ outBuffer.add(str);
Lasse Reichstein Nielsen 2012/08/08 11:16:38 You can move the outBuffer into the if too.
floitsch 2012/08/09 16:24:07 Done.
+ if (str != "") {
+ lastCharCode = str.charCodeAt(str.length - 1);
+ }
+ }
+ void outLn(String str) {
+ out(str);
+ lineOut();
+ }
+ void outIndent(String str) { indent(); out(str); }
+ void outIndentLn(String str) { indent(); outLn(str); }
+ void indent() {
+ if (!shouldCompressOutput) {
+ for (int i = 0; i < indentLevel; i++) out(" ");
+ }
+ }
+
+ void recordSourcePosition(Dynamic position) {
Lasse Reichstein Nielsen 2012/08/08 11:16:38 Dynamic -> var, but please find a type.
floitsch 2012/08/09 16:24:07 As discussed. I would prefer to keep var here.
+ if (position != null) {
+ outBuffer.setSourceLocation(positionElement, position);
+ }
+ }
+
+ visit(Node node) {
+ recordSourcePosition(node.sourcePosition);
+ node.accept(this);
+ recordSourcePosition(node.endSourcePosition);
+ }
+
+ visitCommaSeparated(List<Node> nodes, int hasRequiredType,
+ [bool newInForInit, bool newAtStatementBegin]) {
+ for (int i = 0; i < nodes.length; i++) {
+ if (i != 0) {
+ atStatementBegin = false;
+ out(",");
+ spaceOut();
+ }
+ visitNestedExpression(nodes[i], hasRequiredType,
+ newInForInit, newAtStatementBegin);
+ }
+ }
+
+ visitAll(List<Node> nodes) {
+ nodes.forEach(visit);
+ }
+
+ visitProgram(Program program) {
+ visitAll(program.body);
+ }
+
+ bool blockBody(Node body, [bool needsSeparation, bool needsNewline]) {
+ if (body is Block) {
+ spaceOut();
+ blockOut(body, false, needsNewline);
+ return true;
+ }
+ if (shouldCompressOutput && needsSeparation) {
+ // If [shouldCompressOutput] is false, then the 'lineOut' will insert
+ // the separation.
+ out(" ");
+ } else {
+ lineOut();
+ }
+ indentLevel++;
+ visit(body);
+ indentLevel--;
+ return false;
+ }
+
+ void blockOutWithoutBraces(Node node) {
+ if (node is Block) {
+ node.elements.forEach(blockOutWithoutBraces);
+ } else {
+ visit(node);
+ }
+ }
+
+ void blockOut(Block node, bool shouldIndent, bool needsNewline) {
+ if (shouldIndent) indent();
+ out("{");
+ lineOut();
+ indentLevel++;
+ node.elements.forEach(blockOutWithoutBraces);
+ indentLevel--;
+ indent();
+ out("}");
+ if (needsNewline) lineOut();
+ }
+
+ visitBlock(Block block) {
+ blockOut(block, true, true);
+ }
+
+ visitExpressionStatement(ExpressionStatement expressionStatement) {
+ indent();
+ visitNestedExpression(expressionStatement.expr, EXPRESSION,
+ newInForInit: false, newAtStatementBegin: true);
+ outLn(";");
+ }
+
+ visitNOP(NOP nop) {
+ outIndentLn(";");
+ }
+
+ void ifOut(If node, bool shouldIndent) {
+ Node then = node.then;
+ Node elsePart = node.otherwise;
+ bool hasElse = node.hasElse;
+ // Handle dangling elses.
+ // If the then-branch is an if, which has no else-branch, but we do
+ // have one, then we need to put the nested if into braces.
+ if (hasElse && then is If) {
+ Node nested = then;
+ do {
+ If nestedIf = nested;
+ if (!nestedIf.hasElse) {
+ then = new Block(<Statement>[then]);
+ break;
+ }
+ nested = nestedIf.otherwise;
+ } while (nested is If);
+ }
+ if (then is If && !(then as If).hasElse && hasElse) {
+ then = new Block(<Statement>[then]);
+ }
+ if (shouldIndent) indent();
+ out("if");
+ spaceOut();
+ out("(");
+ visitNestedExpression(node.test, EXPRESSION,
+ newInForInit: false, newAtStatementBegin: false);
+ out(")");
+ bool thenWasBlock =
+ blockBody(then, needsSeparation: false, needsNewline: !hasElse);
+ if (hasElse) {
+ if (thenWasBlock) {
+ spaceOut();
+ } else {
+ indent();
+ }
+ out("else");
+ if (elsePart is If) {
+ out(" ");
+ ifOut(elsePart, false);
+ } else {
+ blockBody(elsePart, needsSeparation: true, needsNewline: true);
+ }
+ }
+ }
+
+ visitIf(If node) {
+ ifOut(node, true);
+ }
+
+ visitFor(For loop) {
+ outIndent("for");
+ spaceOut();
+ out("(");
+ if (loop.init !== null) {
+ visitNestedExpression(loop.init, EXPRESSION,
+ newInForInit: true, newAtStatementBegin: false);
+ }
+ out(";");
+ if (loop.test !== null) {
+ spaceOut();
+ visitNestedExpression(loop.test, EXPRESSION,
+ newInForInit: false, newAtStatementBegin: false);
+ }
+ out(";");
+ if (loop.incr !== null) {
+ spaceOut();
+ visitNestedExpression(loop.incr, EXPRESSION,
+ newInForInit: false, newAtStatementBegin: false);
+ }
+ out(")");
+ blockBody(loop.body, needsSeparation: false, needsNewline: true);
+ }
+
+ visitForIn(ForIn loop) {
+ outIndent("for");
+ spaceOut();
+ out("(");
+ visitNestedExpression(loop.lhs, EXPRESSION,
+ newInForInit: true, newAtStatementBegin: false);
+ out(" in ");
+ visitNestedExpression(loop.obj, EXPRESSION,
+ newInForInit: false, newAtStatementBegin: false);
+ out(")");
+ blockBody(loop.body, needsSeparation: false, needsNewline: true);
+ }
+
+ visitWhile(While loop) {
+ outIndent("while");
+ spaceOut();
+ out("(");
+ visitNestedExpression(loop.test, EXPRESSION,
+ newInForInit: false, newAtStatementBegin: false);
+ out(")");
+ blockBody(loop.body, needsSeparation: false, needsNewline: true);
+ }
+
+ visitDo(Do loop) {
+ outIndent("do");
+ if (blockBody(loop.body, needsSeparation: true, needsNewline: false)) {
+ spaceOut();
+ } else {
+ indent();
+ }
+ out("while");
+ spaceOut();
+ out("(");
+ visitNestedExpression(loop.test, EXPRESSION,
+ newInForInit: false, newAtStatementBegin: false);
+ outLn(");");
+ }
+
+ visitContinue(Continue node) {
+ if (node.id == null) {
+ outIndentLn("continue;");
+ } else {
+ outIndentLn("continue ${node.id};");
+ }
+ }
+
+ visitBreak(Break node) {
+ if (node.id == null) {
+ outIndentLn("break;");
+ } else {
+ outIndentLn("break ${node.id};");
+ }
+ }
+
+ visitReturn(Return node) {
+ if (node.expr == null) {
+ outIndentLn("return;");
+ } else {
+ outIndent("return ");
+ visitNestedExpression(node.expr, EXPRESSION,
+ newInForInit: false, newAtStatementBegin: false);
+ outLn(";");
+ }
+ }
+
+ visitThrow(Throw node) {
+ outIndent("throw ");
+ visitNestedExpression(node.expr, EXPRESSION,
+ newInForInit: false, newAtStatementBegin: false);
+ outLn(";");
+ }
+
+ visitTry(Try node) {
+ outIndent("try");
+ blockBody(node.body, needsSeparation: true, needsNewline: false);
+ spaceOut();
+ if (node.catchPart !== null) {
+ visit(node.catchPart);
+ }
+ if (node.finallyPart !== null) {
+ spaceOut();
+ out("finally");
+ blockBody(node.finallyPart, needsSeparation: true, needsNewline: true);
+ } else {
+ lineOut();
+ }
+ }
+
+ visitCatch(Catch node) {
+ spaceOut();
+ out("catch");
+ spaceOut();
+ out("(");
+ // Must be a reference, so just test for a primary.
+ visitNestedExpression(node.decl, PRIMARY,
Lasse Reichstein Nielsen 2012/08/08 11:16:38 It should be able to be a declaration too.
floitsch 2012/08/09 16:24:07 changed to EXPRESSION.
+ newInForInit: false, newAtStatementBegin: false);
+ out(")");
+ blockBody(node.body, needsSeparation: false, needsNewline: true);
+ }
+
+ visitWith(With node) {
+ outIndent("with");
+ spaceOut();
+ out("(");
+ visitNestedExpression(node.object, EXPRESSION,
+ newInForInit: false, newAtStatementBegin: false);
+ out(")");
+ blockBody(node.body, needsSeparation: false, needsNewline: true);
+ }
+
+ visitSwitch(Switch node) {
+ outIndent("switch");
+ spaceOut();
+ out("(");
+ visitNestedExpression(node.key, EXPRESSION,
+ newInForInit: false, newAtStatementBegin: false);
+ out(")");
+ spaceOut();
+ outLn("{");
+ indentLevel++;
+ visitAll(node.cases);
+ indentLevel--;
+ outIndentLn("}");
+ }
+
+ visitCase(Case node) {
+ outIndent("case ");
+ visitNestedExpression(node.expr, EXPRESSION,
Lasse Reichstein Nielsen 2012/08/08 11:16:38 That's ASSIGNMENT_EXPRESSION, not EXPRESSION. You
floitsch 2012/08/09 16:24:07 ignoring comment you sent out unintentionally.
+ newInForInit: false, newAtStatementBegin: false);
+ outLn(":");
+ if (!node.body.elements.isEmpty()) {
+ indentLevel++;
+ blockOutWithoutBraces(node.body);
+ indentLevel--;
+ }
+ }
+
+ visitDefault(Default node) {
+ outIndentLn("default:");
+ if (!node.body.elements.isEmpty()) {
+ indentLevel++;
+ blockOutWithoutBraces(node.body);
+ indentLevel--;
+ }
+ }
+
+ visitLabeled(Labeled node) {
+ outIndent("${node.id}:");
+ blockBody(node.body, needsSeparation: false, needsNewline: true);
+ }
+
+ void functionOut(Fun fun, Node name) {
+ out("function");
+ if (name != null) {
+ out(" ");
+ // Name must be a [Decl]. Therefore only test for primary expressions.
+ visitNestedExpression(name, PRIMARY,
+ newInForInit: false, newAtStatementBegin: false);
+ }
+ out("(");
+ if (fun.params != null) {
+ visitCommaSeparated(fun.params, PRIMARY,
+ newInForInit: false, newAtStatementBegin: false);
+ }
+ out(")");
+ blockBody(fun.body, needsSeparation: false, needsNewline: false);
+ }
+
+ visitFunctionDeclaration(FunctionDeclaration declaration) {
+ indent();
+ functionOut(declaration.fun, declaration.id);
+ lineOut();
+ }
+
+ visitNestedExpression(Expression node, int requiredPrecedence,
+ [bool newInForInit, bool newAtStatementBegin]) {
+ bool needsParentheses =
+ // a - (b + c).
+ (requiredPrecedence != EXPRESSION &&
+ node.precedenceLevel < requiredPrecedence) ||
+ // for (a = (x in o); ... ; ... ) { ... }
+ (newInForInit && node is Binary && (node as Binary).op == "in") ||
+ // (function() { ... })().
+ // ({a: 2, b: 3}.toString()).
+ (newAtStatementBegin && (node is NamedFunction ||
+ node is Fun ||
+ node is ObjectLiteral));
+ if (needsParentheses) {
+ inForInit = false;
+ atStatementBegin = false;
+ out("(");
+ visit(node);
+ out(")");
+ } else {
+ inForInit = newInForInit;
+ atStatementBegin = newAtStatementBegin;
+ visit(node);
+ }
+ }
+
+ visitVariableDeclarationList(VariableDeclarationList list) {
+ out("var ");
+ visitCommaSeparated(list.declarations, ASSIGNMENT,
+ newInForInit: inForInit, newAtStatementBegin: false);
+ }
+
+ visitSequence(Sequence sequence) {
+ // Note that we only require that the entries are expressions and not
+ // assignments. This means that nested sequences are not put into
+ // parenthesis.
+ visitCommaSeparated(sequence.expressions, EXPRESSION,
+ newInForInit: false,
+ newAtStatementBegin: atStatementBegin);
+ }
+
+ outAssignment(Node lhs, Node value, [String op = ""]) {
+ visitNestedExpression(lhs, LHS,
+ newInForInit: inForInit,
+ newAtStatementBegin: atStatementBegin);
+ if (value !== null) {
+ spaceOut();
+ out(op);
+ out("=");
+ spaceOut();
+ visitNestedExpression(value, ASSIGNMENT,
+ newInForInit: inForInit,
+ newAtStatementBegin: false);
+ }
+ }
+
+ visitVassign(Vassign vassign) {
+ outAssignment(vassign.lhs, vassign.value);
+ }
+ visitInit(Init init) {
+ outAssignment(init.decl, init.value);
+ }
+ visitAccsign(Accsign accsign) {
+ outAssignment(accsign.lhs, accsign.value);
+ }
+
+ visitVassignOp(VassignOp vassignOp) {
+ outAssignment(vassignOp.lhs, vassignOp.value, vassignOp.op);
+ }
+
+ visitAccsignOp(AccsignOp accsignOp) {
+ outAssignment(accsignOp.lhs, accsignOp.value, accsignOp.op);
+ }
+
+ visitConditional(Conditional cond) {
+ visitNestedExpression(cond.test, LOGICAL_OR,
+ newInForInit: inForInit,
+ newAtStatementBegin: atStatementBegin);
+ spaceOut();
+ out("?");
+ spaceOut();
+ // The then part is allowed to have an 'in'.
+ visitNestedExpression(cond.then, ASSIGNMENT,
+ newInForInit: false, newAtStatementBegin: false);
+ spaceOut();
+ out(":");
+ spaceOut();
+ visitNestedExpression(cond.otherwise, ASSIGNMENT,
+ newInForInit: inForInit, newAtStatementBegin: false);
+ }
+
+ visitNew(New node) {
+ out("new ");
+ visitNestedExpression(node.cls, CALL,
+ newInForInit: inForInit, newAtStatementBegin: false);
+ out("(");
+ visitCommaSeparated(node.arguments, ASSIGNMENT,
+ newInForInit: false, newAtStatementBegin: false);
+ out(")");
+ }
+
+ visitCall(Call call) {
+ visitNestedExpression(call.target, LHS,
+ newInForInit: inForInit,
+ newAtStatementBegin: atStatementBegin);
+ out("(");
+ visitCommaSeparated(call.arguments, ASSIGNMENT,
+ newInForInit: false, newAtStatementBegin: false);
+ out(")");
+ }
+
+ visitBinary(Binary binary) {
+ Expression left = binary.left;
+ Expression right = binary.right;
+ String op = binary.op;
+ int leftPrecedenceRequirement;
+ int rightPrecedenceRequirement;
+ switch (op) {
+ case "||":
+ leftPrecedenceRequirement = LOGICAL_OR;
+ // x || (y || z) <=> (x || y) || z.
+ rightPrecedenceRequirement = LOGICAL_OR;
+ break;
+ case "&&":
+ leftPrecedenceRequirement = LOGICAL_AND;
+ // x && (y && z) <=> (x && y) && z.
+ rightPrecedenceRequirement = LOGICAL_AND;
+ break;
+ case "|":
+ leftPrecedenceRequirement = BIT_OR;
+ // x | (y | z) <=> (x | y) | z.
+ rightPrecedenceRequirement = BIT_OR;
+ break;
+ case "^":
+ leftPrecedenceRequirement = BIT_XOR;
+ // x ^ (y ^ z) <=> (x ^ y) ^ z.
+ rightPrecedenceRequirement = BIT_XOR;
+ break;
+ case "&":
+ leftPrecedenceRequirement = BIT_AND;
+ // x & (y & z) <=> (x & y) & z.
+ rightPrecedenceRequirement = BIT_AND;
+ break;
+ case "==":
+ case "!=":
+ case "===":
+ case "!==":
+ leftPrecedenceRequirement = EQUALITY;
+ rightPrecedenceRequirement = RELATIONAL;
+ break;
+ case "<":
+ case ">":
+ case "<=":
+ case ">=":
+ case "instanceof":
+ case "in":
+ leftPrecedenceRequirement = RELATIONAL;
+ rightPrecedenceRequirement = SHIFT;
+ break;
+ case ">>":
+ case "<<":
+ case ">>>":
+ leftPrecedenceRequirement = SHIFT;
+ rightPrecedenceRequirement = ADDITIVE;
+ break;
+ case "+":
+ case "-":
+ leftPrecedenceRequirement = ADDITIVE;
+ // We cannot remove parenthesis for "+" because
+ // x + (y + z) <!=> (x + y) + z:
+ // Example:
+ // "a" + (1 + 2) => "a3";
+ // ("a" + 1) + 2 => "a12";
+ rightPrecedenceRequirement = MULTIPLICATIVE;
+ break;
+ case "*":
+ case "/":
+ case "%":
+ leftPrecedenceRequirement = MULTIPLICATIVE;
+ // We cannot remove parenthesis for "*" because of precision issues.
+ rightPrecedenceRequirement = UNARY;
+ break;
+ default:
+ compiler.internalError("Forgot operator: $op");
+ }
+
+ visitNestedExpression(left, leftPrecedenceRequirement,
+ newInForInit: inForInit,
+ newAtStatementBegin: atStatementBegin);
+
+ if (op == "in" || op == "instanceof") {
+ // There are cases where the space is not required but without further
+ // analysis we cannot know.
+ out(" ");
+ out(op);
+ out(" ");
+ } else {
+ spaceOut();
+ out(op);
+ spaceOut();
+ }
+ visitNestedExpression(right, rightPrecedenceRequirement,
+ newInForInit: inForInit,
+ newAtStatementBegin: false);
+ }
+
+ visitUnary(Unary unary) {
+ String op = unary.op;
+ switch (op) {
+ case "delete":
+ case "void":
+ case "typeof":
+ // There are cases where the space is not required but without further
+ // analysis we cannot know.
+ out(op);
+ out(" ");
+ break;
+ case "+":
+ case "++":
+ if (lastCharCode == "+".charCodeAt(0)) out(" ");
Lasse Reichstein Nielsen 2012/08/08 11:16:38 If you are going to be this primitive, just store
floitsch 2012/08/09 16:24:07 Importing the charcodes from ../util/characters.da
+ out(op);
+ break;
+ case "-":
+ case "--":
+ if (lastCharCode == "-".charCodeAt(0)) out(" ");
+ out(op);
+ break;
+ default:
+ out(op);
+ }
+ visitNestedExpression(unary.arg, UNARY,
+ newInForInit: inForInit, newAtStatementBegin: false);
+ }
+
+ visitPostfix(Postfix postfix) {
+ visitNestedExpression(postfix.arg, LHS,
+ newInForInit: inForInit,
+ newAtStatementBegin: atStatementBegin);
+ out(postfix.op);
+ }
+
+ visitRef(Ref ref) {
+ out(ref.id);
+ }
+
+ visitThis(This node) {
+ out("this");
+ }
+
+ visitDecl(Decl decl) {
+ out(decl.id);
+ }
+
+ visitParam(Param param) {
+ out(param.id);
+ }
+
+ bool isDigit(int charCode) {
+ return '0'.charCodeAt(0) <= charCode && charCode <= '9'.charCodeAt(0);
+ }
+
+ bool isValidJavaScriptId(String field) {
+ if (field.length < 3) return false;
+ // Ignore the leading and trailing string-delimiter.
+ for (int i = 1; i < field.length - 1; i++) {
+ // TODO(floitsch): allow more characters.
+ int charCode = field.charCodeAt(i);
+ if (!('a'.charCodeAt(0) <= charCode && charCode <= 'z'.charCodeAt(0) ||
+ 'A'.charCodeAt(0) <= charCode && charCode <= 'Z'.charCodeAt(0) ||
+ charCode == @'$'.charCodeAt(0) ||
+ charCode == '_'.charCodeAt(0) ||
+ i != 1 && isDigit(charCode))) {
+ return false;
+ }
+ }
+ // TODO(floitsch): normally we should also check that the field is not
+ // a reserved word.
+ return true;
+ }
+
+ visitAccess(Access access) {
+ visitNestedExpression(access.receiver, CALL,
+ newInForInit: inForInit,
+ newAtStatementBegin: atStatementBegin);
+ Node selector = access.selector;
+ if (selector is StringLiteral) {
+ String fieldWithQuotes = (selector as StringLiteral).value;
+ if (isValidJavaScriptId(fieldWithQuotes)) {
+ if (isDigit(lastCharCode)) out(" ");
Lasse Reichstein Nielsen 2012/08/08 11:16:38 You should be able to parenthesize the number, som
floitsch 2012/08/09 16:24:07 As discussed: we can change this later.
+ out(".");
+ out(fieldWithQuotes.substring(1, fieldWithQuotes.length - 1));
+ return;
+ }
+ }
+ out("[");
+ visitNestedExpression(selector, EXPRESSION,
+ newInForInit: false, newAtStatementBegin: false);
+ out("]");
+ }
+
+ visitNamedFunction(NamedFunction namedFunction) {
+ functionOut(namedFunction.fun, namedFunction.id);
+ }
+
+ visitFun(Fun fun) {
+ functionOut(fun, null);
+ }
+
+ visitBoolLiteral(BoolLiteral node) {
+ out(node.value ? "true" : "false");
+ }
+
+ visitStringLiteral(StringLiteral node) {
+ out(node.value);
+ }
+
+ visitNumberLiteral(NumberLiteral node) {
+ int charCode = node.value.charCodeAt(0);
+ if (charCode == '-'.charCodeAt(0) && lastCharCode == "-".charCodeAt(0)) {
+ out(" ");
+ }
+ out(node.value);
+ }
+
+ visitNullLiteral(NullLiteral node) {
+ out("null");
+ }
+
+ visitArrayLiteral(ArrayLiteral node) {
+ out("[");
+ List<ArrayElement> elements = node.elements;
+ int elementIndex = 0;
+ for (int i = 0; i < node.length; i++) {
+ if (elementIndex < elements.length &&
+ elements[elementIndex].index == i) {
+ visitNestedExpression(elements[elementIndex].value, ASSIGNMENT,
+ newInForInit: false, newAtStatementBegin: false);
+ elementIndex++;
+ // We can avoid a trailing "," if there was an element just before. So
+ // `[1]` and `[1,]` are the same, but `[,]` and `[]` are not.
+ if (i != node.length - 1) {
+ out(",");
+ spaceOut();
+ }
+ } else {
+ out(",");
+ }
+ }
+ out("]");
+ }
+
+ visitArrayElement(ArrayElement node) {
+ throw "Unreachable";
+ }
+
+ visitObjectLiteral(ObjectLiteral node) {
+ out("{");
+ List<PropertyInit> properties = node.properties;
+ for (int i = 0; i < properties.length; i++) {
+ if (i != 0) {
+ out(",");
+ spaceOut();
+ }
+ visitPropertyInit(properties[i]);
+ }
+ out("}");
+ }
+
+ visitPropertyInit(PropertyInit node) {
+ if (node.name is StringLiteral) {
+ String name = (node.name as StringLiteral).value;
+ if (isValidJavaScriptId(name)) {
+ out(name.substring(1, name.length - 1));
+ } else {
+ out(name);
+ }
+ } else {
+ assert(node.name is NumberLiteral);
+ out((node.name as NumberLiteral).value);
+ }
+ out(":");
+ spaceOut();
+ visitNestedExpression(node.value, ASSIGNMENT,
+ newInForInit: false, newAtStatementBegin: false);
+ }
+
+ visitRegExpLiteral(RegExpLiteral node) {
+ out(node.pattern);
+ }
+
+ visitExpressionBlob(ExpressionBlob node) {
+ String blob = node.blob;
+ List<Expression> data = node.data;
+
+ List<String> parts = blob.split('#');
Lasse Reichstein Nielsen 2012/08/08 11:16:38 "blob" is really the wrong name when you interpret
floitsch 2012/08/09 16:24:07 Done.
+ if (parts.length != data.length + 1) {
+ compiler.internalError('Wrong number of arguments for JS: $blob');
+ }
+ out("(");
+ out(parts[0]);
+ for (int i = 0; i < data.length; i++) {
+ visit(data[i]);
+ out(parts[i + 1]);
+ }
+ out(")");
+ }
+
+ visitStatementBlob(StatementBlob node) {
+ outLn(node.blob);
+ }
+}
+
+CodeBuffer prettyPrint(Node node, Compiler compiler, Dynamic positionElement) {
+ Printer printer = new Printer(compiler, positionElement);
+ printer.visit(node);
+ return printer.outBuffer;
+}

Powered by Google App Engine
This is Rietveld 408576698