github.com/MontFerret/ferret@v0.18.0/pkg/compiler/namespace.go (about) 1 package compiler 2 3 import ( 4 "regexp" 5 "strings" 6 7 "github.com/pkg/errors" 8 9 "github.com/MontFerret/ferret/pkg/runtime/core" 10 ) 11 12 var fnNameValidation = regexp.MustCompile("^[a-zA-Z]+[a-zA-Z0-9_]*(::[a-zA-Z]+[a-zA-Z0-9_]*)*$") 13 14 const emptyNS = "" 15 const separator = "::" 16 17 type NamespaceContainer struct { 18 funcs *core.Functions 19 name string 20 } 21 22 func newRootNamespace() *NamespaceContainer { 23 ns := new(NamespaceContainer) 24 ns.funcs = core.NewFunctions() 25 26 return ns 27 } 28 29 func newNamespace(funcs *core.Functions, name string) *NamespaceContainer { 30 return &NamespaceContainer{funcs, strings.ToUpper(name)} 31 } 32 33 func (nc *NamespaceContainer) Namespace(name string) core.Namespace { 34 return newNamespace(nc.funcs, nc.makeFullName(name)) 35 } 36 37 func (nc *NamespaceContainer) MustRegisterFunction(name string, fun core.Function) { 38 if err := nc.RegisterFunction(name, fun); err != nil { 39 panic(err) 40 } 41 } 42 43 func (nc *NamespaceContainer) RegisterFunction(name string, fun core.Function) error { 44 nsName := nc.makeFullName(name) 45 46 _, exists := nc.funcs.Get(nsName) 47 48 if exists { 49 return errors.Errorf("function already exists: %s", name) 50 } 51 52 // validation the name 53 if strings.Contains(name, separator) { 54 return errors.Errorf("invalid function name: %s", name) 55 } 56 57 if !fnNameValidation.MatchString(nsName) { 58 return errors.Errorf("invalid function or namespace name: %s", nsName) 59 } 60 61 nc.funcs.Set(nsName, fun) 62 63 return nil 64 } 65 66 func (nc *NamespaceContainer) RemoveFunction(name string) { 67 nc.funcs.Unset(nc.makeFullName(name)) 68 } 69 70 func (nc *NamespaceContainer) MustRegisterFunctions(funcs *core.Functions) { 71 if err := nc.RegisterFunctions(funcs); err != nil { 72 panic(err) 73 } 74 } 75 76 func (nc *NamespaceContainer) RegisterFunctions(funcs *core.Functions) error { 77 for _, name := range funcs.Names() { 78 fun, _ := funcs.Get(name) 79 80 if err := nc.RegisterFunction(name, fun); err != nil { 81 return err 82 } 83 } 84 85 return nil 86 } 87 88 func (nc *NamespaceContainer) RegisteredFunctions() []string { 89 fnames := nc.funcs.Names() 90 res := make([]string, 0, len(fnames)) 91 92 // root namespace, return all functions 93 if nc.name == emptyNS { 94 res = append(res, fnames...) 95 } else { 96 nsPrefix := nc.name + separator 97 for _, k := range fnames { 98 if strings.HasPrefix(k, nsPrefix) { 99 res = append(res, k) 100 } 101 } 102 } 103 104 return res 105 } 106 107 func (nc *NamespaceContainer) makeFullName(name string) string { 108 if nc.name == emptyNS { 109 return name 110 } 111 112 return nc.name + separator + name 113 }