Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 class Constant implements Hashable { | 5 class Constant implements Hashable { |
| 6 const Constant(); | 6 const Constant(); |
| 7 | 7 |
| 8 bool isNull() => false; | 8 bool isNull() => false; |
| 9 bool isBool() => false; | 9 bool isBool() => false; |
| 10 bool isTrue() => false; | 10 bool isTrue() => false; |
| (...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 479 | 479 |
| 480 /** | 480 /** |
| 481 * Compiles the initial value of the given field and stores it in an internal | 481 * Compiles the initial value of the given field and stores it in an internal |
| 482 * map. | 482 * map. |
| 483 * | 483 * |
| 484 * [WorkItem] must contain a [VariableElement] refering to a global or | 484 * [WorkItem] must contain a [VariableElement] refering to a global or |
| 485 * static field. | 485 * static field. |
| 486 */ | 486 */ |
| 487 void compileWorkItem(WorkItem work) { | 487 void compileWorkItem(WorkItem work) { |
| 488 assert(work.element.kind == ElementKind.FIELD | 488 assert(work.element.kind == ElementKind.FIELD |
| 489 || work.element.kind == ElementKind.PARAMETER); | 489 || work.element.kind == ElementKind.PARAMETER |
| 490 || work.element.kind == ElementKind.FIELD_PARAMETER); | |
| 490 VariableElement element = work.element; | 491 VariableElement element = work.element; |
| 491 // Shortcut if it has already been compiled. | 492 // Shortcut if it has already been compiled. |
| 492 if (initialVariableValues.containsKey(element)) return; | 493 if (initialVariableValues.containsKey(element)) return; |
| 493 compileVariableWithDefinitions(element, work.resolutionTree); | 494 compileVariableWithDefinitions(element, work.resolutionTree); |
| 494 assert(pendingVariables.isEmpty()); | 495 assert(pendingVariables.isEmpty()); |
| 495 } | 496 } |
| 496 | 497 |
| 497 compileVariable(VariableElement element) { | 498 compileVariable(VariableElement element) { |
| 498 if (initialVariableValues.containsKey(element)) { | 499 if (initialVariableValues.containsKey(element)) { |
| 499 Constant result = initialVariableValues[element]; | 500 Constant result = initialVariableValues[element]; |
| (...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 913 link = link.tail) { | 914 link = link.tail) { |
| 914 arguments.add(evaluate(link.head)); | 915 arguments.add(evaluate(link.head)); |
| 915 } | 916 } |
| 916 } | 917 } |
| 917 return arguments; | 918 return arguments; |
| 918 } | 919 } |
| 919 | 920 |
| 920 void assignArgumentsToParameters( | 921 void assignArgumentsToParameters( |
| 921 List<Constant> arguments, | 922 List<Constant> arguments, |
| 922 FunctionParameters parameters, | 923 FunctionParameters parameters, |
| 923 Map<Element, Constant> constructorDefinitions) { | 924 Map<Element, Constant> constructorDefinitions, |
|
ngeoffray
2012/03/15 15:16:25
constructorDefinitions -> parameterValues ?
floitsch
2012/03/15 15:37:24
I want to rename some elements in this file anyway
| |
| 925 Map<Element, Constant> fieldValues) { | |
| 924 if (arguments.length != parameters.parameterCount) { | 926 if (arguments.length != parameters.parameterCount) { |
| 925 if (arguments.length < parameters.parameterCount && | 927 if (arguments.length < parameters.parameterCount && |
| 926 arguments.length >= parameters.requiredParameterCount) { | 928 arguments.length >= parameters.requiredParameterCount) { |
| 927 compiler.unimplemented("ConstantHandler with optional arguments", | 929 compiler.unimplemented("ConstantHandler with optional arguments", |
| 928 node: node); | 930 node: node); |
| 929 } else { | 931 } else { |
| 930 error(node); | 932 error(node); |
| 931 } | 933 } |
| 932 } | 934 } |
| 933 int index = 0; | 935 int index = 0; |
| 934 parameters.forEachParameter((Element parameter) { | 936 parameters.forEachParameter((Element parameter) { |
| 935 constructorDefinitions[parameter] = arguments[index++]; | 937 Constant argument = arguments[index++]; |
| 938 constructorDefinitions[parameter] = argument; | |
| 939 if (parameter.kind == ElementKind.FIELD_PARAMETER) { | |
| 940 FieldParameterElement fieldParameterElement = parameter; | |
| 941 fieldValues[fieldParameterElement.fieldElement] = argument; | |
| 942 } | |
| 936 }); | 943 }); |
| 937 } | 944 } |
| 938 | 945 |
| 939 void compileInitializers(Link<Node> initializers, | 946 void compileInitializers(Link<Node> initializers, |
| 940 CompileTimeConstantEvaluator evaluator, | 947 CompileTimeConstantEvaluator evaluator, |
| 941 TreeElements constructorElements, | 948 TreeElements constructorElements, |
| 942 Map<Element, Constant> constructorDefinitions) { | 949 Map<Element, Constant> constructorDefinitions, |
| 950 Map<Element, Constant> fieldValues) { | |
| 943 for (Link<Node> link = initializers; !link.isEmpty(); link = link.tail) { | 951 for (Link<Node> link = initializers; !link.isEmpty(); link = link.tail) { |
| 944 assert(link.head is Send); | 952 assert(link.head is Send); |
| 945 if (link.head is !SendSet) { | 953 if (link.head is !SendSet) { |
| 946 // A super initializer or constructor redirection. | 954 // A super initializer or constructor redirection. |
| 947 Send call = link.head; | 955 Send call = link.head; |
| 948 assert(Initializers.isSuperConstructorCall(call) || | 956 assert(Initializers.isSuperConstructorCall(call) || |
| 949 Initializers.isConstructorRedirect(call)); | 957 Initializers.isConstructorRedirect(call)); |
| 950 compiler.unimplemented("ConstantHandler with this or super", | 958 compiler.unimplemented("ConstantHandler with this or super", |
| 951 node: call); | 959 node: call); |
| 952 } else { | 960 } else { |
| 953 // A field initializer. | 961 // A field initializer. |
| 954 SendSet init = link.head; | 962 SendSet init = link.head; |
| 955 Link<Node> arguments = init.arguments; | 963 Link<Node> arguments = init.arguments; |
| 956 assert(!arguments.isEmpty() && arguments.tail.isEmpty()); | 964 assert(!arguments.isEmpty() && arguments.tail.isEmpty()); |
| 957 Constant fieldValue = evaluator.evaluate(arguments.head); | 965 Constant fieldValue = evaluator.evaluate(arguments.head); |
| 958 constructorDefinitions[constructorElements[init]] = fieldValue; | 966 fieldValues[constructorElements[init]] = fieldValue; |
| 959 } | 967 } |
| 960 } | 968 } |
| 961 } | 969 } |
| 962 | 970 |
| 963 List<Constant> buildJsConstructorArguments( | 971 List<Constant> buildJsNewArguments(ClassElement classElement, |
| 964 ClassElement classElement, | 972 Map<Element, Constant> fieldValues) { |
| 965 Map<Element, Constant> constructorDefinitions) { | 973 List<Constant> jsNewArguments = <Constant>[]; |
| 966 List<Constant> fieldValues = <Constant>[]; | |
| 967 for (Element member in classElement.members) { | 974 for (Element member in classElement.members) { |
| 968 if (member.isInstanceMember() && member.kind == ElementKind.FIELD) { | 975 if (member.isInstanceMember() && member.kind == ElementKind.FIELD) { |
| 969 Constant fieldValue = constructorDefinitions[member]; | 976 Constant fieldValue = fieldValues[member]; |
| 970 if (fieldValue === null) { | 977 if (fieldValue === null) { |
| 971 // Use the default value. | 978 // Use the default value. |
| 972 fieldValue = constantHandler.compileVariable(member); | 979 fieldValue = constantHandler.compileVariable(member); |
| 973 } | 980 } |
| 974 fieldValues.add(fieldValue); | 981 jsNewArguments.add(fieldValue); |
| 975 } | 982 } |
| 976 } | 983 } |
| 977 if (classElement.superclass != compiler.coreLibrary.find(Types.OBJECT)) { | 984 if (classElement.superclass != compiler.coreLibrary.find(Types.OBJECT)) { |
| 978 compiler.unimplemented("ConstantHandler with super", node: node); | 985 compiler.unimplemented("ConstantHandler with super", node: node); |
| 979 } | 986 } |
| 980 return fieldValues; | 987 return jsNewArguments; |
| 981 } | 988 } |
| 982 | 989 |
| 983 // TODO(floitsch): get the type from somewhere. | 990 // TODO(floitsch): get the type from somewhere. |
| 984 FunctionElement constructor = elements[node.send]; | 991 FunctionElement constructor = elements[node.send]; |
| 985 ClassElement classElement = constructor.enclosingElement; | 992 ClassElement classElement = constructor.enclosingElement; |
| 986 TreeElements constructorElements = | 993 TreeElements constructorElements = |
| 987 compiler.resolver.resolveMethodElement(constructor); | 994 compiler.resolver.resolveMethodElement(constructor); |
| 988 FunctionExpression functionNode = constructor.parseNode(compiler); | 995 FunctionExpression functionNode = constructor.parseNode(compiler); |
| 989 NodeList initializerList = functionNode.initializers; | 996 NodeList initializerList = functionNode.initializers; |
| 990 FunctionParameters parameters = constructor.computeParameters(compiler); | 997 FunctionParameters parameters = constructor.computeParameters(compiler); |
| 991 | 998 |
| 999 Map<Element, Constant> fieldValues = new Map<Element, Constant>(); | |
| 992 Map<Element, Constant> constructorDefinitions = | 1000 Map<Element, Constant> constructorDefinitions = |
| 993 new Map<Element, Constant>(); | 1001 new Map<Element, Constant>(); |
| 994 | 1002 |
| 995 List<Constant> arguments = compileArguments(); | 1003 List<Constant> arguments = compileArguments(); |
| 996 assignArgumentsToParameters(arguments, parameters, constructorDefinitions); | 1004 assignArgumentsToParameters(arguments, parameters, |
| 1005 constructorDefinitions, fieldValues); | |
|
ngeoffray
2012/03/15 15:16:25
This is all happening in the same function, so you
floitsch
2012/03/15 15:37:24
I think I will need separate arguments when implem
| |
| 997 CompileTimeConstantEvaluator initializerEvaluator = | 1006 CompileTimeConstantEvaluator initializerEvaluator = |
| 998 new CompileTimeConstantEvaluator.insideConstructor( | 1007 new CompileTimeConstantEvaluator.insideConstructor( |
| 999 constantHandler, constructorElements, compiler, | 1008 constantHandler, constructorElements, compiler, |
| 1000 constructorDefinitions); | 1009 constructorDefinitions); |
| 1001 if (initializerList !== null) { | 1010 if (initializerList !== null) { |
| 1002 Link<Node> initializers = functionNode.initializers.nodes; | 1011 Link<Node> initializers = functionNode.initializers.nodes; |
| 1003 compileInitializers(initializers, | 1012 compileInitializers(initializers, |
| 1004 initializerEvaluator, | 1013 initializerEvaluator, |
| 1005 constructorElements, | 1014 constructorElements, |
| 1006 constructorDefinitions); | 1015 constructorDefinitions, |
| 1016 fieldValues); | |
| 1007 } | 1017 } |
| 1008 List<Constant> fieldValues = | 1018 List<Constant> jsNewArguments = |
| 1009 buildJsConstructorArguments(classElement, constructorDefinitions); | 1019 buildJsNewArguments(classElement, fieldValues); |
| 1010 | 1020 |
| 1011 compiler.registerInstantiatedClass(classElement); | 1021 compiler.registerInstantiatedClass(classElement); |
| 1012 Type type = new SimpleType(classElement.name, classElement); | 1022 Type type = new SimpleType(classElement.name, classElement); |
| 1013 Constant constant = new ConstructedConstant(type, fieldValues); | 1023 Constant constant = new ConstructedConstant(type, jsNewArguments); |
| 1014 constantHandler.registerCompileTimeConstant(constant); | 1024 constantHandler.registerCompileTimeConstant(constant); |
| 1015 return constant; | 1025 return constant; |
| 1016 } | 1026 } |
| 1017 | 1027 |
| 1018 error(Node node) { | 1028 error(Node node) { |
| 1019 // TODO(floitsch): get the list of constants that are currently compiled | 1029 // TODO(floitsch): get the list of constants that are currently compiled |
| 1020 // and present some kind of stack-trace. | 1030 // and present some kind of stack-trace. |
| 1021 MessageKind kind = MessageKind.NOT_A_COMPILE_TIME_CONSTANT; | 1031 MessageKind kind = MessageKind.NOT_A_COMPILE_TIME_CONSTANT; |
| 1022 compiler.reportError(node, new CompileTimeConstantError(kind, const [])); | 1032 compiler.reportError(node, new CompileTimeConstantError(kind, const [])); |
| 1023 } | 1033 } |
| 1024 } | 1034 } |
| OLD | NEW |