mirror of
https://github.com/chaisql/chai.git
synced 2025-10-05 15:46:55 +08:00
87 lines
2.1 KiB
Go
87 lines
2.1 KiB
Go
package functions
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/genjidb/genji/internal/expr"
|
|
)
|
|
|
|
// variadicArity represents an unlimited number of arguments.
|
|
const variadicArity = -1
|
|
|
|
// A Definition transforms a list of expressions into a Function.
|
|
type Definition interface {
|
|
Name() string
|
|
String() string
|
|
Function(...expr.Expr) (expr.Function, error)
|
|
Arity() int
|
|
}
|
|
|
|
// Definitions table holds a map of definition, indexed by their names.
|
|
type Definitions map[string]Definition
|
|
|
|
// Packages represent a table of SQL functions grouped by their packages
|
|
type Packages map[string]Definitions
|
|
|
|
func DefaultPackages() Packages {
|
|
return Packages{
|
|
"": BuiltinDefinitions(),
|
|
"math": MathFunctions(),
|
|
"strings": StringsDefinitions(),
|
|
}
|
|
}
|
|
|
|
// GetFunc return a function definition by its package and name.
|
|
func (t Packages) GetFunc(pkg string, fname string) (Definition, error) {
|
|
fs, ok := t[pkg]
|
|
if !ok {
|
|
return nil, fmt.Errorf("no such package: %q", fname)
|
|
}
|
|
def, ok := fs[strings.ToLower(fname)]
|
|
if !ok {
|
|
if pkg == "" {
|
|
return nil, fmt.Errorf("no such function: %q", fname)
|
|
}
|
|
return nil, fmt.Errorf("no such function: %q.%q", pkg, fname)
|
|
}
|
|
return def, nil
|
|
}
|
|
|
|
// A definition is the most basic version of a function definition.
|
|
type definition struct {
|
|
name string
|
|
arity int
|
|
constructorFn func(...expr.Expr) (expr.Function, error)
|
|
}
|
|
|
|
func (fd *definition) Name() string {
|
|
return fd.name
|
|
}
|
|
|
|
func (fd *definition) Function(args ...expr.Expr) (expr.Function, error) {
|
|
if fd.arity == variadicArity && len(args) == 0 {
|
|
return nil, fmt.Errorf("%s() requires at least one argument", fd.name)
|
|
}
|
|
if fd.arity != variadicArity && (len(args) != fd.arity) {
|
|
return nil, fmt.Errorf("%s() takes %d argument(s), not %d", fd.name, fd.arity, len(args))
|
|
}
|
|
return fd.constructorFn(args...)
|
|
}
|
|
|
|
func (fd *definition) String() string {
|
|
arity := fd.arity
|
|
if arity < 0 {
|
|
arity = 0
|
|
}
|
|
args := make([]string, 0, arity)
|
|
for i := 0; i < arity; i++ {
|
|
args = append(args, fmt.Sprintf("arg%d", i+1))
|
|
}
|
|
return fmt.Sprintf("%s(%s)", fd.name, strings.Join(args, ", "))
|
|
}
|
|
|
|
func (fd *definition) Arity() int {
|
|
return fd.arity
|
|
}
|