lang: core, funcs: Port some functions to CallableFunc API

Some modern features of our function engine and language might require
this new API, so port what we can and figure out the rest later.
This commit is contained in:
James Shubin
2025-03-16 23:23:57 -04:00
parent f313380480
commit 642c6b952f
29 changed files with 702 additions and 291 deletions

View File

@@ -55,12 +55,15 @@ func init() {
funcs.ModuleRegister(ModuleName, GetValFuncName, func() interfaces.Func { return &GetValFunc{} })
}
var _ interfaces.CallableFunc = &GetValFunc{}
// GetValFunc is special function which returns the value of a given key in the
// exposed world.
type GetValFunc struct {
init *interfaces.Init
key string
key string
args []types.Value
last types.Value
result types.Value // last calculated output
@@ -132,7 +135,13 @@ func (obj *GetValFunc) Stream(ctx context.Context) error {
}
obj.last = input // store for next
key := input.Struct()[getValArgNameKey].Str()
args, err := interfaces.StructToCallableArgs(input) // []types.Value, error)
if err != nil {
return err
}
obj.args = args
key := args[0].Str()
if key == "" {
return fmt.Errorf("can't use an empty key")
}
@@ -169,7 +178,7 @@ func (obj *GetValFunc) Stream(ctx context.Context) error {
return errwrap.Wrapf(err, "channel watch failed on `%s`", obj.key)
}
result, err := obj.getValue(ctx) // get the value...
result, err := obj.Call(ctx, obj.args) // get the value...
if err != nil {
return err
}
@@ -193,14 +202,17 @@ func (obj *GetValFunc) Stream(ctx context.Context) error {
}
}
// getValue gets the value we're looking for.
func (obj *GetValFunc) getValue(ctx context.Context) (types.Value, error) {
// Call this function with the input args and return the value if it is possible
// to do so at this time. This was previously getValue which gets the value
// we're looking for.
func (obj *GetValFunc) Call(ctx context.Context, args []types.Value) (types.Value, error) {
key := args[0].Str()
exists := true // assume true
val, err := obj.init.World.StrGet(ctx, obj.key)
val, err := obj.init.World.StrGet(ctx, key)
if err != nil && obj.init.World.StrIsNotExist(err) {
exists = false // val doesn't exist
} else if err != nil {
return nil, errwrap.Wrapf(err, "channel read failed on `%s`", obj.key)
return nil, errwrap.Wrapf(err, "channel read failed on `%s`", key)
}
s := &types.StrValue{V: val}

View File

@@ -51,12 +51,15 @@ func init() {
funcs.ModuleRegister(ModuleName, KVLookupFuncName, func() interfaces.Func { return &KVLookupFunc{} })
}
var _ interfaces.CallableFunc = &KVLookupFunc{}
// KVLookupFunc is special function which returns all the values of a given key
// in the exposed world. It is similar to exchange, but it does not set a key.
type KVLookupFunc struct {
init *interfaces.Init
namespace string
args []types.Value
last types.Value
result types.Value // last calculated output
@@ -127,7 +130,13 @@ func (obj *KVLookupFunc) Stream(ctx context.Context) error {
}
obj.last = input // store for next
namespace := input.Struct()[kvLookupArgNameNamespace].Str()
args, err := interfaces.StructToCallableArgs(input) // []types.Value, error)
if err != nil {
return err
}
obj.args = args
namespace := args[0].Str()
if namespace == "" {
return fmt.Errorf("can't use an empty namespace")
}
@@ -145,7 +154,7 @@ func (obj *KVLookupFunc) Stream(ctx context.Context) error {
return err
}
result, err := obj.buildMap(ctx) // build the map...
result, err := obj.Call(ctx, obj.args) // build the map...
if err != nil {
return err
}
@@ -174,7 +183,7 @@ func (obj *KVLookupFunc) Stream(ctx context.Context) error {
return errwrap.Wrapf(err, "channel watch failed on `%s`", obj.namespace)
}
result, err := obj.buildMap(ctx) // build the map...
result, err := obj.Call(ctx, obj.args) // build the map...
if err != nil {
return err
}
@@ -198,11 +207,14 @@ func (obj *KVLookupFunc) Stream(ctx context.Context) error {
}
}
// buildMap builds the result map which we'll need. It uses struct variables.
func (obj *KVLookupFunc) buildMap(ctx context.Context) (types.Value, error) {
keyMap, err := obj.init.World.StrMapGet(ctx, obj.namespace)
// Call this function with the input args and return the value if it is possible
// to do so at this time. This was previously buildMap, which builds the result
// map which we'll need. It uses struct variables.
func (obj *KVLookupFunc) Call(ctx context.Context, args []types.Value) (types.Value, error) {
namespace := args[0].Str()
keyMap, err := obj.init.World.StrMapGet(ctx, namespace)
if err != nil {
return nil, errwrap.Wrapf(err, "channel read failed on `%s`", obj.namespace)
return nil, errwrap.Wrapf(err, "channel read failed on `%s`", namespace)
}
d := types.NewMap(obj.Info().Sig.Out)

View File

@@ -88,6 +88,8 @@ type ScheduleFunc struct {
init *interfaces.Init
args []types.Value
namespace string
scheduler *scheduler.Result
@@ -303,7 +305,15 @@ func (obj *ScheduleFunc) Stream(ctx context.Context) error {
}
obj.last = input // store for next
namespace := input.Struct()[scheduleArgNameNamespace].Str()
args, err := interfaces.StructToCallableArgs(input) // []types.Value, error)
if err != nil {
return err
}
obj.args = args
namespace := args[0].Str()
//namespace := input.Struct()[scheduleArgNameNamespace].Str()
if namespace == "" {
return fmt.Errorf("can't use an empty namespace")
}