| 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 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 315 } | 315 } |
| 316 | 316 |
| 317 ir.Primitive continueWithExpression(ir.Expression build(ir.Continuation k)) { | 317 ir.Primitive continueWithExpression(ir.Expression build(ir.Continuation k)) { |
| 318 ir.Parameter v = new ir.Parameter(null); | 318 ir.Parameter v = new ir.Parameter(null); |
| 319 ir.Continuation k = new ir.Continuation([v]); | 319 ir.Continuation k = new ir.Continuation([v]); |
| 320 ir.Expression expression = build(k); | 320 ir.Expression expression = build(k); |
| 321 add(new ir.LetCont(k, expression)); | 321 add(new ir.LetCont(k, expression)); |
| 322 return v; | 322 return v; |
| 323 } | 323 } |
| 324 | 324 |
| 325 ir.Constant makeConst(ConstExp exp, Constant value) { | 325 ir.Constant makeConst(ConstExp exp) { |
| 326 return new ir.Constant(exp, value); | 326 return new ir.Constant(exp); |
| 327 } | 327 } |
| 328 | 328 |
| 329 ir.Constant makePrimConst(PrimitiveConstant value) { | 329 ir.Constant makePrimConst(PrimitiveConstant value) { |
| 330 return makeConst(new PrimitiveConstExp(value), value); | 330 return makeConst(new PrimitiveConstExp(value)); |
| 331 } | 331 } |
| 332 | 332 |
| 333 // TODO(johnniwinther): Build constants directly through [ConstExp] when these | 333 // TODO(johnniwinther): Build constants directly through [ConstExp] when these |
| 334 // are created from analyzer2dart. | 334 // are created from analyzer2dart. |
| 335 ir.Node buildPrimConst(PrimitiveConstant constant) { | 335 ir.Node buildPrimConst(PrimitiveConstant constant) { |
| 336 assert(isOpen); | 336 assert(isOpen); |
| 337 ir.Node prim = makePrimConst(constant); | 337 ir.Node prim = makePrimConst(constant); |
| 338 add(new ir.LetPrim(prim)); | 338 add(new ir.LetPrim(prim)); |
| 339 return prim; | 339 return prim; |
| 340 } | 340 } |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 458 // assigned in the delimited subexpression to their reaching definition --- | 458 // assigned in the delimited subexpression to their reaching definition --- |
| 459 // that is, the definition in effect at the hole in 'current'. These are | 459 // that is, the definition in effect at the hole in 'current'. These are |
| 460 // used to determine if a join-point continuation needs to be passed | 460 // used to determine if a join-point continuation needs to be passed |
| 461 // arguments, and what the arguments are. | 461 // arguments, and what the arguments are. |
| 462 | 462 |
| 463 /// A stack of collectors for breaks. | 463 /// A stack of collectors for breaks. |
| 464 final List<JumpCollector> breakCollectors; | 464 final List<JumpCollector> breakCollectors; |
| 465 /// A stack of collectors for continues. | 465 /// A stack of collectors for continues. |
| 466 final List<JumpCollector> continueCollectors; | 466 final List<JumpCollector> continueCollectors; |
| 467 | 467 |
| 468 ConstExpBuilder constantBuilder; | |
| 469 | |
| 470 final List<ConstDeclaration> localConstants; | 468 final List<ConstDeclaration> localConstants; |
| 471 | 469 |
| 472 FunctionElement currentFunction; | 470 FunctionElement currentFunction; |
| 473 final DetectClosureVariables closureLocals; | 471 final DetectClosureVariables closureLocals; |
| 474 | 472 |
| 475 /// Construct a top-level visitor. | 473 /// Construct a top-level visitor. |
| 476 IrBuilderVisitor(TreeElements elements, this.compiler, this.sourceFile) | 474 IrBuilderVisitor(TreeElements elements, this.compiler, this.sourceFile) |
| 477 : breakCollectors = <JumpCollector>[], | 475 : breakCollectors = <JumpCollector>[], |
| 478 continueCollectors = <JumpCollector>[], | 476 continueCollectors = <JumpCollector>[], |
| 479 localConstants = <ConstDeclaration>[], | 477 localConstants = <ConstDeclaration>[], |
| 480 closureLocals = new DetectClosureVariables(elements), | 478 closureLocals = new DetectClosureVariables(elements), |
| 481 super(elements) { | 479 super(elements) { |
| 482 constantSystem = compiler.backend.constantSystem; | 480 constantSystem = compiler.backend.constantSystem; |
| 483 constantBuilder = new ConstExpBuilder(this); | |
| 484 } | 481 } |
| 485 | 482 |
| 486 /// Construct a delimited visitor for visiting a subtree. | 483 /// Construct a delimited visitor for visiting a subtree. |
| 487 /// | 484 /// |
| 488 /// The delimited visitor has its own compile-time environment mapping | 485 /// The delimited visitor has its own compile-time environment mapping |
| 489 /// local variables to their values, which is initially a copy of the parent | 486 /// local variables to their values, which is initially a copy of the parent |
| 490 /// environment. It has its own context for building an IR expression, so | 487 /// environment. It has its own context for building an IR expression, so |
| 491 /// the built expression is not plugged into the parent's context. | 488 /// the built expression is not plugged into the parent's context. |
| 492 IrBuilderVisitor.delimited(IrBuilderVisitor parent) | 489 IrBuilderVisitor.delimited(IrBuilderVisitor parent) |
| 493 : compiler = parent.compiler, | 490 : compiler = parent.compiler, |
| 494 sourceFile = parent.sourceFile, | 491 sourceFile = parent.sourceFile, |
| 495 breakCollectors = parent.breakCollectors, | 492 breakCollectors = parent.breakCollectors, |
| 496 continueCollectors = parent.continueCollectors, | 493 continueCollectors = parent.continueCollectors, |
| 497 constantBuilder = parent.constantBuilder, | |
| 498 localConstants = parent.localConstants, | 494 localConstants = parent.localConstants, |
| 499 currentFunction = parent.currentFunction, | 495 currentFunction = parent.currentFunction, |
| 500 closureLocals = parent.closureLocals, | 496 closureLocals = parent.closureLocals, |
| 501 super(parent.elements) { | 497 super(parent.elements) { |
| 502 constantSystem = parent.constantSystem; | 498 constantSystem = parent.constantSystem; |
| 503 returnContinuation = parent.returnContinuation; | 499 returnContinuation = parent.returnContinuation; |
| 504 environment = new Environment.from(parent.environment); | 500 environment = new Environment.from(parent.environment); |
| 505 } | 501 } |
| 506 | 502 |
| 507 /// Construct a visitor for a recursive continuation. | 503 /// Construct a visitor for a recursive continuation. |
| 508 /// | 504 /// |
| 509 /// The recursive continuation builder has fresh parameters (i.e. SSA phis) | 505 /// The recursive continuation builder has fresh parameters (i.e. SSA phis) |
| 510 /// for all the local variables in the parent, because the invocation sites | 506 /// for all the local variables in the parent, because the invocation sites |
| 511 /// of the continuation are not all known when the builder is created. The | 507 /// of the continuation are not all known when the builder is created. The |
| 512 /// recursive invocations will be passed values for all the local variables, | 508 /// recursive invocations will be passed values for all the local variables, |
| 513 /// which may be eliminated later if they are redundant---if they take on | 509 /// which may be eliminated later if they are redundant---if they take on |
| 514 /// the same value at all invocation sites. | 510 /// the same value at all invocation sites. |
| 515 IrBuilderVisitor.recursive(IrBuilderVisitor parent) | 511 IrBuilderVisitor.recursive(IrBuilderVisitor parent) |
| 516 : compiler = parent.compiler, | 512 : compiler = parent.compiler, |
| 517 sourceFile = parent.sourceFile, | 513 sourceFile = parent.sourceFile, |
| 518 breakCollectors = parent.breakCollectors, | 514 breakCollectors = parent.breakCollectors, |
| 519 continueCollectors = parent.continueCollectors, | 515 continueCollectors = parent.continueCollectors, |
| 520 constantBuilder = parent.constantBuilder, | |
| 521 localConstants = parent.localConstants, | 516 localConstants = parent.localConstants, |
| 522 currentFunction = parent.currentFunction, | 517 currentFunction = parent.currentFunction, |
| 523 closureLocals = parent.closureLocals, | 518 closureLocals = parent.closureLocals, |
| 524 super(parent.elements) { | 519 super(parent.elements) { |
| 525 constantSystem = parent.constantSystem; | 520 constantSystem = parent.constantSystem; |
| 526 returnContinuation = parent.returnContinuation; | 521 returnContinuation = parent.returnContinuation; |
| 527 parent.environment.index2variable.forEach(createParameter); | 522 parent.environment.index2variable.forEach(createParameter); |
| 528 } | 523 } |
| 529 | 524 |
| 530 /** | 525 /** |
| (...skipping 18 matching lines...) Expand all Loading... |
| 549 _root = _current = null; | 544 _root = _current = null; |
| 550 | 545 |
| 551 FunctionSignature signature = element.functionSignature; | 546 FunctionSignature signature = element.functionSignature; |
| 552 signature.orderedForEachParameter((ParameterElement parameterElement) { | 547 signature.orderedForEachParameter((ParameterElement parameterElement) { |
| 553 createParameter(parameterElement, | 548 createParameter(parameterElement, |
| 554 isClosureVariable: isClosureVariable(parameterElement)); | 549 isClosureVariable: isClosureVariable(parameterElement)); |
| 555 }); | 550 }); |
| 556 | 551 |
| 557 List<ConstExp> defaults = new List<ConstExp>(); | 552 List<ConstExp> defaults = new List<ConstExp>(); |
| 558 signature.orderedOptionalParameters.forEach((ParameterElement element) { | 553 signature.orderedOptionalParameters.forEach((ParameterElement element) { |
| 559 if (element.initializer != null) { | 554 defaults.add(getConstantForVariable(element)); |
| 560 defaults.add(constantBuilder.visit(element.initializer)); | |
| 561 } else { | |
| 562 defaults.add(new PrimitiveConstExp(constantSystem.createNull())); | |
| 563 } | |
| 564 }); | 555 }); |
| 565 | 556 |
| 566 visit(function.body); | 557 visit(function.body); |
| 567 return buildFunctionDefinition(element, localConstants, defaults); | 558 return buildFunctionDefinition(element, localConstants, defaults); |
| 568 } | 559 } |
| 569 | 560 |
| 570 ir.Primitive visit(ast.Node node) => node.accept(this); | 561 ir.Primitive visit(ast.Node node) => node.accept(this); |
| 571 | 562 |
| 572 // ==== Statements ==== | 563 // ==== Statements ==== |
| 573 // Build(Block(stamements), C) = C' | 564 // Build(Block(stamements), C) = C' |
| (...skipping 580 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1154 return null; | 1145 return null; |
| 1155 } | 1146 } |
| 1156 | 1147 |
| 1157 ir.Primitive visitVariableDefinitions(ast.VariableDefinitions node) { | 1148 ir.Primitive visitVariableDefinitions(ast.VariableDefinitions node) { |
| 1158 assert(isOpen); | 1149 assert(isOpen); |
| 1159 if (node.modifiers.isConst) { | 1150 if (node.modifiers.isConst) { |
| 1160 for (ast.SendSet definition in node.definitions.nodes) { | 1151 for (ast.SendSet definition in node.definitions.nodes) { |
| 1161 assert(!definition.arguments.isEmpty); | 1152 assert(!definition.arguments.isEmpty); |
| 1162 assert(definition.arguments.tail.isEmpty); | 1153 assert(definition.arguments.tail.isEmpty); |
| 1163 VariableElement element = elements[definition]; | 1154 VariableElement element = elements[definition]; |
| 1164 ConstExp value = constantBuilder.visit(definition.arguments.head); | 1155 ConstExp value = getConstantForVariable(element); |
| 1165 localConstants.add(new ConstDeclaration(element, value)); | 1156 localConstants.add(new ConstDeclaration(element, value)); |
| 1166 } | 1157 } |
| 1167 } else { | 1158 } else { |
| 1168 for (ast.Node definition in node.definitions.nodes) { | 1159 for (ast.Node definition in node.definitions.nodes) { |
| 1169 Element element = elements[definition]; | 1160 Element element = elements[definition]; |
| 1170 ir.Primitive initialValue; | 1161 ir.Primitive initialValue; |
| 1171 // Definitions are either SendSets if there is an initializer, or | 1162 // Definitions are either SendSets if there is an initializer, or |
| 1172 // Identifiers if there is no initializer. | 1163 // Identifiers if there is no initializer. |
| 1173 if (definition is ast.SendSet) { | 1164 if (definition is ast.SendSet) { |
| 1174 assert(!definition.arguments.isEmpty); | 1165 assert(!definition.arguments.isEmpty); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1275 ir.Primitive visitLiteralNull(ast.LiteralNull node) { | 1266 ir.Primitive visitLiteralNull(ast.LiteralNull node) { |
| 1276 assert(isOpen); | 1267 assert(isOpen); |
| 1277 return translateConstant(node); | 1268 return translateConstant(node); |
| 1278 } | 1269 } |
| 1279 | 1270 |
| 1280 ir.Primitive visitLiteralString(ast.LiteralString node) { | 1271 ir.Primitive visitLiteralString(ast.LiteralString node) { |
| 1281 assert(isOpen); | 1272 assert(isOpen); |
| 1282 return translateConstant(node); | 1273 return translateConstant(node); |
| 1283 } | 1274 } |
| 1284 | 1275 |
| 1285 Constant getConstantForNode(ast.Node node) { | 1276 ConstExp getConstantForNode(ast.Node node) { |
| 1286 Constant constant = | 1277 ConstExp constant = |
| 1287 compiler.backend.constantCompilerTask.compileNode(node, elements); | 1278 compiler.backend.constantCompilerTask.compileNode(node, elements); |
| 1288 assert(invariant(node, constant != null, | 1279 assert(invariant(node, constant != null, |
| 1289 message: 'No constant computed for $node')); | 1280 message: 'No constant computed for $node')); |
| 1290 return constant; | 1281 return constant; |
| 1291 } | 1282 } |
| 1292 | 1283 |
| 1284 ConstExp getConstantForVariable(VariableElement element) { |
| 1285 ConstExp constant = |
| 1286 compiler.backend.constants.getConstantForVariable(element); |
| 1287 assert(invariant(element, constant != null, |
| 1288 message: 'No constant computed for $element')); |
| 1289 return constant; |
| 1290 } |
| 1291 |
| 1293 ir.Primitive visitLiteralList(ast.LiteralList node) { | 1292 ir.Primitive visitLiteralList(ast.LiteralList node) { |
| 1294 assert(isOpen); | 1293 assert(isOpen); |
| 1295 if (node.isConst) { | 1294 if (node.isConst) { |
| 1296 return translateConstant(node); | 1295 return translateConstant(node); |
| 1297 } | 1296 } |
| 1298 List<ir.Primitive> values = node.elements.nodes.mapToList(visit); | 1297 List<ir.Primitive> values = node.elements.nodes.mapToList(visit); |
| 1299 GenericType type = elements.getType(node); | 1298 GenericType type = elements.getType(node); |
| 1300 ir.Primitive result = new ir.LiteralList(type, values); | 1299 ir.Primitive result = new ir.LiteralList(type, values); |
| 1301 add(new ir.LetPrim(result)); | 1300 add(new ir.LetPrim(result)); |
| 1302 return result; | 1301 return result; |
| (...skipping 562 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1865 var it = node.parts.iterator; | 1864 var it = node.parts.iterator; |
| 1866 while (it.moveNext()) { | 1865 while (it.moveNext()) { |
| 1867 ast.StringInterpolationPart part = it.current; | 1866 ast.StringInterpolationPart part = it.current; |
| 1868 arguments.add(visit(part.expression)); | 1867 arguments.add(visit(part.expression)); |
| 1869 arguments.add(visitLiteralString(part.string)); | 1868 arguments.add(visitLiteralString(part.string)); |
| 1870 } | 1869 } |
| 1871 return continueWithExpression( | 1870 return continueWithExpression( |
| 1872 (k) => new ir.ConcatenateStrings(k, arguments)); | 1871 (k) => new ir.ConcatenateStrings(k, arguments)); |
| 1873 } | 1872 } |
| 1874 | 1873 |
| 1875 ir.Primitive translateConstant(ast.Node node, [Constant value]) { | 1874 ir.Primitive translateConstant(ast.Node node, [ConstExp constant]) { |
| 1876 assert(isOpen); | 1875 assert(isOpen); |
| 1877 if (value == null) { | 1876 if (constant == null) { |
| 1878 value = getConstantForNode(node); | 1877 constant = getConstantForNode(node); |
| 1879 } | 1878 } |
| 1880 ir.Primitive primitive = makeConst(constantBuilder.visit(node), value); | 1879 ir.Primitive primitive = makeConst(constant); |
| 1881 add(new ir.LetPrim(primitive)); | 1880 add(new ir.LetPrim(primitive)); |
| 1882 return primitive; | 1881 return primitive; |
| 1883 } | 1882 } |
| 1884 | 1883 |
| 1885 ir.FunctionDefinition makeSubFunction(ast.FunctionExpression node) { | 1884 ir.FunctionDefinition makeSubFunction(ast.FunctionExpression node) { |
| 1886 return new IrBuilderVisitor(elements, compiler, sourceFile) | 1885 return new IrBuilderVisitor(elements, compiler, sourceFile) |
| 1887 .buildFunctionInternal(elements[node]); | 1886 .buildFunctionInternal(elements[node]); |
| 1888 } | 1887 } |
| 1889 | 1888 |
| 1890 ir.Primitive visitFunctionExpression(ast.FunctionExpression node) { | 1889 ir.Primitive visitFunctionExpression(ast.FunctionExpression node) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1924 } | 1923 } |
| 1925 rethrow; | 1924 rethrow; |
| 1926 } | 1925 } |
| 1927 } | 1926 } |
| 1928 | 1927 |
| 1929 void internalError(String reason, {ast.Node node}) { | 1928 void internalError(String reason, {ast.Node node}) { |
| 1930 giveup(node); | 1929 giveup(node); |
| 1931 } | 1930 } |
| 1932 } | 1931 } |
| 1933 | 1932 |
| 1934 /// Translates constant expressions from the AST to the [ConstExp] language. | |
| 1935 class ConstExpBuilder extends ast.Visitor<ConstExp> { | |
| 1936 final IrBuilderVisitor parent; | |
| 1937 final TreeElements elements; | |
| 1938 final ConstantSystem constantSystem; | |
| 1939 final ConstantCompiler constantCompiler; | |
| 1940 | |
| 1941 ConstExpBuilder(IrBuilderVisitor parent) | |
| 1942 : this.parent = parent, | |
| 1943 this.elements = parent.elements, | |
| 1944 this.constantSystem = parent.constantSystem, | |
| 1945 this.constantCompiler = parent.compiler.backend.constantCompilerTask; | |
| 1946 | |
| 1947 Constant computeConstant(ast.Node node) { | |
| 1948 return constantCompiler.compileNode(node, elements); | |
| 1949 } | |
| 1950 | |
| 1951 /// True if the given constant is small enough that inlining it is likely | |
| 1952 /// to be profitable. Always false for non-primitive constants. | |
| 1953 bool isSmallConstant(Constant constant) { | |
| 1954 if (constant is BoolConstant || constant is NullConstant) { | |
| 1955 return true; | |
| 1956 } | |
| 1957 if (constant is IntConstant) { | |
| 1958 return -10 < constant.value && constant.value < 100; | |
| 1959 } | |
| 1960 if (constant is DoubleConstant) { | |
| 1961 return constant.isZero || constant.isOne; | |
| 1962 } | |
| 1963 if (constant is StringConstant) { | |
| 1964 ast.DartString string = constant.value; | |
| 1965 if (string is ast.LiteralDartString) { | |
| 1966 return string.length < 4; | |
| 1967 } | |
| 1968 if (string is ast.SourceBasedDartString) { | |
| 1969 return string.length < 4; | |
| 1970 } | |
| 1971 } | |
| 1972 return false; | |
| 1973 } | |
| 1974 | |
| 1975 ConstExp visit(ast.Node node) => node.accept(this); | |
| 1976 | |
| 1977 ConstExp visitStringJuxtaposition(ast.StringJuxtaposition node) { | |
| 1978 ConstExp first = visit(node.first); | |
| 1979 ConstExp second = visit(node.second); | |
| 1980 return new ConcatenateConstExp([first, second]); | |
| 1981 } | |
| 1982 | |
| 1983 ConstExp visitStringInterpolation(ast.StringInterpolation node) { | |
| 1984 List<ConstExp> arguments = <ConstExp>[]; | |
| 1985 arguments.add(visitLiteralString(node.string)); | |
| 1986 var it = node.parts.iterator; | |
| 1987 while (it.moveNext()) { | |
| 1988 ast.StringInterpolationPart part = it.current; | |
| 1989 arguments.add(visit(part.expression)); | |
| 1990 arguments.add(visitLiteralString(part.string)); | |
| 1991 } | |
| 1992 return new ConcatenateConstExp(arguments); | |
| 1993 } | |
| 1994 | |
| 1995 ConstExp visitNewExpression(ast.NewExpression node) { | |
| 1996 FunctionElement element = elements[node.send]; | |
| 1997 // The resolver will already have thrown an error if the constructor was | |
| 1998 // unresolved. | |
| 1999 assert(invariant(node, !Elements.isUnresolved(element))); | |
| 2000 | |
| 2001 Selector selector = elements.getSelector(node.send); | |
| 2002 ast.Node selectorNode = node.send.selector; | |
| 2003 GenericType type = elements.getType(node); | |
| 2004 List<ConstExp> args = node.send.arguments.mapToList(visit, growable:false); | |
| 2005 return new ConstructorConstExp(type, element, selector, args); | |
| 2006 } | |
| 2007 | |
| 2008 ConstExp visitNamedArgument(ast.NamedArgument node) { | |
| 2009 return visit(node.expression); | |
| 2010 } | |
| 2011 | |
| 2012 ConstExp visitSend(ast.Send node) { | |
| 2013 Element element = elements[node]; | |
| 2014 if (node.isOperator) { | |
| 2015 return new PrimitiveConstExp(computeConstant(node)); | |
| 2016 } | |
| 2017 if (Elements.isStaticOrTopLevelFunction(element)) { | |
| 2018 return new FunctionConstExp(element); | |
| 2019 } | |
| 2020 if (Elements.isLocal(element) || | |
| 2021 Elements.isStaticOrTopLevelField(element)) { | |
| 2022 // If the constant is small, inline it instead of using the declared const | |
| 2023 Constant value = constantCompiler.getConstantForVariable(element); | |
| 2024 if (isSmallConstant(value)) | |
| 2025 return new PrimitiveConstExp(value); | |
| 2026 else | |
| 2027 return new VariableConstExp(element); | |
| 2028 } | |
| 2029 DartType type = elements.getTypeLiteralType(node); | |
| 2030 if (type != null) { | |
| 2031 return new TypeConstExp(type); | |
| 2032 } | |
| 2033 throw "Unexpected constant Send: $node"; | |
| 2034 } | |
| 2035 | |
| 2036 ConstExp visitParenthesizedExpression(ast.ParenthesizedExpression node) { | |
| 2037 return visit(node.expression); | |
| 2038 } | |
| 2039 | |
| 2040 ConstExp visitLiteralList(ast.LiteralList node) { | |
| 2041 List<ConstExp> values = node.elements.nodes.mapToList(visit); | |
| 2042 GenericType type = elements.getType(node); | |
| 2043 return new ListConstExp(type, values); | |
| 2044 } | |
| 2045 | |
| 2046 ConstExp visitLiteralMap(ast.LiteralMap node) { | |
| 2047 List<ConstExp> keys = new List<ConstExp>(); | |
| 2048 List<ConstExp> values = new List<ConstExp>(); | |
| 2049 node.entries.nodes.forEach((ast.LiteralMapEntry node) { | |
| 2050 keys.add(visit(node.key)); | |
| 2051 values.add(visit(node.value)); | |
| 2052 }); | |
| 2053 GenericType type = elements.getType(node); | |
| 2054 return new MapConstExp(type, keys, values); | |
| 2055 } | |
| 2056 | |
| 2057 ConstExp visitLiteralSymbol(ast.LiteralSymbol node) { | |
| 2058 return new SymbolConstExp(node.slowNameString); | |
| 2059 } | |
| 2060 | |
| 2061 ConstExp visitLiteralInt(ast.LiteralInt node) { | |
| 2062 return new PrimitiveConstExp(constantSystem.createInt(node.value)); | |
| 2063 } | |
| 2064 | |
| 2065 ConstExp visitLiteralDouble(ast.LiteralDouble node) { | |
| 2066 return new PrimitiveConstExp(constantSystem.createDouble(node.value)); | |
| 2067 } | |
| 2068 | |
| 2069 ConstExp visitLiteralString(ast.LiteralString node) { | |
| 2070 return new PrimitiveConstExp(constantSystem.createString(node.dartString)); | |
| 2071 } | |
| 2072 | |
| 2073 ConstExp visitLiteralBool(ast.LiteralBool node) { | |
| 2074 return new PrimitiveConstExp(constantSystem.createBool(node.value)); | |
| 2075 } | |
| 2076 | |
| 2077 ConstExp visitLiteralNull(ast.LiteralNull node) { | |
| 2078 return new PrimitiveConstExp(constantSystem.createNull()); | |
| 2079 } | |
| 2080 | |
| 2081 ConstExp visitConditional(ast.Conditional node) { | |
| 2082 BoolConstant condition = computeConstant(node.condition); | |
| 2083 return visit(condition.isTrue ? node.thenExpression : node.elseExpression); | |
| 2084 } | |
| 2085 | |
| 2086 ConstExp visitNode(ast.Node node) { | |
| 2087 throw "Unexpected constant: $node"; | |
| 2088 } | |
| 2089 | |
| 2090 } | |
| 2091 | |
| 2092 /// Classifies local variables and local functions as 'closure variables'. | 1933 /// Classifies local variables and local functions as 'closure variables'. |
| 2093 /// A closure variable is one that is accessed from an inner function nested | 1934 /// A closure variable is one that is accessed from an inner function nested |
| 2094 /// one or more levels inside the one that declares it. | 1935 /// one or more levels inside the one that declares it. |
| 2095 class DetectClosureVariables extends ast.Visitor { | 1936 class DetectClosureVariables extends ast.Visitor { |
| 2096 final TreeElements elements; | 1937 final TreeElements elements; |
| 2097 DetectClosureVariables(this.elements); | 1938 DetectClosureVariables(this.elements); |
| 2098 | 1939 |
| 2099 FunctionElement currentFunction; | 1940 FunctionElement currentFunction; |
| 2100 Set<Local> usedFromClosure = new Set<Local>(); | 1941 Set<Local> usedFromClosure = new Set<Local>(); |
| 2101 Set<FunctionElement> recursiveFunctions = new Set<FunctionElement>(); | 1942 Set<FunctionElement> recursiveFunctions = new Set<FunctionElement>(); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2124 } | 1965 } |
| 2125 | 1966 |
| 2126 visitFunctionExpression(ast.FunctionExpression node) { | 1967 visitFunctionExpression(ast.FunctionExpression node) { |
| 2127 FunctionElement oldFunction = currentFunction; | 1968 FunctionElement oldFunction = currentFunction; |
| 2128 currentFunction = elements[node]; | 1969 currentFunction = elements[node]; |
| 2129 visit(node.body); | 1970 visit(node.body); |
| 2130 currentFunction = oldFunction; | 1971 currentFunction = oldFunction; |
| 2131 } | 1972 } |
| 2132 | 1973 |
| 2133 } | 1974 } |
| OLD | NEW |