Compare commits
4 Commits
382cb7aabd
...
all-in-one
| Author | SHA1 | Date | |
|---|---|---|---|
| e2b0a43640 | |||
| 481074d104 | |||
| 6f08176122 | |||
| d24f1315b2 |
+2
-2
@@ -93,8 +93,8 @@ func runFunc(ctx kern.ExprContext, name string, args map[string]any) (result any
|
|||||||
params[kern.ParamIndex] = it.Index()
|
params[kern.ParamIndex] = it.Index()
|
||||||
params[kern.ParamItem] = item
|
params[kern.ParamItem] = item
|
||||||
|
|
||||||
localCtx.UnsafeSetVar("_", it.Index())
|
localCtx.UnsafeSetVar("_", item)
|
||||||
localCtx.UnsafeSetVar("__", item)
|
localCtx.UnsafeSetVar("__", it.Index())
|
||||||
|
|
||||||
abort := false
|
abort := false
|
||||||
if _, err = op.InvokeNamed(localCtx, iterParamOperator, params); err != nil {
|
if _, err = op.InvokeNamed(localCtx, iterParamOperator, params); err != nil {
|
||||||
|
|||||||
+47
-3
@@ -506,6 +506,50 @@ Currently, boolean operations are evaluated using _short cut evaluation_. This m
|
|||||||
TIP: `ecli` provides the _ctrl()_ function that allows to change this behaviour.
|
TIP: `ecli` provides the _ctrl()_ function that allows to change this behaviour.
|
||||||
====
|
====
|
||||||
|
|
||||||
|
=== Intervals
|
||||||
|
_Expr_ supports intervals, which are a special kind of data type. An interval is a range *_open on the right_* of integer values between a lower and an upper bound. The lower and upper bounds can be specified in any order, i.e. the lower bound can be greater than the upper bound. In this case, the interval is considered _descending_.
|
||||||
|
|
||||||
|
Unlike arrays, intervals are not collections of values, but rather a compact representation of a range of values. And unlike other programming languages that separate lower and upper bounds by a colonn, _Expr_ separates them by a double dot symbol `..`.
|
||||||
|
|
||||||
|
NOTE: Intervals are _open on the right_, which means that the upper bound is not included in the interval. For example, the interval `1..5` contains the values 1, 2, 3, and 4, but not 5.
|
||||||
|
|
||||||
|
_Expr_'s intervals also support step values, which are optionally specified by a third integer value after the upper bound, separated by another doble dot symbol `..`. In this case, the interval represents a range of values starting from the lower bound, up to the upper bound, with a step increment equal to the specified step value. If the step value is not specified, it defaults to 1.
|
||||||
|
|
||||||
|
IMPORTANT: The step value must be a positive integer, despite the fact that the lower bound is greater than the upper bound. If it is negative or zero, an error is returned.
|
||||||
|
|
||||||
|
.Interval literal syntax
|
||||||
|
====
|
||||||
|
*_interval_* = [_lower-bound_] "**..**" _upper-bound_ ["**..**" _step_]
|
||||||
|
|
||||||
|
_lower-bound_ = _integer-expr_ +
|
||||||
|
_upper-bound_ = _integer-expr_ +
|
||||||
|
_step_ = _positive-integer-expr_
|
||||||
|
====
|
||||||
|
|
||||||
|
.Examples
|
||||||
|
`>>>` [blue]`3..5` +
|
||||||
|
[green]`3..5..1`
|
||||||
|
|
||||||
|
`>>>` [blue]`5..3` +
|
||||||
|
[green]`5..3..1`
|
||||||
|
|
||||||
|
`>>>` [blue]`..4` +
|
||||||
|
[green]`0..4..1`
|
||||||
|
|
||||||
|
`>>>` [blue]`4..` +
|
||||||
|
[green]`4..4..1`
|
||||||
|
|
||||||
|
`>>>` [blue]`-1..-4` +
|
||||||
|
[green]`-1..-4..1`
|
||||||
|
|
||||||
|
`>>>` [blue]`-1..-4..-1` +
|
||||||
|
[red]`Eval Error: [1:8] invalid interval specification: step must be positive`
|
||||||
|
|
||||||
|
`>>>` [blue]`r = -1..-4` [gray]_// assign interval to variable r_ +
|
||||||
|
[green]`-1..-4..1`
|
||||||
|
|
||||||
|
Main usages of intervals are to generate slices of arrays and to check if a value is in an interval.
|
||||||
|
|
||||||
=== Arrays
|
=== Arrays
|
||||||
_Expr_ supports arrays of mixed-type values, also specified by normal expressions. Internally, _Expr_'s arrays are Go slices.
|
_Expr_ supports arrays of mixed-type values, also specified by normal expressions. Internally, _Expr_'s arrays are Go slices.
|
||||||
|
|
||||||
@@ -513,7 +557,7 @@ _Expr_ supports arrays of mixed-type values, also specified by normal expression
|
|||||||
====
|
====
|
||||||
*_array_* = _empty-array_ | _non-empty-array_ +
|
*_array_* = _empty-array_ | _non-empty-array_ +
|
||||||
_empty-array_ = "**[]**" +
|
_empty-array_ = "**[]**" +
|
||||||
_non-empty-array_ = "**[**" _any-value_ {"**,**" _any-value_} "**]**" +
|
_non-empty-array_ = "**[**" _any-value_ {"**,**" _any-value_} "**]**"
|
||||||
====
|
====
|
||||||
|
|
||||||
.Examples
|
.Examples
|
||||||
@@ -559,7 +603,7 @@ Array's items can be accessed using the index `[]` operator.
|
|||||||
|
|
||||||
.Sub-array (or slice of array) syntax
|
.Sub-array (or slice of array) syntax
|
||||||
====
|
====
|
||||||
*_slice_* = _array-expr_ "**[**" _integer-expr_ "**:**" _integer-expr_ "**]**"
|
*_slice_* = _array-expr_ "**[**" _interval-expr_ "**]**"
|
||||||
====
|
====
|
||||||
|
|
||||||
.Examples: Getting items from arrays
|
.Examples: Getting items from arrays
|
||||||
@@ -569,7 +613,7 @@ Array's items can be accessed using the index `[]` operator.
|
|||||||
`>>>` [blue]`index=2; ["a", "b", "c", "d"][index]` +
|
`>>>` [blue]`index=2; ["a", "b", "c", "d"][index]` +
|
||||||
[green]`c`
|
[green]`c`
|
||||||
|
|
||||||
`>>>` [blue]`["a", "b", "c", "d"][2:]` +
|
`>>>` [blue]`["a", "b", "c", "d"][2..4]` +
|
||||||
[green]`["c", "d"]`
|
[green]`["c", "d"]`
|
||||||
|
|
||||||
`>>>` [blue]`array=[1,2,3]; array[1]` +
|
`>>>` [blue]`array=[1,2,3]; array[1]` +
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ const (
|
|||||||
ParamIterator = "iterator"
|
ParamIterator = "iterator"
|
||||||
)
|
)
|
||||||
|
|
||||||
// to be moved in its own source file
|
// to be moved into its own source file
|
||||||
const (
|
const (
|
||||||
ConstLastIndex = 0xFFFF_FFFF
|
ConstLastIndex = 0xFFFF_FFFF
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"git.portale-stac.it/go-pkg/expr/sym"
|
"git.portale-stac.it/go-pkg/expr/sym"
|
||||||
"git.portale-stac.it/go-pkg/expr/types/array"
|
"git.portale-stac.it/go-pkg/expr/types/array"
|
||||||
"git.portale-stac.it/go-pkg/expr/types/dict"
|
"git.portale-stac.it/go-pkg/expr/types/dict"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/types/interval"
|
||||||
"git.portale-stac.it/go-pkg/expr/types/list"
|
"git.portale-stac.it/go-pkg/expr/types/list"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -46,6 +47,9 @@ func evalIn(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
|||||||
} else if list.IsLinkedList(rightValue) {
|
} else if list.IsLinkedList(rightValue) {
|
||||||
ls, _ := rightValue.(*list.LinkedList)
|
ls, _ := rightValue.(*list.LinkedList)
|
||||||
v = ls.HasValue(leftValue)
|
v = ls.HasValue(leftValue)
|
||||||
|
} else if interval.IsInterval(rightValue) {
|
||||||
|
r, _ := rightValue.(*interval.IntervalType)
|
||||||
|
v = r.Contains(leftValue)
|
||||||
} else {
|
} else {
|
||||||
err = opTerm.ErrIncompatibleTypes(leftValue, rightValue)
|
err = opTerm.ErrIncompatibleTypes(leftValue, rightValue)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,6 @@ type TermPriority uint32
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
PriNone TermPriority = iota
|
PriNone TermPriority = iota
|
||||||
PriInterval
|
|
||||||
PriBut
|
PriBut
|
||||||
PriAssign
|
PriAssign
|
||||||
PriIterOp // map, filter, digest, etc
|
PriIterOp // map, filter, digest, etc
|
||||||
@@ -24,6 +23,7 @@ const (
|
|||||||
PriAnd
|
PriAnd
|
||||||
PriNot
|
PriNot
|
||||||
PriRelational
|
PriRelational
|
||||||
|
PriInterval
|
||||||
PriBitwiseOr
|
PriBitwiseOr
|
||||||
PriBitwiseAnd
|
PriBitwiseAnd
|
||||||
PriBitwiseNot
|
PriBitwiseNot
|
||||||
|
|||||||
+2
-1
@@ -45,10 +45,11 @@ func TestCollections(t *testing.T) {
|
|||||||
/* 29 */ {`"abcdef"['x'..]`, nil, `[1:14] interval expression expected integer, got string (x)`},
|
/* 29 */ {`"abcdef"['x'..]`, nil, `[1:14] interval expression expected integer, got string (x)`},
|
||||||
/* 30 */ {`"abcdef"[1+..]`, nil, `[1:12] infix operator "+" requires two non-nil operands, got 1`},
|
/* 30 */ {`"abcdef"[1+..]`, nil, `[1:12] infix operator "+" requires two non-nil operands, got 1`},
|
||||||
/* 31 */ {`"abcdef"[1..4+]`, nil, `[1:15] infix operator "+" requires two non-nil operands, got 1`},
|
/* 31 */ {`"abcdef"[1..4+]`, nil, `[1:15] infix operator "+" requires two non-nil operands, got 1`},
|
||||||
|
/* 32 */ {`r=-1..0..2; "abcdef"[r]`, "fdb", nil},
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Setenv("EXPR_PATH", ".")
|
t.Setenv("EXPR_PATH", ".")
|
||||||
|
|
||||||
// RunTestSuiteSpec(t, section, inputs, 30)
|
// RunTestSuiteSpec(t, section, inputs, 32)
|
||||||
RunTestSuite(t, section, inputs)
|
RunTestSuite(t, section, inputs)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
|
"git.portale-stac.it/go-pkg/expr/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
const TypeName = "interval"
|
const TypeName = "interval"
|
||||||
@@ -60,6 +61,17 @@ func (p *IntervalType) ToIntTriple() (b, e, s int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *IntervalType) Contains(value any) (ok bool) {
|
||||||
|
if v, err := types.ToGoInt64(value, TypeName); err == nil {
|
||||||
|
if p.begin <= p.end {
|
||||||
|
ok = (v >= p.begin && v < p.end && (v-p.begin)%p.step == 0)
|
||||||
|
} else {
|
||||||
|
ok = (v <= p.begin && v > p.end && (v-p.begin)%p.step == 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// func (b *bool) EqualTo(other kern.Equaler) (equal bool) {
|
// func (b *bool) EqualTo(other kern.Equaler) (equal bool) {
|
||||||
// if otherBool, ok := other.(*bool); ok {
|
// if otherBool, ok := other.(*bool); ok {
|
||||||
// equal = b == otherBool
|
// equal = b == otherBool
|
||||||
|
|||||||
Reference in New Issue
Block a user