1//  Copyright (c) 2014 Couchbase, Inc.
2//  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
3//  except in compliance with the License. You may obtain a copy of the License at
4//    http://www.apache.org/licenses/LICENSE-2.0
5//  Unless required by applicable law or agreed to in writing, software distributed under the
6//  License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
7//  either express or implied. See the License for the specific language governing permissions
8//  and limitations under the License.
9
10package expression
11
12import (
13	"github.com/couchbase/query/value"
14)
15
16/*
17Represents multiplication for arithmetic expressions. Type Mult is a
18struct that implements CommutativeFunctionBase.
19*/
20type Mult struct {
21	CommutativeFunctionBase
22}
23
24func NewMult(operands ...Expression) Function {
25	rv := &Mult{
26		*NewCommutativeFunctionBase("mult", operands...),
27	}
28
29	rv.expr = rv
30	return rv
31}
32
33/*
34Visitor pattern.
35*/
36func (this *Mult) Accept(visitor Visitor) (interface{}, error) {
37	return visitor.VisitMult(this)
38}
39
40func (this *Mult) Type() value.Type { return value.NUMBER }
41
42func (this *Mult) Evaluate(item value.Value, context Context) (value.Value, error) {
43	return this.Eval(this, item, context)
44}
45
46/*
47Range over input arguments, if the type is a number multiply it to
48the product. If the value is missing, return a missing value. For
49all other types return a null value. Return the final product.
50*/
51func (this *Mult) Apply(context Context, args ...value.Value) (value.Value, error) {
52	null := false
53	prod := value.ONE_NUMBER
54
55	for _, arg := range args {
56		if !null && arg.Type() == value.NUMBER {
57			prod = prod.Mult(value.AsNumberValue(arg))
58		} else if arg.Type() == value.MISSING {
59			return value.MISSING_VALUE, nil
60		} else {
61			null = true
62		}
63	}
64
65	if null {
66		return value.NULL_VALUE, nil
67	}
68
69	return prod, nil
70}
71
72/*
73Factory method pattern.
74*/
75func (this *Mult) Constructor() FunctionConstructor {
76	return NewMult
77}
78