Skip to content

Commit

Permalink
lang: core: Port some functions to CallableFunc API
Browse files Browse the repository at this point in the history
  • Loading branch information
purpleidea committed Dec 8, 2024
1 parent f5806e0 commit ec5d569
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 22 deletions.
27 changes: 19 additions & 8 deletions lang/core/value/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ type GetFunc struct {

init *interfaces.Init

key string
key string
args []types.Value

last types.Value
result types.Value // last calculated output
Expand Down Expand Up @@ -229,7 +230,13 @@ func (obj *GetFunc) Stream(ctx context.Context) error {
}
obj.last = input // store for next

key := input.Struct()[getArgNameKey].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")
}
Expand Down Expand Up @@ -263,7 +270,7 @@ func (obj *GetFunc) 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
}
Expand All @@ -287,8 +294,12 @@ func (obj *GetFunc) Stream(ctx context.Context) error {
}
}

// getValue gets the value we're looking for.
func (obj *GetFunc) 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 *GetFunc) Call(ctx context.Context, args []types.Value) (types.Value, error) {
key := args[0].Str()

typ, exists := obj.Info().Sig.Out.Map[getFieldNameValue] // type of value field
if !exists || typ == nil {
// programming error
Expand All @@ -303,9 +314,9 @@ func (obj *GetFunc) getValue(ctx context.Context) (types.Value, error) {
// step that might be needed if the value started out empty...
// TODO: We could even add a stored: bool field in the returned struct!
isReady := true // assume true
val, err := obj.init.Local.ValueGet(ctx, obj.key)
val, err := obj.init.Local.ValueGet(ctx, key)
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)
}
if val == nil { // val doesn't exist
isReady = false
Expand All @@ -324,7 +335,7 @@ func (obj *GetFunc) getValue(ctx context.Context) (types.Value, error) {
// an str for example, this error happens... Do we want
// to: (1) coerce? -- no; (2) error? -- yep for now; (3)
// improve type unification? -- if it's possible, yes.
return nil, errwrap.Wrapf(err, "type mismatch, check type in Value[%s]", obj.key)
return nil, errwrap.Wrapf(err, "type mismatch, check type in Value[%s]", key)
}
}

Expand Down
24 changes: 17 additions & 7 deletions lang/core/world/getval.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ func init() {
type GetValFunc struct {
init *interfaces.Init

key string
key string
args []types.Value

last types.Value
result types.Value // last calculated output
Expand Down Expand Up @@ -132,7 +133,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")
}
Expand Down Expand Up @@ -169,7 +176,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
}
Expand All @@ -193,14 +200,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}
Expand Down
26 changes: 19 additions & 7 deletions lang/core/world/kvlookup.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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")
}
Expand All @@ -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
}
Expand Down Expand Up @@ -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
}
Expand All @@ -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)
Expand Down

0 comments on commit ec5d569

Please sign in to comment.