mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-02-18 11:31:20 -05:00
putting in a special check for returns within array comprehensions -- not very nice
This commit is contained in:
@@ -49,7 +49,7 @@ _.each: obj, iterator, context =>
|
|||||||
try
|
try
|
||||||
return obj.forEach(iterator, context) if obj.forEach
|
return obj.forEach(iterator, context) if obj.forEach
|
||||||
if _.isArray(obj) or _.isArguments(obj)
|
if _.isArray(obj) or _.isArguments(obj)
|
||||||
return (iterator.call(context, obj[i], i, obj) for i in [0...obj.length])
|
return iterator.call(context, obj[i], i, obj) for i in [0...obj.length]
|
||||||
iterator.call(context, val, key, obj) for val, key in obj
|
iterator.call(context, val, key, obj) for val, key in obj
|
||||||
catch e
|
catch e
|
||||||
throw e if e isnt breaker
|
throw e if e isnt breaker
|
||||||
@@ -129,10 +129,9 @@ _.any: obj, iterator, context =>
|
|||||||
# based on '==='.
|
# based on '==='.
|
||||||
_.include: obj, target =>
|
_.include: obj, target =>
|
||||||
return _.indexOf(obj, target) isnt -1 if _.isArray(obj)
|
return _.indexOf(obj, target) isnt -1 if _.isArray(obj)
|
||||||
found: false
|
for val in obj
|
||||||
_.each(obj) value =>
|
return true if val is target
|
||||||
_.breakLoop() if found: value is target
|
false
|
||||||
found
|
|
||||||
|
|
||||||
# Invoke a method with arguments on every item in a collection.
|
# Invoke a method with arguments on every item in a collection.
|
||||||
_.invoke: obj, method =>
|
_.invoke: obj, method =>
|
||||||
@@ -247,7 +246,8 @@ _.zip: =>
|
|||||||
args: _.toArray(arguments)
|
args: _.toArray(arguments)
|
||||||
length: _.max(_.pluck(args, 'length'))
|
length: _.max(_.pluck(args, 'length'))
|
||||||
results: new Array(length)
|
results: new Array(length)
|
||||||
(results[i]: _.pluck(args, String(i))) for i in [0...length]
|
for i in [0...length]
|
||||||
|
results[i]: _.pluck(args, String(i))
|
||||||
results
|
results
|
||||||
|
|
||||||
# If the browser doesn't supply us with indexOf (I'm looking at you, MSIE),
|
# If the browser doesn't supply us with indexOf (I'm looking at you, MSIE),
|
||||||
@@ -326,7 +326,8 @@ _.compose: =>
|
|||||||
funcs: _.toArray(arguments)
|
funcs: _.toArray(arguments)
|
||||||
=>
|
=>
|
||||||
args: _.toArray(arguments)
|
args: _.toArray(arguments)
|
||||||
(args: [funcs[i].apply(this, args)]) for i in [(funcs.length - 1)..0]
|
for i in [(funcs.length - 1)..0]
|
||||||
|
args: [funcs[i].apply(this, args)]
|
||||||
args[0]
|
args[0]
|
||||||
|
|
||||||
# ------------------------- Object Functions: ----------------------------
|
# ------------------------- Object Functions: ----------------------------
|
||||||
@@ -346,7 +347,8 @@ _.functions: obj =>
|
|||||||
|
|
||||||
# Extend a given object with all of the properties in a source object.
|
# Extend a given object with all of the properties in a source object.
|
||||||
_.extend: destination, source =>
|
_.extend: destination, source =>
|
||||||
(destination[key]: val) for val, key in source
|
for val, key in source
|
||||||
|
destination[key]: val
|
||||||
destination
|
destination
|
||||||
|
|
||||||
# Create a (shallow-cloned) duplicate of an object.
|
# Create a (shallow-cloned) duplicate of an object.
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ module CoffeeScript
|
|||||||
class_eval "def statement_only?; true; end"
|
class_eval "def statement_only?; true; end"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.no_return
|
||||||
|
class_eval "def returns?; false; end"
|
||||||
|
end
|
||||||
|
|
||||||
def write(code)
|
def write(code)
|
||||||
puts "#{self.class.to_s}:\n#{@options.inspect}\n#{code}\n\n" if ENV['VERBOSE']
|
puts "#{self.class.to_s}:\n#{@options.inspect}\n#{code}\n\n" if ENV['VERBOSE']
|
||||||
code
|
code
|
||||||
@@ -40,6 +44,10 @@ module CoffeeScript
|
|||||||
"(function() {\n#{compile_node(o.merge(:return => true))}\n#{indent}})()"
|
"(function() {\n#{compile_node(o.merge(:return => true))}\n#{indent}})()"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def returns?
|
||||||
|
children.any? {|node| node && node.returns? }
|
||||||
|
end
|
||||||
|
|
||||||
# Default implementations of the common node methods.
|
# Default implementations of the common node methods.
|
||||||
def unwrap; self; end
|
def unwrap; self; end
|
||||||
def statement?; false; end
|
def statement?; false; end
|
||||||
@@ -50,6 +58,7 @@ module CoffeeScript
|
|||||||
class Expressions < Node
|
class Expressions < Node
|
||||||
statement
|
statement
|
||||||
attr_reader :expressions
|
attr_reader :expressions
|
||||||
|
alias_method :children, :expressions
|
||||||
|
|
||||||
STRIP_TRAILING_WHITESPACE = /\s+$/
|
STRIP_TRAILING_WHITESPACE = /\s+$/
|
||||||
|
|
||||||
@@ -132,6 +141,7 @@ module CoffeeScript
|
|||||||
# Literals are static values that have a Ruby representation, eg.: a string, a number,
|
# Literals are static values that have a Ruby representation, eg.: a string, a number,
|
||||||
# true, false, nil, etc.
|
# true, false, nil, etc.
|
||||||
class LiteralNode < Node
|
class LiteralNode < Node
|
||||||
|
no_return
|
||||||
STATEMENTS = ['break', 'continue']
|
STATEMENTS = ['break', 'continue']
|
||||||
|
|
||||||
attr_reader :value
|
attr_reader :value
|
||||||
@@ -162,6 +172,10 @@ module CoffeeScript
|
|||||||
@expression = expression
|
@expression = expression
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def returns?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
def compile_node(o)
|
def compile_node(o)
|
||||||
return write(@expression.compile(o.merge(:return => true))) if @expression.statement?
|
return write(@expression.compile(o.merge(:return => true))) if @expression.statement?
|
||||||
compiled = @expression.compile(o)
|
compiled = @expression.compile(o)
|
||||||
@@ -173,6 +187,7 @@ module CoffeeScript
|
|||||||
# same position.
|
# same position.
|
||||||
class CommentNode < Node
|
class CommentNode < Node
|
||||||
statement_only
|
statement_only
|
||||||
|
no_return
|
||||||
|
|
||||||
def initialize(lines)
|
def initialize(lines)
|
||||||
@lines = lines.value
|
@lines = lines.value
|
||||||
@@ -189,6 +204,7 @@ module CoffeeScript
|
|||||||
# Node for a function invocation. Takes care of converting super() calls into
|
# Node for a function invocation. Takes care of converting super() calls into
|
||||||
# calls against the prototype's function of the same name.
|
# calls against the prototype's function of the same name.
|
||||||
class CallNode < Node
|
class CallNode < Node
|
||||||
|
no_return
|
||||||
attr_reader :variable, :arguments
|
attr_reader :variable, :arguments
|
||||||
|
|
||||||
def initialize(variable, arguments=[])
|
def initialize(variable, arguments=[])
|
||||||
@@ -245,6 +261,7 @@ module CoffeeScript
|
|||||||
# After goog.inherits from the Closure Library.
|
# After goog.inherits from the Closure Library.
|
||||||
class ExtendsNode < Node
|
class ExtendsNode < Node
|
||||||
statement
|
statement
|
||||||
|
no_return
|
||||||
attr_reader :sub_object, :super_object
|
attr_reader :sub_object, :super_object
|
||||||
|
|
||||||
def initialize(sub_object, super_object)
|
def initialize(sub_object, super_object)
|
||||||
@@ -262,6 +279,7 @@ module CoffeeScript
|
|||||||
|
|
||||||
# A value, indexed or dotted into, or vanilla.
|
# A value, indexed or dotted into, or vanilla.
|
||||||
class ValueNode < Node
|
class ValueNode < Node
|
||||||
|
no_return
|
||||||
attr_reader :literal, :properties, :last, :source
|
attr_reader :literal, :properties, :last, :source
|
||||||
|
|
||||||
def initialize(literal, properties=[])
|
def initialize(literal, properties=[])
|
||||||
@@ -295,6 +313,7 @@ module CoffeeScript
|
|||||||
|
|
||||||
# A dotted accessor into a part of a value.
|
# A dotted accessor into a part of a value.
|
||||||
class AccessorNode < Node
|
class AccessorNode < Node
|
||||||
|
no_return
|
||||||
attr_reader :name
|
attr_reader :name
|
||||||
|
|
||||||
def initialize(name)
|
def initialize(name)
|
||||||
@@ -308,6 +327,7 @@ module CoffeeScript
|
|||||||
|
|
||||||
# An indexed accessor into a part of an array or object.
|
# An indexed accessor into a part of an array or object.
|
||||||
class IndexNode < Node
|
class IndexNode < Node
|
||||||
|
no_return
|
||||||
attr_reader :index
|
attr_reader :index
|
||||||
|
|
||||||
def initialize(index)
|
def initialize(index)
|
||||||
@@ -322,6 +342,7 @@ module CoffeeScript
|
|||||||
# A range literal. Ranges can be used to extract portions (slices) of arrays,
|
# A range literal. Ranges can be used to extract portions (slices) of arrays,
|
||||||
# or to specify a range for array comprehensions.
|
# or to specify a range for array comprehensions.
|
||||||
class RangeNode < Node
|
class RangeNode < Node
|
||||||
|
no_return
|
||||||
attr_reader :from, :to
|
attr_reader :from, :to
|
||||||
|
|
||||||
def initialize(from, to, exclusive=false)
|
def initialize(from, to, exclusive=false)
|
||||||
@@ -363,6 +384,7 @@ module CoffeeScript
|
|||||||
# specifies the index of the end of the slice (just like the first parameter)
|
# specifies the index of the end of the slice (just like the first parameter)
|
||||||
# is the index of the beginning.
|
# is the index of the beginning.
|
||||||
class SliceNode < Node
|
class SliceNode < Node
|
||||||
|
no_return
|
||||||
attr_reader :range
|
attr_reader :range
|
||||||
|
|
||||||
def initialize(range)
|
def initialize(range)
|
||||||
@@ -388,6 +410,10 @@ module CoffeeScript
|
|||||||
@variable, @value, @context = variable, value, context
|
@variable, @value, @context = variable, value, context
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def children
|
||||||
|
[@value]
|
||||||
|
end
|
||||||
|
|
||||||
def compile_node(o)
|
def compile_node(o)
|
||||||
return compile_splice(o) if @variable.properties.last.is_a?(SliceNode)
|
return compile_splice(o) if @variable.properties.last.is_a?(SliceNode)
|
||||||
name = @variable.compile(o)
|
name = @variable.compile(o)
|
||||||
@@ -433,6 +459,10 @@ module CoffeeScript
|
|||||||
@operator = CONVERSIONS[operator.to_sym] || operator
|
@operator = CONVERSIONS[operator.to_sym] || operator
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def children
|
||||||
|
[@first, @second]
|
||||||
|
end
|
||||||
|
|
||||||
def unary?
|
def unary?
|
||||||
@second.nil?
|
@second.nil?
|
||||||
end
|
end
|
||||||
@@ -459,6 +489,7 @@ module CoffeeScript
|
|||||||
|
|
||||||
# A function definition. The only node that creates a new Scope.
|
# A function definition. The only node that creates a new Scope.
|
||||||
class CodeNode < Node
|
class CodeNode < Node
|
||||||
|
no_return
|
||||||
attr_reader :params, :body
|
attr_reader :params, :body
|
||||||
|
|
||||||
def initialize(params, body)
|
def initialize(params, body)
|
||||||
@@ -489,6 +520,7 @@ module CoffeeScript
|
|||||||
|
|
||||||
# A parameter splat in a function definition.
|
# A parameter splat in a function definition.
|
||||||
class ParamSplatNode < Node
|
class ParamSplatNode < Node
|
||||||
|
no_return
|
||||||
attr_accessor :index
|
attr_accessor :index
|
||||||
attr_reader :name
|
attr_reader :name
|
||||||
|
|
||||||
@@ -503,6 +535,7 @@ module CoffeeScript
|
|||||||
end
|
end
|
||||||
|
|
||||||
class ArgSplatNode < Node
|
class ArgSplatNode < Node
|
||||||
|
no_return
|
||||||
attr_reader :value
|
attr_reader :value
|
||||||
|
|
||||||
def initialize(value)
|
def initialize(value)
|
||||||
@@ -517,6 +550,7 @@ module CoffeeScript
|
|||||||
|
|
||||||
# An object literal.
|
# An object literal.
|
||||||
class ObjectNode < Node
|
class ObjectNode < Node
|
||||||
|
no_return
|
||||||
attr_reader :properties
|
attr_reader :properties
|
||||||
|
|
||||||
def initialize(properties = [])
|
def initialize(properties = [])
|
||||||
@@ -544,6 +578,7 @@ module CoffeeScript
|
|||||||
|
|
||||||
# An array literal.
|
# An array literal.
|
||||||
class ArrayNode < Node
|
class ArrayNode < Node
|
||||||
|
no_return
|
||||||
attr_reader :objects
|
attr_reader :objects
|
||||||
|
|
||||||
def initialize(objects=[])
|
def initialize(objects=[])
|
||||||
@@ -574,6 +609,10 @@ module CoffeeScript
|
|||||||
@condition, @body = condition, body
|
@condition, @body = condition, body
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def children
|
||||||
|
[@body]
|
||||||
|
end
|
||||||
|
|
||||||
def compile_node(o)
|
def compile_node(o)
|
||||||
returns = o.delete(:return)
|
returns = o.delete(:return)
|
||||||
indent = o[:indent]
|
indent = o[:indent]
|
||||||
@@ -601,6 +640,10 @@ module CoffeeScript
|
|||||||
@step = source[:step]
|
@step = source[:step]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def children
|
||||||
|
[@body]
|
||||||
|
end
|
||||||
|
|
||||||
def compile_node(o)
|
def compile_node(o)
|
||||||
range = @source.is_a?(RangeNode)
|
range = @source.is_a?(RangeNode)
|
||||||
scope = o[:scope]
|
scope = o[:scope]
|
||||||
@@ -629,10 +672,12 @@ module CoffeeScript
|
|||||||
set_result = "#{rvar} = [];\n#{o[:indent]}"
|
set_result = "#{rvar} = [];\n#{o[:indent]}"
|
||||||
return_result = rvar
|
return_result = rvar
|
||||||
temp_var = ValueNode.new(LiteralNode.new(tvar))
|
temp_var = ValueNode.new(LiteralNode.new(tvar))
|
||||||
body = Expressions.wrap(
|
unless @body.returns?
|
||||||
AssignNode.new(temp_var, @body.unwrap),
|
body = Expressions.wrap(
|
||||||
CallNode.new(ValueNode.new(LiteralNode.new(rvar), [AccessorNode.new('push')]), [temp_var])
|
AssignNode.new(temp_var, @body.unwrap),
|
||||||
)
|
CallNode.new(ValueNode.new(LiteralNode.new(rvar), [AccessorNode.new('push')]), [temp_var])
|
||||||
|
)
|
||||||
|
end
|
||||||
if o[:return]
|
if o[:return]
|
||||||
return_result = "return #{return_result}" if o[:return]
|
return_result = "return #{return_result}" if o[:return]
|
||||||
o.delete(:return)
|
o.delete(:return)
|
||||||
@@ -657,6 +702,10 @@ module CoffeeScript
|
|||||||
@try, @error, @recovery, @finally = try, error, recovery, finally
|
@try, @error, @recovery, @finally = try, error, recovery, finally
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def children
|
||||||
|
[@try, @recovery, @finally]
|
||||||
|
end
|
||||||
|
|
||||||
def compile_node(o)
|
def compile_node(o)
|
||||||
indent = o[:indent]
|
indent = o[:indent]
|
||||||
o[:indent] += TAB
|
o[:indent] += TAB
|
||||||
@@ -670,6 +719,7 @@ module CoffeeScript
|
|||||||
|
|
||||||
# Throw an exception.
|
# Throw an exception.
|
||||||
class ThrowNode < Node
|
class ThrowNode < Node
|
||||||
|
no_return
|
||||||
statement_only
|
statement_only
|
||||||
|
|
||||||
attr_reader :expression
|
attr_reader :expression
|
||||||
@@ -685,6 +735,7 @@ module CoffeeScript
|
|||||||
|
|
||||||
# Check an expression for existence (meaning not null or undefined).
|
# Check an expression for existence (meaning not null or undefined).
|
||||||
class ExistenceNode < Node
|
class ExistenceNode < Node
|
||||||
|
no_return
|
||||||
attr_reader :expression
|
attr_reader :expression
|
||||||
|
|
||||||
def initialize(expression)
|
def initialize(expression)
|
||||||
@@ -708,6 +759,10 @@ module CoffeeScript
|
|||||||
@line = line
|
@line = line
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def children
|
||||||
|
[@expressions]
|
||||||
|
end
|
||||||
|
|
||||||
def compile_node(o)
|
def compile_node(o)
|
||||||
compiled = @expressions.compile(o)
|
compiled = @expressions.compile(o)
|
||||||
compiled = compiled[0...-1] if compiled[-1..-1] == ';'
|
compiled = compiled[0...-1] if compiled[-1..-1] == ';'
|
||||||
@@ -730,6 +785,10 @@ module CoffeeScript
|
|||||||
@condition = OpNode.new("!", ParentheticalNode.new(@condition)) if @tags[:invert]
|
@condition = OpNode.new("!", ParentheticalNode.new(@condition)) if @tags[:invert]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def children
|
||||||
|
[@body, @else_body]
|
||||||
|
end
|
||||||
|
|
||||||
def <<(else_body)
|
def <<(else_body)
|
||||||
eb = else_body.unwrap
|
eb = else_body.unwrap
|
||||||
@else_body ? @else_body << eb : @else_body = eb
|
@else_body ? @else_body << eb : @else_body = eb
|
||||||
|
|||||||
Reference in New Issue
Block a user