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

     1  package expressions
     2  
     3  import (
     4  	"math"
     5  
     6  	"github.com/MontFerret/ferret/pkg/runtime/core"
     7  	"github.com/MontFerret/ferret/pkg/runtime/values"
     8  )
     9  
    10  // Vector TODO: Finish and add unit tests
    11  type Vector struct {
    12  	slices   map[int][]core.Value
    13  	capacity int
    14  	current  int
    15  }
    16  
    17  func NewVector(capacity int) *Vector {
    18  	el := new(Vector)
    19  	el.slices = make(map[int][]core.Value)
    20  	el.capacity = capacity
    21  	el.current = -1
    22  
    23  	return el
    24  }
    25  
    26  func (vec *Vector) Push(value core.Value) *Vector {
    27  	slice := vec.getCurrentSlice()
    28  	slice[len(slice)] = value
    29  
    30  	return vec
    31  }
    32  
    33  func (vec *Vector) Get(index int) core.Value {
    34  	var sliceIndex int
    35  	var itemIndex int
    36  
    37  	// if it's within a capacity
    38  	if index < vec.capacity {
    39  		sliceIndex = 0
    40  		itemIndex = index
    41  	} else {
    42  		sliceIndex = int(math.Floor(float64(index / vec.capacity)))
    43  		itemIndex = index % vec.capacity
    44  	}
    45  
    46  	// if out of range
    47  	if sliceIndex >= len(vec.slices) {
    48  		return values.None
    49  	}
    50  
    51  	return vec.slices[sliceIndex][itemIndex]
    52  }
    53  
    54  func (vec *Vector) ForEach(predicate func(item core.Value, index int)) {
    55  	if len(vec.slices) == 0 {
    56  		return
    57  	}
    58  
    59  	lastIndex := vec.capacity * len(vec.slices)
    60  
    61  	for i := 0; i <= lastIndex; i++ {
    62  		itemIndex := i % vec.capacity
    63  		sliceIndex := int(math.Floor(float64(i / vec.capacity)))
    64  
    65  		predicate(vec.slices[sliceIndex][itemIndex], i)
    66  	}
    67  }
    68  
    69  func (vec *Vector) ToSlice() []core.Value {
    70  	out := make([]core.Value, vec.capacity*len(vec.slices))
    71  
    72  	if len(vec.slices) == 0 {
    73  		return out
    74  	}
    75  
    76  	lastIndex := vec.capacity * len(vec.slices)
    77  
    78  	for i := 0; i <= lastIndex; i++ {
    79  		itemIndex := i % vec.capacity
    80  		sliceIndex := int(math.Floor(float64(i / vec.capacity)))
    81  
    82  		out[i] = vec.slices[sliceIndex][itemIndex]
    83  	}
    84  
    85  	return out
    86  }
    87  
    88  func (vec *Vector) getCurrentSlice() []core.Value {
    89  	if vec.current < 0 {
    90  		return vec.newSlice()
    91  	}
    92  
    93  	current := vec.slices[vec.current]
    94  
    95  	if len(current) < vec.capacity {
    96  		return current
    97  	}
    98  
    99  	return vec.newSlice()
   100  }
   101  
   102  func (vec *Vector) newSlice() []core.Value {
   103  	slice := make([]core.Value, 0, vec.capacity)
   104  
   105  	vec.current++
   106  	vec.slices[vec.current] = slice
   107  
   108  	return slice
   109  }