def evaluate env = nil
if size > 2 or !terminal?
evaled = self.class.new(map {|e| e.respond_to?(:evaluate) ? e.evaluate(env) : e }, parent, delimiter)
unit = evaled.literals.map do |node|
node.unit
end.compact.uniq.tap do |ary|
raise MixedUnitsError, evaled * ' ' if ary.size > 1 && !evaled.operators.empty?
end.join
entity = evaled.literals.find {|e| e.unit == unit } || evaled.literals.first || evaled.entities.first
result = evaled.operators.empty?? evaled : eval(evaled.to_ruby.join)
case result
when Entity then result
when Expression then result.one?? result.first : self.class.new(result, parent, delimiter)
else entity.class.new(result, *(unit if entity.class == Node::Number))
end
elsif size == 1
if first.is_a? Variable
first.evaluate(env)
elsif first.is_a? Function
first.evaluate(env)
else
first
end
else
self
end
end