func operatorKind(operator ast.TokenType) string { switch { case ast.IsMathOperator(operator): return "math" case ast.IsCompOperator(operator): return "comparison" case ast.IsLogicalOperator(operator): return "logical" } // Actually, we shouldn't get here.. because this function is called only // after the operator validation! return "INVALID" }
// getCostantNodeType - Given a ast.Node we want to know it's return type // this method does exactly this, few examples: // *) StringNode -> ast.TString // *) UnaryNode -> we base the type by the node type func getConstantNodeType(n ast.Node) ast.ValueType { switch node := n.(type) { case *ast.NumberNode: if node.IsInt { return ast.TInt } if node.IsFloat { return ast.TFloat } case *ast.DurationNode: return ast.TDuration case *ast.StringNode: return ast.TString case *ast.BoolNode: return ast.TBool case *ast.RegexNode: return ast.TRegex case *ast.UnaryNode: // If this is comparison operator we know for sure the output must be boolean if node.Operator == ast.TokenNot { return ast.TBool } // Could be float int or duration if node.Operator == ast.TokenMinus { return getConstantNodeType(node.Node) } case *ast.BinaryNode: // Check first using only the operator if ast.IsCompOperator(node.Operator) || ast.IsLogicalOperator(node.Operator) { return ast.TBool } leftType := getConstantNodeType(node.Left) rightType := getConstantNodeType(node.Right) // Check known constant types return binaryConstantTypes[operationKey{operator: node.Operator, leftType: leftType, rightType: rightType}] case *ast.LambdaNode: return getConstantNodeType(node.Expression) } return ast.InvalidType }