Skip to content
Browse files

more conversion of tame -> iced

  • Loading branch information...
1 parent 42b7013 commit 02cecb995e9068a4435fac8ff11d8f1914b93a80 @maxtaco committed
Showing with 133 additions and 6,357 deletions.
  1. +2 −2 Cakefile
  2. +1 −6,228 extras/coffee-script.js
  3. +22 −20 iced.md
  4. +107 −0 src/icedlib.coffee
  5. +0 −107 src/tamelib.coffee
  6. +1 −0 src/tamelib.coffee
View
4 Cakefile
@@ -30,7 +30,7 @@ header = """
sources = [
'coffee-script', 'grammar', 'helpers'
'lexer', 'nodes', 'rewriter', 'scope',
- 'tame'
+ 'tame', 'tamelib', 'icedlib'
].map (filename) -> "src/#{filename}.coffee"
# Run a CoffeeScript through our node/coffee interpreter.
@@ -97,7 +97,7 @@ task 'build:ultraviolet', 'build and install the Ultraviolet syntax highlighter'
task 'build:browser', 'rebuild the merged script for inclusion in the browser', ->
code = ''
- for name in ['helpers', 'rewriter', 'lexer', 'parser', 'scope', 'tame', 'nodes', 'coffee-script', 'browser' ]
+ for name in ['helpers', 'rewriter', 'lexer', 'parser', 'scope', 'tame', 'nodes', 'coffee-script', 'browser', 'icedlib' ]
code += """
require['./#{name}'] = new function() {
var exports = this;
View
6,229 extras/coffee-script.js
1 addition, 6,228 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
42 iced.md
@@ -1,19 +1,21 @@
What Is IcedCoffeeScript?
==================
-IcedCoffeeScript is a system for handling callbacks in event-based code. There
-were two existing implementations, one in [the sfslite library for
-C++](https://github.com/maxtaco/sfslite), and another in the [tamejs
-translator for JavaScript](https://github.com/maxtaco/tamejs).
-This extension to CoffeeScript is a third implementation. The code
-and translation techniques are derived from experience with JS, but
-with some new Coffee-style flavoring.
+IcedCoffeeScript (ICS) is a system for handling callbacks in event-based code.
+There were two existing implementations, one in [the sfslite library for
+C++](https://github.com/maxtaco/sfslite), and another in the [tamejs translator
+for JavaScript](https://github.com/maxtaco/tamejs). This extension to
+CoffeeScript is a third implementation. The code and translation techniques
+are derived from experience with JS, but with some new Coffee-style
+flavoring.
This document first presents a "Iced" tutorial (adapted from the JavaScript
version), and then discusses the specifics of the CoffeeScript implementation.
-(Note: we are slowly changing all instances of the word "tame" over to
-"iced" in the repository, and in the general code.)
+(Note: we are slowly changing all instances of the word "tame" in
+the repository and the generated code to "iced". This should have
+little impact on ICS source in the wild, since the word "tame"
+only appears in your code if you're using advanced features.)
# Quick Tutorial and Examples
@@ -113,7 +115,7 @@ fulfilled (rather than the last):
icedRequire(node) # need full library via require() for rendezvous
do_all = (lst, windowsz) ->
- rv = new tame.Rendezvous
+ rv = new iced.Rendezvous
nsent = 0
nrecv = 0
@@ -144,7 +146,7 @@ after faster ones, even if issued before them.
### Composing Serial And Parallel Patterns
-In Tame, arbitrary composition of serial and parallel control flows is
+In IcedCoffeeScript, arbitrary composition of serial and parallel control flows is
possible with just normal functional decomposition. Therefore, we
don't allow direct `await` nesting. With inline anonymous CoffeeScript
functions, you can concisely achieve interesting patterns. The code
@@ -493,7 +495,7 @@ Here is the translated output (slightly hand-edited for clarity):
## API and Library Documentation
-### tame.Rendezvous
+### iced.Rendezvous
The `Rendezvous` is a not a core feature, meaning it's written as a
straight-ahead CoffeeScript library. It's quite useful for more advanced
@@ -502,7 +504,7 @@ control flows, so we've included it in the main runtime library.
The `Rendezvous` is similar to a blocking condition variable (or a
"Hoare sytle monitor") in threaded programming.
-#### tame.Rendezvous.id(i).defer slots...
+#### iced.Rendezvous.id(i).defer slots...
Associate a new deferral with the given Rendezvous, whose deferral ID
is `i`, and whose callbacks slots are supplied as `slots`. Those
@@ -512,13 +514,13 @@ fed to a function expecting a callback. As soon as that callback
fires (and the deferral is fulfilled), the provided slots will be
filled with the arguments to that callback.
-#### tame.Rendezvous.defer slots...
+#### iced.Rendezvous.defer slots...
You don't need to explicitly assign an ID to a deferral generated from a
Rendezvous. If you don't, one will automatically be assigned, in
ascending order starting from `0`.
-#### tame.Rendezvous.wait cb
+#### iced.Rendezvous.wait cb
Wait until the next deferral on this rendezvous is fulfilled. When it
is, callback `cb` with the ID of the fulfilled deferral. If an
@@ -538,7 +540,7 @@ and reports only when the first returns:
```coffeescript
hosts = [ "okcupid.com", "google.com" ];
ips = errs = []
-rv = new tame.Rendezvous ();
+rv = new iced.Rendezvous
for h,i in hosts
dns.resolve hosts[i], rv.id(i).defer errs[i], ips[i]
@@ -552,7 +554,7 @@ A *connector* is a function that takes as input
a callback, and outputs another callback. The best example
is a `timeout`, given here:
-#### tame.timeout(cb, time, res = [])
+#### iced.timeout(cb, time, res = [])
Timeout an arbitrary async operation.
@@ -566,7 +568,7 @@ caller fires first, then fill `res[0] = true;`. If the timer won
In the following example, we timeout a DNS lookup after 100ms:
```coffeescript
-{timeout} = require 'tamelib'
+{timeout} = require 'icedlib'
info = [];
host = "pirateWarezSite.ru";
await dns.lookup host, timeout(defer(err, ip), 100, info)
@@ -585,10 +587,10 @@ you can use the control flow library called `Pipeliner`, which
manages the common pattern of having "m calls total, with only
n of them in flight at once, where m > n."
-The Pipeliner class is available in the `tamelib` library:
+The Pipeliner class is available in the `icedlib` library:
```coffeescript
-{Pipeliner} = require 'tamelib'
+{Pipeliner} = require 'icedlib'
pipeliner = new Pipeliner w,s
```
View
107 src/icedlib.coffee
@@ -0,0 +1,107 @@
+icedRequire(none)
+
+tame_internals = require('./tame')
+tame = tame_internals.runtime
+
+#
+# tamelib
+#
+# This class contains non-essential but convenient runtime libraries
+# for tame programs
+#
+
+#
+# The `timeout` connector, which allows us to compose timeouts with
+# existing event-based calls
+#
+_timeout = (cb, t, res, tmp) ->
+ rv = new tame.Rendezvous
+ tmp[0] = rv.id(true).defer(arr...)
+ setTimeout rv.id(false).defer(), t
+ await rv.wait defer which
+ res[0] = which if res
+ cb.apply(null, arr)
+
+exports.timeout = (cb, t, res) ->
+ tmp = []
+ _timeout cb, t, res, tmp
+ tmp[0]
+
+####
+#
+# Pipeliner -- a class for firing a follow of network calls in a pipelined
+# fashion, so that only so many of them are outstanding at once.
+#
+exports.Pipeliner = class Pipeliner
+
+ constructor : (window, delay) ->
+ @window = window || 1
+ @delay = delay || 0
+ @queue = []
+ @n_out = 0
+ @cb = null
+
+ # This is a hack to work with the desugaring of
+ # 'defer' output by the coffee compiler. Same as in rendezvous
+ @[tame_internals.const.deferrals] = this
+
+ # Rebind "defer" to "_defer"; We can't do this directly since the
+ # compiler would pick it up
+ @["defer"] = @_defer
+
+
+ # Call this to wait in a queue until there is room in the window
+ waitInQueue : (cb) ->
+
+ # Wait until there is room in the window.
+ while @n_out > @window
+ await (@cb = defer())
+
+ # Lanuch a computation, so mark that there's one more
+ # guy outstanding.
+ @n_out++
+
+ # Delay if that was asked for...
+ if @delay
+ await setTimeout defer(), @delay
+
+ cb()
+
+
+ # Helper for this._defer, seen below..
+ __defer : (out, deferArgs) ->
+
+ # Make a callback that this.defer can return.
+ # This callback might have to fill in slots when its
+ # fulfilled, so that's why we need to wrap the output
+ # of defer() in an anonymous wrapper.
+ await
+ voidCb = defer()
+ out[0] = (args...) ->
+ deferArgs.assign_fn?.apply null, args
+ voidCb()
+
+ # There is now one fewer outstanding computation.
+ @n_out--
+
+ # If some is waiting in waitInQueue above, then now is the
+ # time to release him. Use "race-free" callback technique.
+ if @cb
+ tmp = @cb
+ @cb = null
+ tmp()
+
+ # This function, Pipeliner._defer, has to return a
+ # callback to its caller. It does this with the same trick above.
+ # The helper function _defer() does the heavy lifting, returning
+ # its callback to us as the first slot in tmp[0].
+ _defer : (deferArgs) ->
+ tmp = []
+ @__defer tmp, deferArgs
+ tmp[0]
+
+ # flush everything left in the pipe
+ flush : (autocb) ->
+ while @n_out
+ await (@cb = defer())
+
View
107 src/tamelib.coffee
@@ -1,107 +0,0 @@
-icedRequire(none)
-
-tame_internals = require('./tame')
-tame = tame_internals.runtime
-
-#
-# tamelib
-#
-# This class contains non-essential but convenient runtime libraries
-# for tame programs
-#
-
-#
-# The `timeout` connector, which allows us to compose timeouts with
-# existing event-based calls
-#
-_timeout = (cb, t, res, tmp) ->
- rv = new tame.Rendezvous
- tmp[0] = rv.id(true).defer(arr...)
- setTimeout rv.id(false).defer(), t
- await rv.wait defer which
- res[0] = which if res
- cb.apply(null, arr)
-
-exports.timeout = (cb, t, res) ->
- tmp = []
- _timeout cb, t, res, tmp
- tmp[0]
-
-####
-#
-# Pipeliner -- a class for firing a follow of network calls in a pipelined
-# fashion, so that only so many of them are outstanding at once.
-#
-exports.Pipeliner = class Pipeliner
-
- constructor : (window, delay) ->
- @window = window || 1
- @delay = delay || 0
- @queue = []
- @n_out = 0
- @cb = null
-
- # This is a hack to work with the desugaring of
- # 'defer' output by the coffee compiler. Same as in rendezvous
- @[tame_internals.const.deferrals] = this
-
- # Rebind "defer" to "_defer"; We can't do this directly since the
- # compiler would pick it up
- @["defer"] = @_defer
-
-
- # Call this to wait in a queue until there is room in the window
- waitInQueue : (cb) ->
-
- # Wait until there is room in the window.
- while @n_out > @window
- await (@cb = defer())
-
- # Lanuch a computation, so mark that there's one more
- # guy outstanding.
- @n_out++
-
- # Delay if that was asked for...
- if @delay
- await setTimeout defer(), @delay
-
- cb()
-
-
- # Helper for this._defer, seen below..
- __defer : (out, deferArgs) ->
-
- # Make a callback that this.defer can return.
- # This callback might have to fill in slots when its
- # fulfilled, so that's why we need to wrap the output
- # of defer() in an anonymous wrapper.
- await
- voidCb = defer()
- out[0] = (args...) ->
- deferArgs.assign_fn?.apply null, args
- voidCb()
-
- # There is now one fewer outstanding computation.
- @n_out--
-
- # If some is waiting in waitInQueue above, then now is the
- # time to release him. Use "race-free" callback technique.
- if @cb
- tmp = @cb
- @cb = null
- tmp()
-
- # This function, Pipeliner._defer, has to return a
- # callback to its caller. It does this with the same trick above.
- # The helper function _defer() does the heavy lifting, returning
- # its callback to us as the first slot in tmp[0].
- _defer : (deferArgs) ->
- tmp = []
- @__defer tmp, deferArgs
- tmp[0]
-
- # flush everything left in the pipe
- flush : (autocb) ->
- while @n_out
- await (@cb = defer())
-
View
1 src/tamelib.coffee

0 comments on commit 02cecb9

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