class PowNode < ContainerNode

    include BinaryNode

    def initialize(lhs, rhs)
	@lhs, @rhs = lhs, rhs
	raise TypeError unless NumberNode === @rhs
    end

    def to_s
	lhs = @lhs.to_s
	case lhs
	when /\d$/, /[\d\.]/
	    lhs = "(#{lhs})"
	end
	rhs = @rhs.to_s
        if rhs == '1'
	    lhs
	else
	    rhs = "^(#{rhs})" if (/\./ =~ rhs)
	    lhs + rhs
	end
    end

    attr_reader :lhs, :rhs
    alias :power :rhs

    def pow_eval(other)
	case other
	when NumberNode
	    PowNode.new(@lhs, @rhs.mul_eval(other))
	else
	    super(other)
	end
    end

    def flatten2
	x = @lhs.flatten2
	case x
	when NumberNode
	    a = @lhs.pow_eval(@rhs)
	when TerminalNode
	    a = self
	when PowNode
	    a = PowNode.new(x.lhs, x.rhs.mul_eval(@rhs))
	when MulNode, MultiNode
	    a = MultiNode.new()
	    for gc in x
		a.append(gc.pow_eval(@rhs))
	    end
	else
	    raise "internal error"
	end
	return a
    end

    def name
	case @lhs
	when NumberNode, NameNode
	    @lhs.name
	else
	    raise "internal error"
	end
    end

    def value
	case @lhs
	when NumberNode
	    Units::pow_f(@lhs.value, @rhs.value)
	else
	    raise(format('%s#value: internal error', self.class.to_s))
	end
    end

    def mul_eval(another)
	raise "internal error (#{name}, #{another.name})" if name != another.name
	case @lhs
	when NumberNode
	    NumberNode.new(Units::pow_f(@lhs.value, @rhs.value) * another.value)
	else
	    self.class.new(@lhs, @rhs.add_eval(another.power))
	end
    end

    def sort
	case @lhs
	when NumberNode
	    NumberNode.new(Units::pow_f(@lhs.value, @rhs.value))
	else
	    self
	end
    end

    def factor
	Units::pow_f(@lhs.factor, @rhs.value)
    end

end
