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