80 lines
1.7 KiB
Go
80 lines
1.7 KiB
Go
package cmdlang
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"strconv"
|
|
)
|
|
|
|
type object interface {
|
|
String() string
|
|
}
|
|
|
|
type strObject string
|
|
|
|
func (s strObject) String() string {
|
|
return string(s)
|
|
}
|
|
|
|
func toGoValue(obj object) (interface{}, bool) {
|
|
switch v := obj.(type) {
|
|
case nil:
|
|
return nil, true
|
|
case strObject:
|
|
return string(v), true
|
|
}
|
|
|
|
return nil, false
|
|
}
|
|
|
|
type invocationArgs struct {
|
|
inst *Inst
|
|
ec *evalCtx
|
|
args []object
|
|
}
|
|
|
|
func (ia invocationArgs) expectArgn(x int) error {
|
|
if len(ia.args) < x {
|
|
return errors.New("expected at least " + strconv.Itoa(x) + " args")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (ia invocationArgs) stringArg(i int) (string, error) {
|
|
if len(ia.args) < i {
|
|
return "", errors.New("expected at least " + strconv.Itoa(i) + " args")
|
|
}
|
|
s, ok := ia.args[i].(fmt.Stringer)
|
|
if !ok {
|
|
return "", errors.New("expected a string arg")
|
|
}
|
|
return s.String(), nil
|
|
}
|
|
|
|
// invokable is an object that can be executed as a command
|
|
type invokable interface {
|
|
invoke(ctx context.Context, args invocationArgs) (object, error)
|
|
}
|
|
|
|
type streamInvokable interface {
|
|
invokable
|
|
invokeWithStream(context.Context, stream, invocationArgs) (object, error)
|
|
}
|
|
|
|
type invokableFunc func(ctx context.Context, args invocationArgs) (object, error)
|
|
|
|
func (i invokableFunc) invoke(ctx context.Context, args invocationArgs) (object, error) {
|
|
return i(ctx, args)
|
|
}
|
|
|
|
type invokableStreamFunc func(ctx context.Context, inStream stream, args invocationArgs) (object, error)
|
|
|
|
func (i invokableStreamFunc) invoke(ctx context.Context, args invocationArgs) (object, error) {
|
|
return i(ctx, nil, args)
|
|
}
|
|
|
|
func (i invokableStreamFunc) invokeWithStream(ctx context.Context, inStream stream, args invocationArgs) (object, error) {
|
|
return i(ctx, inStream, args)
|
|
}
|