mirror of
https://github.com/aljazceru/turso.git
synced 2026-01-08 18:54:21 +01:00
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:
@@ -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!(),
|
||||
}
|
||||
}
|
||||
|
||||
668
core/vdbe/mod.rs
668
core/vdbe/mod.rs
@@ -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 } => {
|
||||
|
||||
Reference in New Issue
Block a user