Implement IndexerCaller.

Now we have M-expression!
This commit is contained in:
Qi Xiao 2016-02-15 15:00:34 +01:00
parent a2635d78b7
commit 5609dd1a84
3 changed files with 22 additions and 13 deletions

View File

@ -27,19 +27,23 @@ type Caller interface {
}
func mustCaller(v Value) Caller {
caller, ok := getCaller(v)
caller, ok := getCaller(v, true)
if !ok {
throw(fmt.Errorf("a %s is not callable", v.Kind()))
}
return caller
}
func getCaller(v Value) (Caller, bool) {
// getCaller adapts a Value to a Caller if there is an adapter. It adapts an
// Indexer if adaptIndexer is true.
func getCaller(v Value, adaptIndexer bool) (Caller, bool) {
if caller, ok := v.(Caller); ok {
return caller, true
}
if indexer, ok := getIndexer(v); ok {
return IndexerCaller{indexer}, true
if adaptIndexer {
if indexer, ok := getIndexer(v, nil); ok {
return IndexerCaller{indexer}, true
}
}
return nil, false
}

View File

@ -411,7 +411,7 @@ func (cp *compiler) singleVariable(n *parse.Indexing, msg string) VariableOp {
value := variable.Get()
n := len(indexOps)
for _, op := range indexOps[:n-1] {
indexer := mustIndexer(value)
indexer := mustIndexer(value, ec)
indicies := op(ec)
values := indexer.Index(indicies)
@ -700,7 +700,7 @@ func (cp *compiler) indexing(n *parse.Indexing) ValuesOp {
indicies := indexOp(ec)
newvs := make([]Value, 0, len(vs)*len(indicies))
for _, v := range vs {
newvs = append(newvs, mustIndexer(v).Index(indicies)...)
newvs = append(newvs, mustIndexer(v, ec).Index(indicies)...)
}
vs = newvs
}

View File

@ -24,21 +24,28 @@ type IndexSetter interface {
IndexSet(idx Value, v Value)
}
func mustIndexer(v Value) Indexer {
indexer, ok := getIndexer(v)
func mustIndexer(v Value, ec *EvalCtx) Indexer {
indexer, ok := getIndexer(v, ec)
if !ok {
throw(fmt.Errorf("a %s is not indexable", v.Kind()))
}
return indexer
}
func getIndexer(v Value) (Indexer, bool) {
// getIndexer adapts a Value to an Indexer if there is an adapter. It adapts a
// Caller if ec is not nil.
func getIndexer(v Value, ec *EvalCtx) (Indexer, bool) {
if indexer, ok := v.(Indexer); ok {
return indexer, true
}
if indexOneer, ok := v.(IndexOneer); ok {
return IndexOneerIndexer{indexOneer}, true
}
if ec != nil {
if caller, ok := v.(Caller); ok {
return CallerIndexer{caller, ec}, true
}
}
return nil, false
}
@ -104,16 +111,14 @@ func intIndex(idx Value) int {
return i
}
/*
// CallerIndexer adapts a Caller to an Indexer.
type CallerIndexer struct {
Caller
ec *EvalCtx
}
func (ci CallerIndexer) Index(idx Value) Value {
func (ci CallerIndexer) Index(idx []Value) []Value {
return captureOutput(ci.ec, func(ec *EvalCtx) {
ci.Caller.Call(ec, []Value{idx})
ci.Caller.Call(ec, idx)
})
}
*/