///|
/// Evaluate binary operation
fn eval_binary_op(
op : BinaryOp,
left : Json,
right : Json,
) -> Json raise InterpreterError {
match op {
Add => json_add(left, right)
Subtract => json_subtract(left, right)
Multiply => json_multiply(left, right)
Divide => json_divide(left, right)
Modulo => json_modulo(left, right)
Equal => Json::boolean(compare_json(left, right) == 0)
NotEqual => Json::boolean(compare_json(left, right) != 0)
LessThan => Json::boolean(compare_json(left, right) < 0)
LessEq => Json::boolean(compare_json(left, right) <= 0)
GreaterThan => Json::boolean(compare_json(left, right) > 0)
GreaterEq => Json::boolean(compare_json(left, right) >= 0)
And =>
if @ast_internal.is_truthy(left) {
right
} else {
Json::boolean(false)
}
Or => if @ast_internal.is_truthy(left) { left } else { right }
}
}
///|
/// Arithmetic operations
fn json_add(left : Json, right : Json) -> Json raise InterpreterError {
match (left, right) {
(Number(a, ..), Number(b, ..)) => Json::number(a + b)
(String(a), String(b)) => Json::string(a + b)
(Array(a), Array(b)) => Json::array(a + b)
(Object(a), Object(b)) => Json::object(a.merge(b))
_ =>
raise InvalidOperation(
"Cannot add \{@ast_internal.json_type_name(left)} and \{@ast_internal.json_type_name(right)}",
)
}
}
///|
fn json_subtract(left : Json, right : Json) -> Json raise InterpreterError {
match (left, right) {
(Number(a, ..), Number(b, ..)) => Json::number(a - b)
(Array(a), Array(b)) => Json::array(array_without(a, b))
_ =>
raise InvalidOperation(
"Cannot subtract \{@ast_internal.json_type_name(right)} from \{@ast_internal.json_type_name(left)}",
)
}
}
///|
fn json_multiply(left : Json, right : Json) -> Json raise InterpreterError {
match (left, right) {
(Number(a, ..), Number(b, ..)) => Json::number(a * b)
(String(s), Number(n, ..)) | (Number(n, ..), String(s)) => {
let count = n.to_int()
Json::string(repeat_string(s, count))
}
_ =>
raise InvalidOperation(
"Cannot multiply \{@ast_internal.json_type_name(left)} and \{@ast_internal.json_type_name(right)}",
)
}
}
///|
fn repeat_string(s : String, count : Int) -> String {
if count <= 0 {
""
} else {
let builder = StringBuilder::new()
for _ in 0.. Bool {
haystack.iter().any(fn(value) { compare_json(value, needle) == 0 })
}
///|
fn array_without(
source : ArrayView[Json],
remove : ArrayView[Json],
) -> Array[Json] {
source
.iter()
.filter(fn(value) { !array_contains_compare(remove, value) })
.collect()
}
///|
fn json_divide(left : Json, right : Json) -> Json raise InterpreterError {
match (left, right) {
(Number(a, ..), Number(b, ..)) => {
if b == 0.0 {
raise DivisionByZero
}
Json::number(a / b)
}
_ =>
raise InvalidOperation(
"Cannot divide \{@ast_internal.json_type_name(left)} by \{@ast_internal.json_type_name(right)}",
)
}
}
///|
fn json_modulo(left : Json, right : Json) -> Json raise InterpreterError {
match (left, right) {
(Number(a, ..), Number(b, ..)) => {
if b == 0.0 {
raise DivisionByZero
}
Json::number(a % b)
}
_ =>
raise InvalidOperation(
"Cannot modulo \{@ast_internal.json_type_name(left)} by \{@ast_internal.json_type_name(right)}",
)
}
}