mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-12 17:27:50 +08:00
Introduce an Elemser interface.
This commit is contained in:
parent
83cbe3b230
commit
3d7e5a819f
|
@ -291,18 +291,18 @@ func ratFn(ec *EvalCtx, arg Value) {
|
|||
out <- r
|
||||
}
|
||||
|
||||
// unpack takes any number of tables and output their list elements.
|
||||
// unpack takes Elemser's from the input and unpack them.
|
||||
func unpack(ec *EvalCtx) {
|
||||
in := ec.ports[0].Chan
|
||||
out := ec.ports[1].Chan
|
||||
|
||||
for v := range in {
|
||||
if list, ok := v.(List); !ok {
|
||||
elemser, ok := v.(Elemser)
|
||||
if !ok {
|
||||
throw(ErrInput)
|
||||
} else {
|
||||
for _, e := range *list.inner {
|
||||
out <- e
|
||||
}
|
||||
}
|
||||
for e := range elemser.Elems() {
|
||||
out <- e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -693,11 +693,11 @@ func variable(qname string, p int) ValuesOp {
|
|||
}
|
||||
value := variable.Get()
|
||||
if splice {
|
||||
list, ok := value.(List)
|
||||
elemser, ok := value.(Elemser)
|
||||
if !ok {
|
||||
ec.errorf(p, "variable $%s is not a list", qname)
|
||||
ec.errorf(p, "variable $%s (kind %s) cannot be spliced", qname, value.Kind())
|
||||
}
|
||||
return *list.inner
|
||||
return collectElems(elemser)
|
||||
}
|
||||
return []Value{value}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
|
||||
// Errors
|
||||
var (
|
||||
ErrCanOnlyAssignList = errors.New("can only assign list")
|
||||
ErrCanOnlyAssignList = errors.New("can only assign compatible values")
|
||||
ErrPathMustBeString = errors.New("path must be string")
|
||||
ErrPathCannotContainColonZero = errors.New(`path cannot contain colon or \0`)
|
||||
)
|
||||
|
@ -30,13 +30,12 @@ func (epl *EnvPathList) Get() Value {
|
|||
}
|
||||
|
||||
func (epl *EnvPathList) Set(v Value) {
|
||||
// TODO: maybe support assigning list-like values.
|
||||
l, ok := v.(List)
|
||||
elemser, ok := v.(Elemser)
|
||||
if !ok {
|
||||
throw(ErrCanOnlyAssignList)
|
||||
}
|
||||
paths := make([]string, len(*l.inner))
|
||||
for i, v := range *l.inner {
|
||||
var paths []string
|
||||
for v := range elemser.Elems() {
|
||||
s, ok := v.(String)
|
||||
if !ok {
|
||||
throw(ErrPathMustBeString)
|
||||
|
@ -45,7 +44,7 @@ func (epl *EnvPathList) Set(v Value) {
|
|||
if strings.ContainsAny(path, ":\x00") {
|
||||
throw(ErrPathCannotContainColonZero)
|
||||
}
|
||||
paths[i] = string(s)
|
||||
paths = append(paths, string(s))
|
||||
}
|
||||
epl.set(paths)
|
||||
}
|
||||
|
|
17
eval/list.go
17
eval/list.go
|
@ -12,6 +12,13 @@ var (
|
|||
ErrIndexOutOfRange = errors.New("index out of range")
|
||||
)
|
||||
|
||||
type ListLike struct {
|
||||
Value
|
||||
Lener
|
||||
Elemser
|
||||
IndexOneer
|
||||
}
|
||||
|
||||
// List is a list of Value's.
|
||||
type List struct {
|
||||
inner *[]Value
|
||||
|
@ -38,6 +45,16 @@ func (l List) Len() int {
|
|||
return len(*l.inner)
|
||||
}
|
||||
|
||||
func (l List) Elems() <-chan Value {
|
||||
ch := make(chan Value)
|
||||
go func() {
|
||||
for _, v := range *l.inner {
|
||||
ch <- v
|
||||
}
|
||||
}()
|
||||
return ch
|
||||
}
|
||||
|
||||
func (l List) IndexOne(idx Value) Value {
|
||||
i := intIndexWithin(idx, len(*l.inner))
|
||||
return (*l.inner)[i]
|
||||
|
|
|
@ -36,6 +36,19 @@ type Lener interface {
|
|||
Len() int
|
||||
}
|
||||
|
||||
// Elemser is anything that can produce a series of Value elements.
|
||||
type Elemser interface {
|
||||
Elems() <-chan Value
|
||||
}
|
||||
|
||||
func collectElems(elemser Elemser) []Value {
|
||||
var vs []Value
|
||||
for v := range elemser.Elems() {
|
||||
vs = append(vs, v)
|
||||
}
|
||||
return vs
|
||||
}
|
||||
|
||||
// Caller is anything may be called on an evalCtx with a list of Value's.
|
||||
type Caller interface {
|
||||
Value
|
||||
|
|
Loading…
Reference in New Issue
Block a user