             [alandipert.kahn :as kahn])
   (:require-macros [cljs.core.async.macros :refer [go go-loop]]))
 
+; Events come in from "the outside world" and get transformed into Messages by input signal nodes
 (defrecord Event
   [topic value])
 
 (defprotocol Message
-  (fresh? [msg]))
-
+  "Messages are propagated through the signal graph, and can either be \"fresh\" or \"cached\"."
+  (fresh? [msg] "returns `true` if the message represents a fresh value, `false` otherwise"))
+
+; a box for a "fresh" value
 (defrecord Fresh
   [value]
   Message
   (fresh? [_] true))
 
+; a box for a "cached" value
 (defrecord Cached
   [value]
   Message
   (fresh? [_] false))
 
 (defprotocol SignalProtocol
-  (signal-deps [s])
-  (message-emitter [s]))
+  (signal-deps [s] "returns the set of \"parent\" signal which this signal depends on")
+  (message-emitter [s]
+    "returns a map with two entries:
+     * `:sources` is a vector of signals from which to get messages
+     * `:msg-fn` is a function which takes two arguments:
+       - the previous message emitted by this signal
+       - a sequence of new messages emitted by the corresponding signals listed in `:sources`"))
 
 (defn signal?
+  "returns `true` if the argument satisfies `SignalProtocol`, `false` otherwise"
   [x]
   (satisfies? SignalProtocol x))
 
 (defn- event-relay
+  "takes a sequence of topics, and returns an input signal which relays matching events as messages to its children"
   [topics]
   (let [topics (if (set? topics) topics (set topics))]
     {:sources [:events]

                                    :msg-fn (constantly cached)}})))

(defn pipeline
  [xform base sig]
  (let [reducer ((comp (core/map :value)
                       xform

    (pipe-to-atom* (spawn* s nil) atm ks)))

(defn spawn
  "Take an inert signal and produce a live, running graph."
  ([g] (spawn* g nil))
  ([g opts] (spawn* g opts)))

(defn pipe-to-atom
  "Pipes fresh values from a live graph into an atom. If `x` is a signal, it is `spawn`ed
  as a live graph first. If no atom is provided, then a new atom is created which takes its
  initial value from that of the given signal or graph. If an existing atom is provided along
  with a sequence of keys `ks`, then fresh values will be inserted into the atom's value using
  `swap!` with `assoc-in`. If `ks` is not present, then the whole atom value is replaced with
  `reset!`."
  ([x]
   (let [live-graph (spawn x)]
     (pipe-to-atom live-graph
