Chromium Code Reviews| 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 663 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 674 Set<String> captures; | 674 Set<String> captures; |
| 675 | 675 |
| 676 MethodGenerator(this.method, this.enclosingMethod) | 676 MethodGenerator(this.method, this.enclosingMethod) |
| 677 : writer = new CodeWriter(), needsThis = false { | 677 : writer = new CodeWriter(), needsThis = false { |
| 678 if (enclosingMethod != null) { | 678 if (enclosingMethod != null) { |
| 679 _scope = new BlockScope(this, enclosingMethod._scope); | 679 _scope = new BlockScope(this, enclosingMethod._scope); |
| 680 captures = new Set(); | 680 captures = new Set(); |
| 681 } else { | 681 } else { |
| 682 _scope = new BlockScope(this, null); | 682 _scope = new BlockScope(this, null); |
| 683 } | 683 } |
| 684 // For named lambdas, add the name to this scope so we can call it | |
| 685 // recursively. | |
| 686 if (enclosingMethod != null && method.name != '') { | |
| 687 MethodMember m = method; // lambdas must be MethodMembers | |
| 688 _scope.create(m.name, m.functionType, m.definition.span, isFinal:true); | |
| 689 } | |
| 690 _usedTemps = new Set(); | 684 _usedTemps = new Set(); |
| 691 _freeTemps = []; | 685 _freeTemps = []; |
| 692 } | 686 } |
| 693 | 687 |
| 694 Library get library() => method.library; | 688 Library get library() => method.library; |
| 695 | 689 |
| 696 // TODO(jimhug): Where does this really belong? | 690 // TODO(jimhug): Where does this really belong? |
| 697 MemberSet findMembers(String name) { | 691 MemberSet findMembers(String name) { |
| 698 return library._findMembers(name); | 692 return library._findMembers(name); |
| 699 } | 693 } |
| (...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1140 | 1134 |
| 1141 _popBlock() { | 1135 _popBlock() { |
| 1142 _scope = _scope.parent; | 1136 _scope = _scope.parent; |
| 1143 } | 1137 } |
| 1144 | 1138 |
| 1145 MethodMember _makeLambdaMethod(String name, FunctionDefinition func) { | 1139 MethodMember _makeLambdaMethod(String name, FunctionDefinition func) { |
| 1146 var meth = new MethodMember(name, method.declaringType, func); | 1140 var meth = new MethodMember(name, method.declaringType, func); |
| 1147 meth.isLambda = true; | 1141 meth.isLambda = true; |
| 1148 meth.enclosingElement = method; | 1142 meth.enclosingElement = method; |
| 1149 meth.resolve(); | 1143 meth.resolve(); |
| 1150 world.gen.genMethod(meth, this); | |
| 1151 return meth; | 1144 return meth; |
| 1152 } | 1145 } |
| 1153 | 1146 |
| 1154 visitBool(Expression node) { | 1147 visitBool(Expression node) { |
| 1155 // Boolean conversions in if/while/do/for/conditions require non-null bool. | 1148 // Boolean conversions in if/while/do/for/conditions require non-null bool. |
| 1156 | 1149 |
| 1157 // TODO(jmesserly): why do we have this rule? It seems inconsistent with | 1150 // TODO(jmesserly): why do we have this rule? It seems inconsistent with |
| 1158 // the rest of the type system, and just causes bogus asserts unless all | 1151 // the rest of the type system, and just causes bogus asserts unless all |
| 1159 // bools are initialized to false. | 1152 // bools are initialized to false. |
| 1160 return visitValue(node).convertTo(this, world.nonNullBool, node); | 1153 return visitValue(node).convertTo(this, world.nonNullBool, node); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1229 value = value.convertTo(this, type, node.values[i]); | 1222 value = value.convertTo(this, type, node.values[i]); |
| 1230 writer.write('${val.code} = ${value.code}'); | 1223 writer.write('${val.code} = ${value.code}'); |
| 1231 } | 1224 } |
| 1232 } | 1225 } |
| 1233 writer.writeln(';'); | 1226 writer.writeln(';'); |
| 1234 return false; | 1227 return false; |
| 1235 | 1228 |
| 1236 } | 1229 } |
| 1237 | 1230 |
| 1238 bool visitFunctionDefinition(FunctionDefinition node) { | 1231 bool visitFunctionDefinition(FunctionDefinition node) { |
| 1239 var name = world.toJsIdentifier(node.name.name); | 1232 var meth = _makeLambdaMethod(node.name.name, node); |
|
Jennifer Messerly
2011/12/05 23:05:11
MethodMember "jsname" handles this now.
| |
| 1233 var funcValue = _scope.create(meth.name, meth.functionType, | |
| 1234 method.definition.span, isFinal:true); | |
| 1240 | 1235 |
| 1241 var meth = _makeLambdaMethod(name, node); | 1236 world.gen.genMethod(meth, this); |
| 1242 | |
| 1243 // TODO(jimhug): Pass js name into writeDefinition? | |
| 1244 var funcValue = _scope.create(name, meth.functionType, | |
| 1245 method.definition.span, isFinal:true); | |
| 1246 meth.generator.writeDefinition(writer, null); | 1237 meth.generator.writeDefinition(writer, null); |
| 1247 return false; | 1238 return false; |
| 1248 } | 1239 } |
| 1249 | 1240 |
| 1250 /** | 1241 /** |
| 1251 * Returns true indicating that normal control-flow is interrupted by | 1242 * Returns true indicating that normal control-flow is interrupted by |
| 1252 * this statement. (This could be a return, break, throw, or continue.) | 1243 * this statement. (This could be a return, break, throw, or continue.) |
| 1253 */ | 1244 */ |
| 1254 bool visitReturnStatement(ReturnStatement node) { | 1245 bool visitReturnStatement(ReturnStatement node) { |
| 1255 if (node.value == null) { | 1246 if (node.value == null) { |
| (...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1696 node != null ? node.span : null, /*needsTemp:*/false); | 1687 node != null ? node.span : null, /*needsTemp:*/false); |
| 1697 } else { | 1688 } else { |
| 1698 _checkNonStatic(node); | 1689 _checkNonStatic(node); |
| 1699 return new Value(method.declaringType, 'this', node != null ? node.span : null, | 1690 return new Value(method.declaringType, 'this', node != null ? node.span : null, |
| 1700 /*needsTemp:*/false); | 1691 /*needsTemp:*/false); |
| 1701 } | 1692 } |
| 1702 } | 1693 } |
| 1703 | 1694 |
| 1704 // ******************* Expressions ******************* | 1695 // ******************* Expressions ******************* |
| 1705 visitLambdaExpression(LambdaExpression node) { | 1696 visitLambdaExpression(LambdaExpression node) { |
| 1706 var name = ''; | 1697 var name = (node.func.name != null) ? node.func.name.name : ''; |
| 1707 if (node.func.name != null) { | 1698 |
| 1708 name = world.toJsIdentifier(node.func.name.name); | 1699 MethodMember meth = _makeLambdaMethod(name, node.func); |
| 1700 final lambdaGen = new MethodGenerator(meth, this); | |
| 1701 if (name != '') { | |
| 1702 // Note: we don't want to put this in our enclosing scope because the | |
| 1703 // name shouldn't be visible except inside the lambda. We also don't want | |
| 1704 // to put the name directly in the lambda's scope because parameters are | |
| 1705 // allowed to shadow it. So we create an extra scope for it to go into. | |
| 1706 lambdaGen._scope.create(name, meth.functionType, meth.definition.span, | |
| 1707 isFinal:true); | |
| 1708 lambdaGen._pushBlock(); | |
|
Jennifer Messerly
2011/12/05 23:05:11
no need to pop the scope, for the same reason we d
| |
| 1709 } | 1709 } |
| 1710 | 1710 lambdaGen.run(); |
| 1711 var meth = _makeLambdaMethod(name, node.func); | |
| 1712 | 1711 |
| 1713 var w = new CodeWriter(); | 1712 var w = new CodeWriter(); |
| 1714 meth.generator.writeDefinition(w, node); | 1713 meth.generator.writeDefinition(w, node); |
| 1715 | |
| 1716 return new Value(meth.functionType, w.text, node.span); | 1714 return new Value(meth.functionType, w.text, node.span); |
| 1717 } | 1715 } |
| 1718 | 1716 |
| 1719 visitCallExpression(CallExpression node) { | 1717 visitCallExpression(CallExpression node) { |
| 1720 var target; | 1718 var target; |
| 1721 var position = node.target; | 1719 var position = node.target; |
| 1722 var name = ':call'; | 1720 var name = ':call'; |
| 1723 if (node.target is DotExpression) { | 1721 if (node.target is DotExpression) { |
| 1724 DotExpression dot = node.target; | 1722 DotExpression dot = node.target; |
| 1725 target = dot.self.visit(this); | 1723 target = dot.self.visit(this); |
| (...skipping 723 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2449 result.add(new Value(world.varType, '\$$i', null, /*needsTemp:*/false)); | 2447 result.add(new Value(world.varType, '\$$i', null, /*needsTemp:*/false)); |
| 2450 } | 2448 } |
| 2451 for (int i = bareCount; i < length; i++) { | 2449 for (int i = bareCount; i < length; i++) { |
| 2452 var name = getName(i); | 2450 var name = getName(i); |
| 2453 if (name == null) name = '\$$i'; | 2451 if (name == null) name = '\$$i'; |
| 2454 result.add(new Value(world.varType, name, null, /*needsTemp:*/false)); | 2452 result.add(new Value(world.varType, name, null, /*needsTemp:*/false)); |
| 2455 } | 2453 } |
| 2456 return new Arguments(nodes, result); | 2454 return new Arguments(nodes, result); |
| 2457 } | 2455 } |
| 2458 } | 2456 } |
| OLD | NEW |