| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * Top level generator object for writing code and keeping track of | 6 * Top level generator object for writing code and keeping track of |
| 7 * dependencies. | 7 * dependencies. |
| 8 * | 8 * |
| 9 * Should have two compilation models, but only one implemented so far. | 9 * Should have two compilation models, but only one implemented so far. |
| 10 * | 10 * |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 353 } else { | 353 } else { |
| 354 writer.writeln('var ${global.name} = ${global.exp.code};'); | 354 writer.writeln('var ${global.name} = ${global.exp.code};'); |
| 355 } | 355 } |
| 356 } | 356 } |
| 357 } | 357 } |
| 358 | 358 |
| 359 /** Order a list of values in a Map by SourceSpan, then by name. */ | 359 /** Order a list of values in a Map by SourceSpan, then by name. */ |
| 360 List _orderValues(Map map) { | 360 List _orderValues(Map map) { |
| 361 // TODO(jmesserly): should we copy the list? | 361 // TODO(jmesserly): should we copy the list? |
| 362 // Right now, the Maps are returning a copy already. | 362 // Right now, the Maps are returning a copy already. |
| 363 List values = map.getValues(); | 363 final values = map.getValues(); |
| 364 values.sort(_compareMembers); | 364 values.sort(_compareMembers); |
| 365 return values; | 365 return values; |
| 366 } | 366 } |
| 367 | 367 |
| 368 int _compareMembers(x, y) { | 368 int _compareMembers(x, y) { |
| 369 if (x.span != null && y.span != null) { | 369 if (x.span != null && y.span != null) { |
| 370 // First compare by source span. | 370 // First compare by source span. |
| 371 int spans = x.span.compareTo(y.span); | 371 int spans = x.span.compareTo(y.span); |
| 372 if (spans != 0) return spans; | 372 if (spans != 0) return spans; |
| 373 } | 373 } |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 565 : writer = new CodeWriter(), needsThis = false { | 565 : writer = new CodeWriter(), needsThis = false { |
| 566 if (enclosingMethod != null) { | 566 if (enclosingMethod != null) { |
| 567 _scope = new BlockScope(this, enclosingMethod._scope); | 567 _scope = new BlockScope(this, enclosingMethod._scope); |
| 568 captures = new Set(); | 568 captures = new Set(); |
| 569 } else { | 569 } else { |
| 570 _scope = new BlockScope(this, null); | 570 _scope = new BlockScope(this, null); |
| 571 } | 571 } |
| 572 // For named lambdas, add the name to this scope so we can call it | 572 // For named lambdas, add the name to this scope so we can call it |
| 573 // recursively. | 573 // recursively. |
| 574 if (enclosingMethod != null && method.name != '') { | 574 if (enclosingMethod != null && method.name != '') { |
| 575 MethodMember m = method; // lambdas must be MethodMembers | 575 _scope.create(method.name, method.functionType, method.definition); |
| 576 _scope.create(m.name, m.functionType, m.definition); | |
| 577 } | 576 } |
| 578 _usedTemps = new Set(); | 577 _usedTemps = new Set(); |
| 579 _freeTemps = []; | 578 _freeTemps = []; |
| 580 } | 579 } |
| 581 | 580 |
| 582 // TODO(jimhug): Where does this really belong? | 581 // TODO(jimhug): Where does this really belong? |
| 583 MemberSet findMembers(String name) { | 582 MemberSet findMembers(String name) { |
| 584 return method.library._findMembers(name); | 583 return method.library._findMembers(name); |
| 585 } | 584 } |
| 586 | 585 |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 709 defWriter.exitBlock('}'); | 708 defWriter.exitBlock('}'); |
| 710 } | 709 } |
| 711 if (method.isConstructor && method.constructorName != '') { | 710 if (method.isConstructor && method.constructorName != '') { |
| 712 defWriter.writeln( | 711 defWriter.writeln( |
| 713 '${method.declaringType.jsname}.${method.constructorName}\$ctor.prototyp
e = ' + | 712 '${method.declaringType.jsname}.${method.constructorName}\$ctor.prototyp
e = ' + |
| 714 '${method.declaringType.jsname}.prototype;'); | 713 '${method.declaringType.jsname}.prototype;'); |
| 715 } | 714 } |
| 716 | 715 |
| 717 _provideOptionalParamInfo(defWriter); | 716 _provideOptionalParamInfo(defWriter); |
| 718 | 717 |
| 719 if (method is MethodMember) { | 718 if (method is MethodMember && method._providePropertySyntax) { |
| 720 MethodMember m = method; | 719 defWriter.enterBlock( |
| 721 if (m._providePropertySyntax) { | 720 '${method.declaringType.jsname}.prototype.get\$${method.jsname} = functi
on() {'); |
| 722 defWriter.enterBlock('${m.declaringType.jsname}.prototype' | 721 // TODO(jimhug): Bind not availabe in Safari, need fallback. |
| 723 + '.get\$${m.jsname} = function() {'); | 722 defWriter.writeln( |
| 724 // TODO(jimhug): Bind not available in older Safari, need fallback? | 723 'return ${method.declaringType.jsname}.prototype.${method.jsname}.bind(t
his);'); |
| 725 defWriter.writeln('return ${m.declaringType.jsname}.prototype.' | 724 defWriter.exitBlock('}'); |
| 726 + '${m.jsname}.bind(this);'); | |
| 727 defWriter.exitBlock('}'); | |
| 728 | 725 |
| 729 if (m._provideFieldSyntax) { | 726 if (method._provideFieldSyntax) { |
| 730 world.internalError('bound m accessed with field syntax'); | 727 world.internalError('bound method accessed with field syntax'); |
| 731 } | |
| 732 } | 728 } |
| 733 } | 729 } |
| 734 } | 730 } |
| 735 | 731 |
| 736 /** | 732 /** |
| 737 * Generates information about the default/named arguments into the JS code. | 733 * Generates information about the default/named arguments into the JS code. |
| 738 * Only methods that are passed as bound methods to "var" need this. It is | 734 * Only methods that are passed as bound methods to "var" need this. It is |
| 739 * generated to support run time stub creation. | 735 * generated to support run time stub creation. |
| 740 */ | 736 */ |
| 741 _provideOptionalParamInfo(CodeWriter defWriter) { | 737 _provideOptionalParamInfo(CodeWriter defWriter) { |
| 742 if (method is MethodMember) { | 738 if (method is MethodMember && method._provideOptionalParamInfo) { |
| 743 MethodMember meth = method; | 739 var optNames = []; |
| 744 if (meth._provideOptionalParamInfo) { | 740 var optValues = []; |
| 745 var optNames = []; | 741 method.genParameterValues(); |
| 746 var optValues = []; | 742 for (var param in method.parameters) { |
| 747 meth.genParameterValues(); | 743 if (param.isOptional) { |
| 748 for (var param in meth.parameters) { | 744 optNames.add(param.name); |
| 749 if (param.isOptional) { | 745 optValues.add(_escapeString(param.value.code)); |
| 750 optNames.add(param.name); | 746 } |
| 751 optValues.add(_escapeString(param.value.code)); | 747 } |
| 748 if (optNames.length > 0) { |
| 749 // TODO(jmesserly): the logic for how to refer to |
| 750 // static/instance/top-level members is duplicated all over the place. |
| 751 // Badly needs cleanup. |
| 752 var start = ''; |
| 753 if (method.isStatic) { |
| 754 if (!method.declaringType.isTop) { |
| 755 start = method.declaringType.jsname + '.'; |
| 752 } | 756 } |
| 757 } else { |
| 758 start = method.declaringType.jsname + '.prototype.'; |
| 753 } | 759 } |
| 754 if (optNames.length > 0) { | |
| 755 // TODO(jmesserly): the logic for how to refer to | |
| 756 // static/instance/top-level members is duplicated all over the place. | |
| 757 // Badly needs cleanup. | |
| 758 var start = ''; | |
| 759 if (meth.isStatic) { | |
| 760 if (!meth.declaringType.isTop) { | |
| 761 start = meth.declaringType.jsname + '.'; | |
| 762 } | |
| 763 } else { | |
| 764 start = meth.declaringType.jsname + '.prototype.'; | |
| 765 } | |
| 766 | 760 |
| 767 optNames.addAll(optValues); | 761 optNames.addAll(optValues); |
| 768 var optional = "['" + Strings.join(optNames, "', '") + "']"; | 762 var optional = "['" + Strings.join(optNames, "', '") + "']"; |
| 769 defWriter.writeln('${start}${meth.jsname}.\$optional = $optional'); | 763 defWriter.writeln('${start}${method.jsname}.\$optional = $optional'); |
| 770 } | |
| 771 } | 764 } |
| 772 } | 765 } |
| 773 } | 766 } |
| 774 | 767 |
| 775 writeBody() { | 768 writeBody() { |
| 776 var initializers = null; | 769 var initializers = null; |
| 777 var initializedFields = null; // to check that final fields are initialized | 770 var initializedFields = null; // to check that final fields are initialized |
| 778 if (method.isConstructor) { | 771 if (method.isConstructor) { |
| 779 initializers = []; | 772 initializers = []; |
| 780 initializedFields = new Set(); | 773 initializedFields = new Set(); |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 967 */ | 960 */ |
| 968 static String _escapeString(String text) { | 961 static String _escapeString(String text) { |
| 969 // TODO(jimhug): Use a regex for performance here. | 962 // TODO(jimhug): Use a regex for performance here. |
| 970 return text.replaceAll('\\', '\\\\').replaceAll('"', '\\"').replaceAll( | 963 return text.replaceAll('\\', '\\\\').replaceAll('"', '\\"').replaceAll( |
| 971 '\n', '\\n').replaceAll('\r', '\\r'); | 964 '\n', '\\n').replaceAll('\r', '\\r'); |
| 972 } | 965 } |
| 973 | 966 |
| 974 /** Visits [body] without creating a new block for a [BlockStatement]. */ | 967 /** Visits [body] without creating a new block for a [BlockStatement]. */ |
| 975 bool visitStatementsInBlock(Statement body) { | 968 bool visitStatementsInBlock(Statement body) { |
| 976 if (body is BlockStatement) { | 969 if (body is BlockStatement) { |
| 977 BlockStatement block = body; | 970 for (var stmt in body.body) { |
| 978 for (var stmt in block.body) { | |
| 979 stmt.visit(this); | 971 stmt.visit(this); |
| 980 } | 972 } |
| 981 } else { | 973 } else { |
| 982 if (body != null) body.visit(this); | 974 if (body != null) body.visit(this); |
| 983 } | 975 } |
| 984 return false; | 976 return false; |
| 985 } | 977 } |
| 986 | 978 |
| 987 _pushBlock([bool reentrant = false]) { | 979 _pushBlock([bool reentrant = false]) { |
| 988 _scope = new BlockScope(this, _scope, reentrant); | 980 _scope = new BlockScope(this, _scope, reentrant); |
| (...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1535 meth.generator.writeDefinition(w, node); | 1527 meth.generator.writeDefinition(w, node); |
| 1536 | 1528 |
| 1537 return new Value(meth.functionType, w.text); | 1529 return new Value(meth.functionType, w.text); |
| 1538 } | 1530 } |
| 1539 | 1531 |
| 1540 visitCallExpression(CallExpression node) { | 1532 visitCallExpression(CallExpression node) { |
| 1541 var target; | 1533 var target; |
| 1542 var position = node.target; | 1534 var position = node.target; |
| 1543 var name = '\$call'; | 1535 var name = '\$call'; |
| 1544 if (node.target is DotExpression) { | 1536 if (node.target is DotExpression) { |
| 1545 DotExpression dot = node.target; | 1537 target = node.target.self.visit(this); |
| 1546 target = dot.self.visit(this); | 1538 name = node.target.name.name; |
| 1547 name = dot.name.name; | 1539 position = node.target.name; |
| 1548 position = dot.name; | |
| 1549 } else if (node.target is VarExpression) { | 1540 } else if (node.target is VarExpression) { |
| 1550 VarExpression varExpr = node.target; | 1541 name = node.target.name.name; |
| 1551 name = varExpr.name.name; | |
| 1552 var meth = method.declaringType.resolveMember(name); | 1542 var meth = method.declaringType.resolveMember(name); |
| 1553 if (meth != null) { | 1543 if (meth != null) { |
| 1554 target = _makeThisOrType(); | 1544 target = _makeThisOrType(); |
| 1555 return meth.invoke(this, varExpr, target, | 1545 return meth.invoke(this, node.target, target, |
| 1556 _makeArgs(node.arguments)); | 1546 _makeArgs(node.arguments)); |
| 1557 } | 1547 } |
| 1558 // Look for members of the top-level type (or imported libs). | 1548 // Look for members of the top-level type (or imported libs). |
| 1559 meth = method.declaringType.library.lookup(name, varExpr.span); | 1549 meth = method.declaringType.library.lookup(name, node.target.span); |
| 1560 if (meth != null) { | 1550 if (meth != null) { |
| 1561 return meth.invoke(this, varExpr, null, _makeArgs(node.arguments)); | 1551 return meth.invoke(this, node.target, null, |
| 1552 _makeArgs(node.arguments)); |
| 1562 } | 1553 } |
| 1563 | 1554 |
| 1564 name = '\$call'; | 1555 name = '\$call'; |
| 1565 target = varExpr.visit(this); | 1556 target = node.target.visit(this); |
| 1566 } else { | 1557 } else { |
| 1567 target = node.target.visit(this); | 1558 target = node.target.visit(this); |
| 1568 } | 1559 } |
| 1569 | 1560 |
| 1570 return target.invoke(this, name, position, _makeArgs(node.arguments)); | 1561 return target.invoke(this, name, position, _makeArgs(node.arguments)); |
| 1571 } | 1562 } |
| 1572 | 1563 |
| 1573 visitIndexExpression(IndexExpression node) { | 1564 visitIndexExpression(IndexExpression node) { |
| 1574 var target = visitValue(node.target); | 1565 var target = visitValue(node.target); |
| 1575 var index = visitValue(node.index); | 1566 var index = visitValue(node.index); |
| (...skipping 647 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2223 result.add(new Value(world.varType, '\$$i', false, /*needsTemp:*/false)); | 2214 result.add(new Value(world.varType, '\$$i', false, /*needsTemp:*/false)); |
| 2224 } | 2215 } |
| 2225 for (int i = bareCount; i < length; i++) { | 2216 for (int i = bareCount; i < length; i++) { |
| 2226 var name = getName(i); | 2217 var name = getName(i); |
| 2227 if (name == null) name = '\$$i'; | 2218 if (name == null) name = '\$$i'; |
| 2228 result.add(new Value(world.varType, name, false, /*needsTemp:*/false)); | 2219 result.add(new Value(world.varType, name, false, /*needsTemp:*/false)); |
| 2229 } | 2220 } |
| 2230 return new Arguments(nodes, result); | 2221 return new Arguments(nodes, result); |
| 2231 } | 2222 } |
| 2232 } | 2223 } |
| OLD | NEW |