| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 library dart2js.ir_builder; | 5 library dart2js.ir_builder; |
| 6 | 6 |
| 7 import 'cps_ir_nodes.dart' as ir; | 7 import 'cps_ir_nodes.dart' as ir; |
| 8 import '../elements/elements.dart'; | 8 import '../elements/elements.dart'; |
| 9 import '../dart2jslib.dart'; | 9 import '../dart2jslib.dart'; |
| 10 import '../dart_types.dart'; | 10 import '../dart_types.dart'; |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 320 } | 320 } |
| 321 | 321 |
| 322 ir.Primitive continueWithExpression(ir.Expression build(ir.Continuation k)) { | 322 ir.Primitive continueWithExpression(ir.Expression build(ir.Continuation k)) { |
| 323 ir.Parameter v = new ir.Parameter(null); | 323 ir.Parameter v = new ir.Parameter(null); |
| 324 ir.Continuation k = new ir.Continuation([v]); | 324 ir.Continuation k = new ir.Continuation([v]); |
| 325 ir.Expression expression = build(k); | 325 ir.Expression expression = build(k); |
| 326 add(new ir.LetCont(k, expression)); | 326 add(new ir.LetCont(k, expression)); |
| 327 return v; | 327 return v; |
| 328 } | 328 } |
| 329 | 329 |
| 330 ir.Constant makeConst(ConstExp exp, Constant value) { | 330 ir.Constant makeConst(ConstExp exp) { |
| 331 return new ir.Constant(exp, value); | 331 return new ir.Constant(exp); |
| 332 } | 332 } |
| 333 | 333 |
| 334 ir.Constant makePrimConst(PrimitiveConstant value) { | 334 ir.Constant makePrimConst(PrimitiveConstant value) { |
| 335 return makeConst(new PrimitiveConstExp(value), value); | 335 return makeConst(new PrimitiveConstExp(value)); |
| 336 } | 336 } |
| 337 | 337 |
| 338 // TODO(johnniwinther): Build constants directly through [ConstExp] when these | 338 // TODO(johnniwinther): Build constants directly through [ConstExp] when these |
| 339 // are created from analyzer2dart. | 339 // are created from analyzer2dart. |
| 340 ir.Node buildPrimConst(PrimitiveConstant constant) { | 340 ir.Node buildPrimConst(PrimitiveConstant constant) { |
| 341 assert(isOpen); | 341 assert(isOpen); |
| 342 ir.Node prim = makePrimConst(constant); | 342 ir.Node prim = makePrimConst(constant); |
| 343 add(new ir.LetPrim(prim)); | 343 add(new ir.LetPrim(prim)); |
| 344 return prim; | 344 return prim; |
| 345 } | 345 } |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 463 // assigned in the delimited subexpression to their reaching definition --- | 463 // assigned in the delimited subexpression to their reaching definition --- |
| 464 // that is, the definition in effect at the hole in 'current'. These are | 464 // that is, the definition in effect at the hole in 'current'. These are |
| 465 // used to determine if a join-point continuation needs to be passed | 465 // used to determine if a join-point continuation needs to be passed |
| 466 // arguments, and what the arguments are. | 466 // arguments, and what the arguments are. |
| 467 | 467 |
| 468 /// A stack of collectors for breaks. | 468 /// A stack of collectors for breaks. |
| 469 final List<JumpCollector> breakCollectors; | 469 final List<JumpCollector> breakCollectors; |
| 470 /// A stack of collectors for continues. | 470 /// A stack of collectors for continues. |
| 471 final List<JumpCollector> continueCollectors; | 471 final List<JumpCollector> continueCollectors; |
| 472 | 472 |
| 473 ConstExpBuilder constantBuilder; | |
| 474 | |
| 475 final List<ConstDeclaration> localConstants; | 473 final List<ConstDeclaration> localConstants; |
| 476 | 474 |
| 477 FunctionElement currentFunction; | 475 FunctionElement currentFunction; |
| 478 final DetectClosureVariables closureLocals; | 476 final DetectClosureVariables closureLocals; |
| 479 | 477 |
| 480 /// Construct a top-level visitor. | 478 /// Construct a top-level visitor. |
| 481 IrBuilderVisitor(TreeElements elements, this.compiler, this.sourceFile) | 479 IrBuilderVisitor(TreeElements elements, this.compiler, this.sourceFile) |
| 482 : breakCollectors = <JumpCollector>[], | 480 : breakCollectors = <JumpCollector>[], |
| 483 continueCollectors = <JumpCollector>[], | 481 continueCollectors = <JumpCollector>[], |
| 484 localConstants = <ConstDeclaration>[], | 482 localConstants = <ConstDeclaration>[], |
| 485 closureLocals = new DetectClosureVariables(elements), | 483 closureLocals = new DetectClosureVariables(elements), |
| 486 super(elements) { | 484 super(elements) { |
| 487 constantSystem = compiler.backend.constantSystem; | 485 constantSystem = compiler.backend.constantSystem; |
| 488 constantBuilder = new ConstExpBuilder(this); | |
| 489 } | 486 } |
| 490 | 487 |
| 491 /// Construct a delimited visitor for visiting a subtree. | 488 /// Construct a delimited visitor for visiting a subtree. |
| 492 /// | 489 /// |
| 493 /// The delimited visitor has its own compile-time environment mapping | 490 /// The delimited visitor has its own compile-time environment mapping |
| 494 /// local variables to their values, which is initially a copy of the parent | 491 /// local variables to their values, which is initially a copy of the parent |
| 495 /// environment. It has its own context for building an IR expression, so | 492 /// environment. It has its own context for building an IR expression, so |
| 496 /// the built expression is not plugged into the parent's context. | 493 /// the built expression is not plugged into the parent's context. |
| 497 IrBuilderVisitor.delimited(IrBuilderVisitor parent) | 494 IrBuilderVisitor.delimited(IrBuilderVisitor parent) |
| 498 : compiler = parent.compiler, | 495 : compiler = parent.compiler, |
| 499 sourceFile = parent.sourceFile, | 496 sourceFile = parent.sourceFile, |
| 500 breakCollectors = parent.breakCollectors, | 497 breakCollectors = parent.breakCollectors, |
| 501 continueCollectors = parent.continueCollectors, | 498 continueCollectors = parent.continueCollectors, |
| 502 constantBuilder = parent.constantBuilder, | |
| 503 localConstants = parent.localConstants, | 499 localConstants = parent.localConstants, |
| 504 currentFunction = parent.currentFunction, | 500 currentFunction = parent.currentFunction, |
| 505 closureLocals = parent.closureLocals, | 501 closureLocals = parent.closureLocals, |
| 506 super(parent.elements) { | 502 super(parent.elements) { |
| 507 constantSystem = parent.constantSystem; | 503 constantSystem = parent.constantSystem; |
| 508 returnContinuation = parent.returnContinuation; | 504 returnContinuation = parent.returnContinuation; |
| 509 environment = new Environment.from(parent.environment); | 505 environment = new Environment.from(parent.environment); |
| 510 } | 506 } |
| 511 | 507 |
| 512 /// Construct a visitor for a recursive continuation. | 508 /// Construct a visitor for a recursive continuation. |
| 513 /// | 509 /// |
| 514 /// The recursive continuation builder has fresh parameters (i.e. SSA phis) | 510 /// The recursive continuation builder has fresh parameters (i.e. SSA phis) |
| 515 /// for all the local variables in the parent, because the invocation sites | 511 /// for all the local variables in the parent, because the invocation sites |
| 516 /// of the continuation are not all known when the builder is created. The | 512 /// of the continuation are not all known when the builder is created. The |
| 517 /// recursive invocations will be passed values for all the local variables, | 513 /// recursive invocations will be passed values for all the local variables, |
| 518 /// which may be eliminated later if they are redundant---if they take on | 514 /// which may be eliminated later if they are redundant---if they take on |
| 519 /// the same value at all invocation sites. | 515 /// the same value at all invocation sites. |
| 520 IrBuilderVisitor.recursive(IrBuilderVisitor parent) | 516 IrBuilderVisitor.recursive(IrBuilderVisitor parent) |
| 521 : compiler = parent.compiler, | 517 : compiler = parent.compiler, |
| 522 sourceFile = parent.sourceFile, | 518 sourceFile = parent.sourceFile, |
| 523 breakCollectors = parent.breakCollectors, | 519 breakCollectors = parent.breakCollectors, |
| 524 continueCollectors = parent.continueCollectors, | 520 continueCollectors = parent.continueCollectors, |
| 525 constantBuilder = parent.constantBuilder, | |
| 526 localConstants = parent.localConstants, | 521 localConstants = parent.localConstants, |
| 527 currentFunction = parent.currentFunction, | 522 currentFunction = parent.currentFunction, |
| 528 closureLocals = parent.closureLocals, | 523 closureLocals = parent.closureLocals, |
| 529 super(parent.elements) { | 524 super(parent.elements) { |
| 530 constantSystem = parent.constantSystem; | 525 constantSystem = parent.constantSystem; |
| 531 returnContinuation = parent.returnContinuation; | 526 returnContinuation = parent.returnContinuation; |
| 532 parent.environment.index2variable.forEach(createParameter); | 527 parent.environment.index2variable.forEach(createParameter); |
| 533 } | 528 } |
| 534 | 529 |
| 535 /** | 530 /** |
| (...skipping 18 matching lines...) Expand all Loading... |
| 554 _root = _current = null; | 549 _root = _current = null; |
| 555 | 550 |
| 556 FunctionSignature signature = element.functionSignature; | 551 FunctionSignature signature = element.functionSignature; |
| 557 signature.orderedForEachParameter((ParameterElement parameterElement) { | 552 signature.orderedForEachParameter((ParameterElement parameterElement) { |
| 558 createParameter(parameterElement, | 553 createParameter(parameterElement, |
| 559 isClosureVariable: isClosureVariable(parameterElement)); | 554 isClosureVariable: isClosureVariable(parameterElement)); |
| 560 }); | 555 }); |
| 561 | 556 |
| 562 List<ConstExp> defaults = new List<ConstExp>(); | 557 List<ConstExp> defaults = new List<ConstExp>(); |
| 563 signature.orderedOptionalParameters.forEach((ParameterElement element) { | 558 signature.orderedOptionalParameters.forEach((ParameterElement element) { |
| 564 if (element.initializer != null) { | 559 defaults.add(getConstantForVariable(element)); |
| 565 defaults.add(constantBuilder.visit(element.initializer)); | |
| 566 } else { | |
| 567 defaults.add(new PrimitiveConstExp(constantSystem.createNull())); | |
| 568 } | |
| 569 }); | 560 }); |
| 570 | 561 |
| 571 visit(function.body); | 562 visit(function.body); |
| 572 return buildFunctionDefinition(element, localConstants, defaults); | 563 return buildFunctionDefinition(element, localConstants, defaults); |
| 573 } | 564 } |
| 574 | 565 |
| 575 ir.Primitive visit(ast.Node node) => node.accept(this); | 566 ir.Primitive visit(ast.Node node) => node.accept(this); |
| 576 | 567 |
| 577 // ==== Statements ==== | 568 // ==== Statements ==== |
| 578 // Build(Block(stamements), C) = C' | 569 // Build(Block(stamements), C) = C' |
| (...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1043 return null; | 1034 return null; |
| 1044 } | 1035 } |
| 1045 | 1036 |
| 1046 ir.Primitive visitVariableDefinitions(ast.VariableDefinitions node) { | 1037 ir.Primitive visitVariableDefinitions(ast.VariableDefinitions node) { |
| 1047 assert(isOpen); | 1038 assert(isOpen); |
| 1048 if (node.modifiers.isConst) { | 1039 if (node.modifiers.isConst) { |
| 1049 for (ast.SendSet definition in node.definitions.nodes) { | 1040 for (ast.SendSet definition in node.definitions.nodes) { |
| 1050 assert(!definition.arguments.isEmpty); | 1041 assert(!definition.arguments.isEmpty); |
| 1051 assert(definition.arguments.tail.isEmpty); | 1042 assert(definition.arguments.tail.isEmpty); |
| 1052 VariableElement element = elements[definition]; | 1043 VariableElement element = elements[definition]; |
| 1053 ConstExp value = constantBuilder.visit(definition.arguments.head); | 1044 ConstExp value = getConstantForVariable(element); |
| 1054 localConstants.add(new ConstDeclaration(element, value)); | 1045 localConstants.add(new ConstDeclaration(element, value)); |
| 1055 } | 1046 } |
| 1056 } else { | 1047 } else { |
| 1057 for (ast.Node definition in node.definitions.nodes) { | 1048 for (ast.Node definition in node.definitions.nodes) { |
| 1058 Element element = elements[definition]; | 1049 Element element = elements[definition]; |
| 1059 ir.Primitive initialValue; | 1050 ir.Primitive initialValue; |
| 1060 // Definitions are either SendSets if there is an initializer, or | 1051 // Definitions are either SendSets if there is an initializer, or |
| 1061 // Identifiers if there is no initializer. | 1052 // Identifiers if there is no initializer. |
| 1062 if (definition is ast.SendSet) { | 1053 if (definition is ast.SendSet) { |
| 1063 assert(!definition.arguments.isEmpty); | 1054 assert(!definition.arguments.isEmpty); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1164 ir.Primitive visitLiteralNull(ast.LiteralNull node) { | 1155 ir.Primitive visitLiteralNull(ast.LiteralNull node) { |
| 1165 assert(isOpen); | 1156 assert(isOpen); |
| 1166 return translateConstant(node); | 1157 return translateConstant(node); |
| 1167 } | 1158 } |
| 1168 | 1159 |
| 1169 ir.Primitive visitLiteralString(ast.LiteralString node) { | 1160 ir.Primitive visitLiteralString(ast.LiteralString node) { |
| 1170 assert(isOpen); | 1161 assert(isOpen); |
| 1171 return translateConstant(node); | 1162 return translateConstant(node); |
| 1172 } | 1163 } |
| 1173 | 1164 |
| 1174 Constant getConstantForNode(ast.Node node) { | 1165 ConstExp getConstantForNode(ast.Node node) { |
| 1175 Constant constant = | 1166 ConstExp constant = |
| 1176 compiler.backend.constantCompilerTask.compileNode(node, elements); | 1167 compiler.backend.constantCompilerTask.compileNode(node, elements); |
| 1177 assert(invariant(node, constant != null, | 1168 assert(invariant(node, constant != null, |
| 1178 message: 'No constant computed for $node')); | 1169 message: 'No constant computed for $node')); |
| 1179 return constant; | 1170 return constant; |
| 1180 } | 1171 } |
| 1181 | 1172 |
| 1173 ConstExp getConstantForVariable(VariableElement element) { |
| 1174 ConstExp constant = |
| 1175 compiler.backend.constants.getConstantForVariable(element); |
| 1176 assert(invariant(element, constant != null, |
| 1177 message: 'No constant computed for $element')); |
| 1178 return constant; |
| 1179 } |
| 1180 |
| 1182 ir.Primitive visitLiteralList(ast.LiteralList node) { | 1181 ir.Primitive visitLiteralList(ast.LiteralList node) { |
| 1183 assert(isOpen); | 1182 assert(isOpen); |
| 1184 if (node.isConst) { | 1183 if (node.isConst) { |
| 1185 return translateConstant(node); | 1184 return translateConstant(node); |
| 1186 } | 1185 } |
| 1187 List<ir.Primitive> values = node.elements.nodes.mapToList(visit); | 1186 List<ir.Primitive> values = node.elements.nodes.mapToList(visit); |
| 1188 GenericType type = elements.getType(node); | 1187 GenericType type = elements.getType(node); |
| 1189 ir.Primitive result = new ir.LiteralList(type, values); | 1188 ir.Primitive result = new ir.LiteralList(type, values); |
| 1190 add(new ir.LetPrim(result)); | 1189 add(new ir.LetPrim(result)); |
| 1191 return result; | 1190 return result; |
| (...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1726 var it = node.parts.iterator; | 1725 var it = node.parts.iterator; |
| 1727 while (it.moveNext()) { | 1726 while (it.moveNext()) { |
| 1728 ast.StringInterpolationPart part = it.current; | 1727 ast.StringInterpolationPart part = it.current; |
| 1729 arguments.add(visit(part.expression)); | 1728 arguments.add(visit(part.expression)); |
| 1730 arguments.add(visitLiteralString(part.string)); | 1729 arguments.add(visitLiteralString(part.string)); |
| 1731 } | 1730 } |
| 1732 return continueWithExpression( | 1731 return continueWithExpression( |
| 1733 (k) => new ir.ConcatenateStrings(k, arguments)); | 1732 (k) => new ir.ConcatenateStrings(k, arguments)); |
| 1734 } | 1733 } |
| 1735 | 1734 |
| 1736 ir.Primitive translateConstant(ast.Node node, [Constant value]) { | 1735 ir.Primitive translateConstant(ast.Node node, [ConstExp constant]) { |
| 1737 assert(isOpen); | 1736 assert(isOpen); |
| 1738 if (value == null) { | 1737 if (constant == null) { |
| 1739 value = getConstantForNode(node); | 1738 constant = getConstantForNode(node); |
| 1740 } | 1739 } |
| 1741 ir.Primitive primitive = makeConst(constantBuilder.visit(node), value); | 1740 ir.Primitive primitive = makeConst(constant); |
| 1742 add(new ir.LetPrim(primitive)); | 1741 add(new ir.LetPrim(primitive)); |
| 1743 return primitive; | 1742 return primitive; |
| 1744 } | 1743 } |
| 1745 | 1744 |
| 1746 ir.FunctionDefinition makeSubFunction(ast.FunctionExpression node) { | 1745 ir.FunctionDefinition makeSubFunction(ast.FunctionExpression node) { |
| 1747 return new IrBuilderVisitor(elements, compiler, sourceFile) | 1746 return new IrBuilderVisitor(elements, compiler, sourceFile) |
| 1748 .buildFunctionInternal(elements[node]); | 1747 .buildFunctionInternal(elements[node]); |
| 1749 } | 1748 } |
| 1750 | 1749 |
| 1751 ir.Primitive visitFunctionExpression(ast.FunctionExpression node) { | 1750 ir.Primitive visitFunctionExpression(ast.FunctionExpression node) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1785 } | 1784 } |
| 1786 rethrow; | 1785 rethrow; |
| 1787 } | 1786 } |
| 1788 } | 1787 } |
| 1789 | 1788 |
| 1790 void internalError(String reason, {ast.Node node}) { | 1789 void internalError(String reason, {ast.Node node}) { |
| 1791 giveup(node); | 1790 giveup(node); |
| 1792 } | 1791 } |
| 1793 } | 1792 } |
| 1794 | 1793 |
| 1795 /// Translates constant expressions from the AST to the [ConstExp] language. | |
| 1796 class ConstExpBuilder extends ast.Visitor<ConstExp> { | |
| 1797 final IrBuilderVisitor parent; | |
| 1798 final TreeElements elements; | |
| 1799 final ConstantSystem constantSystem; | |
| 1800 final ConstantCompiler constantCompiler; | |
| 1801 | |
| 1802 ConstExpBuilder(IrBuilderVisitor parent) | |
| 1803 : this.parent = parent, | |
| 1804 this.elements = parent.elements, | |
| 1805 this.constantSystem = parent.constantSystem, | |
| 1806 this.constantCompiler = parent.compiler.backend.constantCompilerTask; | |
| 1807 | |
| 1808 Constant computeConstant(ast.Node node) { | |
| 1809 return constantCompiler.compileNode(node, elements); | |
| 1810 } | |
| 1811 | |
| 1812 /// True if the given constant is small enough that inlining it is likely | |
| 1813 /// to be profitable. Always false for non-primitive constants. | |
| 1814 bool isSmallConstant(Constant constant) { | |
| 1815 if (constant is BoolConstant || constant is NullConstant) { | |
| 1816 return true; | |
| 1817 } | |
| 1818 if (constant is IntConstant) { | |
| 1819 return -10 < constant.value && constant.value < 100; | |
| 1820 } | |
| 1821 if (constant is DoubleConstant) { | |
| 1822 return constant.isZero || constant.isOne; | |
| 1823 } | |
| 1824 if (constant is StringConstant) { | |
| 1825 ast.DartString string = constant.value; | |
| 1826 if (string is ast.LiteralDartString) { | |
| 1827 return string.length < 4; | |
| 1828 } | |
| 1829 if (string is ast.SourceBasedDartString) { | |
| 1830 return string.length < 4; | |
| 1831 } | |
| 1832 } | |
| 1833 return false; | |
| 1834 } | |
| 1835 | |
| 1836 ConstExp visit(ast.Node node) => node.accept(this); | |
| 1837 | |
| 1838 ConstExp visitStringJuxtaposition(ast.StringJuxtaposition node) { | |
| 1839 ConstExp first = visit(node.first); | |
| 1840 ConstExp second = visit(node.second); | |
| 1841 return new ConcatenateConstExp([first, second]); | |
| 1842 } | |
| 1843 | |
| 1844 ConstExp visitStringInterpolation(ast.StringInterpolation node) { | |
| 1845 List<ConstExp> arguments = <ConstExp>[]; | |
| 1846 arguments.add(visitLiteralString(node.string)); | |
| 1847 var it = node.parts.iterator; | |
| 1848 while (it.moveNext()) { | |
| 1849 ast.StringInterpolationPart part = it.current; | |
| 1850 arguments.add(visit(part.expression)); | |
| 1851 arguments.add(visitLiteralString(part.string)); | |
| 1852 } | |
| 1853 return new ConcatenateConstExp(arguments); | |
| 1854 } | |
| 1855 | |
| 1856 ConstExp visitNewExpression(ast.NewExpression node) { | |
| 1857 FunctionElement element = elements[node.send]; | |
| 1858 if (Elements.isUnresolved(element)) { | |
| 1859 throw parent.giveup(node, 'const NewExpression: unresolved constructor'); | |
| 1860 } | |
| 1861 Selector selector = elements.getSelector(node.send); | |
| 1862 ast.Node selectorNode = node.send.selector; | |
| 1863 GenericType type = elements.getType(node); | |
| 1864 List<ConstExp> args = node.send.arguments.mapToList(visit, growable:false); | |
| 1865 return new ConstructorConstExp(type, element, selector, args); | |
| 1866 } | |
| 1867 | |
| 1868 ConstExp visitNamedArgument(ast.NamedArgument node) { | |
| 1869 return visit(node.expression); | |
| 1870 } | |
| 1871 | |
| 1872 ConstExp visitSend(ast.Send node) { | |
| 1873 Element element = elements[node]; | |
| 1874 if (node.isOperator) { | |
| 1875 return new PrimitiveConstExp(computeConstant(node)); | |
| 1876 } | |
| 1877 if (Elements.isStaticOrTopLevelFunction(element)) { | |
| 1878 return new FunctionConstExp(element); | |
| 1879 } | |
| 1880 if (Elements.isLocal(element) || | |
| 1881 Elements.isStaticOrTopLevelField(element)) { | |
| 1882 // If the constant is small, inline it instead of using the declared const | |
| 1883 Constant value = constantCompiler.getConstantForVariable(element); | |
| 1884 if (isSmallConstant(value)) | |
| 1885 return new PrimitiveConstExp(value); | |
| 1886 else | |
| 1887 return new VariableConstExp(element); | |
| 1888 } | |
| 1889 DartType type = elements.getTypeLiteralType(node); | |
| 1890 if (type != null) { | |
| 1891 return new TypeConstExp(type); | |
| 1892 } | |
| 1893 throw "Unexpected constant Send: $node"; | |
| 1894 } | |
| 1895 | |
| 1896 ConstExp visitParenthesizedExpression(ast.ParenthesizedExpression node) { | |
| 1897 return visit(node.expression); | |
| 1898 } | |
| 1899 | |
| 1900 ConstExp visitLiteralList(ast.LiteralList node) { | |
| 1901 List<ConstExp> values = node.elements.nodes.mapToList(visit); | |
| 1902 GenericType type = elements.getType(node); | |
| 1903 return new ListConstExp(type, values); | |
| 1904 } | |
| 1905 | |
| 1906 ConstExp visitLiteralMap(ast.LiteralMap node) { | |
| 1907 List<ConstExp> keys = new List<ConstExp>(); | |
| 1908 List<ConstExp> values = new List<ConstExp>(); | |
| 1909 node.entries.nodes.forEach((ast.LiteralMapEntry node) { | |
| 1910 keys.add(visit(node.key)); | |
| 1911 values.add(visit(node.value)); | |
| 1912 }); | |
| 1913 GenericType type = elements.getType(node); | |
| 1914 return new MapConstExp(type, keys, values); | |
| 1915 } | |
| 1916 | |
| 1917 ConstExp visitLiteralSymbol(ast.LiteralSymbol node) { | |
| 1918 return new SymbolConstExp(node.slowNameString); | |
| 1919 } | |
| 1920 | |
| 1921 ConstExp visitLiteralInt(ast.LiteralInt node) { | |
| 1922 return new PrimitiveConstExp(constantSystem.createInt(node.value)); | |
| 1923 } | |
| 1924 | |
| 1925 ConstExp visitLiteralDouble(ast.LiteralDouble node) { | |
| 1926 return new PrimitiveConstExp(constantSystem.createDouble(node.value)); | |
| 1927 } | |
| 1928 | |
| 1929 ConstExp visitLiteralString(ast.LiteralString node) { | |
| 1930 return new PrimitiveConstExp(constantSystem.createString(node.dartString)); | |
| 1931 } | |
| 1932 | |
| 1933 ConstExp visitLiteralBool(ast.LiteralBool node) { | |
| 1934 return new PrimitiveConstExp(constantSystem.createBool(node.value)); | |
| 1935 } | |
| 1936 | |
| 1937 ConstExp visitLiteralNull(ast.LiteralNull node) { | |
| 1938 return new PrimitiveConstExp(constantSystem.createNull()); | |
| 1939 } | |
| 1940 | |
| 1941 ConstExp visitConditional(ast.Conditional node) { | |
| 1942 BoolConstant condition = computeConstant(node.condition); | |
| 1943 return visit(condition.isTrue ? node.thenExpression : node.elseExpression); | |
| 1944 } | |
| 1945 | |
| 1946 ConstExp visitNode(ast.Node node) { | |
| 1947 throw "Unexpected constant: $node"; | |
| 1948 } | |
| 1949 | |
| 1950 } | |
| 1951 | |
| 1952 /// Classifies local variables and local functions as 'closure variables'. | 1794 /// Classifies local variables and local functions as 'closure variables'. |
| 1953 /// A closure variable is one that is accessed from an inner function nested | 1795 /// A closure variable is one that is accessed from an inner function nested |
| 1954 /// one or more levels inside the one that declares it. | 1796 /// one or more levels inside the one that declares it. |
| 1955 class DetectClosureVariables extends ast.Visitor { | 1797 class DetectClosureVariables extends ast.Visitor { |
| 1956 final TreeElements elements; | 1798 final TreeElements elements; |
| 1957 DetectClosureVariables(this.elements); | 1799 DetectClosureVariables(this.elements); |
| 1958 | 1800 |
| 1959 FunctionElement currentFunction; | 1801 FunctionElement currentFunction; |
| 1960 Set<Local> usedFromClosure = new Set<Local>(); | 1802 Set<Local> usedFromClosure = new Set<Local>(); |
| 1961 Set<FunctionElement> recursiveFunctions = new Set<FunctionElement>(); | 1803 Set<FunctionElement> recursiveFunctions = new Set<FunctionElement>(); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1984 } | 1826 } |
| 1985 | 1827 |
| 1986 visitFunctionExpression(ast.FunctionExpression node) { | 1828 visitFunctionExpression(ast.FunctionExpression node) { |
| 1987 FunctionElement oldFunction = currentFunction; | 1829 FunctionElement oldFunction = currentFunction; |
| 1988 currentFunction = elements[node]; | 1830 currentFunction = elements[node]; |
| 1989 visit(node.body); | 1831 visit(node.body); |
| 1990 currentFunction = oldFunction; | 1832 currentFunction = oldFunction; |
| 1991 } | 1833 } |
| 1992 | 1834 |
| 1993 } | 1835 } |
| OLD | NEW |