Merge 'Refactor out repetitive agg_func code in vdbe' from Preston Thorpe

This PR cleans up a lot of the repetitive code that caused having to
match the `AggFunc` cases repeatedly 😄
Most of the repetition was caused by the binary math operators, so I
just added it for those for now.

Reviewed-by: Jussi Saurio <penberg@iki.fi>
Reviewed-by: Pere Diaz Bou <preston@unlockedlabs.org>

Closes #575
This commit is contained in:
Jussi Saurio
2024-12-31 15:02:57 +02:00
2 changed files with 176 additions and 641 deletions

View File

@@ -1,5 +1,5 @@
use super::{AggFunc, BranchOffset, CursorID, FuncCtx, PageIdx};
use crate::types::OwnedRecord;
use crate::types::{OwnedRecord, OwnedValue};
use limbo_macros::Description;
#[derive(Description, Debug)]
@@ -488,3 +488,150 @@ pub enum Insn {
where_clause: String,
},
}
pub fn exec_add(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
if let OwnedValue::Agg(agg) = lhs {
lhs = agg.final_value();
}
if let OwnedValue::Agg(agg) = rhs {
rhs = agg.final_value();
}
match (lhs, rhs) {
(OwnedValue::Integer(lhs), OwnedValue::Integer(rhs)) => OwnedValue::Integer(lhs + rhs),
(OwnedValue::Float(lhs), OwnedValue::Float(rhs)) => OwnedValue::Float(lhs + rhs),
(OwnedValue::Float(f), OwnedValue::Integer(i))
| (OwnedValue::Integer(i), OwnedValue::Float(f)) => OwnedValue::Float(*f + *i as f64),
(OwnedValue::Null, _) | (_, OwnedValue::Null) => OwnedValue::Null,
_ => todo!(),
}
}
pub fn exec_subtract(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
if let OwnedValue::Agg(agg) = lhs {
lhs = agg.final_value();
}
if let OwnedValue::Agg(agg) = rhs {
rhs = agg.final_value();
}
match (lhs, rhs) {
(OwnedValue::Integer(lhs), OwnedValue::Integer(rhs)) => OwnedValue::Integer(lhs - rhs),
(OwnedValue::Float(lhs), OwnedValue::Float(rhs)) => OwnedValue::Float(lhs - rhs),
(OwnedValue::Float(lhs), OwnedValue::Integer(rhs)) => OwnedValue::Float(lhs - *rhs as f64),
(OwnedValue::Integer(lhs), OwnedValue::Float(rhs)) => OwnedValue::Float(*lhs as f64 - rhs),
(OwnedValue::Null, _) | (_, OwnedValue::Null) => OwnedValue::Null,
_ => todo!(),
}
}
pub fn exec_multiply(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
if let OwnedValue::Agg(agg) = lhs {
lhs = agg.final_value();
}
if let OwnedValue::Agg(agg) = rhs {
rhs = agg.final_value();
}
match (lhs, rhs) {
(OwnedValue::Integer(lhs), OwnedValue::Integer(rhs)) => OwnedValue::Integer(lhs * rhs),
(OwnedValue::Float(lhs), OwnedValue::Float(rhs)) => OwnedValue::Float(lhs * rhs),
(OwnedValue::Integer(i), OwnedValue::Float(f))
| (OwnedValue::Float(f), OwnedValue::Integer(i)) => OwnedValue::Float(*i as f64 * { *f }),
(OwnedValue::Null, _) | (_, OwnedValue::Null) => OwnedValue::Null,
_ => todo!(),
}
}
pub fn exec_divide(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
if let OwnedValue::Agg(agg) = lhs {
lhs = agg.final_value();
}
if let OwnedValue::Agg(agg) = rhs {
rhs = agg.final_value();
}
match (lhs, rhs) {
(_, OwnedValue::Integer(0)) | (_, OwnedValue::Float(0.0)) => OwnedValue::Null,
(OwnedValue::Integer(lhs), OwnedValue::Integer(rhs)) => OwnedValue::Integer(lhs / rhs),
(OwnedValue::Float(lhs), OwnedValue::Float(rhs)) => OwnedValue::Float(lhs / rhs),
(OwnedValue::Float(lhs), OwnedValue::Integer(rhs)) => OwnedValue::Float(lhs / *rhs as f64),
(OwnedValue::Integer(lhs), OwnedValue::Float(rhs)) => OwnedValue::Float(*lhs as f64 / rhs),
(OwnedValue::Null, _) | (_, OwnedValue::Null) => OwnedValue::Null,
_ => todo!(),
}
}
pub fn exec_bit_and(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
if let OwnedValue::Agg(agg) = lhs {
lhs = agg.final_value();
}
if let OwnedValue::Agg(agg) = rhs {
rhs = agg.final_value();
}
match (lhs, rhs) {
(OwnedValue::Null, _) | (_, OwnedValue::Null) => OwnedValue::Null,
(_, OwnedValue::Integer(0))
| (OwnedValue::Integer(0), _)
| (_, OwnedValue::Float(0.0))
| (OwnedValue::Float(0.0), _) => OwnedValue::Integer(0),
(OwnedValue::Integer(lh), OwnedValue::Integer(rh)) => OwnedValue::Integer(lh & rh),
(OwnedValue::Float(lh), OwnedValue::Float(rh)) => {
OwnedValue::Integer(*lh as i64 & *rh as i64)
}
(OwnedValue::Float(lh), OwnedValue::Integer(rh)) => OwnedValue::Integer(*lh as i64 & rh),
(OwnedValue::Integer(lh), OwnedValue::Float(rh)) => OwnedValue::Integer(lh & *rh as i64),
_ => todo!(),
}
}
pub fn exec_bit_or(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
if let OwnedValue::Agg(agg) = lhs {
lhs = agg.final_value();
}
if let OwnedValue::Agg(agg) = rhs {
rhs = agg.final_value();
}
match (lhs, rhs) {
(OwnedValue::Null, _) | (_, OwnedValue::Null) => OwnedValue::Null,
(OwnedValue::Integer(lh), OwnedValue::Integer(rh)) => OwnedValue::Integer(lh | rh),
(OwnedValue::Float(lh), OwnedValue::Integer(rh)) => OwnedValue::Integer(*lh as i64 | rh),
(OwnedValue::Integer(lh), OwnedValue::Float(rh)) => OwnedValue::Integer(lh | *rh as i64),
(OwnedValue::Float(lh), OwnedValue::Float(rh)) => {
OwnedValue::Integer(*lh as i64 | *rh as i64)
}
_ => todo!(),
}
}
pub fn exec_remainder(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
if let OwnedValue::Agg(agg) = lhs {
lhs = agg.final_value();
}
if let OwnedValue::Agg(agg) = rhs {
rhs = agg.final_value();
}
match (lhs, rhs) {
(OwnedValue::Null, _)
| (_, OwnedValue::Null)
| (_, OwnedValue::Integer(0))
| (_, OwnedValue::Float(0.0)) => OwnedValue::Null,
(OwnedValue::Integer(lhs), OwnedValue::Integer(rhs)) => OwnedValue::Integer(lhs % rhs),
(OwnedValue::Float(lhs), OwnedValue::Float(rhs)) => {
OwnedValue::Float(((*lhs as i64) % (*rhs as i64)) as f64)
}
(OwnedValue::Float(lhs), OwnedValue::Integer(rhs)) => {
OwnedValue::Float(((*lhs as i64) % rhs) as f64)
}
(OwnedValue::Integer(lhs), OwnedValue::Float(rhs)) => {
OwnedValue::Float((lhs % *rhs as i64) as f64)
}
_ => todo!(),
}
}
pub fn exec_bit_not(mut reg: &OwnedValue) -> OwnedValue {
if let OwnedValue::Agg(agg) = reg {
reg = agg.final_value();
}
match reg {
OwnedValue::Null => OwnedValue::Null,
OwnedValue::Integer(i) => OwnedValue::Integer(!i),
OwnedValue::Float(f) => OwnedValue::Integer(!(*f as i64)),
_ => todo!(),
}
}

View File

@@ -42,6 +42,10 @@ use crate::vdbe::insn::Insn;
use crate::{function::JsonFunc, json::get_json, json::json_array, json::json_array_length};
use crate::{Connection, Result, Rows, TransactionState, DATABASE_VERSION};
use datetime::{exec_date, exec_time, exec_unixepoch};
use insn::{
exec_add, exec_bit_and, exec_bit_not, exec_bit_or, exec_divide, exec_multiply, exec_remainder,
exec_subtract,
};
use likeop::{construct_like_escape_arg, exec_glob, exec_like_with_escape};
use rand::distributions::{Distribution, Uniform};
use rand::{thread_rng, Rng};
@@ -186,658 +190,42 @@ impl Program {
state.pc = *target_pc;
}
Insn::Add { lhs, rhs, dest } => {
let lhs = *lhs;
let rhs = *rhs;
let dest = *dest;
match (&state.registers[lhs], &state.registers[rhs]) {
(OwnedValue::Integer(lhs), OwnedValue::Integer(rhs)) => {
state.registers[dest] = OwnedValue::Integer(lhs + rhs);
}
(OwnedValue::Float(lhs), OwnedValue::Float(rhs)) => {
state.registers[dest] = OwnedValue::Float(lhs + rhs);
}
(OwnedValue::Float(f), OwnedValue::Integer(i))
| (OwnedValue::Integer(i), OwnedValue::Float(f)) => {
state.registers[dest] = OwnedValue::Float(*f + *i as f64);
}
(OwnedValue::Null, _) | (_, OwnedValue::Null) => {
state.registers[dest] = OwnedValue::Null;
}
(OwnedValue::Agg(aggctx), other) | (other, OwnedValue::Agg(aggctx)) => {
match other {
OwnedValue::Null => {
state.registers[dest] = OwnedValue::Null;
}
OwnedValue::Integer(i) => match aggctx.final_value() {
OwnedValue::Float(acc) => {
state.registers[dest] = OwnedValue::Float(acc + *i as f64);
}
OwnedValue::Integer(acc) => {
state.registers[dest] = OwnedValue::Integer(acc + i);
}
_ => {
todo!("{:?}", aggctx);
}
},
OwnedValue::Float(f) => match aggctx.final_value() {
OwnedValue::Float(acc) => {
state.registers[dest] = OwnedValue::Float(acc + f);
}
OwnedValue::Integer(acc) => {
state.registers[dest] = OwnedValue::Float(*acc as f64 + f);
}
_ => {
todo!("{:?}", aggctx);
}
},
OwnedValue::Agg(aggctx2) => {
let acc = aggctx.final_value();
let acc2 = aggctx2.final_value();
match (acc, acc2) {
(OwnedValue::Integer(acc), OwnedValue::Integer(acc2)) => {
state.registers[dest] = OwnedValue::Integer(acc + acc2);
}
(OwnedValue::Float(acc), OwnedValue::Float(acc2)) => {
state.registers[dest] = OwnedValue::Float(acc + acc2);
}
(OwnedValue::Integer(acc), OwnedValue::Float(acc2)) => {
state.registers[dest] =
OwnedValue::Float(*acc as f64 + acc2);
}
(OwnedValue::Float(acc), OwnedValue::Integer(acc2)) => {
state.registers[dest] =
OwnedValue::Float(acc + *acc2 as f64);
}
_ => {
todo!("{:?} {:?}", acc, acc2);
}
}
}
rest => unimplemented!("{:?}", rest),
}
}
_ => {
todo!();
}
}
state.registers[*dest] =
exec_add(&state.registers[*lhs], &state.registers[*rhs]);
state.pc += 1;
}
Insn::Subtract { lhs, rhs, dest } => {
let lhs = *lhs;
let rhs = *rhs;
let dest = *dest;
match (&state.registers[lhs], &state.registers[rhs]) {
(OwnedValue::Integer(lhs), OwnedValue::Integer(rhs)) => {
state.registers[dest] = OwnedValue::Integer(lhs - rhs);
}
(OwnedValue::Float(lhs), OwnedValue::Float(rhs)) => {
state.registers[dest] = OwnedValue::Float(lhs - rhs);
}
(OwnedValue::Float(lhs), OwnedValue::Integer(rhs)) => {
state.registers[dest] = OwnedValue::Float(lhs - *rhs as f64);
}
(OwnedValue::Integer(lhs), OwnedValue::Float(rhs)) => {
state.registers[dest] = OwnedValue::Float(*lhs as f64 - rhs);
}
(OwnedValue::Null, _) | (_, OwnedValue::Null) => {
state.registers[dest] = OwnedValue::Null;
}
(OwnedValue::Agg(aggctx), rhs) => match rhs {
OwnedValue::Null => {
state.registers[dest] = OwnedValue::Null;
}
OwnedValue::Integer(i) => match aggctx.final_value() {
OwnedValue::Float(acc) => {
state.registers[dest] = OwnedValue::Float(acc - *i as f64);
}
OwnedValue::Integer(acc) => {
state.registers[dest] = OwnedValue::Integer(acc - i);
}
_ => {
todo!("{:?}", aggctx);
}
},
OwnedValue::Float(f) => match aggctx.final_value() {
OwnedValue::Float(acc) => {
state.registers[dest] = OwnedValue::Float(acc - f);
}
OwnedValue::Integer(acc) => {
state.registers[dest] = OwnedValue::Float(*acc as f64 - f);
}
_ => {
todo!("{:?}", aggctx);
}
},
OwnedValue::Agg(aggctx2) => {
let acc = aggctx.final_value();
let acc2 = aggctx2.final_value();
match (acc, acc2) {
(OwnedValue::Integer(acc), OwnedValue::Integer(acc2)) => {
state.registers[dest] = OwnedValue::Integer(acc - acc2);
}
(OwnedValue::Float(acc), OwnedValue::Float(acc2)) => {
state.registers[dest] = OwnedValue::Float(acc - acc2);
}
(OwnedValue::Integer(acc), OwnedValue::Float(acc2)) => {
state.registers[dest] =
OwnedValue::Float(*acc as f64 - acc2);
}
(OwnedValue::Float(acc), OwnedValue::Integer(acc2)) => {
state.registers[dest] =
OwnedValue::Float(acc - *acc2 as f64);
}
_ => {
todo!("{:?} {:?}", acc, acc2);
}
}
}
rest => unimplemented!("{:?}", rest),
},
(lhs, OwnedValue::Agg(aggctx)) => match lhs {
OwnedValue::Null => {
state.registers[dest] = OwnedValue::Null;
}
OwnedValue::Integer(i) => match aggctx.final_value() {
OwnedValue::Float(acc) => {
state.registers[dest] = OwnedValue::Float(*i as f64 - acc);
}
OwnedValue::Integer(acc) => {
state.registers[dest] = OwnedValue::Integer(i - acc);
}
_ => {
todo!("{:?}", aggctx);
}
},
OwnedValue::Float(f) => match aggctx.final_value() {
OwnedValue::Float(acc) => {
state.registers[dest] = OwnedValue::Float(f - acc);
}
OwnedValue::Integer(acc) => {
state.registers[dest] = OwnedValue::Float(f - *acc as f64);
}
_ => {
todo!("{:?}", aggctx);
}
},
rest => unimplemented!("{:?}", rest),
},
others => {
todo!("{:?}", others);
}
}
state.registers[*dest] =
exec_subtract(&state.registers[*lhs], &state.registers[*rhs]);
state.pc += 1;
}
Insn::Multiply { lhs, rhs, dest } => {
let lhs = *lhs;
let rhs = *rhs;
let dest = *dest;
match (&state.registers[lhs], &state.registers[rhs]) {
(OwnedValue::Integer(lhs), OwnedValue::Integer(rhs)) => {
state.registers[dest] = OwnedValue::Integer(lhs * rhs);
}
(OwnedValue::Float(lhs), OwnedValue::Float(rhs)) => {
state.registers[dest] = OwnedValue::Float(lhs * rhs);
}
(OwnedValue::Integer(i), OwnedValue::Float(f))
| (OwnedValue::Float(f), OwnedValue::Integer(i)) => {
state.registers[dest] = OwnedValue::Float(*i as f64 * { *f });
}
(OwnedValue::Null, _) | (_, OwnedValue::Null) => {
state.registers[dest] = OwnedValue::Null;
}
(OwnedValue::Agg(aggctx), other) | (other, OwnedValue::Agg(aggctx)) => {
match other {
OwnedValue::Null => {
state.registers[dest] = OwnedValue::Null;
}
OwnedValue::Integer(i) => match aggctx.final_value() {
OwnedValue::Float(acc) => {
state.registers[dest] = OwnedValue::Float(acc * *i as f64);
}
OwnedValue::Integer(acc) => {
state.registers[dest] = OwnedValue::Integer(acc * i);
}
_ => {
todo!("{:?}", aggctx);
}
},
OwnedValue::Float(f) => match aggctx.final_value() {
OwnedValue::Float(acc) => {
state.registers[dest] = OwnedValue::Float(acc * f);
}
OwnedValue::Integer(acc) => {
state.registers[dest] = OwnedValue::Float(*acc as f64 * f);
}
_ => {
todo!("{:?}", aggctx);
}
},
OwnedValue::Agg(aggctx2) => {
let acc = aggctx.final_value();
let acc2 = aggctx2.final_value();
match (acc, acc2) {
(OwnedValue::Integer(acc), OwnedValue::Integer(acc2)) => {
state.registers[dest] = OwnedValue::Integer(acc * acc2);
}
(OwnedValue::Float(acc), OwnedValue::Float(acc2)) => {
state.registers[dest] = OwnedValue::Float(acc * acc2);
}
(OwnedValue::Integer(acc), OwnedValue::Float(acc2)) => {
state.registers[dest] =
OwnedValue::Float(*acc as f64 * acc2);
}
(OwnedValue::Float(acc), OwnedValue::Integer(acc2)) => {
state.registers[dest] =
OwnedValue::Float(acc * *acc2 as f64);
}
_ => {
todo!("{:?} {:?}", acc, acc2);
}
}
}
rest => unimplemented!("{:?}", rest),
}
}
others => {
todo!("{:?}", others);
}
}
state.registers[*dest] =
exec_multiply(&state.registers[*lhs], &state.registers[*rhs]);
state.pc += 1;
}
Insn::Divide { lhs, rhs, dest } => {
let lhs = *lhs;
let rhs = *rhs;
let dest = *dest;
match (&state.registers[lhs], &state.registers[rhs]) {
// If the divisor is zero, the result is NULL.
(_, OwnedValue::Integer(0)) | (_, OwnedValue::Float(0.0)) => {
state.registers[dest] = OwnedValue::Null;
}
(OwnedValue::Integer(lhs), OwnedValue::Integer(rhs)) => {
state.registers[dest] = OwnedValue::Integer(lhs / rhs);
}
(OwnedValue::Float(lhs), OwnedValue::Float(rhs)) => {
state.registers[dest] = OwnedValue::Float(lhs / rhs);
}
(OwnedValue::Float(lhs), OwnedValue::Integer(rhs)) => {
state.registers[dest] = OwnedValue::Float(lhs / *rhs as f64);
}
(OwnedValue::Integer(lhs), OwnedValue::Float(rhs)) => {
state.registers[dest] = OwnedValue::Float(*lhs as f64 / rhs);
}
(OwnedValue::Null, _) | (_, OwnedValue::Null) => {
state.registers[dest] = OwnedValue::Null;
}
(OwnedValue::Agg(aggctx), rhs) => match rhs {
OwnedValue::Null => {
state.registers[dest] = OwnedValue::Null;
}
OwnedValue::Integer(i) => match aggctx.final_value() {
OwnedValue::Float(acc) => {
state.registers[dest] = OwnedValue::Float(acc / *i as f64);
}
OwnedValue::Integer(acc) => {
state.registers[dest] = OwnedValue::Integer(acc / i);
}
_ => {
todo!("{:?}", aggctx);
}
},
OwnedValue::Float(f) => match aggctx.final_value() {
OwnedValue::Float(acc) => {
state.registers[dest] = OwnedValue::Float(acc / f);
}
OwnedValue::Integer(acc) => {
state.registers[dest] = OwnedValue::Float(*acc as f64 / f);
}
_ => {
todo!("{:?}", aggctx);
}
},
OwnedValue::Agg(aggctx2) => {
let acc = aggctx.final_value();
let acc2 = aggctx2.final_value();
match (acc, acc2) {
(OwnedValue::Integer(acc), OwnedValue::Integer(acc2)) => {
state.registers[dest] = OwnedValue::Integer(acc / acc2);
}
(OwnedValue::Float(acc), OwnedValue::Float(acc2)) => {
state.registers[dest] = OwnedValue::Float(acc / acc2);
}
(OwnedValue::Integer(acc), OwnedValue::Float(acc2)) => {
state.registers[dest] =
OwnedValue::Float(*acc as f64 / acc2);
}
(OwnedValue::Float(acc), OwnedValue::Integer(acc2)) => {
state.registers[dest] =
OwnedValue::Float(acc / *acc2 as f64);
}
_ => {
todo!("{:?} {:?}", acc, acc2);
}
}
}
rest => unimplemented!("{:?}", rest),
},
(lhs, OwnedValue::Agg(aggctx)) => match lhs {
OwnedValue::Null => {
state.registers[dest] = OwnedValue::Null;
}
OwnedValue::Integer(i) => match aggctx.final_value() {
OwnedValue::Float(acc) => {
state.registers[dest] = OwnedValue::Float(*i as f64 / acc);
}
OwnedValue::Integer(acc) => {
state.registers[dest] = OwnedValue::Integer(i / acc);
}
_ => {
todo!("{:?}", aggctx);
}
},
OwnedValue::Float(f) => match aggctx.final_value() {
OwnedValue::Float(acc) => {
state.registers[dest] = OwnedValue::Float(f / acc);
}
OwnedValue::Integer(acc) => {
state.registers[dest] = OwnedValue::Float(f / *acc as f64);
}
_ => {
todo!("{:?}", aggctx);
}
},
rest => unimplemented!("{:?}", rest),
},
others => {
todo!("{:?}", others);
}
}
state.pc += 1;
}
Insn::BitAnd { lhs, rhs, dest } => {
let lhs = *lhs;
let rhs = *rhs;
let dest = *dest;
match (&state.registers[lhs], &state.registers[rhs]) {
// handle 0 and null cases
(OwnedValue::Null, _) | (_, OwnedValue::Null) => {
state.registers[dest] = OwnedValue::Null;
}
(_, OwnedValue::Integer(0))
| (OwnedValue::Integer(0), _)
| (_, OwnedValue::Float(0.0))
| (OwnedValue::Float(0.0), _) => {
state.registers[dest] = OwnedValue::Integer(0);
}
(OwnedValue::Integer(lh), OwnedValue::Integer(rh)) => {
state.registers[dest] = OwnedValue::Integer(lh & rh);
}
(OwnedValue::Float(lh), OwnedValue::Float(rh)) => {
state.registers[dest] = OwnedValue::Integer(*lh as i64 & *rh as i64);
}
(OwnedValue::Float(lh), OwnedValue::Integer(rh)) => {
state.registers[dest] = OwnedValue::Integer(*lh as i64 & rh);
}
(OwnedValue::Integer(lh), OwnedValue::Float(rh)) => {
state.registers[dest] = OwnedValue::Integer(lh & *rh as i64);
}
(OwnedValue::Agg(aggctx), other) | (other, OwnedValue::Agg(aggctx)) => {
match other {
OwnedValue::Agg(aggctx2) => {
match (aggctx.final_value(), aggctx2.final_value()) {
(OwnedValue::Integer(lh), OwnedValue::Integer(rh)) => {
state.registers[dest] = OwnedValue::Integer(lh & rh);
}
(OwnedValue::Float(lh), OwnedValue::Float(rh)) => {
state.registers[dest] =
OwnedValue::Integer(*lh as i64 & *rh as i64);
}
(OwnedValue::Integer(lh), OwnedValue::Float(rh)) => {
state.registers[dest] =
OwnedValue::Integer(lh & *rh as i64);
}
(OwnedValue::Float(lh), OwnedValue::Integer(rh)) => {
state.registers[dest] =
OwnedValue::Integer(*lh as i64 & rh);
}
_ => {
unimplemented!(
"{:?} {:?}",
aggctx.final_value(),
aggctx2.final_value()
);
}
}
}
other => match (aggctx.final_value(), other) {
(OwnedValue::Null, _) | (_, OwnedValue::Null) => {
state.registers[dest] = OwnedValue::Null;
}
(_, OwnedValue::Integer(0))
| (OwnedValue::Integer(0), _)
| (_, OwnedValue::Float(0.0))
| (OwnedValue::Float(0.0), _) => {
state.registers[dest] = OwnedValue::Integer(0);
}
(OwnedValue::Integer(lh), OwnedValue::Integer(rh)) => {
state.registers[dest] = OwnedValue::Integer(lh & rh);
}
(OwnedValue::Float(lh), OwnedValue::Integer(rh)) => {
state.registers[dest] =
OwnedValue::Integer(*lh as i64 & rh);
}
(OwnedValue::Integer(lh), OwnedValue::Float(rh)) => {
state.registers[dest] =
OwnedValue::Integer(lh & *rh as i64);
}
_ => {
unimplemented!("{:?} {:?}", aggctx.final_value(), other);
}
},
}
}
_ => {
unimplemented!("{:?} {:?}", state.registers[lhs], state.registers[rhs]);
}
}
state.pc += 1;
}
Insn::BitOr { lhs, rhs, dest } => {
let lhs = *lhs;
let rhs = *rhs;
let dest = *dest;
match (&state.registers[lhs], &state.registers[rhs]) {
(OwnedValue::Null, _) | (_, OwnedValue::Null) => {
state.registers[dest] = OwnedValue::Null;
}
(OwnedValue::Integer(lh), OwnedValue::Integer(rh)) => {
state.registers[dest] = OwnedValue::Integer(lh | rh);
}
(OwnedValue::Float(lh), OwnedValue::Integer(rh)) => {
state.registers[dest] = OwnedValue::Integer(*lh as i64 | rh);
}
(OwnedValue::Integer(lh), OwnedValue::Float(rh)) => {
state.registers[dest] = OwnedValue::Integer(lh | *rh as i64);
}
(OwnedValue::Float(lh), OwnedValue::Float(rh)) => {
state.registers[dest] = OwnedValue::Integer(*lh as i64 | *rh as i64);
}
(OwnedValue::Agg(aggctx), other) | (other, OwnedValue::Agg(aggctx)) => {
match other {
OwnedValue::Agg(aggctx2) => {
let final_lhs = aggctx.final_value();
let final_rhs = aggctx2.final_value();
match (final_lhs, final_rhs) {
(OwnedValue::Integer(lh), OwnedValue::Integer(rh)) => {
state.registers[dest] = OwnedValue::Integer(lh | rh);
}
(OwnedValue::Float(lh), OwnedValue::Float(rh)) => {
state.registers[dest] =
OwnedValue::Integer(*lh as i64 | *rh as i64);
}
(OwnedValue::Integer(lh), OwnedValue::Float(rh)) => {
state.registers[dest] =
OwnedValue::Integer(lh | *rh as i64);
}
(OwnedValue::Float(lh), OwnedValue::Integer(rh)) => {
state.registers[dest] =
OwnedValue::Integer(*lh as i64 | rh);
}
_ => {
unimplemented!("{:?} {:?}", final_lhs, final_rhs);
}
}
}
other => match (aggctx.final_value(), other) {
(OwnedValue::Null, _) | (_, OwnedValue::Null) => {
state.registers[dest] = OwnedValue::Null;
}
(OwnedValue::Integer(lh), OwnedValue::Integer(rh)) => {
state.registers[dest] = OwnedValue::Integer(lh | rh);
}
(OwnedValue::Float(lh), OwnedValue::Integer(rh)) => {
state.registers[dest] =
OwnedValue::Integer(*lh as i64 | rh);
}
(OwnedValue::Integer(lh), OwnedValue::Float(rh)) => {
state.registers[dest] =
OwnedValue::Integer(lh | *rh as i64);
}
_ => {
unimplemented!("{:?} {:?}", aggctx.final_value(), other);
}
},
}
}
_ => {
unimplemented!("{:?} {:?}", state.registers[lhs], state.registers[rhs]);
}
}
state.pc += 1;
}
Insn::BitNot { reg, dest } => {
let reg = *reg;
let dest = *dest;
match &state.registers[reg] {
OwnedValue::Integer(i) => state.registers[dest] = OwnedValue::Integer(!i),
OwnedValue::Float(f) => {
state.registers[dest] = OwnedValue::Integer(!{ *f as i64 })
}
OwnedValue::Null => {
state.registers[dest] = OwnedValue::Null;
}
OwnedValue::Agg(aggctx) => match aggctx.final_value() {
OwnedValue::Integer(i) => {
state.registers[dest] = OwnedValue::Integer(!i);
}
OwnedValue::Float(f) => {
state.registers[dest] = OwnedValue::Integer(!{ *f as i64 });
}
OwnedValue::Null => {
state.registers[dest] = OwnedValue::Null;
}
_ => unimplemented!("{:?}", aggctx),
},
_ => {
unimplemented!("{:?}", state.registers[reg]);
}
}
state.registers[*dest] =
exec_divide(&state.registers[*lhs], &state.registers[*rhs]);
state.pc += 1;
}
Insn::Remainder { lhs, rhs, dest } => {
let lhs = *lhs;
let rhs = *rhs;
let dest = *dest;
state.registers[dest] = match (&state.registers[lhs], &state.registers[rhs]) {
(OwnedValue::Null, _)
| (_, OwnedValue::Null)
| (_, OwnedValue::Integer(0))
| (_, OwnedValue::Float(0.0)) => OwnedValue::Null,
(OwnedValue::Integer(lhs), OwnedValue::Integer(rhs)) => {
OwnedValue::Integer(lhs % rhs)
}
(OwnedValue::Float(lhs), OwnedValue::Float(rhs)) => {
OwnedValue::Float(((*lhs as i64) % (*rhs as i64)) as f64)
}
(OwnedValue::Float(lhs), OwnedValue::Integer(rhs)) => {
OwnedValue::Float(((*lhs as i64) % rhs) as f64)
}
(OwnedValue::Integer(lhs), OwnedValue::Float(rhs)) => {
OwnedValue::Float((lhs % *rhs as i64) as f64)
}
(lhs, OwnedValue::Agg(agg_rhs)) => match lhs {
OwnedValue::Agg(agg_lhs) => {
let acc = agg_lhs.final_value();
let acc2 = agg_rhs.final_value();
match (acc, acc2) {
(_, OwnedValue::Integer(0))
| (_, OwnedValue::Float(0.0))
| (_, OwnedValue::Null)
| (OwnedValue::Null, _) => OwnedValue::Null,
(OwnedValue::Integer(l), OwnedValue::Integer(r)) => {
OwnedValue::Integer(l % r)
}
(OwnedValue::Float(lh_f), OwnedValue::Float(rh_f)) => {
OwnedValue::Float(((*lh_f as i64) % (*rh_f as i64)) as f64)
}
(OwnedValue::Integer(lh_i), OwnedValue::Float(rh_f)) => {
OwnedValue::Float((lh_i % (*rh_f as i64)) as f64)
}
_ => {
todo!("{:?} {:?}", acc, acc2);
}
}
}
OwnedValue::Integer(lh_i) => match agg_rhs.final_value() {
OwnedValue::Null => OwnedValue::Null,
OwnedValue::Float(rh_f) => {
OwnedValue::Float((lh_i % (*rh_f as i64)) as f64)
}
OwnedValue::Integer(rh_i) => OwnedValue::Integer(lh_i % rh_i),
_ => {
todo!("{:?}", agg_rhs);
}
},
OwnedValue::Float(lh_f) => match agg_rhs.final_value() {
OwnedValue::Null => OwnedValue::Null,
OwnedValue::Float(rh_f) => {
OwnedValue::Float(((*lh_f as i64) % (*rh_f as i64)) as f64)
}
OwnedValue::Integer(rh_i) => {
OwnedValue::Float(((*lh_f as i64) % rh_i) as f64)
}
_ => {
todo!("{:?}", agg_rhs);
}
},
_ => todo!("{:?}", rhs),
},
(OwnedValue::Agg(aggctx), rhs) => match rhs {
OwnedValue::Integer(rh_i) => match aggctx.final_value() {
OwnedValue::Null => OwnedValue::Null,
OwnedValue::Float(lh_f) => {
OwnedValue::Float(((*lh_f as i64) % rh_i) as f64)
}
OwnedValue::Integer(lh_i) => OwnedValue::Integer(lh_i % rh_i),
_ => {
todo!("{:?}", aggctx);
}
},
OwnedValue::Float(rh_f) => match aggctx.final_value() {
OwnedValue::Null => OwnedValue::Null,
OwnedValue::Float(lh_f) => {
OwnedValue::Float(((*lh_f as i64) % (*rh_f as i64)) as f64)
}
OwnedValue::Integer(lh_i) => {
OwnedValue::Float((lh_i % (*rh_f as i64)) as f64)
}
_ => {
todo!("{:?}", aggctx);
}
},
_ => todo!("{:?}", rhs),
},
_ => todo!("{:?} {:?}", state.registers[lhs], state.registers[rhs]),
};
state.registers[*dest] =
exec_remainder(&state.registers[*lhs], &state.registers[*rhs]);
state.pc += 1;
}
Insn::BitAnd { lhs, rhs, dest } => {
state.registers[*dest] =
exec_bit_and(&state.registers[*lhs], &state.registers[*rhs]);
state.pc += 1;
}
Insn::BitOr { lhs, rhs, dest } => {
state.registers[*dest] =
exec_bit_or(&state.registers[*lhs], &state.registers[*rhs]);
state.pc += 1;
}
Insn::BitNot { reg, dest } => {
state.registers[*dest] = exec_bit_not(&state.registers[*reg]);
state.pc += 1;
}
Insn::Null { dest, dest_end } => {