-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfunction.go
More file actions
81 lines (74 loc) · 2.67 KB
/
Copy pathfunction.go
File metadata and controls
81 lines (74 loc) · 2.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package baml_go
import (
"context"
"errors"
"fmt"
"runtime"
"github.com/boundaryml/baml-go/internal/cffi"
)
// Function is an owned BAML closure returned to Go. It retains the captured
// BAML environment and may be invoked repeatedly.
type Function struct {
key uint64
parameters []string
owner *resultOwner
}
// Function decodes a returned FUNCTION_REF and transfers its result ownership
// into an invokable Go value.
func (value Value) Function() (Function, error) {
if value.value == nil {
return Function{}, errors.New("decode BAML function: empty value")
}
handle := value.value.GetHandleValue()
if handle == nil || handle.GetHandleType() != cffi.BamlHandleType_FUNCTION_REF || handle.GetKey() == 0 {
return Function{}, fmt.Errorf("decode BAML function: expected FUNCTION_REF, received %T", value.value.GetValue())
}
functionType := handle.GetTy().GetFunction()
if functionType == nil {
return Function{}, errors.New("decode BAML function: handle is missing its function type")
}
parameters := make([]string, len(functionType.GetParams()))
for index, parameter := range functionType.GetParams() {
if parameter == nil || parameter.GetName() == "" {
return Function{}, fmt.Errorf("decode BAML function: parameter %d has no name", index)
}
parameters[index] = parameter.GetName()
}
return Function{key: handle.GetKey(), parameters: parameters, owner: value.owner}, nil
}
// ParameterNames returns the BAML parameter names in invocation order.
func (function Function) ParameterNames() []string {
return append([]string(nil), function.parameters...)
}
// Call invokes the closure through the native handle table.
func (function Function) Call(ctx context.Context, args map[string]Input) (Value, error) {
if function.key == 0 || function.owner == nil {
return Value{}, errors.New("call BAML function: invalid or released function handle")
}
value, err := callHandle(ctx, function.key, args)
runtime.KeepAlive(function.owner)
return value, err
}
// CallPositional invokes the closure with required arguments in declaration
// order and supplied optional arguments by name.
func (function Function) CallPositional(
ctx context.Context,
required []Input,
optional map[string]Input,
) (Value, error) {
if len(required) > len(function.parameters) {
return Value{}, fmt.Errorf(
"call BAML function: received %d positional arguments for %d parameters",
len(required),
len(function.parameters),
)
}
arguments := make(map[string]Input, len(required)+len(optional))
for index, value := range required {
arguments[function.parameters[index]] = value
}
for name, value := range optional {
arguments[name] = value
}
return function.Call(ctx, arguments)
}