dep.js: Add optional debugging blather.
[dep-ui] / dep.js
diff --git a/dep.js b/dep.js
index e79b9ad..989e871 100644 (file)
--- a/dep.js
+++ b/dep.js
@@ -25,6 +25,19 @@ var DEP = { }; (function () {
 
 /*----- Utility functions and classes -------------------------------------*/
 
+DEP.DEBUG = false;
+function blather(msg) {
+  /* Report MSG to the log if we're debugging. */
+  if (DEP.DEBUG) console.log(";; " + msg);
+}
+function show(what, value) {
+  /* Report that WHAT has the value VALUE, if we're debugging; and,
+   * regardless, return VALUE.
+   */
+  blather(what + " = " + value);
+  return value;
+}
+
 function dolist(list, func) {
   /* Apply FUNC to each element of LIST, discarding the results.
    *
@@ -118,7 +131,7 @@ var F_CHANGED = 4;                  // Changed in current phase.
 var F_RECOMPUTING = 8;                 // Currently being recomputed.
 var F_QUEUED = 16;                     // Queued for recomputation.
 
-var BAD = Tag('BAD')                   // Used for the value of `bad' deps.
+var BAD = new Tag('BAD');              // Used for the value of `bad' deps.
 
 var DELAYED = [];                      // Actions delayed by `with_frozen'.
 var PENDING = [];                      // Deps awaiting recomputation.
@@ -178,7 +191,7 @@ function Dep(value, maybefunc) {
     func = value;
     f |= F_QUEUED;
   } else {
-    val = value;
+    val = value === undefined ? BAD : value;
     func = null;
     f |= F_VALUE | F_DEPS;
   }
@@ -203,9 +216,11 @@ function Dep(value, maybefunc) {
   this._dependencies = { };            // Set of objects we depend on.
 
   // If we have a recomputation function then exercise it.
+  blather("new dep " + me);
   if (func !== null) {
     with_frozen(function () {
       PENDING.push(me);
+      blather("push new dep " + me);
     });
   }
 }
@@ -235,7 +250,7 @@ Dep.prototype = {
     s += ' #' + this._seq;
 
     // The value, or some kind of marker that it doesn't have one.
-    if (!(f & F_VALUE)) s += ' #{out-of-date}';
+    if (!(f & F_VALUE)) s += ' #{stale}';
     else if (v === BAD) s += ' #{bad}';
     else s += ' ' + v.toString();
 
@@ -255,7 +270,7 @@ Dep.prototype = {
      * If the receiver isn't up-to-date then we synthesize the flags.
      */
 
-    if (this.state === 'ready') return F_VALUE | F_DEPS;
+    if (STATE === 'ready') return F_VALUE | F_DEPS;
     else if (this._generation === GENERATION) return this.__flags;
     else if (this._value_function === null) return F_VALUE | F_DEPS;
     else return 0;
@@ -268,6 +283,7 @@ Dep.prototype = {
      * function which doesn't handle propagation or anything like that.
      */
 
+    blather("_update " + this + ": " + value);
     if (value === BAD ?
        this._value === BAD :
        (this._value !== BAD &&
@@ -293,8 +309,9 @@ Dep.prototype = {
     this._dependencies = { };
     return try_finally(function () {
       EVALUATING = me;
-      return orelse(function () { return me._value_function(); },
-                   function () { return BAD; });
+      return show("_new_value for " + me,
+                 orelse(function () { return me._value_function(); },
+                        function () { return show("ret", BAD); }));
     }, function() {
       EVALUATING = old;
     });
@@ -394,14 +411,15 @@ Dep.prototype = {
 
     var val;
 
-    if (state === 'recomputing') {
+    if (STATE === 'recomputing') {
+      this._force();
       if (EVALUATING) {
        this._dependents[EVALUATING._seq] = EVALUATING;
        EVALUATING._dependencies[this._seq] = this;
       }
-      this._force();
     }
     val = this._value;
+    blather("value " + this + ": " + val);
     if (val === BAD) throw BAD;
     return val;
   },
@@ -444,7 +462,7 @@ Dep.prototype = {
 
 function orelse(thunk, errthunk) {
   /* Call THUNK.  If it succeeds, then return its result.  If THUNK
-   * reads a bad dep then call ERRTHINK and return its result instead.
+   * reads a bad dep then call ERRTHUNK and return its result instead.
    */
 
   var e;
@@ -469,8 +487,9 @@ function recompute_pending() {
    */
 
   var d, f;
-
-  state = 'recomputing';
+  var old_state = STATE;
+  STATE = 'recomputing';
+  blather("STATE <- :recomputing");
   try_finally(function () {
     while (PENDING.length) {
       d = PENDING.shift();
@@ -487,7 +506,10 @@ function recompute_pending() {
     while (PENDING.length) {
       d = PENDING.shift();
       d._value = BAD;
+      blather("recompute_pending mark " + d);
     }
+    STATE = old_state;
+    blather("STATE <- :" + old_state);
   });
 }
 
@@ -503,7 +525,7 @@ function with_frozen(body, delay) {
    */
 
   var op, val;
-  var old_delayed, old_pending;
+  var old_delayed, old_pending, old_state;
 
   switch (STATE) {
   case 'frozen':
@@ -516,6 +538,9 @@ function with_frozen(body, delay) {
   case 'ready':
     old_delayed = DELAYED;
     old_pending = PENDING;
+    old_state = STATE;
+    STATE = "frozen";
+    blather("STATE <- :frozen");
     try_finally(function () {
       DELAYED = [];
       PENDING = [];
@@ -530,6 +555,8 @@ function with_frozen(body, delay) {
     }, function () {
       DELAYED = old_delayed;
       PENDING = old_pending;
+      STATE = old_state;
+      blather("STATE <- :" + old_state);
     });
     break;
   }