module SPARQL; module Algebra
class Operator
##
# The SPARQL `if` function.
#
# [121] BuiltInCall ::= ... | 'IF' '(' Expression ',' Expression ',' Expression ')'
#
# @example SPARQL Grammar
# BASE
# PREFIX xsd:
# SELECT ?o (IF(lang(?o) = "ja", true, false) AS ?integer)
# WHERE { ?s ?p ?o }
#
# @example SSE
# (base
# (prefix ((xsd: ))
# (project (?o ?integer)
# (extend ((?integer (if (= (lang ?o) "ja") true false)))
# (bgp (triple ?s ?p ?o))))))
#
# @see https://www.w3.org/TR/sparql11-query/#func-if
class If < Operator::Ternary
include Evaluatable
NAME = :if
##
# The IF function form evaluates the first argument, interprets it as a effective boolean value, then returns the value of `expression2` if the EBV is true, otherwise it returns the value of `expression3`. Only one of `expression2` and `expression3` is evaluated. If evaluating the first argument raises an error, then an error is raised for the evaluation of the IF expression.
#
# @example
#
# IF(?x = 2, "yes", "no") #=> "yes"
# IF(bound(?y), "yes", "no") #=> "no"
# IF(?x=2, "yes", 1/?z) #=> "yes", the expression 1/?z is not evaluated
# IF(?x=1, "yes", 1/?z) #=> raises an error
# IF("2" > 1, "yes", "no") #=> raises an error
#
# Evaluates the first operand and returns the evaluation of either the second or third operands
#
# @param [RDF::Query::Solution] bindings
# a query solution containing zero or more variable bindings
# @return [RDF::Term]
# @raise [TypeError]
def evaluate(bindings, **options)
operand(0).evaluate(bindings, **options.merge(depth: options[:depth].to_i + 1)) == RDF::Literal::TRUE ?
operand(1).evaluate(bindings, **options.merge(depth: options[:depth].to_i + 1)) :
operand(2).evaluate(bindings, **options.merge(depth: options[:depth].to_i + 1))
rescue
raise TypeError
end
##
#
# Returns a partial SPARQL grammar for this operator.
#
# @return [String]
def to_sparql(**options)
"IF(" + operands.to_sparql(delimiter: ', ', **options) + ")"
end
end # If
end # Operator
end; end # SPARQL::Algebra