Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(288)

Side by Side Diff: frog/leg/compile_time_constants.dart

Issue 9663068: Avoid cyclic computations in compile-time constants. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | frog/leg/warnings.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 435 matching lines...) Expand 10 before | Expand all | Expand 10 after
446 } 446 }
447 447
448 /** 448 /**
449 * The [ConstantHandler] keeps track of compile-time constants, 449 * The [ConstantHandler] keeps track of compile-time constants,
450 * initializations of global and static fields, and default values of 450 * initializations of global and static fields, and default values of
451 * optional parameters. 451 * optional parameters.
452 */ 452 */
453 class ConstantHandler extends CompilerTask { 453 class ConstantHandler extends CompilerTask {
454 // Contains the initial value of fields. Must contain all static and global 454 // Contains the initial value of fields. Must contain all static and global
455 // initializations of used fields. May contain caches for instance fields. 455 // initializations of used fields. May contain caches for instance fields.
456 final Map<VariableElement, Dynamic> initialVariableValues; 456 final Map<VariableElement, Constant> initialVariableValues;
457 457
458 // Map from compile-time constants to their JS name. 458 // Map from compile-time constants to their JS name.
459 final Map<Constant, String> compiledConstants; 459 final Map<Constant, String> compiledConstants;
460 460
461 // The set of variable elements that are in the process of being computed.
462 final Set<VariableElement> pendingVariables;
463
461 ConstantHandler(Compiler compiler) 464 ConstantHandler(Compiler compiler)
462 : initialVariableValues = new Map<VariableElement, Dynamic>(), 465 : initialVariableValues = new Map<VariableElement, Dynamic>(),
463 compiledConstants = new Map<Constant, String>(), 466 compiledConstants = new Map<Constant, String>(),
467 pendingVariables = new Set<Constant>(),
464 super(compiler); 468 super(compiler);
465 String get name() => 'ConstantHandler'; 469 String get name() => 'ConstantHandler';
466 470
467 void registerCompileTimeConstant(Constant constant) { 471 void registerCompileTimeConstant(Constant constant) {
468 Function ifAbsentThunk = (() => compiler.namer.getFreshGlobalName("CTC")); 472 Function ifAbsentThunk = (() => compiler.namer.getFreshGlobalName("CTC"));
469 compiledConstants.putIfAbsent(constant, ifAbsentThunk); 473 compiledConstants.putIfAbsent(constant, ifAbsentThunk);
470 } 474 }
471 475
472 /** 476 /**
473 * Compiles the initial value of the given field and stores it in an internal 477 * Compiles the initial value of the given field and stores it in an internal
474 * map. 478 * map.
475 * 479 *
476 * [WorkItem] must contain a [VariableElement] refering to a global or 480 * [WorkItem] must contain a [VariableElement] refering to a global or
477 * static field. 481 * static field.
478 */ 482 */
479 void compileWorkItem(WorkItem work) { 483 void compileWorkItem(WorkItem work) {
480 assert(work.element.kind == ElementKind.FIELD 484 assert(work.element.kind == ElementKind.FIELD
481 || work.element.kind == ElementKind.PARAMETER); 485 || work.element.kind == ElementKind.PARAMETER);
482 VariableElement element = work.element; 486 VariableElement element = work.element;
483 // Shortcut if it has already been compiled. 487 // Shortcut if it has already been compiled.
484 if (initialVariableValues.containsKey(element)) return; 488 if (initialVariableValues.containsKey(element)) return;
485 compileVariableWithDefinitions(element, work.resolutionTree); 489 compileVariableWithDefinitions(element, work.resolutionTree);
490 assert(pendingVariables.isEmpty());
486 } 491 }
487 492
488 compileVariable(VariableElement element) { 493 compileVariable(VariableElement element) {
489 if (initialVariableValues.containsKey(element)) { 494 if (initialVariableValues.containsKey(element)) {
490 Constant result = initialVariableValues[element]; 495 Constant result = initialVariableValues[element];
491 return result; 496 return result;
492 } 497 }
493 // TODO(floitsch): keep track of currently compiling elements so that we 498 // TODO(floitsch): keep track of currently compiling elements so that we
494 // don't end up in an infinite loop: final x = y; final y = x; 499 // don't end up in an infinite loop: final x = y; final y = x;
495 TreeElements definitions = compiler.analyzeElement(element); 500 TreeElements definitions = compiler.analyzeElement(element);
496 Constant constant = compileVariableWithDefinitions(element, definitions); 501 Constant constant = compileVariableWithDefinitions(element, definitions);
497 return constant; 502 return constant;
498 } 503 }
499 504
500 Constant compileVariableWithDefinitions(VariableElement element, 505 Constant compileVariableWithDefinitions(VariableElement element,
501 TreeElements definitions) { 506 TreeElements definitions) {
502 return measure(() { 507 return measure(() {
503 Node node = element.parseNode(compiler); 508 Node node = element.parseNode(compiler);
504 assert(node !== null); 509 assert(node !== null);
505 SendSet assignment = node.asSendSet(); 510 SendSet assignment = node.asSendSet();
506 var value; 511 var value;
507 if (assignment === null) { 512 if (assignment === null) {
508 // No initial value. 513 // No initial value.
509 value = new NullConstant(); 514 value = new NullConstant();
510 } else { 515 } else {
516 if (pendingVariables.contains(element)) {
517 MessageKind kind = MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS;
518 compiler.reportError(node,
519 new CompileTimeConstantError(kind, const []));
520 }
521 pendingVariables.add(element);
522
511 Node right = assignment.arguments.head; 523 Node right = assignment.arguments.head;
512 CompileTimeConstantEvaluator evaluator = 524 CompileTimeConstantEvaluator evaluator =
513 new CompileTimeConstantEvaluator(this, definitions, compiler); 525 new CompileTimeConstantEvaluator(this, definitions, compiler);
514 value = evaluator.evaluate(right); 526 value = evaluator.evaluate(right);
527
528 pendingVariables.remove(element);
515 } 529 }
516 initialVariableValues[element] = value; 530 initialVariableValues[element] = value;
517 return value; 531 return value;
518 }); 532 });
519 } 533 }
520 534
521 /** 535 /**
522 * Returns a [List] of static non final fields that need to be initialized. 536 * Returns a [List] of static non final fields that need to be initialized.
523 * The list must be evaluated in order since the fields might depend on each 537 * The list must be evaluated in order since the fields might depend on each
524 * other. 538 * other.
(...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after
997 return constant; 1011 return constant;
998 } 1012 }
999 1013
1000 error(Node node) { 1014 error(Node node) {
1001 // TODO(floitsch): get the list of constants that are currently compiled 1015 // TODO(floitsch): get the list of constants that are currently compiled
1002 // and present some kind of stack-trace. 1016 // and present some kind of stack-trace.
1003 MessageKind kind = MessageKind.NOT_A_COMPILE_TIME_CONSTANT; 1017 MessageKind kind = MessageKind.NOT_A_COMPILE_TIME_CONSTANT;
1004 compiler.reportError(node, new CompileTimeConstantError(kind, const [])); 1018 compiler.reportError(node, new CompileTimeConstantError(kind, const []));
1005 } 1019 }
1006 } 1020 }
OLDNEW
« no previous file with comments | « no previous file | frog/leg/warnings.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698