-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #22 from otiai10/develop
Develop
- Loading branch information
Showing
9 changed files
with
267 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package functioncall | ||
|
||
import ( | ||
"encoding/json" | ||
"testing" | ||
|
||
. "github.com/otiai10/mint" | ||
) | ||
|
||
func TestFunctions(t *testing.T) { | ||
funcs := Funcs{} | ||
Expect(t, funcs).TypeOf("functioncall.Funcs") | ||
} | ||
|
||
func TestFunctions_MarshalJSON(t *testing.T) { | ||
repeat := func(word string, count int) (r string) { | ||
for i := 0; i < count; i++ { | ||
r += word | ||
} | ||
return r | ||
} | ||
funcs := Funcs{ | ||
"repeat": Func{repeat, "Repeat given string N times", Params{ | ||
{"word", "string", "String to be repeated", true}, | ||
{"count", "number", "How many times to repeat", true}, | ||
}}, | ||
} | ||
b, err := funcs.MarshalJSON() | ||
Expect(t, err).ToBe(nil) | ||
|
||
v := []map[string]any{} | ||
err = json.Unmarshal(b, &v) | ||
Expect(t, err).ToBe(nil) | ||
|
||
Expect(t, v).Query("0.name").ToBe("repeat") | ||
Expect(t, v).Query("0.description").ToBe("Repeat given string N times") | ||
Expect(t, v).Query("0.parameters.type").ToBe("object") | ||
Expect(t, v).Query("0.parameters.properties.word.type").ToBe("string") | ||
Expect(t, v).Query("0.parameters.required.1").ToBe("count") | ||
} | ||
|
||
func TestAs(t *testing.T) { | ||
repeat := func(word string, count int) (r string) { | ||
for i := 0; i < count; i++ { | ||
r += word | ||
} | ||
return r | ||
} | ||
funcs := Funcs{ | ||
"repeat": Func{repeat, "Repeat given string N times", Params{ | ||
{"word", "string", "String to be repeated", true}, | ||
{"count", "number", "How many times to repeat", true}, | ||
}}, | ||
} | ||
a := As[[]map[string]any](funcs) | ||
Expect(t, a).TypeOf("[]map[string]interface {}") | ||
Expect(t, a).Query("0.name").ToBe("repeat") | ||
Expect(t, a).Query("0.parameters.type").ToBe("object") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package functioncall | ||
|
||
import ( | ||
"encoding/json" | ||
) | ||
|
||
type Funcs map[string]Func | ||
|
||
type Func struct { | ||
Value any `json:"-"` | ||
Description string `json:"description,omitempty"` | ||
Parameters Params `json:"parameters,omitempty"` | ||
} | ||
|
||
type Params []Param | ||
|
||
type Param struct { | ||
Name string `json:"-"` | ||
Type string `json:"type,omitempty"` | ||
Description string `json:"description,omitempty"` | ||
Required bool `json:"-"` | ||
// Enum []any `json:"enum,omitempty"` | ||
} | ||
|
||
func (funcs Funcs) MarshalJSON() ([]byte, error) { | ||
// Convert map to slice | ||
sl := []map[string]any{} | ||
for key, fun := range funcs { | ||
f := map[string]any{ | ||
"name": key, | ||
"description": fun.Description, | ||
"parameters": fun.Parameters, | ||
} | ||
sl = append(sl, f) | ||
} | ||
return json.Marshal(sl) | ||
} | ||
|
||
func (params Params) MarshalJSON() ([]byte, error) { | ||
required := []string{} | ||
props := map[string]Param{} | ||
for _, p := range params { | ||
if p.Required { | ||
required = append(required, p.Name) | ||
} | ||
props[p.Name] = p | ||
} | ||
schema := map[string]any{ | ||
"type": "object", | ||
"properties": props, | ||
"required": required, | ||
} | ||
return json.Marshal(schema) | ||
} | ||
|
||
func As[T any](funcs Funcs) (dest T) { | ||
b, err := funcs.MarshalJSON() | ||
if err != nil { | ||
panic(err) | ||
} | ||
err = json.Unmarshal(b, &dest) | ||
if err != nil { | ||
panic(err) | ||
} | ||
return dest | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package functioncall | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"reflect" | ||
) | ||
|
||
type Invocation interface { | ||
Name() string | ||
Args() map[string]any | ||
} | ||
|
||
func (funcs Funcs) Call(invocation Invocation) string { | ||
b, err := json.Marshal(funcs.Invoke(invocation)) | ||
if err != nil { | ||
return err.Error() | ||
} | ||
return string(b) | ||
} | ||
|
||
func (funcs Funcs) Invoke(invocation Invocation) any { | ||
f, ok := funcs[invocation.Name()] | ||
if !ok { | ||
return fmt.Sprintf("function not found: %s", invocation.Name()) | ||
} | ||
v := reflect.ValueOf(f.Value) | ||
if !v.IsValid() || v.IsZero() { | ||
return fmt.Sprintf("function is invalid: %s", invocation.Name()) | ||
} | ||
if v.Kind() != reflect.Func { | ||
return fmt.Sprintf("function is not a function: %s", invocation.Name()) | ||
} | ||
if v.Type().NumIn() != len(invocation.Args()) { | ||
return fmt.Sprintf("function argument length mismatch: %s", invocation.Name()) | ||
} | ||
// Call the function with given arguments by using `reflect` package | ||
args := invocation.Args() | ||
params := []reflect.Value{} | ||
for i, p := range f.Parameters { | ||
if arg, ok := args[p.Name]; ok { | ||
params = append(params, reflect.ValueOf(arg)) | ||
} else { | ||
params = append(params, reflect.Zero(v.Type().In(i))) | ||
} | ||
} | ||
rets := []any{} | ||
for _, r := range v.Call(params) { | ||
rets = append(rets, r.Interface()) | ||
} | ||
return rets | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,2 @@ | ||
github.com/otiai10/curr v1.0.0 h1:TJIWdbX0B+kpNagQrjgq8bCMrbhiuX73M2XwgtDMoOI= | ||
github.com/otiai10/mint v1.4.1 h1:HOVBfKP1oXIc0wWo9hZ8JLdZtyCPWqjvmFDuVZ0yv2Y= | ||
github.com/otiai10/mint v1.4.1/go.mod h1:gifjb2MYOoULtKLqUAEILUG/9KONW6f7YsJ6vQLTlFI= | ||
github.com/otiai10/mint v1.6.1 h1:kgbTJmOpp/0ce7hk3H8jiSuR0MXmpwWRfqUdKww17qg= | ||
github.com/otiai10/mint v1.6.1/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters