Skip to content
Browse files

more comments and commentary

  • Loading branch information...
1 parent 3a8fbfe commit b8d3e72a9ffc5c0bdbd0e35c5cb0a02649aed977 @maxtaco committed
Showing with 45 additions and 6 deletions.
  1. +35 −3 TAME.md
  2. +10 −3 src/nodes.coffee
View
38 TAME.md
@@ -279,19 +279,51 @@ file `nodes.coffee`.
### Awaits Can work as Expressions
-*In a rush*
+I don't really like this feature, but people have requested it, so
+here goes a trip down the rabbit hole. It's possible to use `await`
+blocks as expressions. And recursively speaking, it's possible to use
+statements that contain `await` blocks as expressions.
-An `await` block takes the value of its first `defer'ed slot.
+The simple rule is that an `await` block takes on the value of the
+`defer` slot named `_` after its been fulfilled. If there
+are multiple `defer` slots named `_` within the `await` block, then
+the last writer wins. In practice, there's usually only one. Thus:
```coffeescript
add = (a,b,cb) ->
await setTimeout defer(), 10
cb(a+b)
-x = (await add 3, 4, defer()) + (await add 1, 2, defer())
+x = (await add 3, 4, defer _) + (await add 1, 2, defer _)
console.log "#{x} == 10"
```
+Of course, things can get arbitrarily compicated and nested, so it
+gets hairy. Consider this:
+
+```coffeescript
+x = await add (await add 1, 2, defer _), (await add 3, 4, defer _), defer _
+```
+
+The rule is that all nested `await` blocks (barf!) are evaluated
+sequentially in DFS order. You will get `10` in the above example
+after three sequential calls to `add`.
+
+I really don't like this feature for two reasons: (1) it's tricky to
+get the implementation right, and I'm sure I haven't tested all of the
+corner cases yet; (2) it's difficult to read and understand what
+happens in which order. I would suggest you save yourself the heartache,
+and just write the above as this:
+
+```coffeescript
+await add 1, 2, defer l
+await add 3, 4, defer r
+await add l, r, defer x
+```
+
+It's just so much clearer what happens in which order, and it's easier
+to parallelize or serialize as you see fit.
+
## Translation Technique
The CoffeeScript tame addition uses a similar continuation-passing translation
View
13 src/nodes.coffee
@@ -239,16 +239,23 @@ exports.Base = class Base
# AST Walking Routines for CPS Pivots, etc.
#
# There are three passes:
- # 3. Find await's and trace upward.
- # 4. Find loops found in #1, and flood downward
- # 5. Find break/continue found in #2, and trace upward
+ # 1. Find await's and trace upward.
+ # 2. Find loops found in #1, and flood downward
+ # 3. Find break/continue found in #2, and trace upward
#
# tameWalkAst
+ #
# Walk the AST looking for taming. Mark a node as with tame flags
# if any of its children are tamed, but don't cross scope boundary
# when considering the children.
#
+ # The paremeter `p` is the parent `await`. All nodes beneath the
+ # first `await` in a function scope should point to its highest
+ # parent `await`. This is so in the case of nested `await`s,
+ # they're really pulled out and run in sequence as the level of the
+ # topmost await.
+ #
tameWalkAst : (p) ->
@tameParentAwait = p
for child in @flattenChildren()

0 comments on commit b8d3e72

Please sign in to comment.
Something went wrong with that request. Please try again.