Skip to content

Commit

Permalink
some progress --- got some loops working as we would expect, but stil…
Browse files Browse the repository at this point in the history
…l can't handle paren'ed awaits, something's up with that.
  • Loading branch information
maxtaco committed Jan 24, 2012
1 parent b8d3e72 commit a588590
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 33 deletions.
2 changes: 1 addition & 1 deletion clean
Expand Up @@ -3,6 +3,6 @@
rm lib/coffee-script/*.js rm lib/coffee-script/*.js
git checkout lib git checkout lib
./bin/cake build ./bin/cake build
./bin/cake build:parser #./bin/cake build:parser
./bin/cake build ./bin/cake build


62 changes: 47 additions & 15 deletions lib/coffee-script/nodes.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions lib/coffee-script/tame.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 22 additions & 8 deletions lib/coffee-script/tamelib.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

56 changes: 47 additions & 9 deletions src/nodes.coffee
Expand Up @@ -394,7 +394,7 @@ exports.Block = class Block extends Base
expr = @expressions[len] expr = @expressions[len]
if expr.isStatement() if expr.isStatement()
break break
if expr not instanceof Comment and expr not instanceof Return if expr not instanceof Comment and expr not instanceof Return
call.assignValue expr call.assignValue expr
@expressions[len] = call @expressions[len] = call
return return
Expand Down Expand Up @@ -1807,13 +1807,27 @@ exports.While = class While extends Base
tameWrap : (d) -> tameWrap : (d) ->
condition = d.condition condition = d.condition
body = d.body body = d.body
rvar = d.rvar
outStatements = [] outStatements = []

if rvar
rvar_value = new Value new Literal rvar


# Set up all of the IDs # Set up all of the IDs
top_id = new Value new Literal tame.const.t_while top_id = new Value new Literal tame.const.t_while
k_id = new Value new Literal tame.const.k k_id = new Value new Literal tame.const.k

# Break will just call the parent continuation, but in some
# cases, there will be a return value, so then we have to pass
# that back out. Hence the split below:
break_id = new Value new Literal tame.const.b_while break_id = new Value new Literal tame.const.b_while
break_assign = new Assign break_id, k_id, null, { tamelocal : yes } if rvar
break_expr = new Call k_id, [ rvar_value ]
break_block = new Block [ break_expr ]
break_body = new Code [], break_block, 'tamegen'
break_assign = new Assign break_id, break_body, null, { tamelocal : yes }
else
break_assign = new Assign break_id, k_id, null, { tamelocal : yes }


# The continue assignment is the increment at the end # The continue assignment is the increment at the end
# of the loop (if it's there), and also the recursive # of the loop (if it's there), and also the recursive
Expand All @@ -1824,29 +1838,49 @@ exports.While = class While extends Base
continue_body = new Code [], continue_block, 'tamegen' continue_body = new Code [], continue_block, 'tamegen'
continue_assign = new Assign continue_id, continue_body, null, { tamelocal : yes } continue_assign = new Assign continue_id, continue_body, null, { tamelocal : yes }


# Next is like continue, but it also squirrels away the return
# value, if required!
next_id = new Value new Literal tame.const.n_while
if rvar
next_arg = new Value new Literal tame.const.n_arg
f = rvar_value.copy()
f.add new Access new Value new Literal 'push'
call1 = new Call f, [ next_arg ]
call2 = new Call continue_id, []
next_block = new Block [ call1, call2 ]
next_body = new Code [ next_arg ], next_block, 'tamegen'
next_assign = new Assign next_id, next_body, null, { tamelocal : yes }
else
next_assign = new Assign next_id, continue_id

# The whole body is wrapped in an if, with the positive # The whole body is wrapped in an if, with the positive
# condition being the loop, and the negative condition # condition being the loop, and the negative condition
# being the break out of the loop # being the break out of the loop
cond = new If condition, body cond = new If condition, body
cond.addElse new Block [ new Call break_id, [] ] cond.addElse new Block [ new Call break_id, [] ]


# The top of the loop construct. # The top of the loop construct.
top_body = new Block [ break_assign, continue_assign, cond ] top_body = new Block [ break_assign, continue_assign, next_assign, cond ]
top_func = new Code [ k_id ], top_body, 'tamegen' top_func = new Code [ k_id ], top_body, 'tamegen'
top_assign = new Assign top_id, top_func, null, { tamelocal : yes } top_assign = new Assign top_id, top_func, null, { tamelocal : yes }
top_call = new Call top_id, [ k_id ] top_call = new Call top_id, [ k_id ]
top_statements = [] top_statements = []
top_statements = top_statements.concat d.init if d.init top_statements = top_statements.concat d.init if d.init
if rvar
rvar_init = new Assign rvar_value, new Arr
top_statements.push rvar_init
top_statements = top_statements.concat [ top_assign, top_call ] top_statements = top_statements.concat [ top_assign, top_call ]
top_block = new Block top_statements top_block = new Block top_statements


tameCallContinuation : -> tameCallContinuation : ->
k = new TameTailCall tame.const.c_while @body.tameThreadReturn new TameTailCall tame.const.n_while
@body.push k


compileTame: (o) -> compileTame: (o) ->
return null unless @tameNodeFlag return null unless @tameNodeFlag
b = @tameWrap { @condition, @body } opts = { @condition, @body }
if @returns
opts.rvar = o.scope.freeVariable 'results'
b = @tameWrap opts
return b.compile o return b.compile o


# The main difference from a JavaScript *while* is that the CoffeeScript # The main difference from a JavaScript *while* is that the CoffeeScript
Expand Down Expand Up @@ -2388,13 +2422,16 @@ exports.Existence = class Existence extends Base
exports.Parens = class Parens extends Base exports.Parens = class Parens extends Base
constructor: (@body) -> constructor: (@body) ->
super() super()
@body.parens = true


children: ['body'] children: ['body']


unwrap : -> @body unwrap : -> @body
isComplex : -> @body.isComplex() isComplex : -> @body.isComplex()


#tameWrapContinuation : YES
#tameCpsRotate: ->
# @body = b if (b = @tameCpsExprRotate @body)

compileNode: (o) -> compileNode: (o) ->
expr = @body.unwrap() expr = @body.unwrap()
if expr instanceof Value and expr.isAtomic() if expr instanceof Value and expr.isAtomic()
Expand Down Expand Up @@ -2513,7 +2550,8 @@ exports.For = class For extends While
a4 = new Assign @name, ref_val_copy a4 = new Assign @name, ref_val_copy
body.unshift a4 body.unshift a4


b = @tameWrap { condition, body, init, step } rvar = d.rvar
b = @tameWrap { condition, body, init, step, rvar }
b.compile o b.compile o


# Welcome to the hairiest method in all of CoffeeScript. Handles the inner # Welcome to the hairiest method in all of CoffeeScript. Handles the inner
Expand Down Expand Up @@ -2542,7 +2580,7 @@ exports.For = class For extends While
defPart = '' defPart = ''
idt1 = @tab + TAB idt1 = @tab + TAB


return code if code = @compileTame o, { ivar, stepvar, body } return code if code = @compileTame o, { ivar, stepvar, body, rvar }


if @range if @range
forPart = source.compile merge(o, {index: ivar, name, @step}) forPart = source.compile merge(o, {index: ivar, name, @step})
Expand Down
2 changes: 2 additions & 0 deletions src/tame.coffee
Expand Up @@ -15,6 +15,8 @@ exports.const =
b_while : "_break" b_while : "_break"
t_while : "_while" t_while : "_while"
c_while : "_continue" c_while : "_continue"
n_while : "_next"
n_arg : "__tame_next_arg"
defer_method : "defer" defer_method : "defer"
slot : "__slot" slot : "__slot"
assign_fn : "assign_fn" assign_fn : "assign_fn"
Expand Down
22 changes: 22 additions & 0 deletions test/tame.coffee
Expand Up @@ -444,3 +444,25 @@ atest 'nesting', (cb) ->
render = (x) -> x + x render = (x) -> x + x
y = render(await loadImage "test.png", defer _) y = render(await loadImage "test.png", defer _)
cb(y is (id + id), {}) cb(y is (id + id), {})

atest 'expressions + loops', (cb) ->
parrot = (n, cb) ->
await delay defer()
cb n
x = for i in [0..10]
await parrot i, defer _
y = while i--
await parrot i, defer _
z = (v + y[i] for v,i in x)
ok = true
for v in z
ok = false unless v == 9
cb(ok, {})

#atest 'expressions + loops', (cb) ->
# eat = (item, cb) ->
# await delay defer()
# cb item.length
# lunch = ((await eat food, defer _) for food in ['toast', 'wine', 'pea'])
# ok = (lunch[0] is 5 and lunch[1] is 4 and lunch[2] is 3)
# cb(ok, {})

0 comments on commit a588590

Please sign in to comment.