| 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 /** [isInt] implies [isNum]. */ | 9 /** [isInt] implies [isNum]. */ |
| 10 bool isInt() => false; | 10 bool isInt() => false; |
| 11 /** [isDouble] implies [isNum]. */ | 11 /** [isDouble] implies [isNum]. */ |
| 12 bool isDouble() => false; | 12 bool isDouble() => false; |
| 13 bool isBool() => false; | 13 bool isBool() => false; |
| 14 bool isString() => false; | 14 bool isString() => false; |
| 15 /** [isList] implies [isObject]. */ | 15 /** [isList] implies [isObject]. */ |
| 16 bool isList() => false; | 16 bool isList() => false; |
| 17 /** [isMap] implies [isObject]. */ | 17 /** [isMap] implies [isObject]. */ |
| 18 bool isMap() => false; | 18 bool isMap() => false; |
| 19 bool isConstructedObject() => false; | 19 bool isConstructedObject() => false; |
| 20 | 20 |
| 21 bool isNum() => isInt() || isDouble(); | 21 bool isNum() => isInt() || isDouble(); |
| 22 bool isObject() => isList() || isMap() || isConstructedObject(); | 22 bool isObject() => isList() || isMap() || isConstructedObject(); |
| 23 bool isTrue() { |
| 24 if (!isBool()) return false; |
| 25 BoolConstant boolConstant = this; |
| 26 return boolConstant.value; |
| 27 } |
| 28 bool isFalse() { |
| 29 if (!isBool()) return false; |
| 30 BoolConstant boolConstant = this; |
| 31 return !boolConstant.value; |
| 32 } |
| 23 | 33 |
| 24 /** | 34 /** |
| 25 * Returns [:null:] if the operation is not supported on this constant. | 35 * Returns [:null:] if the operation is not supported on this constant. |
| 26 * The [op] operator is assumed to be a prefix operator. | 36 * The [op] operator is assumed to be a prefix operator. |
| 27 */ | 37 */ |
| 28 Constant unaryFold(String op) => null; | 38 Constant unaryFold(String op) => null; |
| 29 | 39 |
| 30 /** | 40 /** |
| 31 * Returns [:null:] if the operation is not supported on this constant, or | 41 * Returns [:null:] if the operation is not supported on this constant, or |
| 32 * if the operation would have thrown an exception. | 42 * if the operation would have thrown an exception. |
| 33 */ | 43 */ |
| 34 Constant binaryFold(String op, Constant other) { | 44 Constant binaryFold(String op, Constant other) { |
| 35 if (op == "==" || op == "===") { | 45 if (op == "==" || op == "===") { |
| 36 return new BoolConstant(this == other); | 46 return new BoolConstant(this == other); |
| 37 } else if (op == "!=" || op == "!==") { | 47 } else if (op == "!=" || op == "!==") { |
| 38 return new BoolConstant(this != other); | 48 return new BoolConstant(this != other); |
| 39 } | 49 } |
| 40 } | 50 } |
| 41 | 51 |
| 42 abstract void writeJsCode(StringBuffer buffer, | 52 abstract void writeJsCode(StringBuffer buffer, ConstantHandler handler); |
| 43 CompileTimeConstantHandler handler); | |
| 44 } | 53 } |
| 45 | 54 |
| 46 class PrimitiveConstant extends Constant { | 55 class PrimitiveConstant extends Constant { |
| 47 // TODO(floitsch): this should be an abstract getter, but there is a bug in | 56 abstract get value(); |
| 48 // the VM. | |
| 49 get value() => null; | |
| 50 const PrimitiveConstant(); | 57 const PrimitiveConstant(); |
| 51 | 58 |
| 52 bool operator ==(var other) { | 59 bool operator ==(var other) { |
| 53 if (other is !PrimitiveConstant) return false; | 60 if (other is !PrimitiveConstant) return false; |
| 54 PrimitiveConstant otherPrimitive = other; | 61 PrimitiveConstant otherPrimitive = other; |
| 55 // We use == instead of === so that DartStrings compare correctly. | 62 // We use == instead of === so that DartStrings compare correctly. |
| 56 return value == otherPrimitive.value; | 63 return value == otherPrimitive.value; |
| 57 } | 64 } |
| 65 |
| 66 String toString() => value.toString(); |
| 58 } | 67 } |
| 59 | 68 |
| 60 class NullConstant extends PrimitiveConstant { | 69 class NullConstant extends PrimitiveConstant { |
| 61 const NullConstant(); | 70 const NullConstant(); |
| 62 bool isNull() => true; | 71 bool isNull() => true; |
| 63 get value() => null; | 72 get value() => null; |
| 64 | 73 |
| 65 void writeJsCode(StringBuffer buffer, CompileTimeConstantHandler handler) { | 74 void writeJsCode(StringBuffer buffer, ConstantHandler handler) { |
| 66 buffer.add("(void 0)"); | 75 buffer.add("(void 0)"); |
| 67 } | 76 } |
| 68 | 77 |
| 69 // The magic constant has no meaning. It is just a random value. | 78 // The magic constant has no meaning. It is just a random value. |
| 70 int hashCode() => 785965825; | 79 int hashCode() => 785965825; |
| 71 } | 80 } |
| 72 | 81 |
| 73 class IntConstant extends PrimitiveConstant { | 82 class IntConstant extends PrimitiveConstant { |
| 74 final int value; | 83 final int value; |
| 75 // TODO(floitsch): cache the most common integer values. | 84 // TODO(floitsch): cache the most common integer values. |
| 76 const IntConstant(this.value); | 85 const IntConstant(this.value); |
| 77 bool isInt() => true; | 86 bool isInt() => true; |
| 78 | 87 |
| 79 void writeJsCode(StringBuffer buffer, CompileTimeConstantHandler handler) { | 88 void writeJsCode(StringBuffer buffer, ConstantHandler handler) { |
| 80 buffer.add("($value)"); | 89 buffer.add("($value)"); |
| 81 } | 90 } |
| 82 | 91 |
| 83 IntConstant unaryFold(String op) { | 92 IntConstant unaryFold(String op) { |
| 84 if (op == "-") return new IntConstant(-value); | 93 if (op == "-") return new IntConstant(-value); |
| 85 if (op == "~") return new IntConstant(~value); | 94 if (op == "~") return new IntConstant(~value); |
| 86 return null; | 95 return null; |
| 87 } | 96 } |
| 88 | 97 |
| 89 Constant binaryFold(String op, Constant other) { | 98 Constant binaryFold(String op, Constant other) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 107 case "-": return new IntConstant(value - right); | 116 case "-": return new IntConstant(value - right); |
| 108 case "*": return new IntConstant(value * right); | 117 case "*": return new IntConstant(value * right); |
| 109 case "%": return new IntConstant(value % right); | 118 case "%": return new IntConstant(value % right); |
| 110 case "~/": return new IntConstant(value ~/ right); | 119 case "~/": return new IntConstant(value ~/ right); |
| 111 case "|": return new IntConstant(value | right); | 120 case "|": return new IntConstant(value | right); |
| 112 case "&": return new IntConstant(value & right); | 121 case "&": return new IntConstant(value & right); |
| 113 case "^": return new IntConstant(value ^ right); | 122 case "^": return new IntConstant(value ^ right); |
| 114 case "<<": | 123 case "<<": |
| 115 // TODO(floitsch): find a better way to guard against shifts to the | 124 // TODO(floitsch): find a better way to guard against shifts to the |
| 116 // left. | 125 // left. |
| 117 if (right > 100) null; | 126 if (right > 100) return null; |
| 118 if (right < 0) null; | 127 if (right < 0) return null; |
| 119 return new IntConstant(value << right); | 128 return new IntConstant(value << right); |
| 120 case ">>": | 129 case ">>": |
| 121 if (right < 0) return null; | 130 if (right < 0) return null; |
| 122 return new IntConstant(value >> right); | 131 return new IntConstant(value >> right); |
| 123 } | 132 } |
| 124 } else if (other.isDouble()) { | 133 } else if (other.isDouble()) { |
| 125 double right = rightNum; | 134 double right = rightNum; |
| 126 switch (op) { | 135 switch (op) { |
| 127 case "+": return new DoubleConstant(value + right); | 136 case "+": return new DoubleConstant(value + right); |
| 128 case "-": return new DoubleConstant(value - right); | 137 case "-": return new DoubleConstant(value - right); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 147 } | 156 } |
| 148 | 157 |
| 149 int hashCode() => value.hashCode(); | 158 int hashCode() => value.hashCode(); |
| 150 } | 159 } |
| 151 | 160 |
| 152 class DoubleConstant extends PrimitiveConstant { | 161 class DoubleConstant extends PrimitiveConstant { |
| 153 final double value; | 162 final double value; |
| 154 const DoubleConstant(this.value); | 163 const DoubleConstant(this.value); |
| 155 bool isDouble() => true; | 164 bool isDouble() => true; |
| 156 | 165 |
| 157 void writeJsCode(StringBuffer buffer, CompileTimeConstantHandler handler) { | 166 void writeJsCode(StringBuffer buffer, ConstantHandler handler) { |
| 158 if (value.isNaN()) { | 167 if (value.isNaN()) { |
| 159 buffer.add("(0/0)"); | 168 buffer.add("(0/0)"); |
| 160 } else if (value == double.INFINITY) { | 169 } else if (value == double.INFINITY) { |
| 161 buffer.add("(1/0)"); | 170 buffer.add("(1/0)"); |
| 162 } else if (value == -double.INFINITY) { | 171 } else if (value == -double.INFINITY) { |
| 163 buffer.add("(-1/0)"); | 172 buffer.add("(-1/0)"); |
| 164 } else { | 173 } else { |
| 165 buffer.add("($value)"); | 174 buffer.add("($value)"); |
| 166 } | 175 } |
| 167 } | 176 } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 } | 219 } |
| 211 | 220 |
| 212 int hashCode() => value.hashCode(); | 221 int hashCode() => value.hashCode(); |
| 213 } | 222 } |
| 214 | 223 |
| 215 class BoolConstant extends PrimitiveConstant { | 224 class BoolConstant extends PrimitiveConstant { |
| 216 final bool value; | 225 final bool value; |
| 217 const BoolConstant(this.value); | 226 const BoolConstant(this.value); |
| 218 bool isBool() => true; | 227 bool isBool() => true; |
| 219 | 228 |
| 220 void writeJsCode(StringBuffer buffer, CompileTimeConstantHandler handler) { | 229 void writeJsCode(StringBuffer buffer, ConstantHandler handler) { |
| 221 buffer.add(value ? "true" : "false"); | 230 buffer.add(value ? "true" : "false"); |
| 222 } | 231 } |
| 223 | 232 |
| 224 BoolConstant unaryFold(String op) { | 233 BoolConstant unaryFold(String op) { |
| 225 if (op == "!") return new BoolConstant(!value); | 234 if (op == "!") return new BoolConstant(!value); |
| 226 return null; | 235 return null; |
| 227 } | 236 } |
| 228 | 237 |
| 229 bool operator ==(var other) { | 238 bool operator ==(var other) { |
| 230 if (other is !BoolConstant) return false; | 239 if (other is !BoolConstant) return false; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 241 final DartString value; | 250 final DartString value; |
| 242 int _hashCode; | 251 int _hashCode; |
| 243 | 252 |
| 244 StringConstant(this.value) { | 253 StringConstant(this.value) { |
| 245 // TODO(floitsch): compute hashcode without calling toString() on the | 254 // TODO(floitsch): compute hashcode without calling toString() on the |
| 246 // DartString. | 255 // DartString. |
| 247 _hashCode = value.toString().hashCode(); | 256 _hashCode = value.toString().hashCode(); |
| 248 } | 257 } |
| 249 bool isString() => true; | 258 bool isString() => true; |
| 250 | 259 |
| 251 void writeJsCode(StringBuffer buffer, CompileTimeConstantHandler handler) { | 260 void writeJsCode(StringBuffer buffer, ConstantHandler handler) { |
| 252 buffer.add("'"); | 261 buffer.add("'"); |
| 253 CompileTimeConstantHandler.writeEscapedString(value, buffer, (reason) { | 262 ConstantHandler.writeEscapedString(value, buffer, (reason) { |
| 254 throw new CompilerCancelledException(reason); | 263 throw new CompilerCancelledException(reason); |
| 255 }); | 264 }); |
| 256 buffer.add("'"); | 265 buffer.add("'"); |
| 257 } | 266 } |
| 258 | 267 |
| 259 Constant binaryFold(String op, Constant other) { | 268 Constant binaryFold(String op, Constant other) { |
| 260 if (other.isString() && op == "+") { | 269 if (other.isString() && op == "+") { |
| 261 StringConstant otherString = other; | 270 StringConstant otherString = other; |
| 262 DartString right = otherString.value; | 271 DartString right = otherString.value; |
| 263 return new StringConstant(new ConsDartString(value, right)); | 272 return new StringConstant(new ConsDartString(value, right)); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 286 int _hashCode; | 295 int _hashCode; |
| 287 | 296 |
| 288 ListConstant(Type type, this.entries) : super(type) { | 297 ListConstant(Type type, this.entries) : super(type) { |
| 289 // TODO(floitsch): create a better hash. | 298 // TODO(floitsch): create a better hash. |
| 290 int hash = 0; | 299 int hash = 0; |
| 291 for (Constant input in entries) hash ^= input.hashCode(); | 300 for (Constant input in entries) hash ^= input.hashCode(); |
| 292 _hashCode = hash; | 301 _hashCode = hash; |
| 293 } | 302 } |
| 294 bool isList() => true; | 303 bool isList() => true; |
| 295 | 304 |
| 296 void writeJsCode(StringBuffer buffer, CompileTimeConstantHandler handler) { | 305 void writeJsCode(StringBuffer buffer, ConstantHandler handler) { |
| 297 // TODO(floitsch): we should not need to go through the compiler to make | 306 // TODO(floitsch): we should not need to go through the compiler to make |
| 298 // the list constant. | 307 // the list constant. |
| 299 buffer.add(handler.compiler.namer.ISOLATE); | 308 String isolatePrototype = "${handler.compiler.namer.ISOLATE}.prototype"; |
| 300 buffer.add(".prototype.makeConstantList"); | 309 buffer.add("$isolatePrototype.makeConstantList"); |
| 301 buffer.add("(["); | 310 buffer.add("(["); |
| 302 for (int i = 0; i < entries.length; i++) { | 311 for (int i = 0; i < entries.length; i++) { |
| 303 if (i != 0) buffer.add(", "); | 312 if (i != 0) buffer.add(", "); |
| 304 Constant entry = entries[i]; | 313 Constant entry = entries[i]; |
| 305 if (entry.isObject()) { | 314 if (entry.isObject()) { |
| 306 handler.getNameForConstant(entry); | 315 String name = handler.getNameForConstant(entry); |
| 316 buffer.add("$isolatePrototype.$name"); |
| 307 } else { | 317 } else { |
| 308 entry.writeJsCode(buffer, handler); | 318 entry.writeJsCode(buffer, handler); |
| 309 } | 319 } |
| 310 } | 320 } |
| 311 buffer.add("])"); | 321 buffer.add("])"); |
| 312 } | 322 } |
| 313 | 323 |
| 314 bool operator ==(var other) { | 324 bool operator ==(var other) { |
| 315 if (other is !ListConstant) return false; | 325 if (other is !ListConstant) return false; |
| 316 ListConstant otherList = other; | 326 ListConstant otherList = other; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 335 // TODO(floitsch): create a better hash. | 345 // TODO(floitsch): create a better hash. |
| 336 int hash = 0; | 346 int hash = 0; |
| 337 for (Constant field in fields) { | 347 for (Constant field in fields) { |
| 338 hash ^= field.hashCode(); | 348 hash ^= field.hashCode(); |
| 339 } | 349 } |
| 340 hash ^= type.element.hashCode(); | 350 hash ^= type.element.hashCode(); |
| 341 _hashCode = hash; | 351 _hashCode = hash; |
| 342 } | 352 } |
| 343 bool isConstructedObject() => true; | 353 bool isConstructedObject() => true; |
| 344 | 354 |
| 345 void writeJsCode(StringBuffer buffer, CompileTimeConstantHandler handler) { | 355 void writeJsCode(StringBuffer buffer, ConstantHandler handler) { |
| 346 buffer.add("new "); | 356 buffer.add("new "); |
| 347 buffer.add(handler.getJsConstructor(type.element)); | 357 buffer.add(handler.getJsConstructor(type.element)); |
| 348 buffer.add("("); | 358 buffer.add("("); |
| 349 for (int i = 0; i < fields.length; i++) { | 359 for (int i = 0; i < fields.length; i++) { |
| 350 if (i != 0) buffer.add(", "); | 360 if (i != 0) buffer.add(", "); |
| 351 Constant field = fields[i]; | 361 Constant field = fields[i]; |
| 352 // TODO(floitsch): share this code with the ListConstant. | 362 // TODO(floitsch): share this code with the ListConstant. |
| 353 if (field.isObject()) { | 363 if (field.isObject()) { |
| 354 handler.getNameForConstant(field); | 364 handler.getNameForConstant(field); |
| 355 } else { | 365 } else { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 369 for (int i = 0; i < fields.length; i++) { | 379 for (int i = 0; i < fields.length; i++) { |
| 370 if (fields[i] != other.fields[i]) return false; | 380 if (fields[i] != other.fields[i]) return false; |
| 371 } | 381 } |
| 372 return true; | 382 return true; |
| 373 } | 383 } |
| 374 | 384 |
| 375 int hashCode() => _hashCode; | 385 int hashCode() => _hashCode; |
| 376 } | 386 } |
| 377 | 387 |
| 378 /** | 388 /** |
| 379 * The [CompileTimeConstantHandler] keeps track of compile-time constants, | 389 * The [ConstantHandler] keeps track of compile-time constants, |
| 380 * initializations of global and static fields, and default values of | 390 * initializations of global and static fields, and default values of |
| 381 * optional parameters. | 391 * optional parameters. |
| 382 */ | 392 */ |
| 383 class CompileTimeConstantHandler extends CompilerTask { | 393 class ConstantHandler extends CompilerTask { |
| 384 // Contains the initial value of fields. Must contain all static and global | 394 // Contains the initial value of fields. Must contain all static and global |
| 385 // initializations of used fields. May contain caches for instance fields. | 395 // initializations of used fields. May contain caches for instance fields. |
| 386 final Map<VariableElement, Dynamic> initialVariableValues; | 396 final Map<VariableElement, Dynamic> initialVariableValues; |
| 387 | 397 |
| 388 // Map from compile-time constants to their JS name. | 398 // Map from compile-time constants to their JS name. |
| 389 final Map<Constant, String> compiledConstants; | 399 final Map<Constant, String> compiledConstants; |
| 390 | 400 |
| 391 CompileTimeConstantHandler(Compiler compiler) | 401 ConstantHandler(Compiler compiler) |
| 392 : initialVariableValues = new Map<VariableElement, Dynamic>(), | 402 : initialVariableValues = new Map<VariableElement, Dynamic>(), |
| 393 compiledConstants = new Map<Constant, String>(), | 403 compiledConstants = new Map<Constant, String>(), |
| 394 super(compiler); | 404 super(compiler); |
| 395 String get name() => 'CompileTimeConstantHandler'; | 405 String get name() => 'ConstantHandler'; |
| 396 | 406 |
| 397 void registerCompileTimeConstant(Constant constant) { | 407 void registerCompileTimeConstant(Constant constant) { |
| 398 Function ifAbsentThunk = (() => compiler.namer.getFreshGlobalName("CTC")); | 408 Function ifAbsentThunk = (() => compiler.namer.getFreshGlobalName("CTC")); |
| 399 compiledConstants.putIfAbsent(constant, ifAbsentThunk); | 409 compiledConstants.putIfAbsent(constant, ifAbsentThunk); |
| 400 } | 410 } |
| 401 | 411 |
| 402 /** | 412 /** |
| 403 * Compiles the initial value of the given field and stores it in an internal | 413 * Compiles the initial value of the given field and stores it in an internal |
| 404 * map. | 414 * map. |
| 405 * | 415 * |
| 406 * [WorkItem] must contain a [VariableElement] refering to a global or | 416 * [WorkItem] must contain a [VariableElement] refering to a global or |
| 407 * static field. | 417 * static field. |
| 408 */ | 418 */ |
| 409 void compileWorkItem(WorkItem work) { | 419 void compileWorkItem(WorkItem work) { |
| 410 assert(work.element.kind == ElementKind.FIELD | 420 assert(work.element.kind == ElementKind.FIELD |
| 411 || work.element.kind == ElementKind.PARAMETER); | 421 || work.element.kind == ElementKind.PARAMETER); |
| 412 VariableElement element = work.element; | 422 VariableElement element = work.element; |
| 413 // Shortcut if it has already been compiled. | 423 // Shortcut if it has already been compiled. |
| 414 if (initialVariableValues.containsKey(element)) return; | 424 if (initialVariableValues.containsKey(element)) return; |
| 415 compileVariableWithDefinitions(element, work.resolutionTree); | 425 compileVariableWithDefinitions(element, work.resolutionTree); |
| 416 } | 426 } |
| 417 | 427 |
| 418 compileVariable(VariableElement element) { | 428 compileVariable(VariableElement element) { |
| 419 if (initialVariableValues.containsKey(element)) { | 429 if (initialVariableValues.containsKey(element)) { |
| 420 Constant result = initialVariableValues[element]; | 430 Constant result = initialVariableValues[element]; |
| 421 // TODO(floitsch): remove the following line once the rest of the | |
| 422 // compiler has been adapted. | |
| 423 if (!result.isObject()) return result.dynamic.value; | |
| 424 return result; | 431 return result; |
| 425 } | 432 } |
| 426 // TODO(floitsch): keep track of currently compiling elements so that we | 433 // TODO(floitsch): keep track of currently compiling elements so that we |
| 427 // don't end up in an infinite loop: final x = y; final y = x; | 434 // don't end up in an infinite loop: final x = y; final y = x; |
| 428 TreeElements definitions = compiler.analyzeElement(element); | 435 TreeElements definitions = compiler.analyzeElement(element); |
| 429 Constant constant = compileVariableWithDefinitions(element, definitions); | 436 Constant constant = compileVariableWithDefinitions(element, definitions); |
| 430 // TODO(floitsch): remove the following line once the rest of the | |
| 431 // compiler has been adapted. | |
| 432 if (!constant.isObject()) return constant.dynamic.value; | |
| 433 return constant; | 437 return constant; |
| 434 } | 438 } |
| 435 | 439 |
| 436 compileVariableWithDefinitions(VariableElement element, | 440 compileVariableWithDefinitions(VariableElement element, |
| 437 TreeElements definitions) { | 441 TreeElements definitions) { |
| 438 return measure(() { | 442 return measure(() { |
| 439 Node node = element.parseNode(compiler); | 443 Node node = element.parseNode(compiler); |
| 440 assert(node !== null); | 444 assert(node !== null); |
| 441 SendSet assignment = node.asSendSet(); | 445 SendSet assignment = node.asSendSet(); |
| 442 var value; | 446 var value; |
| 443 if (assignment === null) { | 447 if (assignment === null) { |
| 444 // No initial value. | 448 // No initial value. |
| 445 value = const NullConstant(); | 449 value = const NullConstant(); |
| 446 } else { | 450 } else { |
| 447 Node right = assignment.arguments.head; | 451 Node right = assignment.arguments.head; |
| 448 CompileTimeConstantEvaluator evaluator = | 452 CompileTimeConstantEvaluator evaluator = |
| 449 new CompileTimeConstantEvaluator(this, definitions, compiler); | 453 new CompileTimeConstantEvaluator(this, definitions, compiler); |
| 450 value = evaluator.evaluate(right); | 454 value = evaluator.evaluate(right); |
| 451 } | 455 } |
| 452 initialVariableValues[element] = value; | 456 initialVariableValues[element] = value; |
| 453 return value; | 457 return value; |
| 454 }); | 458 }); |
| 455 } | 459 } |
| 456 | 460 |
| 457 ConstructedConstant compileObjectConstruction(Node node, | 461 ConstructedConstant compileObjectConstruction(Node node, |
| 458 Type type, | 462 Type type, |
| 459 List arguments) { | 463 List arguments) { |
| 460 if (!arguments.isEmpty()) { | 464 if (!arguments.isEmpty()) { |
| 461 compiler.unimplemented("CompileTimeConstantHandler with arguments", | 465 compiler.unimplemented("ConstantHandler with arguments", node: node); |
| 462 node: node); | |
| 463 } | 466 } |
| 464 ClassElement classElement = type.element; | 467 ClassElement classElement = type.element; |
| 465 for (Element member in classElement.members) { | 468 for (Element member in classElement.members) { |
| 466 if (Elements.isInstanceField(member)) { | 469 if (Elements.isInstanceField(member)) { |
| 467 compiler.unimplemented("CompileTimeConstantHandler with fields", | 470 compiler.unimplemented("ConstantHandler with fields", node: node); |
| 468 node: node); | |
| 469 } | 471 } |
| 470 } | 472 } |
| 471 if (classElement.superclass != compiler.coreLibrary.find(Types.OBJECT)) { | 473 if (classElement.superclass != compiler.coreLibrary.find(Types.OBJECT)) { |
| 472 compiler.unimplemented("CompileTimeConstantHandler with super", | 474 compiler.unimplemented("ConstantHandler with super", node: node); |
| 473 node: node); | |
| 474 } | 475 } |
| 475 compiler.registerInstantiatedClass(classElement); | 476 compiler.registerInstantiatedClass(classElement); |
| 476 Constant constant = new ConstructedConstant(type, arguments); | 477 Constant constant = new ConstructedConstant(type, arguments); |
| 477 registerCompileTimeConstant(constant); | 478 registerCompileTimeConstant(constant); |
| 478 return constant; | 479 return constant; |
| 479 } | 480 } |
| 480 | 481 |
| 481 ListConstant compileListLiteral(Node node, | 482 ListConstant compileListLiteral(Node node, |
| 482 Type type, | 483 Type type, |
| 483 List<Constant> arguments) { | 484 List<Constant> arguments) { |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 600 } | 601 } |
| 601 } | 602 } |
| 602 } | 603 } |
| 603 | 604 |
| 604 String getJsConstructor(ClassElement element) { | 605 String getJsConstructor(ClassElement element) { |
| 605 return compiler.namer.isolatePropertyAccess(element); | 606 return compiler.namer.isolatePropertyAccess(element); |
| 606 } | 607 } |
| 607 } | 608 } |
| 608 | 609 |
| 609 class CompileTimeConstantEvaluator extends AbstractVisitor { | 610 class CompileTimeConstantEvaluator extends AbstractVisitor { |
| 610 final CompileTimeConstantHandler constantHandler; | 611 final ConstantHandler constantHandler; |
| 611 final TreeElements definitions; | 612 final TreeElements definitions; |
| 612 final Compiler compiler; | 613 final Compiler compiler; |
| 613 | 614 |
| 614 CompileTimeConstantEvaluator(this.constantHandler, | 615 CompileTimeConstantEvaluator(this.constantHandler, |
| 615 this.definitions, | 616 this.definitions, |
| 616 this.compiler); | 617 this.compiler); |
| 617 | 618 |
| 618 Constant evaluate(Node node) { | 619 Constant evaluate(Node node) { |
| 619 return node.accept(this); | 620 return node.accept(this); |
| 620 } | 621 } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 663 } | 664 } |
| 664 | 665 |
| 665 // TODO(floitsch): provide better error-messages. | 666 // TODO(floitsch): provide better error-messages. |
| 666 visitSend(Send send) { | 667 visitSend(Send send) { |
| 667 Element element = definitions[send]; | 668 Element element = definitions[send]; |
| 668 if (Elements.isStaticOrTopLevelField(element)) { | 669 if (Elements.isStaticOrTopLevelField(element)) { |
| 669 if (element.modifiers === null || | 670 if (element.modifiers === null || |
| 670 !element.modifiers.isFinal()) { | 671 !element.modifiers.isFinal()) { |
| 671 error(send); | 672 error(send); |
| 672 } | 673 } |
| 673 // TODO(floitsch): compileVariable temporarily returns primitives, so | 674 return constantHandler.compileVariable(element); |
| 674 // that the rest of the compiler can be adapted incrementally. Therefore | |
| 675 // we have to get the constant from the hashtable instead of using the | |
| 676 // returned result directly. | |
| 677 constantHandler.compileVariable(element); | |
| 678 return constantHandler.initialVariableValues[element]; | |
| 679 } else if (send.isPrefix) { | 675 } else if (send.isPrefix) { |
| 680 assert(send.isOperator); | 676 assert(send.isOperator); |
| 681 Constant receiverConstant = evaluate(send.receiver); | 677 Constant receiverConstant = evaluate(send.receiver); |
| 682 Operator op = send.selector; | 678 Operator op = send.selector; |
| 683 Constant folded = receiverConstant.unaryFold(op.source.stringValue); | 679 Constant folded = receiverConstant.unaryFold(op.source.stringValue); |
| 684 if (folded === null) error(send); | 680 if (folded === null) error(send); |
| 685 return folded; | 681 return folded; |
| 686 } else if (send.isOperator && !send.isPostfix) { | 682 } else if (send.isOperator && !send.isPostfix) { |
| 687 assert(send.argumentCount() == 1); | 683 assert(send.argumentCount() == 1); |
| 688 Constant left = evaluate(send.receiver); | 684 Constant left = evaluate(send.receiver); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 722 arguments); | 718 arguments); |
| 723 } | 719 } |
| 724 | 720 |
| 725 error(Node node) { | 721 error(Node node) { |
| 726 // TODO(floitsch): get the list of constants that are currently compiled | 722 // TODO(floitsch): get the list of constants that are currently compiled |
| 727 // and present some kind of stack-trace. | 723 // and present some kind of stack-trace. |
| 728 MessageKind kind = MessageKind.NOT_A_COMPILE_TIME_CONSTANT; | 724 MessageKind kind = MessageKind.NOT_A_COMPILE_TIME_CONSTANT; |
| 729 compiler.reportError(node, new CompileTimeConstantError(kind, const [])); | 725 compiler.reportError(node, new CompileTimeConstantError(kind, const [])); |
| 730 } | 726 } |
| 731 } | 727 } |
| OLD | NEW |