86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
# File 'lib/red/nodes/definition_nodes.rb', line 86
def initialize(function_name_sexp, scope_sexp, options)
return if @@red_import && !@@red_methods.include?(function_name_sexp)
function = (METHOD_ESCAPE[function_name_sexp] || function_name_sexp).red!
@@red_function = function
block_sexp = scope_sexp.assoc(:block)
block_arg_sexp = block_sexp.delete(block_sexp.assoc(:block_arg)) || ([:block_arg, :_block] if block_sexp.flatten.include?(:yield))
@@red_block_arg = block_arg_sexp.last if block_arg_sexp
argument_sexps = block_sexp.assoc(:args)[1..-1] || []
defaults_sexp = argument_sexps.delete(argument_sexps.assoc(:block))
splat_arg = argument_sexps.pop.to_s[1..-1] if argument_sexps.last && argument_sexps.last.to_s.include?('*')
argument_sexps += [block_arg_sexp.last] if block_arg_sexp
args_array = argument_sexps.map {|argument| argument.red! }
maximum_args = args_array.length - (block_arg_sexp ? 1 : 0)
minimum_args = maximum_args - (defaults_sexp ? defaults_sexp.flatten.select {|x| x == :lasgn}.length : 0)
splatten_args = "for(var l=arguments.length,i=#{argument_sexps.size},#{splat_arg}=[];i<l;++i){#{splat_arg}.push(arguments[i]);}" if splat_arg && !block_arg_sexp
splat_block = "for(var l=arguments.length,bg=m$block_given_bool(arguments[l-1]),l=bg?l-1:l,i=#{argument_sexps.size - 1},#{splat_arg}=[];i<l;++i){#{splat_arg}.push(arguments[i]);};var #{block_arg_sexp.last rescue :_block}=(bg?c$Proc.m$new(arguments[arguments.length-1]):nil)" if splat_arg && block_arg_sexp
block_arg = "var z=arguments[arguments.length-1],bg=m$block_given_bool(z),#{block_arg_sexp.last rescue :_block}=bg?c$Proc.m$new(z):nil" if block_arg_sexp && !splat_arg
args_checker = "$a(%s,%s,arguments,%s)" % [minimum_args, (splat_arg ? -1 : maximum_args), (splat_block || block_arg ? "bg?1:0" : "arguments[arguments.length-1]&&arguments[arguments.length-1].__block__?1:0")] if Red.debug && ![:new, :initialize].include?(function_name_sexp)
defaults = defaults_sexp.red!(:as_argument_default => true) if defaults_sexp
arguments = args_array.join(",")
scope = scope_sexp.red!(:force_return => function != 'initialize')
contents = [(splatten_args || splat_block || block_arg), args_checker, defaults, scope].compact.join(";")
if options[:as_class_eval]
string = "_.m$%s=function(%s){%s;}"
else
string = "m$%s=function(%s){%s;}"
end
self << string % [function, arguments, contents]
@@red_block_arg = nil
@@red_function = nil
end
|