mirror of
https://github.com/microsoft/regorus.git
synced 2026-08-05 02:16:11 +00:00
Merge pull request #7 from anakrish/main
Implement comparison operators. Formalize semantics.
This commit is contained in:
@@ -1,30 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
use crate::ast::*;
|
||||
use crate::value::{Value::*, *};
|
||||
|
||||
pub fn eq(v1: &Value, v2: &Value) -> Value {
|
||||
match (v1, v2) {
|
||||
(Undefined, _) | (_, Undefined) => Undefined,
|
||||
_ => Bool(v1 == v2),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ne(v1: &Value, v2: &Value) -> Value {
|
||||
match (v1, v2) {
|
||||
(Undefined, _) | (_, Undefined) => Undefined,
|
||||
_ => Bool(v1 != v2),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compare(op: &BoolOp, v1: &Value, v2: &Value) -> Value {
|
||||
match op {
|
||||
BoolOp::Eq => eq(v1, v2),
|
||||
BoolOp::Ne => ne(v1, v2),
|
||||
BoolOp::Ge => Bool(v1 >= v2),
|
||||
BoolOp::Gt => Bool(v1 > v2),
|
||||
BoolOp::Le => Bool(v1 <= v2),
|
||||
BoolOp::Lt => Bool(v1 < v2),
|
||||
}
|
||||
}
|
||||
60
src/builtins/comparison.rs
Normal file
60
src/builtins/comparison.rs
Normal file
@@ -0,0 +1,60 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
use crate::ast::BoolOp;
|
||||
use crate::value::Value;
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
/// compare two values
|
||||
///
|
||||
/// When comparing values of different kinds, the following order is honored.
|
||||
/// That is, null is less than all other kinds of values. bool is greater than
|
||||
/// null, but less than other kinds of values, and so on.
|
||||
///
|
||||
/// 1. null
|
||||
/// 2. bool
|
||||
/// 3. number
|
||||
/// 4. string
|
||||
/// 5. Array
|
||||
/// 6. Object
|
||||
/// 7. Set
|
||||
///
|
||||
/// Scalar types like null, bool, number, string follow ordering same as what is seen in other languages when compared with values of the same kind.
|
||||
///
|
||||
/// When comparing arrays, each item from the first array is compared with the corresponding item from the second array. The ordering is determined by
|
||||
// the ordering of the first non-equal items. In case all the compared items
|
||||
/// are equal, the ordering is determined by comparing the length of the first array
|
||||
/// with the length of the second array. The smaller array is 'Less' than the larger array.
|
||||
///
|
||||
/// Sets compare similar to arrays.
|
||||
///
|
||||
/// When comparing objects, each entry (key, value) from the first object is compared with the corresponding
|
||||
/// entry from the second object. The ordering is determined by the ordering of the first non-equal entries. In case all the compared entries are equal,
|
||||
/// the ordering is determined by comparing the length of the first object with the length of the second object. The smaller object is 'Less' then the larger object.
|
||||
///
|
||||
/// Undefined values are a special case. Comparing an Undefined value with
|
||||
/// any other value results in Undefined.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `op` - The comparison operation to perform.
|
||||
/// * `v1` - The first value.
|
||||
/// * `v2` - The second value.
|
||||
pub fn compare(op: &BoolOp, v1: &Value, v2: &Value) -> Result<Value> {
|
||||
// Handle undefined values.
|
||||
if v1 == &Value::Undefined || v2 == &Value::Undefined {
|
||||
return Ok(Value::Undefined);
|
||||
}
|
||||
|
||||
// Rely on generated comparison operators.
|
||||
// The variants of Value enum are specified in the order necessary to
|
||||
// obtain the desired semantics.
|
||||
Ok(Value::Bool(match op {
|
||||
BoolOp::Eq => v1 == v2,
|
||||
BoolOp::Ne => v1 != v2,
|
||||
BoolOp::Lt => v1 < v2,
|
||||
BoolOp::Le => v1 <= v2,
|
||||
BoolOp::Gt => v1 > v2,
|
||||
BoolOp::Ge => v1 >= v2,
|
||||
}))
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
mod compare;
|
||||
mod comparison;
|
||||
|
||||
pub use self::compare::*;
|
||||
pub use self::comparison::*;
|
||||
|
||||
@@ -262,7 +262,7 @@ impl<'source> Interpreter<'source> {
|
||||
) -> Result<Value> {
|
||||
let lhs = self.eval_expr(lhs_expr)?;
|
||||
let rhs = self.eval_expr(rhs_expr)?;
|
||||
Ok(builtins::compare(op, &lhs, &rhs))
|
||||
builtins::compare(op, &lhs, &rhs)
|
||||
}
|
||||
|
||||
fn eval_bin_expr(
|
||||
@@ -531,10 +531,23 @@ impl<'source> Interpreter<'source> {
|
||||
if loops.is_empty() {
|
||||
if !stmts.is_empty() {
|
||||
// Evaluate the current statement whose loop expressions have been hoisted.
|
||||
if !self.eval_stmt(&stmts[0])? {
|
||||
return Ok(false);
|
||||
}
|
||||
self.eval_stmts(&stmts[1..])
|
||||
// Save the current scope and restore it after evaluating the statements so
|
||||
// that the effects of the current loop iteration are cleared.
|
||||
let scope_saved = match self.scopes.last() {
|
||||
Some(scope) => scope.clone(),
|
||||
_ => bail!("internal error: missing scope"),
|
||||
};
|
||||
let result = if self.eval_stmt(&stmts[0])? {
|
||||
self.eval_stmts(&stmts[1..])
|
||||
} else {
|
||||
Ok(false)
|
||||
};
|
||||
|
||||
match self.scopes.last_mut() {
|
||||
Some(scope) => *scope = scope_saved,
|
||||
_ => bail!("internal error: missing scope"),
|
||||
};
|
||||
result
|
||||
} else {
|
||||
self.eval_stmts(stmts)
|
||||
}
|
||||
@@ -568,7 +581,7 @@ impl<'source> Interpreter<'source> {
|
||||
));
|
||||
}
|
||||
}
|
||||
self.loop_var_values.remove(loop_expr.expr);
|
||||
|
||||
// Return true if at least on iteration returned true
|
||||
Ok(result)
|
||||
}
|
||||
@@ -1617,6 +1630,15 @@ impl<'source> Interpreter<'source> {
|
||||
if let Some(data) = data {
|
||||
self.data = data.clone();
|
||||
}
|
||||
// Ensure that each module has an empty object
|
||||
for m in &self.modules {
|
||||
let path = Parser::get_path_ref_components(&m.package.refr)?;
|
||||
let path: Vec<&str> = path.iter().map(|s| s.text()).collect();
|
||||
let vref = Self::make_or_get_value_mut(&mut self.data, &path[..])?;
|
||||
if *vref == Value::Undefined {
|
||||
*vref = Value::new_object();
|
||||
}
|
||||
}
|
||||
|
||||
self.check_default_rules()?;
|
||||
self.update_function_table()?;
|
||||
|
||||
@@ -87,8 +87,8 @@ pub enum Value {
|
||||
// Json data types. serde will automatically map json to these variants.
|
||||
Null,
|
||||
Bool(bool),
|
||||
String(String),
|
||||
Number(Number),
|
||||
String(String),
|
||||
Array(Rc<Vec<Value>>),
|
||||
Object(Rc<BTreeMap<Value, Value>>),
|
||||
|
||||
|
||||
@@ -2,233 +2,568 @@
|
||||
# Licensed under the MIT License.
|
||||
|
||||
cases:
|
||||
- note: number-equals
|
||||
- note: undefined
|
||||
data: {}
|
||||
modules:
|
||||
- |
|
||||
package test
|
||||
import future.keywords.if
|
||||
# All the following rules will be undefined.
|
||||
x if false
|
||||
|
||||
v = 1
|
||||
r = [
|
||||
# Comparison with number
|
||||
v == 1,
|
||||
v == 2,
|
||||
|
||||
# Comparison with primitives
|
||||
v == null,
|
||||
v == "hello",
|
||||
v == true,
|
||||
v == false,
|
||||
|
||||
# Comparison with arrays
|
||||
v == [],
|
||||
v == [v],
|
||||
|
||||
# Comparison with sets
|
||||
v == set(),
|
||||
v == { v },
|
||||
|
||||
# Comparison with objects
|
||||
v == {},
|
||||
v == { "a": v},
|
||||
]
|
||||
sort_bindings: false
|
||||
v1 = x == 1
|
||||
v2 = 1 == x
|
||||
|
||||
v3 = x != 1
|
||||
v4 = 1 != x
|
||||
|
||||
v5 = x < 1
|
||||
v6 = 1 < x
|
||||
|
||||
v7 = x <= 1
|
||||
v8 = 1 <= x
|
||||
|
||||
v9 = x > 1
|
||||
v10 = 1 > x
|
||||
|
||||
v11 = x >= 1
|
||||
v12 = 1 >= x
|
||||
query: data.test
|
||||
want_result:
|
||||
v: 1
|
||||
r: [ true, false, false, false, false, false,
|
||||
false, false, false, false, false, false]
|
||||
|
||||
- note: null-equals
|
||||
want_result: {}
|
||||
|
||||
- note: eq
|
||||
data: {}
|
||||
modules:
|
||||
- |
|
||||
package test
|
||||
|
||||
v = null
|
||||
r = [
|
||||
# Comparison with number
|
||||
v == 1,
|
||||
v == 2,
|
||||
|
||||
# Comparison with primitives
|
||||
v == null,
|
||||
v == "hello",
|
||||
v == true,
|
||||
v == false,
|
||||
|
||||
# Comparison with arrays
|
||||
v == [],
|
||||
v == [v],
|
||||
|
||||
# Comparison with sets
|
||||
v == set(),
|
||||
v == { v },
|
||||
|
||||
# Comparison with objects
|
||||
v == {},
|
||||
v == { "a": v},
|
||||
]
|
||||
sort_bindings: false
|
||||
query: data.test
|
||||
want_result:
|
||||
v: null
|
||||
r: [ false, false, true, false, false, false,
|
||||
false, false, false, false, false, false]
|
||||
|
||||
- note: string-equals
|
||||
data: {}
|
||||
modules:
|
||||
- |
|
||||
package test
|
||||
|
||||
v = "hello"
|
||||
r = [
|
||||
# Comparison with number
|
||||
v == 1,
|
||||
v == 2,
|
||||
|
||||
# Comparison with primitives
|
||||
v == null,
|
||||
v == "hello",
|
||||
v == true,
|
||||
v == false,
|
||||
|
||||
# Comparison with arrays
|
||||
v == [],
|
||||
v == [v],
|
||||
|
||||
# Comparison with sets
|
||||
v == set(),
|
||||
v == { v },
|
||||
|
||||
# Comparison with objects
|
||||
v == {},
|
||||
v == { "a": v},
|
||||
]
|
||||
sort_bindings: false
|
||||
query: data.test
|
||||
want_result:
|
||||
v: "hello"
|
||||
r: [ false, false, false, true, false, false,
|
||||
false, false, false, false, false, false]
|
||||
|
||||
- note: true-equals
|
||||
data: {}
|
||||
modules:
|
||||
- |
|
||||
package test
|
||||
|
||||
v = true
|
||||
r = [
|
||||
# Comparison with number
|
||||
v == 1,
|
||||
v == 2,
|
||||
|
||||
# Comparison with primitives
|
||||
v == null,
|
||||
v == "hello",
|
||||
v == true,
|
||||
v == false,
|
||||
|
||||
# Comparison with arrays
|
||||
v == [],
|
||||
v == [v],
|
||||
|
||||
# Comparison with sets
|
||||
v == set(),
|
||||
v == { v },
|
||||
|
||||
# Comparison with objects
|
||||
v == {},
|
||||
v == { "a": v},
|
||||
]
|
||||
sort_bindings: false
|
||||
query: data.test
|
||||
want_result:
|
||||
v: true
|
||||
r: [ false, false, false, false, true, false,
|
||||
false, false, false, false, false, false]
|
||||
|
||||
|
||||
- note: false-equals
|
||||
data: {}
|
||||
modules:
|
||||
- |
|
||||
package test
|
||||
|
||||
v = false
|
||||
r = [
|
||||
# Comparison with number
|
||||
v == 1, # true
|
||||
v == 1, # false
|
||||
|
||||
# Comparison with primitives
|
||||
v == null,
|
||||
v == "hello",
|
||||
v == true,
|
||||
v == false,
|
||||
|
||||
# Comparison with arrays
|
||||
v == [],
|
||||
v == [v],
|
||||
|
||||
# Comparison with sets
|
||||
v == set(),
|
||||
v == { v },
|
||||
|
||||
# Comparison with objects
|
||||
v == {},
|
||||
v == { "a": v},
|
||||
]
|
||||
sort_bindings: false
|
||||
query: data.test
|
||||
want_result:
|
||||
v: false
|
||||
r: [ false, false, false, false, false, true,
|
||||
false, false, false, false, false, false]
|
||||
|
||||
- note: undefined-equals
|
||||
data: {}
|
||||
modules:
|
||||
- |
|
||||
package test
|
||||
import future.keywords
|
||||
|
||||
v = 1 if false
|
||||
r = [
|
||||
# Comparison with number
|
||||
v == 1,
|
||||
v == 2,
|
||||
|
||||
# Comparison with primitives
|
||||
v == null,
|
||||
v == "hello",
|
||||
v == true,
|
||||
v == false,
|
||||
|
||||
# Comparison with arrays
|
||||
v == [],
|
||||
v == [v],
|
||||
|
||||
# Comparison with sets
|
||||
v == set(),
|
||||
v == { v },
|
||||
|
||||
# Comparison with objects
|
||||
v == {},
|
||||
v == { "a": v},
|
||||
# true
|
||||
values = [
|
||||
1,
|
||||
-1,
|
||||
null,
|
||||
"hello",
|
||||
`hello`,
|
||||
true,
|
||||
false,
|
||||
[],
|
||||
[1, 2, 3],
|
||||
[4,"abc", null],
|
||||
set(),
|
||||
{1, 2, 3},
|
||||
{4, "abc", null},
|
||||
{},
|
||||
{"a" : 1},
|
||||
]
|
||||
|
||||
r2 = 1 if v
|
||||
|
||||
# This variable should appear in output since it is not undefined.
|
||||
ok = true
|
||||
|
||||
sort_bindings: false
|
||||
query: data.test
|
||||
values_1 = values
|
||||
# Evaluate rule so that rule[x] = [ values equal to x ]
|
||||
results[x] = y {
|
||||
x = values[_]
|
||||
y = [ z |
|
||||
z := values_1[_]
|
||||
x == z
|
||||
]
|
||||
}
|
||||
query: data.test.results
|
||||
want_result:
|
||||
ok: true
|
||||
object!:
|
||||
- key: 1
|
||||
value: [ 1 ]
|
||||
- key: -1
|
||||
value: [ -1 ]
|
||||
- key: null
|
||||
value: [null]
|
||||
- key: "hello"
|
||||
value: ["hello", "hello"]
|
||||
- key: true
|
||||
value: [true]
|
||||
- key: false
|
||||
value: [false]
|
||||
- key: []
|
||||
value: [[]]
|
||||
- key: [1, 2, 3]
|
||||
value: [[1, 2, 3]]
|
||||
- key: [4, "abc", null]
|
||||
value: [[4, "abc", null]]
|
||||
- key:
|
||||
set!: []
|
||||
value:
|
||||
- set!: []
|
||||
- key:
|
||||
set!: [ 1, 2, 3]
|
||||
value:
|
||||
- set!: [1, 2, 3]
|
||||
- key:
|
||||
set!: [4, "abc", null]
|
||||
value:
|
||||
- set!: [4, "abc", null]
|
||||
- key:
|
||||
object!: []
|
||||
value:
|
||||
- object!: []
|
||||
- key:
|
||||
object!:
|
||||
- key: a
|
||||
value: 1
|
||||
value:
|
||||
- a: 1
|
||||
|
||||
|
||||
|
||||
- note: eq-undefined
|
||||
data: {}
|
||||
modules:
|
||||
- |
|
||||
package test
|
||||
import future.keywords.if
|
||||
# All the following rules will be undefined.
|
||||
x if false
|
||||
y = x == 1
|
||||
z = 1 == x
|
||||
query: data.test
|
||||
want_result: {}
|
||||
|
||||
- note: ne
|
||||
data: {}
|
||||
modules:
|
||||
- |
|
||||
package test
|
||||
|
||||
# true
|
||||
values = [
|
||||
1,
|
||||
-1,
|
||||
null,
|
||||
"hello",
|
||||
`hello`,
|
||||
true,
|
||||
false,
|
||||
[],
|
||||
[1, 2, 3],
|
||||
[4,"abc", null],
|
||||
set(),
|
||||
{1, 2, 3},
|
||||
{4, "abc", null},
|
||||
{},
|
||||
{"a" : 1},
|
||||
]
|
||||
|
||||
values_1 = values
|
||||
# Evaluate rule so that rule[x] = [ values equal to x ]
|
||||
results[x] = y {
|
||||
x = values[_]
|
||||
y = [ z |
|
||||
z := values_1[_]
|
||||
# Use != and ne
|
||||
not x != z
|
||||
]
|
||||
}
|
||||
query: data.test.results
|
||||
want_result:
|
||||
object!:
|
||||
- key: 1
|
||||
value: [ 1 ]
|
||||
- key: -1
|
||||
value: [ -1 ]
|
||||
- key: null
|
||||
value: [null]
|
||||
- key: "hello"
|
||||
value: ["hello", "hello"]
|
||||
- key: true
|
||||
value: [true]
|
||||
- key: false
|
||||
value: [false]
|
||||
- key: []
|
||||
value: [[]]
|
||||
- key: [1, 2, 3]
|
||||
value: [[1, 2, 3]]
|
||||
- key: [4, "abc", null]
|
||||
value: [[4, "abc", null]]
|
||||
- key:
|
||||
set!: []
|
||||
value:
|
||||
- set!: []
|
||||
- key:
|
||||
set!: [ 1, 2, 3]
|
||||
value:
|
||||
- set!: [1, 2, 3]
|
||||
- key:
|
||||
set!: [4, "abc", null]
|
||||
value:
|
||||
- set!: [4, "abc", null]
|
||||
- key:
|
||||
object!: []
|
||||
value:
|
||||
- object!: []
|
||||
- key:
|
||||
object!:
|
||||
- key: a
|
||||
value: 1
|
||||
value:
|
||||
- a: 1
|
||||
|
||||
|
||||
- note: order
|
||||
data: {}
|
||||
modules:
|
||||
- |
|
||||
package test
|
||||
|
||||
v = [
|
||||
null,
|
||||
false,
|
||||
0,
|
||||
"",
|
||||
[],
|
||||
{},
|
||||
set()
|
||||
]
|
||||
|
||||
results = {
|
||||
"lt" : { x : y |
|
||||
x = v[_]
|
||||
y = [z | z = v[_]; x < z]
|
||||
},
|
||||
"le" : { x : y |
|
||||
x = v[_]
|
||||
y = [z | z = v[_]; x <= z]
|
||||
},
|
||||
"gt" : { x : y |
|
||||
x = v[_]
|
||||
y = [z | z = v[_]; x > z]
|
||||
},
|
||||
"ge" : { x : y |
|
||||
x = v[_]
|
||||
y = [z | z = v[_]; x >= z]
|
||||
}
|
||||
}
|
||||
query: data.test.results
|
||||
want_result:
|
||||
lt:
|
||||
object!:
|
||||
- key: null
|
||||
value: [false, 0, "", [], {}, {"set!":[]}]
|
||||
- key: false
|
||||
value: [0, "", [], {}, {"set!":[]}]
|
||||
- key: 0
|
||||
value: ["", [], {}, {"set!":[]}]
|
||||
- key: ""
|
||||
value: [[], {}, {"set!":[]}]
|
||||
- key: []
|
||||
value: [{}, {"set!":[]}]
|
||||
- key: {}
|
||||
value: [{"set!":[]}]
|
||||
- key: {"set!":[]}
|
||||
value: []
|
||||
le:
|
||||
object!:
|
||||
- key: null
|
||||
value: [null, false, 0, "", [], {}, {"set!":[]}]
|
||||
- key: false
|
||||
value: [false, 0, "", [], {}, {"set!":[]}]
|
||||
- key: 0
|
||||
value: [0, "", [], {}, {"set!":[]}]
|
||||
- key: ""
|
||||
value: ["", [], {}, {"set!":[]}]
|
||||
- key: []
|
||||
value: [[], {}, {"set!":[]}]
|
||||
- key: {}
|
||||
value: [{}, {"set!":[]}]
|
||||
- key: {"set!":[]}
|
||||
value: [{"set!":[]}]
|
||||
gt:
|
||||
object!:
|
||||
- key: null
|
||||
value: []
|
||||
- key: false
|
||||
value: [null]
|
||||
- key: 0
|
||||
value: [null, false]
|
||||
- key: ""
|
||||
value: [null, false, 0]
|
||||
- key: []
|
||||
value: [null, false, 0, ""]
|
||||
- key: {}
|
||||
value: [null, false, 0, "", []]
|
||||
- key: {"set!":[]}
|
||||
value: [null, false, 0, "", [], {}]
|
||||
ge:
|
||||
object!:
|
||||
- key: null
|
||||
value: [null]
|
||||
- key: false
|
||||
value: [null, false]
|
||||
- key: 0
|
||||
value: [null, false, 0]
|
||||
- key: ""
|
||||
value: [null, false, 0, ""]
|
||||
- key: []
|
||||
value: [null, false, 0, "", []]
|
||||
- key: {}
|
||||
value: [null, false, 0, "", [], {}]
|
||||
- key: {"set!":[]}
|
||||
value: [null, false, 0, "", [], {}, {"set!":[]}]
|
||||
|
||||
- note: arrays
|
||||
data: {}
|
||||
modules:
|
||||
- |
|
||||
package test
|
||||
|
||||
v = [ [], [1, 2], [0, 1, 2], [1, 2, 3]]
|
||||
|
||||
results = {
|
||||
"lt" : { x : y |
|
||||
x = v[_]
|
||||
y = [z | z = v[_]; x < z]
|
||||
},
|
||||
"le" : { x : y |
|
||||
x = v[_]
|
||||
y = [z | z = v[_]; x <= z]
|
||||
},
|
||||
"gt" : { x : y |
|
||||
x = v[_]
|
||||
y = [z | z = v[_]; x > z]
|
||||
},
|
||||
"ge" : { x : y |
|
||||
x = v[_]
|
||||
y = [z | z = v[_]; x >= z]
|
||||
}
|
||||
}
|
||||
query: data.test.results
|
||||
want_result:
|
||||
lt:
|
||||
object!:
|
||||
- key: []
|
||||
value: [[1,2], [0, 1, 2], [1, 2, 3]]
|
||||
- key: [1, 2]
|
||||
value: [[1, 2, 3]]
|
||||
- key: [0, 1, 2]
|
||||
value: [ [1,2], [1, 2, 3]]
|
||||
- key: [1, 2, 3]
|
||||
value: []
|
||||
le:
|
||||
object!:
|
||||
- key: []
|
||||
value: [[], [1,2], [0, 1, 2], [1, 2, 3]]
|
||||
- key: [1, 2]
|
||||
value: [[1, 2], [1, 2, 3]]
|
||||
- key: [0, 1, 2]
|
||||
value: [[1,2], [0, 1, 2], [1, 2, 3]]
|
||||
- key: [1, 2, 3]
|
||||
value: [[1, 2, 3]]
|
||||
gt:
|
||||
object!:
|
||||
- key: []
|
||||
value: []
|
||||
- key: [1, 2]
|
||||
value: [[], [0, 1, 2]]
|
||||
- key: [0, 1, 2]
|
||||
value: [[]]
|
||||
- key: [1, 2, 3]
|
||||
value: [[], [1, 2], [0, 1, 2]]
|
||||
ge:
|
||||
object!:
|
||||
- key: []
|
||||
value: [[]]
|
||||
- key: [1, 2]
|
||||
value: [[], [1, 2], [0, 1, 2]]
|
||||
- key: [0, 1, 2]
|
||||
value: [[], [0, 1, 2]]
|
||||
- key: [1, 2, 3]
|
||||
value: [[], [1, 2], [0, 1, 2], [1, 2, 3]]
|
||||
|
||||
- note: sets
|
||||
data: {}
|
||||
modules:
|
||||
- |
|
||||
package test
|
||||
|
||||
v = [ set(), {1, 2}, {0, 1, 2}, {1, 2, 3}]
|
||||
|
||||
results = {
|
||||
"lt" : { x : y |
|
||||
x = v[_]
|
||||
y = [z | z = v[_]; x < z]
|
||||
},
|
||||
"le" : { x : y |
|
||||
x = v[_]
|
||||
y = [z | z = v[_]; x <= z]
|
||||
},
|
||||
"gt" : { x : y |
|
||||
x = v[_]
|
||||
y = [z | z = v[_]; x > z]
|
||||
},
|
||||
"ge" : { x : y |
|
||||
x = v[_]
|
||||
y = [z | z = v[_]; x >= z]
|
||||
}
|
||||
}
|
||||
query: data.test.results
|
||||
want_result:
|
||||
lt:
|
||||
object!:
|
||||
- key:
|
||||
set!: []
|
||||
value:
|
||||
- set!: [1,2]
|
||||
- set!: [0, 1, 2]
|
||||
- set!: [1, 2, 3]
|
||||
- key:
|
||||
set!: [1, 2]
|
||||
value:
|
||||
- set!: [1, 2, 3]
|
||||
- key:
|
||||
set!: [0, 1, 2]
|
||||
value:
|
||||
- set!: [1,2]
|
||||
- set!: [1, 2, 3]
|
||||
- key:
|
||||
set!: [1, 2, 3]
|
||||
value: []
|
||||
le:
|
||||
object!:
|
||||
- key:
|
||||
set!: []
|
||||
value:
|
||||
- set!: []
|
||||
- set!: [1,2]
|
||||
- set!: [0, 1, 2]
|
||||
- set!: [1, 2, 3]
|
||||
- key:
|
||||
set!: [1, 2]
|
||||
value:
|
||||
- set!: [1, 2]
|
||||
- set!: [1, 2, 3]
|
||||
- key:
|
||||
set!: [0, 1, 2]
|
||||
value:
|
||||
- set!: [1,2]
|
||||
- set!: [0, 1, 2]
|
||||
- set!: [1, 2, 3]
|
||||
- key:
|
||||
set!: [1, 2, 3]
|
||||
value:
|
||||
- set!: [1, 2, 3]
|
||||
gt:
|
||||
object!:
|
||||
- key:
|
||||
set!: []
|
||||
value: []
|
||||
- key:
|
||||
set!: [1, 2]
|
||||
value:
|
||||
- set!: []
|
||||
- set!: [0, 1, 2]
|
||||
- key:
|
||||
set!: [0, 1, 2]
|
||||
value:
|
||||
- set!: []
|
||||
- key:
|
||||
set!: [1, 2, 3]
|
||||
value:
|
||||
- set!: []
|
||||
- set!: [1, 2]
|
||||
- set!: [0, 1, 2]
|
||||
ge:
|
||||
object!:
|
||||
- key:
|
||||
set!: []
|
||||
value:
|
||||
- set!: []
|
||||
- key:
|
||||
set!: [1, 2]
|
||||
value:
|
||||
- set!: []
|
||||
- set!: [1, 2]
|
||||
- set!: [0, 1, 2]
|
||||
- key:
|
||||
set!: [0, 1, 2]
|
||||
value:
|
||||
- set!: []
|
||||
- set!: [0, 1, 2]
|
||||
- key:
|
||||
set!: [1, 2, 3]
|
||||
value:
|
||||
- set!: []
|
||||
- set!: [1, 2]
|
||||
- set!: [0, 1, 2]
|
||||
- set!: [1, 2, 3]
|
||||
|
||||
- note: objects
|
||||
data: {}
|
||||
modules:
|
||||
- |
|
||||
package test
|
||||
|
||||
v = [{}, {"a":1}, {"a":2}, {"a":1, "b":0}, {"b":0}]
|
||||
|
||||
results = {
|
||||
"lt" : { x : y |
|
||||
x = v[_]
|
||||
y = [z | z = v[_]; x < z]
|
||||
},
|
||||
"le" : { x : y |
|
||||
x = v[_]
|
||||
y = [z | z = v[_]; x <= z]
|
||||
},
|
||||
"gt" : { x : y |
|
||||
x = v[_]
|
||||
y = [z | z = v[_]; x > z]
|
||||
},
|
||||
"ge" : { x : y |
|
||||
x = v[_]
|
||||
y = [z | z = v[_]; x >= z]
|
||||
}
|
||||
}
|
||||
query: data.test.results
|
||||
want_result:
|
||||
lt:
|
||||
object!:
|
||||
- key: {}
|
||||
value: [ {"a":1}, {"a":2}, {"a":1, "b":0}, {"b":0}]
|
||||
- key: {"a":1}
|
||||
value: [{"a":2}, {"a":1, "b":0}, {"b":0}]
|
||||
- key: {"a":2}
|
||||
value: [{"b":0}]
|
||||
- key: {"a":1, "b":0}
|
||||
value: [{"a":2}, {"b":0}]
|
||||
- key: {"b":0}
|
||||
value: []
|
||||
le:
|
||||
object!:
|
||||
- key: {}
|
||||
value: [ {}, {"a":1}, {"a":2}, {"a":1, "b":0}, {"b":0}]
|
||||
- key: {"a":1}
|
||||
value: [{"a":1}, {"a":2}, {"a":1, "b":0}, {"b":0}]
|
||||
- key: {"a":2}
|
||||
value: [{"a":2}, {"b":0}]
|
||||
- key: {"a":1, "b":0}
|
||||
value: [{"a":2}, {"a":1, "b":0}, {"b":0}]
|
||||
- key: {"b":0}
|
||||
value: [{"b":0}]
|
||||
gt:
|
||||
object!:
|
||||
- key: {}
|
||||
value: []
|
||||
- key: {"a":1}
|
||||
value: [{}]
|
||||
- key: {"a":2}
|
||||
value: [{}, {"a":1}, {"a":1, "b":0}]
|
||||
- key: {"a":1, "b":0}
|
||||
value: [{}, {"a":1}]
|
||||
- key: {"b":0}
|
||||
value: [ {}, {"a":1}, {"a":2}, {"a":1, "b":0}]
|
||||
ge:
|
||||
object!:
|
||||
- key: {}
|
||||
value: [{}]
|
||||
- key: {"a":1}
|
||||
value: [{}, {"a":1}]
|
||||
- key: {"a":2}
|
||||
value: [{}, {"a":1}, {"a":2}, {"a":1, "b":0}]
|
||||
- key: {"a":1, "b":0}
|
||||
value: [{}, {"a":1}, {"a":1, "b":0}]
|
||||
- key: {"b":0}
|
||||
value: [ {}, {"a":1}, {"a":2}, {"a":1, "b":0}, {"b":0}]
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user