Skip to content

Commit

Permalink
while loops can now be used as expressions -- they return an array co…
Browse files Browse the repository at this point in the history
…ntaining the computed result of each iteration.
  • Loading branch information
jashkenas committed Jan 14, 2010
1 parent 1e7d638 commit bb9fdd3
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 10 deletions.
6 changes: 3 additions & 3 deletions examples/documents.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ dc.model.Document: dc.Model.extend({
# document by binding to Metadata, instead of on-the-fly.
metadata: =>
docId: this.id
_.select(Metadata.models(), (meta =>
_.any(meta.get('instances'), instance =>
_.select(Metadata.models(), (meta =>
_.any(meta.get('instances'), instance =>
instance.document_id is docId)))

bookmark: pageNumber =>
Expand Down Expand Up @@ -60,7 +60,7 @@ dc.model.DocumentSet: dc.model.RESTfulSet.extend({
# change their selected state.
_onModelEvent: e, model =>
this.base(e, model)
fire: e == dc.Model.CHANGED and model.hasChanged('selected')
fire: e is dc.Model.CHANGED and model.hasChanged('selected')
if fire then _.defer(_(this.fire).bind(this, this.SELECTION_CHANGED, this))

})
Expand Down
1 change: 1 addition & 0 deletions lib/coffee_script/grammar.y
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ rule
While:
WHILE Expression Block { result = WhileNode.new(val[1], val[2]) }
| WHILE Expression { result = WhileNode.new(val[1], nil) }
| Expression WHILE Expression { result = WhileNode.new(val[2], Expressions.wrap(val[0])) }
;

# Array comprehensions, including guard and current index.
Expand Down
30 changes: 24 additions & 6 deletions lib/coffee_script/nodes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ def write(code)
def compile(o={})
@options = o.dup
@indent = o[:indent]
top = self.is_a?(ForNode) ? @options[:top] : @options.delete(:top)
closure = statement? && !statement_only? && !top && !@options[:return]
closure ? compile_closure(@options) : compile_node(@options)
top = self.top_sensitive? ? @options[:top] : @options.delete(:top)
closure = statement? && !statement_only? && !top && !@options[:return]
closure ? compile_closure(@options) : compile_node(@options)
end

def compile_closure(o={})
Expand All @@ -56,6 +56,7 @@ def idt(tabs=0)
def unwrap; self; end
def statement?; false; end
def statement_only?; false; end
def top_sensitive?; false; end
end

# A collection of nodes, each one representing an expression.
Expand Down Expand Up @@ -668,14 +669,27 @@ def initialize(condition, body)
@condition, @body = condition, body
end

def top_sensitive?
true
end

def compile_node(o)
returns = o.delete(:return)
top = o.delete(:top) && !returns
o[:indent] = idt(1)
o[:top] = true
cond = @condition.compile(o)
post = returns ? "\n#{idt}return null;" : ''
return write("#{idt}while (#{cond}) null;#{post}") if @body.nil?
write("#{idt}while (#{cond}) {\n#{@body.compile(o)}\n#{idt}}#{post}")
set = ''
if !top
rvar = o[:scope].free_variable
set = "#{idt}#{rvar} = [];\n"
@body = Expressions.wrap(CallNode.new(
ValueNode.new(LiteralNode.new(rvar), [AccessorNode.new('push')]), [@body.unwrap]
))
end
post = returns ? "\n#{idt}return #{rvar};" : ''
return write("#{set}#{idt}while (#{cond}) null;#{post}") if @body.nil?
write("#{set}#{idt}while (#{cond}) {\n#{@body.compile(o)}\n#{idt}}#{post}")
end
end

Expand All @@ -697,6 +711,10 @@ def initialize(body, source, name, index=nil)
@name, @index = @index, @name if @object
end

def top_sensitive?
true
end

def compile_node(o)
top_level = o.delete(:top) && !o[:return]
range = @source.is_a?(ValueNode) && @source.base.is_a?(RangeNode) && @source.properties.empty?
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/execution/test_everything.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ func: =>

c.single: c.list[1..1][0]

print(func() == '-')
print(func() is '-')
17 changes: 17 additions & 0 deletions test/fixtures/execution/test_while.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
i: 100
while i -= 1

print(i is 0)


i: 5
list: while i -= 1
i * 2

print(list.join(' ') is "8 6 4 2")


i: 5
list: (i * 3 while i -= 1)

print(list.join(' ') is "12 9 6 3")

0 comments on commit bb9fdd3

Please sign in to comment.