Skip to content

Commit

Permalink
support for Timeless FuncValues
Browse files Browse the repository at this point in the history
  • Loading branch information
gelisam committed Jan 29, 2024
1 parent 44e3c06 commit 87c0967
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 21 deletions.
48 changes: 34 additions & 14 deletions lang/funcs/structs/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,9 @@ func SimpleFnToDirectFunc(name string, fv *types.FuncValue) interfaces.Func {
// *full.FuncValue.
func SimpleFnToFuncValue(name string, fv *types.FuncValue) *full.FuncValue {
return &full.FuncValue{
V: func(txn interfaces.Txn, args []interfaces.Func) (interfaces.Func, error) {
wrappedFunc := SimpleFnToDirectFunc(name, fv)
txn.AddVertex(wrappedFunc)
for i, arg := range args {
argName := fv.T.Ord[i]
txn.AddEdge(arg, wrappedFunc, &interfaces.FuncEdge{
Args: []string{argName},
})
}
return wrappedFunc, nil
},
T: fv.T,
Name: &name,
Timeless: fv,
T: fv.T,
}
}

Expand All @@ -76,9 +67,10 @@ func SimpleFnToConstFunc(name string, fv *types.FuncValue) interfaces.Func {
// FuncToFullFuncValue creates a *full.FuncValue which adds the given
// interfaces.Func to the graph. Note that this means the *full.FuncValue
// can only be called once.
func FuncToFullFuncValue(valueTransformingFunc interfaces.Func, typ *types.Type) *full.FuncValue {
func FuncToFullFuncValue(name string, valueTransformingFunc interfaces.Func, typ *types.Type) *full.FuncValue {
return &full.FuncValue{
V: func(txn interfaces.Txn, args []interfaces.Func) (interfaces.Func, error) {
Name: &name,
Timeful: func(txn interfaces.Txn, args []interfaces.Func) (interfaces.Func, error) {
for i, arg := range args {
argName := typ.Ord[i]
txn.AddEdge(arg, valueTransformingFunc, &interfaces.FuncEdge{
Expand All @@ -90,3 +82,31 @@ func FuncToFullFuncValue(valueTransformingFunc interfaces.Func, typ *types.Type)
T: typ,
}
}

// Call calls the function with the provided txn and args.
func CallFuncValue(obj *full.FuncValue, txn interfaces.Txn, args []interfaces.Func) (interfaces.Func, error) {
if obj.Timeful != nil {
return obj.Timeful(txn, args)
}

wrappedFunc := SimpleFnToDirectFunc(*obj.Name, obj.Timeless)
txn.AddVertex(wrappedFunc)
for i, arg := range args {
argName := obj.T.Ord[i]
txn.AddEdge(arg, wrappedFunc, &interfaces.FuncEdge{
Args: []string{argName},
})
}
return wrappedFunc, nil
}

// Speculatively call the function with the provided arguments.
// Only makes sense if the function is timeless (produces a single Value, not a
// stream of values).
func CallTimelessFuncValue(obj *full.FuncValue, args []types.Value) (types.Value, error) {
if obj.Timeless != nil {
return obj.Timeless.V(args)
}

panic("cannot call CallIfTimeless on a Timeful function")
}
11 changes: 4 additions & 7 deletions lang/types/full/full.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ import (
// went horribly wrong. (Think, an internal panic.)
type FuncValue struct {
types.Base
V func(interfaces.Txn, []interfaces.Func) (interfaces.Func, error)
T *types.Type // contains ordered field types, arg names are a bonus part
Name *string
Timeful func(interfaces.Txn, []interfaces.Func) (interfaces.Func, error)
Timeless *types.FuncValue
T *types.Type // contains ordered field types, arg names are a bonus part
}

// String returns a visual representation of this value.
Expand Down Expand Up @@ -111,8 +113,3 @@ func (obj *FuncValue) Value() interface{} {
//val := reflect.MakeFunc(typ, fn)
//return val.Interface()
}

// Call calls the function with the provided txn and args.
func (obj *FuncValue) Call(txn interfaces.Txn, args []interfaces.Func) (interfaces.Func, error) {
return obj.V(txn, args)
}

0 comments on commit 87c0967

Please sign in to comment.