{
'var' => ->(v, d) do
if !(d.is_a?(Hash) || d.is_a?(Array))
d
else
if v == [JSONLogic::ITERABLE_KEY]
if d.is_a?(Array)
d
else
d[JSONLogic::ITERABLE_KEY]
end
else
d.deep_fetch(*v)
end
end
end,
'missing' => ->(v, d) { v.select { |val| d.deep_fetch(val).nil? } },
'missing_some' => ->(v, d) {
present = v[1] & d.keys
present.size >= v[0] ? [] : LAMBDAS['missing'].call(v[1], d)
},
'some' => -> (v,d) do
return false unless v[0].is_a?(Array)
v[0].any? do |val|
interpolated_block(v[1], val).truthy?
end
end,
'filter' => -> (v,d) do
return [] unless v[0].is_a?(Array)
v[0].select do |val|
interpolated_block(v[1], val).truthy?
end
end,
'substr' => -> (v,d) do
limit = -1
if v[2]
if v[2] < 0
limit = v[2] - 1
else
limit = v[1] + v[2] - 1
end
end
v[0][v[1]..limit]
end,
'none' => -> (v,d) do
v[0].each do |val|
this_val_satisfies_condition = interpolated_block(v[1], val)
if this_val_satisfies_condition
return false
end
end
return true
end,
'all' => -> (v,d) do
return false if v[0].empty?
v[0].all? do |val|
interpolated_block(v[1], val)
end
end,
'reduce' => -> (v,d) do
return v[2] unless v[0].is_a?(Array)
v[0].inject(v[2]) { |acc, val| interpolated_block(v[1], { "current": val, "accumulator": acc })}
end,
'map' => -> (v,d) do
return [] unless v[0].is_a?(Array)
v[0].map do |val|
interpolated_block(v[1], val)
end
end,
'if' => ->(v, d) {
v.each_slice(2) do |condition, value|
return condition if value.nil?
return value if condition.truthy?
end
},
'==' => ->(v, d) { v[0].to_s == v[1].to_s },
'===' => ->(v, d) { v[0] == v[1] },
'!=' => ->(v, d) { v[0].to_s != v[1].to_s },
'!==' => ->(v, d) { v[0] != v[1] },
'!' => ->(v, d) { v[0].falsy? },
'!!' => ->(v, d) { v[0].truthy? },
'or' => ->(v, d) { v.find(&:truthy?) || v.last },
'and' => ->(v, d) {
result = v.find(&:falsy?)
result.nil? ? v.last : result
},
'?:' => ->(v, d) { LAMBDAS['if'].call(v, d) },
'>' => ->(v, d) { v.map(&:to_f).each_cons(2).all? { |i, j| i > j } },
'>=' => ->(v, d) { v.map(&:to_f).each_cons(2).all? { |i, j| i >= j } },
'<' => ->(v, d) { v.map(&:to_f).each_cons(2).all? { |i, j| i < j } },
'<=' => ->(v, d) { v.map(&:to_f).each_cons(2).all? { |i, j| i <= j } },
'max' => ->(v, d) { v.map(&:to_f).max },
'min' => ->(v, d) { v.map(&:to_f).min },
'+' => ->(v, d) { v.map(&:to_f).reduce(:+) },
'-' => ->(v, d) { v.map!(&:to_f); v.size == 1 ? -v.first : v.reduce(:-) },
'*' => ->(v, d) { v.map(&:to_f).reduce(:*) },
'/' => ->(v, d) { v.map(&:to_f).reduce(:/) },
'%' => ->(v, d) { v.map(&:to_i).reduce(:%) },
'^' => ->(v, d) { v.map(&:to_f).reduce(:**) },
'merge' => ->(v, d) { v.flatten },
'in' => ->(v, d) { interpolated_block(v[1], d).include? v[0] },
'cat' => ->(v, d) { v.map(&:to_s).join },
'log' => ->(v, d) { puts v }
}