// Function func (this *JSConverter) VisitFunction(expr expression.Function) (interface{}, error) { var buf bytes.Buffer functionExpr := &funcExpr{operands: list.New()} buf.WriteString("(") var nopush bool var pushOperands bool switch strings.ToLower(expr.Name()) { case "lower": functionExpr.name = ".toLowerCase()" this.stack.Push(functionExpr) case "upper": functionExpr.name = ".toUpperCase()" this.stack.Push(functionExpr) case "length": functionExpr.name = ".length" this.stack.Push(functionExpr) case "str_to_millis": fallthrough case "millis": nopush = true buf.WriteString("Date.parse(") case "contains": functionExpr.name = ".indexOf(" this.stack.Push(functionExpr) pushOperands = true case "substr": functionExpr.name = ".substring(" this.stack.Push(functionExpr) pushOperands = true case "now_millis": buf.WriteString("Date.now().toString()") default: nopush = true buf.WriteString(expr.Name()) buf.WriteString("(") } var firstOp expression.Expression for i, op := range expr.Operands() { if pushOperands == true { if i == 0 { firstOp = op continue } else { functionExpr.operands.PushBack(op) } } else { if i > 0 { buf.WriteString(", ") } if op == nil { buf.WriteString("*") // for count(*) } else { buf.WriteString(this.Visit(op)) } } } if firstOp != nil { buf.WriteString(this.Visit(firstOp)) } if nopush == true { buf.WriteString("))") } else { buf.WriteString(")") } return buf.String(), nil }