| 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 // TODO(floitsch): finish implementation. | 5 // TODO(floitsch): finish implementation. |
| 6 class Constant implements Hashable { | 6 class Constant implements Hashable { |
| 7 // TODO(floitsch): remove the direct access to the string. | 7 // TODO(floitsch): remove the direct access to the string. |
| 8 final String jsCode; | 8 final String jsCode; |
| 9 Constant(this.jsCode); | 9 Constant(this.jsCode); |
| 10 | 10 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 | 28 |
| 29 // Map from compile-time constants to their JS name. | 29 // Map from compile-time constants to their JS name. |
| 30 final Map<Constant, String> compiledConstants; | 30 final Map<Constant, String> compiledConstants; |
| 31 | 31 |
| 32 CompileTimeConstantHandler(Compiler compiler) | 32 CompileTimeConstantHandler(Compiler compiler) |
| 33 : initialVariableValues = new Map<VariableElement, Dynamic>(), | 33 : initialVariableValues = new Map<VariableElement, Dynamic>(), |
| 34 compiledConstants = new Map<Constant, String>(), | 34 compiledConstants = new Map<Constant, String>(), |
| 35 super(compiler); | 35 super(compiler); |
| 36 String get name() => 'CompileTimeConstantHandler'; | 36 String get name() => 'CompileTimeConstantHandler'; |
| 37 | 37 |
| 38 void registerCompileTimeConstant(Constant constant) { |
| 39 Function ifAbsentThunk = (() => compiler.namer.getFreshGlobalName("CTC")); |
| 40 compiledConstants.putIfAbsent(constant, ifAbsentThunk); |
| 41 } |
| 42 |
| 38 /** | 43 /** |
| 39 * Compiles the initial value of the given field and stores it in an internal | 44 * Compiles the initial value of the given field and stores it in an internal |
| 40 * map. | 45 * map. |
| 41 * | 46 * |
| 42 * [WorkItem] must contain a [VariableElement] refering to a global or | 47 * [WorkItem] must contain a [VariableElement] refering to a global or |
| 43 * static field. | 48 * static field. |
| 44 */ | 49 */ |
| 45 void compileWorkItem(WorkItem work) { | 50 void compileWorkItem(WorkItem work) { |
| 46 assert(work.element.kind == ElementKind.FIELD | 51 assert(work.element.kind == ElementKind.FIELD |
| 47 || work.element.kind == ElementKind.PARAMETER); | 52 || work.element.kind == ElementKind.PARAMETER); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 } | 100 } |
| 96 } | 101 } |
| 97 if (classElement.superclass != compiler.coreLibrary.find(Types.OBJECT)) { | 102 if (classElement.superclass != compiler.coreLibrary.find(Types.OBJECT)) { |
| 98 compiler.unimplemented("CompileTimeConstantHandler with super", | 103 compiler.unimplemented("CompileTimeConstantHandler with super", |
| 99 node: node); | 104 node: node); |
| 100 } | 105 } |
| 101 compiler.registerInstantiatedClass(classElement); | 106 compiler.registerInstantiatedClass(classElement); |
| 102 Namer namer = compiler.namer; | 107 Namer namer = compiler.namer; |
| 103 String instantiation = "new ${namer.isolatePropertyAccess(classElement)}()"; | 108 String instantiation = "new ${namer.isolatePropertyAccess(classElement)}()"; |
| 104 Constant constant = new Constant(instantiation); | 109 Constant constant = new Constant(instantiation); |
| 105 compiledConstants.putIfAbsent(constant, | 110 registerCompileTimeConstant(constant); |
| 106 () => namer.getFreshGlobalName("CTC")); | |
| 107 return constant; | 111 return constant; |
| 108 } | 112 } |
| 109 | 113 |
| 114 compileListLiteral(Node node, List arguments) { |
| 115 StringBuffer buffer = new StringBuffer(); |
| 116 for (int i = 0; i < arguments.length; i++) { |
| 117 if (i != 0) buffer.add(", "); |
| 118 if (arguments[i] is Constant) { |
| 119 // TODO(floitsch): canonicalize if the constant is in the |
| 120 // [compiledConstant] set. |
| 121 Constant constant = arguments[i]; |
| 122 buffer.add(constant.jsCode); |
| 123 } else { |
| 124 writeJsCode(buffer, arguments[i]); |
| 125 } |
| 126 } |
| 127 // TODO(floitsch): do we have to register 'List' as instantiated class? |
| 128 String array = "[$buffer]"; |
| 129 Constant constant = new Constant(array); |
| 130 registerCompileTimeConstant(constant); |
| 131 return constant; |
| 132 } |
| 133 |
| 110 /** | 134 /** |
| 111 * Returns a [List] of static non final fields that need to be initialized. | 135 * Returns a [List] of static non final fields that need to be initialized. |
| 112 * The list must be evaluated in order since the fields might depend on each | 136 * The list must be evaluated in order since the fields might depend on each |
| 113 * other. | 137 * other. |
| 114 */ | 138 */ |
| 115 List<VariableElement> getStaticNonFinalFieldsForEmission() { | 139 List<VariableElement> getStaticNonFinalFieldsForEmission() { |
| 116 return initialVariableValues.getKeys().filter((element) { | 140 return initialVariableValues.getKeys().filter((element) { |
| 117 return element.kind == ElementKind.FIELD | 141 return element.kind == ElementKind.FIELD |
| 118 && !element.isInstanceMember() | 142 && !element.isInstanceMember() |
| 119 && !element.modifiers.isFinal(); | 143 && !element.modifiers.isFinal(); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 134 } | 158 } |
| 135 | 159 |
| 136 List<Constant> getConstantsForEmission() { | 160 List<Constant> getConstantsForEmission() { |
| 137 return compiledConstants.getKeys(); | 161 return compiledConstants.getKeys(); |
| 138 } | 162 } |
| 139 | 163 |
| 140 String getNameForConstant(Constant constant) { | 164 String getNameForConstant(Constant constant) { |
| 141 return compiledConstants[constant]; | 165 return compiledConstants[constant]; |
| 142 } | 166 } |
| 143 | 167 |
| 144 StringBuffer writeJsCodeForVariable(StringBuffer buffer, | 168 StringBuffer writeJsCode(StringBuffer buffer, var value) { |
| 145 VariableElement element) { | |
| 146 var value = initialVariableValues[element]; | |
| 147 if (value === null) { | 169 if (value === null) { |
| 148 buffer.add("(void 0)"); | 170 buffer.add("(void 0)"); |
| 149 } else if (value is num) { | 171 } else if (value is num) { |
| 150 if (value.isNaN()) { | 172 if (value.isNaN()) { |
| 151 buffer.add("(0/0)"); | 173 buffer.add("(0/0)"); |
| 152 } else if (value == double.INFINITY) { | 174 } else if (value == double.INFINITY) { |
| 153 buffer.add("(1/0)"); | 175 buffer.add("(1/0)"); |
| 154 } else if (value == -double.INFINITY) { | 176 } else if (value == -double.INFINITY) { |
| 155 buffer.add("(-1/0)"); | 177 buffer.add("(-1/0)"); |
| 156 } else { | 178 } else { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 168 buffer.add("'"); | 190 buffer.add("'"); |
| 169 } else if (value is Constant) { | 191 } else if (value is Constant) { |
| 170 String name = compiledConstants[value]; | 192 String name = compiledConstants[value]; |
| 171 buffer.add("${compiler.namer.ISOLATE}.prototype.$name"); | 193 buffer.add("${compiler.namer.ISOLATE}.prototype.$name"); |
| 172 } else { | 194 } else { |
| 173 // TODO(floitsch): support more values. | 195 // TODO(floitsch): support more values. |
| 174 compiler.unimplemented("CompileTimeConstantHandler" + | 196 compiler.unimplemented("CompileTimeConstantHandler" + |
| 175 "writeJsCodeForVariable", | 197 "writeJsCodeForVariable", |
| 176 element: element); | 198 element: element); |
| 177 } | 199 } |
| 178 return buffer; | 200 return buffer; |
| 201 } |
| 202 |
| 203 StringBuffer writeJsCodeForVariable(StringBuffer buffer, |
| 204 VariableElement element) { |
| 205 return writeJsCode(buffer, initialVariableValues[element]); |
| 179 } | 206 } |
| 180 | 207 |
| 181 /** | 208 /** |
| 182 * Write the contents of the quoted string to a [StringBuffer] in | 209 * Write the contents of the quoted string to a [StringBuffer] in |
| 183 * a form that is valid as JavaScript string literal content. | 210 * a form that is valid as JavaScript string literal content. |
| 184 * The string is assumed quoted by single quote characters. | 211 * The string is assumed quoted by single quote characters. |
| 185 */ | 212 */ |
| 186 static void writeEscapedString(DartString string, | 213 static void writeEscapedString(DartString string, |
| 187 StringBuffer buffer, | 214 StringBuffer buffer, |
| 188 void cancel(String reason)) { | 215 void cancel(String reason)) { |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 353 for (Link<Node> link = send.arguments; | 380 for (Link<Node> link = send.arguments; |
| 354 !link.isEmpty(); | 381 !link.isEmpty(); |
| 355 link = link.tail) { | 382 link = link.tail) { |
| 356 arguments.add(evaluate(link.head)); | 383 arguments.add(evaluate(link.head)); |
| 357 } | 384 } |
| 358 } | 385 } |
| 359 return constantHandler.compileObjectCreation(node, definitions[node.send], | 386 return constantHandler.compileObjectCreation(node, definitions[node.send], |
| 360 arguments); | 387 arguments); |
| 361 } | 388 } |
| 362 | 389 |
| 390 visitLiteralList(LiteralList node) { |
| 391 if (!node.isConst()) error(node); |
| 392 List arguments = []; |
| 393 for (Link<Node> link = node.elements.nodes; |
| 394 !link.isEmpty(); |
| 395 link = link.tail) { |
| 396 arguments.add(evaluate(link.head)); |
| 397 } |
| 398 return constantHandler.compileListLiteral(node, arguments); |
| 399 } |
| 400 |
| 363 error(Node node) { | 401 error(Node node) { |
| 364 // TODO(floitsch): get the list of constants that are currently compiled | 402 // TODO(floitsch): get the list of constants that are currently compiled |
| 365 // and present some kind of stack-trace. | 403 // and present some kind of stack-trace. |
| 366 MessageKind kind = MessageKind.NOT_A_COMPILE_TIME_CONSTANT; | 404 MessageKind kind = MessageKind.NOT_A_COMPILE_TIME_CONSTANT; |
| 367 compiler.reportError(node, new CompileTimeConstantError(kind, const [])); | 405 compiler.reportError(node, new CompileTimeConstantError(kind, const [])); |
| 368 } | 406 } |
| 369 } | 407 } |
| OLD | NEW |