mirror of
https://github.com/MontFerret/ferret.git
synced 2025-03-03 15:02:32 +02:00
Added namespace builder (#336)
* Added namespace builder * Fixed linting issues * Added extra check * Updated e2e lib * Renamed NamespaceBuilder to NamespaceContainer and changed func receivers * Renamed NewLib to RegisterLib
This commit is contained in:
parent
ddfb7a20e8
commit
22382a0f61
@ -10,12 +10,16 @@ import (
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
)
|
||||
|
||||
func Assertions() map[string]core.Function {
|
||||
return map[string]core.Function{
|
||||
"EXPECT": expect,
|
||||
"T::EXPECT": expect,
|
||||
"T::HTTP::GET": httpGet,
|
||||
}
|
||||
func HTTPHelpers(ns core.Namespace) error {
|
||||
return ns.RegisterFunctions(core.Functions{
|
||||
"GET": httpGet,
|
||||
})
|
||||
}
|
||||
|
||||
func Assertions(ns core.Namespace) error {
|
||||
return ns.RegisterFunctions(core.Functions{
|
||||
"EXPECT": expect,
|
||||
})
|
||||
}
|
||||
|
||||
func expect(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
|
@ -101,7 +101,18 @@ func (r *Runner) runQueries(ctx context.Context, dir string) ([]Result, error) {
|
||||
|
||||
c := compiler.New()
|
||||
|
||||
if err := c.RegisterFunctions(Assertions()); err != nil {
|
||||
// backward compatible
|
||||
if err := Assertions(c); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ns := c.Namespace("T")
|
||||
|
||||
if err := Assertions(ns); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := HTTPHelpers(ns.Namespace("HTTP")); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,6 @@
|
||||
package compiler
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/MontFerret/ferret/pkg/parser"
|
||||
"github.com/MontFerret/ferret/pkg/runtime"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
@ -11,14 +8,15 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var fnNameValidation = regexp.MustCompile("^[a-zA-Z]+[a-zA-Z0-9_]*(::[a-zA-Z]+[a-zA-Z0-9_]*)*$")
|
||||
|
||||
type FqlCompiler struct {
|
||||
funcs map[string]core.Function
|
||||
*NamespaceContainer
|
||||
}
|
||||
|
||||
func New(setters ...Option) *FqlCompiler {
|
||||
c := &FqlCompiler{}
|
||||
c.NamespaceContainer = newRootNamespace()
|
||||
c.funcs = make(map[string]core.Function)
|
||||
|
||||
opts := &Options{}
|
||||
|
||||
for _, setter := range setters {
|
||||
@ -26,67 +24,14 @@ func New(setters ...Option) *FqlCompiler {
|
||||
}
|
||||
|
||||
if !opts.noStdlib {
|
||||
c.funcs = stdlib.NewLib()
|
||||
} else {
|
||||
c.funcs = make(map[string]core.Function)
|
||||
if err := stdlib.RegisterLib(c.NamespaceContainer); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *FqlCompiler) RegisterFunction(name string, fun core.Function) error {
|
||||
_, exists := c.funcs[name]
|
||||
|
||||
if exists {
|
||||
return errors.Errorf("function already exists: %s", name)
|
||||
}
|
||||
|
||||
// validation the name
|
||||
if !fnNameValidation.MatchString(name) {
|
||||
return errors.Errorf("invalid function name: %s", name)
|
||||
}
|
||||
|
||||
c.funcs[strings.ToUpper(name)] = fun
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *FqlCompiler) RemoveFunction(name string) {
|
||||
delete(c.funcs, strings.ToUpper(name))
|
||||
}
|
||||
|
||||
func (c *FqlCompiler) RegisterFunctions(funcs map[string]core.Function) error {
|
||||
for name, fun := range funcs {
|
||||
if err := c.RegisterFunction(name, fun); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *FqlCompiler) RegisteredFunctions() []string {
|
||||
res := make([]string, 0, len(c.funcs))
|
||||
|
||||
for k := range c.funcs {
|
||||
res = append(res, k)
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func (c *FqlCompiler) RegisteredFunctionsNS(namespace string) []string {
|
||||
res := make([]string, 0, len(c.funcs))
|
||||
|
||||
for k := range c.funcs {
|
||||
if strings.HasPrefix(k, namespace) {
|
||||
res = append(res, k)
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func (c *FqlCompiler) Compile(query string) (program *runtime.Program, err error) {
|
||||
if query == "" {
|
||||
return nil, ErrEmptyQuery
|
||||
|
@ -14,7 +14,7 @@ func TestFunctionNSCall(t *testing.T) {
|
||||
c := compiler.New()
|
||||
|
||||
var counter int
|
||||
err := c.RegisterFunction("T::SPY", func(_ context.Context, _ ...core.Value) (core.Value, error) {
|
||||
err := c.Namespace("T").RegisterFunction("SPY", func(_ context.Context, _ ...core.Value) (core.Value, error) {
|
||||
counter++
|
||||
|
||||
return values.None, nil
|
||||
@ -39,7 +39,7 @@ func TestFunctionNSCall(t *testing.T) {
|
||||
c := compiler.New()
|
||||
|
||||
var counter int
|
||||
err := c.RegisterFunction("T::UTILS::SPY", func(_ context.Context, _ ...core.Value) (core.Value, error) {
|
||||
err := c.Namespace("T").Namespace("UTILS").RegisterFunction("SPY", func(_ context.Context, _ ...core.Value) (core.Value, error) {
|
||||
counter++
|
||||
|
||||
return values.None, nil
|
||||
@ -64,7 +64,7 @@ func TestFunctionNSCall(t *testing.T) {
|
||||
c := compiler.New()
|
||||
|
||||
var counter int
|
||||
err := c.RegisterFunction("T::UTILS::SPY", func(_ context.Context, _ ...core.Value) (core.Value, error) {
|
||||
err := c.Namespace("T").Namespace("UTILS").RegisterFunction("SPY", func(_ context.Context, _ ...core.Value) (core.Value, error) {
|
||||
counter++
|
||||
|
||||
return values.None, nil
|
||||
@ -78,17 +78,4 @@ func TestFunctionNSCall(t *testing.T) {
|
||||
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("Should NOT register RETURN T:UTILS::SPY", t, func() {
|
||||
c := compiler.New()
|
||||
|
||||
var counter int
|
||||
err := c.RegisterFunction("T::UTILS:SPY", func(_ context.Context, _ ...core.Value) (core.Value, error) {
|
||||
counter++
|
||||
|
||||
return values.None, nil
|
||||
})
|
||||
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ func TestRegexpOperator(t *testing.T) {
|
||||
|
||||
Convey("Should be possible to use negative regular expression operator", t, func() {
|
||||
c := compiler.New()
|
||||
c.RegisterFunction("T::REGEXP", func(_ context.Context, _ ...core.Value) (value core.Value, e error) {
|
||||
c.Namespace("T").RegisterFunction("REGEXP", func(_ context.Context, _ ...core.Value) (value core.Value, e error) {
|
||||
return values.NewString("[a-z]+bar$"), nil
|
||||
})
|
||||
|
||||
|
97
pkg/compiler/namespace.go
Normal file
97
pkg/compiler/namespace.go
Normal file
@ -0,0 +1,97 @@
|
||||
package compiler
|
||||
|
||||
import (
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/pkg/errors"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var fnNameValidation = regexp.MustCompile("^[a-zA-Z]+[a-zA-Z0-9_]*(::[a-zA-Z]+[a-zA-Z0-9_]*)*$")
|
||||
|
||||
const emptyNS = ""
|
||||
const separator = "::"
|
||||
|
||||
type NamespaceContainer struct {
|
||||
funcs core.Functions
|
||||
name string
|
||||
}
|
||||
|
||||
func newRootNamespace() *NamespaceContainer {
|
||||
ns := new(NamespaceContainer)
|
||||
ns.funcs = make(core.Functions)
|
||||
|
||||
return ns
|
||||
}
|
||||
|
||||
func newNamespace(funcs core.Functions, name string) *NamespaceContainer {
|
||||
return &NamespaceContainer{funcs, strings.ToUpper(name)}
|
||||
}
|
||||
|
||||
func (nc *NamespaceContainer) Namespace(name string) core.Namespace {
|
||||
return newNamespace(nc.funcs, nc.makeFullName(name))
|
||||
}
|
||||
|
||||
func (nc *NamespaceContainer) RegisterFunction(name string, fun core.Function) error {
|
||||
nsName := nc.makeFullName(name)
|
||||
_, exists := nc.funcs[nsName]
|
||||
|
||||
if exists {
|
||||
return errors.Errorf("function already exists: %s", name)
|
||||
}
|
||||
|
||||
// validation the name
|
||||
if strings.Contains(name, separator) {
|
||||
return errors.Errorf("invalid function name: %s", name)
|
||||
}
|
||||
|
||||
if !fnNameValidation.MatchString(nsName) {
|
||||
return errors.Errorf("invalid function or namespace name: %s", nsName)
|
||||
}
|
||||
|
||||
nc.funcs[strings.ToUpper(nsName)] = fun
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nc *NamespaceContainer) RemoveFunction(name string) {
|
||||
delete(nc.funcs, strings.ToUpper(nc.makeFullName(name)))
|
||||
}
|
||||
|
||||
func (nc *NamespaceContainer) RegisterFunctions(funcs core.Functions) error {
|
||||
for name, fun := range funcs {
|
||||
if err := nc.RegisterFunction(name, fun); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nc *NamespaceContainer) RegisteredFunctions() []string {
|
||||
res := make([]string, 0, len(nc.funcs))
|
||||
|
||||
// root namespace, return all functions
|
||||
if nc.name == emptyNS {
|
||||
for k := range nc.funcs {
|
||||
res = append(res, k)
|
||||
}
|
||||
} else {
|
||||
nsPrefix := nc.name + separator
|
||||
for k := range nc.funcs {
|
||||
if strings.HasPrefix(k, nsPrefix) {
|
||||
res = append(res, k)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func (nc *NamespaceContainer) makeFullName(name string) string {
|
||||
if nc.name == emptyNS {
|
||||
return name
|
||||
}
|
||||
|
||||
return nc.name + separator + name
|
||||
}
|
96
pkg/compiler/namespace_test.go
Normal file
96
pkg/compiler/namespace_test.go
Normal file
@ -0,0 +1,96 @@
|
||||
package compiler_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/compiler"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNamespaceBuilder(t *testing.T) {
|
||||
Convey("Namespaces", t, func() {
|
||||
Convey("Should return an error when a function name contains NS separator", func() {
|
||||
c := compiler.New()
|
||||
err := c.RegisterFunction("T::SPY", func(ctx context.Context, args ...core.Value) (value core.Value, e error) {
|
||||
return values.None, nil
|
||||
})
|
||||
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("Should successfully register a name within a namespace", func() {
|
||||
c := compiler.New()
|
||||
err := c.Namespace("T").RegisterFunction("SPY", func(ctx context.Context, args ...core.Value) (value core.Value, e error) {
|
||||
return values.None, nil
|
||||
})
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
funcs := c.RegisteredFunctions()
|
||||
|
||||
var exists bool
|
||||
|
||||
for _, name := range funcs {
|
||||
exists = name == "T::SPY"
|
||||
|
||||
if exists {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
So(exists, ShouldBeTrue)
|
||||
})
|
||||
|
||||
Convey("Root namespace should return all registered functions", func() {
|
||||
c := compiler.New()
|
||||
err := c.Namespace("T").RegisterFunction("SPY", func(ctx context.Context, args ...core.Value) (value core.Value, e error) {
|
||||
return values.None, nil
|
||||
})
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
funcs := c.RegisteredFunctions()
|
||||
|
||||
So(len(funcs), ShouldBeGreaterThan, 1)
|
||||
})
|
||||
|
||||
Convey("Namespace should return all registered functions", func() {
|
||||
c := compiler.New()
|
||||
err := c.Namespace("T").RegisterFunction("SPY", func(ctx context.Context, args ...core.Value) (value core.Value, e error) {
|
||||
return values.None, nil
|
||||
})
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = c.Namespace("T").Namespace("UTILS").RegisterFunction("SPY", func(ctx context.Context, args ...core.Value) (value core.Value, e error) {
|
||||
return values.None, nil
|
||||
})
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
funcs := c.Namespace("T").RegisteredFunctions()
|
||||
|
||||
So(funcs, ShouldHaveLength, 2)
|
||||
|
||||
funcs2 := c.Namespace("T").Namespace("UTILS").RegisteredFunctions()
|
||||
|
||||
So(funcs2, ShouldHaveLength, 1)
|
||||
})
|
||||
|
||||
Convey("Namespace should return an error if namespace name is incorrect", func() {
|
||||
c := compiler.New()
|
||||
noop := func(ctx context.Context, args ...core.Value) (value core.Value, e error) {
|
||||
return values.None, nil
|
||||
}
|
||||
err := c.Namespace("T::").RegisterFunction("SPY", noop)
|
||||
|
||||
So(err, ShouldNotBeNil)
|
||||
|
||||
err = c.Namespace("@F").RegisterFunction("SPY", noop)
|
||||
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
}
|
@ -7,7 +7,19 @@ import (
|
||||
|
||||
const MaxArgs = 65536
|
||||
|
||||
type Function = func(ctx context.Context, args ...Value) (Value, error)
|
||||
type (
|
||||
Function = func(ctx context.Context, args ...Value) (Value, error)
|
||||
|
||||
Functions map[string]Function
|
||||
|
||||
Namespace interface {
|
||||
Namespace(name string) Namespace
|
||||
RegisterFunction(name string, fun Function) error
|
||||
RegisterFunctions(funs Functions) error
|
||||
RegisteredFunctions() []string
|
||||
RemoveFunction(name string)
|
||||
}
|
||||
)
|
||||
|
||||
func ValidateArgs(args []Value, minimum, maximum int) error {
|
||||
count := len(args)
|
||||
|
@ -5,8 +5,8 @@ import (
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
)
|
||||
|
||||
func NewLib() map[string]core.Function {
|
||||
return map[string]core.Function{
|
||||
func RegisterLib(ns core.Namespace) error {
|
||||
return ns.RegisterFunctions(core.Functions{
|
||||
"APPEND": Append,
|
||||
"FIRST": First,
|
||||
"FLATTEN": Flatten,
|
||||
@ -29,7 +29,7 @@ func NewLib() map[string]core.Function {
|
||||
"UNION_DISTINCT": UnionDistinct,
|
||||
"UNIQUE": Unique,
|
||||
"UNSHIFT": Unshift,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func ToUniqueArray(arr *values.Array) *values.Array {
|
||||
|
@ -2,9 +2,9 @@ package collections
|
||||
|
||||
import "github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
|
||||
func NewLib() map[string]core.Function {
|
||||
return map[string]core.Function{
|
||||
func RegisterLib(ns core.Namespace) error {
|
||||
return ns.RegisterFunctions(core.Functions{
|
||||
"LENGTH": Length,
|
||||
"REVERSE": Reverse,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -12,8 +12,8 @@ import (
|
||||
|
||||
const defaultTimeout = 5000
|
||||
|
||||
func NewLib() map[string]core.Function {
|
||||
return map[string]core.Function{
|
||||
func RegisterLib(ns core.Namespace) error {
|
||||
return ns.RegisterFunctions(core.Functions{
|
||||
"ATTR_GET": AttributeGet,
|
||||
"ATTR_REMOVE": AttributeRemove,
|
||||
"ATTR_SET": AttributeSet,
|
||||
@ -67,7 +67,7 @@ func NewLib() map[string]core.Function {
|
||||
"WAIT_NO_STYLE_ALL": WaitNoStyleAll,
|
||||
"WAIT_NAVIGATION": WaitNavigation,
|
||||
"XPATH": XPath,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func OpenOrCastPage(ctx context.Context, value core.Value) (drivers.HTMLPage, bool, error) {
|
||||
|
@ -1,7 +1,6 @@
|
||||
package stdlib
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/arrays"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/collections"
|
||||
@ -13,27 +12,34 @@ import (
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/utils"
|
||||
)
|
||||
|
||||
func NewLib() map[string]core.Function {
|
||||
lib := make(map[string]core.Function)
|
||||
|
||||
add := func(l map[string]core.Function) {
|
||||
for name, fn := range l {
|
||||
if _, exists := lib[name]; exists {
|
||||
panic(fmt.Sprintf("%s function already exists", name))
|
||||
}
|
||||
|
||||
lib[name] = fn
|
||||
}
|
||||
func RegisterLib(ns core.Namespace) error {
|
||||
if err := types.RegisterLib(ns); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
add(types.NewLib())
|
||||
add(strings.NewLib())
|
||||
add(math.NewLib())
|
||||
add(collections.NewLib())
|
||||
add(arrays.NewLib())
|
||||
add(objects.NewLib())
|
||||
add(html.NewLib())
|
||||
add(utils.NewLib())
|
||||
if err := strings.RegisterLib(ns); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return lib
|
||||
if err := math.RegisterLib(ns); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := collections.RegisterLib(ns); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := arrays.RegisterLib(ns); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := objects.RegisterLib(ns); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := html.RegisterLib(ns); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utils.RegisterLib(ns)
|
||||
}
|
||||
|
@ -15,8 +15,8 @@ const (
|
||||
GradToDeg = math.Pi / 200
|
||||
)
|
||||
|
||||
func NewLib() map[string]core.Function {
|
||||
return map[string]core.Function{
|
||||
func RegisterLib(ns core.Namespace) error {
|
||||
return ns.RegisterFunctions(core.Functions{
|
||||
"ABS": Abs,
|
||||
"ACOS": Acos,
|
||||
"ASIN": Asin,
|
||||
@ -50,7 +50,7 @@ func NewLib() map[string]core.Function {
|
||||
"TAN": Tan,
|
||||
"VARIANCE_POPULATION": PopulationVariance,
|
||||
"VARIANCE_SAMPLE": SampleVariance,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func toFloat(arg core.Value) float64 {
|
||||
|
@ -2,8 +2,8 @@ package objects
|
||||
|
||||
import "github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
|
||||
func NewLib() map[string]core.Function {
|
||||
return map[string]core.Function{
|
||||
func RegisterLib(ns core.Namespace) error {
|
||||
return ns.RegisterFunctions(core.Functions{
|
||||
"HAS": Has,
|
||||
"KEYS": Keys,
|
||||
"KEEP_KEYS": KeepKeys,
|
||||
@ -11,5 +11,5 @@ func NewLib() map[string]core.Function {
|
||||
"ZIP": Zip,
|
||||
"VALUES": Values,
|
||||
"MERGE_RECURSIVE": MergeRecursive,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -2,8 +2,8 @@ package strings
|
||||
|
||||
import "github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
|
||||
func NewLib() map[string]core.Function {
|
||||
return map[string]core.Function{
|
||||
func RegisterLib(ns core.Namespace) error {
|
||||
return ns.RegisterFunctions(core.Functions{
|
||||
"CONCAT": Concat,
|
||||
"CONCAT_SEPARATOR": ConcatWithSeparator,
|
||||
"CONTAINS": Contains,
|
||||
@ -37,5 +37,5 @@ func NewLib() map[string]core.Function {
|
||||
"UPPER": Upper,
|
||||
"FMT": Fmt,
|
||||
"UNESCAPE_HTML": UnescapeHTML,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -5,8 +5,8 @@ import (
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
)
|
||||
|
||||
func NewLib() map[string]core.Function {
|
||||
return map[string]core.Function{
|
||||
func RegisterLib(ns core.Namespace) error {
|
||||
return ns.RegisterFunctions(core.Functions{
|
||||
"TO_BOOL": ToBool,
|
||||
"TO_INT": ToInt,
|
||||
"TO_FLOAT": ToFloat,
|
||||
@ -26,7 +26,7 @@ func NewLib() map[string]core.Function {
|
||||
"IS_BINARY": IsBinary,
|
||||
"IS_NAN": IsNaN,
|
||||
"TYPENAME": TypeName,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func isTypeof(value core.Value, ctype core.Type) core.Value {
|
||||
|
@ -2,9 +2,9 @@ package utils
|
||||
|
||||
import "github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
|
||||
func NewLib() map[string]core.Function {
|
||||
return map[string]core.Function{
|
||||
func RegisterLib(ns core.Namespace) error {
|
||||
return ns.RegisterFunctions(core.Functions{
|
||||
"WAIT": Wait,
|
||||
"PRINT": Print,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user