def process_call exp
return exp if process_call_defn? exp
target_var = exp.target
target_var &&= target_var.deep_clone
if exp.node_type == :safe_call
exp.node_type = :call
end
if exp.method == :[]
return process_bracket_call exp
else
exp = process_default exp
end
unless call? exp
return exp
end
target = exp.target
method = exp.method
first_arg = exp.first_arg
if method == :send or method == :try
collapse_send_call exp, first_arg
end
if node_type? target, :or and [:+, :-, :*, :/].include? method
res = process_or_simple_operation(exp)
return res if res
elsif target == ARRAY_CONST and method == :new
return Sexp.new(:array, *exp.args)
elsif target == HASH_CONST and method == :new and first_arg.nil? and !node_type?(@exp_context.last, :iter)
return Sexp.new(:hash)
elsif exp == RAILS_TEST
return Sexp.new(:false)
end
case method
when :+
if array? target and array? first_arg
exp = join_arrays(target, first_arg, exp)
elsif string? first_arg
exp = join_strings(target, first_arg, exp)
elsif number? first_arg
exp = math_op(:+, target, first_arg, exp)
end
when :-, :*, :/
exp = math_op(method, target, first_arg, exp)
when :[]
if array? target
exp = process_array_access(target, exp.args, exp)
elsif hash? target
exp = process_hash_access(target, first_arg, exp)
end
when :merge!, :update
if hash? target and hash? first_arg
target = process_hash_merge! target, first_arg
env[target_var] = target
return target
end
when :merge
if hash? target and hash? first_arg
return process_hash_merge(target, first_arg)
end
when :<<
if string? target and string? first_arg
target.value << first_arg.value
env[target_var] = target
return target
elsif string? target and string_interp? first_arg
exp = Sexp.new(:dstr, target.value + first_arg[1]).concat(first_arg[2..-1])
env[target_var] = exp
elsif string? first_arg and string_interp? target
if string? target.last
target.last.value << first_arg.value
elsif target.last.is_a? String
target.last << first_arg.value
else
target << first_arg
end
env[target_var] = target
return first_arg
elsif array? target
target << first_arg
env[target_var] = target
return target
else
target = find_push_target(target_var)
env[target] = exp unless target.nil?
end
when :first
if array? target and first_arg.nil? and sexp? target[1]
exp = target[1]
end
when :freeze
unless target.nil?
exp = target
end
when :join
if array? target and target.length > 2 and (string? first_arg or first_arg.nil?)
exp = process_array_join(target, first_arg)
end
end
exp
end