Use outer product semantics for indexing.

This commit is contained in:
Qi Xiao 2016-02-14 18:13:53 +01:00
parent b9a2693e57
commit 4b3d18442a
4 changed files with 21 additions and 23 deletions

View File

@ -617,22 +617,32 @@ func (cp *compiler) indexing(n *parse.Indexing) ValuesOp {
headOp := cp.primary(n.Head)
indexOps := cp.arrays(n.Indicies)
p := n.Begin()
// p := n.Begin()
indexPoses := make([]int, len(n.Indicies))
for i, index := range n.Indicies {
indexPoses[i] = index.Begin()
}
return func(ec *EvalCtx) []Value {
v := ec.must(headOp(ec), "the indexing value", p).mustOne()
for i, indexOp := range indexOps {
index := ec.must(indexOp(ec), "the index", p).mustOne()
v = evalIndex(ec, v, index, p, indexPoses[i])
vs := headOp(ec)
for _, indexOp := range indexOps {
index := indexOp(ec)
vs = outerProduct(vs, index, func(l, r Value) Value {
return mustIndexer(l).Index(r)
})
}
return []Value{v}
return vs
}
}
func mustIndexer(v Value) Indexer {
indexer, ok := v.(Indexer)
if !ok {
throw(fmt.Errorf("%s value cannot be indexed", v.Kind()))
}
return indexer
}
func literalValues(v ...Value) ValuesOp {
return func(e *EvalCtx) []Value {
return v

View File

@ -191,8 +191,7 @@ type IndexerCaller struct {
func (ic IndexerCaller) Call(ec *EvalCtx, argVals []Value) {
var v Value = ic.Indexer
for _, idx := range argVals {
// XXX the positions are obviously wrong.
v = evalIndex(ec, v, idx, 0, 0)
v = mustIndexer(v).Index(idx)
}
ec.ports[1].Chan <- v
}

View File

@ -442,20 +442,6 @@ func stringToSegments(s string) []glob.Segment {
return segs
}
func evalIndex(ec *EvalCtx, l, r Value, lp, rp int) Value {
left, ok := l.(Indexer)
if !ok {
ec.errorf(lp, "%s value cannot be indexing", l.Kind())
}
right, ok := r.(String)
if !ok {
ec.errorf(rp, "%s invalid cannot be used as index", r.Kind())
}
return left.Index(right)
}
// FromJSONInterface converts a interface{} that results from json.Unmarshal to
// a Value.
func FromJSONInterface(v interface{}) Value {

View File

@ -376,7 +376,10 @@ func (ctrl *Control) parse(ps *parser, leader string) {
parseSpaces(ctrl, ps)
ctrl.setIterator(parsePrimary(ps))
parseSpaces(ctrl, ps)
if consumeLeader() != "in" {
if ps.findPossibleLeader() == "in" {
ps.advance(len("in"))
addSep(ctrl, ps)
} else {
ps.error(errShouldBeIn)
}
ctrl.setArray(parseArray(ps))