github.com/MontFerret/ferret@v0.18.0/pkg/runtime/expressions/for_in.go (about)

     1  package expressions
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/MontFerret/ferret/pkg/runtime/collections"
     7  	"github.com/MontFerret/ferret/pkg/runtime/core"
     8  	"github.com/MontFerret/ferret/pkg/runtime/values/types"
     9  )
    10  
    11  type ForInIterableExpression struct {
    12  	src         core.SourceMap
    13  	valVariable string
    14  	keyVariable string
    15  	exp         core.Expression
    16  }
    17  
    18  func NewForInIterableExpression(
    19  	src core.SourceMap,
    20  	valVariable,
    21  	keyVariable string,
    22  	exp core.Expression,
    23  ) (collections.Iterable, error) {
    24  	if exp == nil {
    25  		return nil, core.Error(core.ErrMissedArgument, "expression")
    26  	}
    27  
    28  	return &ForInIterableExpression{
    29  		src,
    30  		valVariable,
    31  		keyVariable,
    32  		exp,
    33  	}, nil
    34  }
    35  
    36  func (iterable *ForInIterableExpression) Iterate(ctx context.Context, scope *core.Scope) (collections.Iterator, error) {
    37  	select {
    38  	case <-ctx.Done():
    39  		return nil, core.ErrTerminated
    40  	default:
    41  		data, err := iterable.exp.Exec(ctx, scope)
    42  
    43  		if err != nil {
    44  			return nil, core.SourceError(iterable.src, err)
    45  		}
    46  
    47  		switch data.Type() {
    48  		case types.Array:
    49  			return collections.NewIndexedIterator(iterable.valVariable, iterable.keyVariable, data.(collections.IndexedCollection))
    50  		case types.Object:
    51  			return collections.NewKeyedIterator(iterable.valVariable, iterable.keyVariable, data.(collections.KeyedCollection))
    52  		default:
    53  			// fallback to user defined types
    54  			switch collection := data.(type) {
    55  			case core.Iterable:
    56  				iterator, err := collection.Iterate(ctx)
    57  
    58  				if err != nil {
    59  					return nil, err
    60  				}
    61  
    62  				return collections.FromCoreIterator(iterable.valVariable, iterable.keyVariable, iterator)
    63  			case collections.KeyedCollection:
    64  				return collections.NewKeyedIterator(iterable.valVariable, iterable.keyVariable, collection)
    65  			case collections.IndexedCollection:
    66  				return collections.NewIndexedIterator(iterable.valVariable, iterable.keyVariable, collection)
    67  			default:
    68  				return nil, core.TypeError(
    69  					data.Type(),
    70  					types.Array,
    71  					types.Object,
    72  					core.NewType("Iterable"),
    73  				)
    74  			}
    75  		}
    76  	}
    77  }