mirror of
https://github.com/aljazceru/turso.git
synced 2026-02-21 07:55:18 +01:00
Add affinity conversion to op_gt, op_le, op_lt, op_eq, op_ne
This commit is contained in:
committed by
Krishna Vishal
parent
30ccbe46c7
commit
e68293a1d1
@@ -552,37 +552,64 @@ pub fn op_eq(
|
||||
let lhs = *lhs;
|
||||
let rhs = *rhs;
|
||||
let target_pc = *target_pc;
|
||||
let cond = *state.registers[lhs].get_owned_value() == *state.registers[rhs].get_owned_value();
|
||||
let nulleq = flags.has_nulleq();
|
||||
let jump_if_null = flags.has_jump_if_null();
|
||||
let collation = collation.unwrap_or_default();
|
||||
match (
|
||||
state.registers[lhs].get_owned_value(),
|
||||
state.registers[rhs].get_owned_value(),
|
||||
) {
|
||||
(_, Value::Null) | (Value::Null, _) => {
|
||||
if (nulleq && cond) || (!nulleq && jump_if_null) {
|
||||
|
||||
let lhs_value = state.registers[lhs].get_owned_value();
|
||||
let rhs_value = state.registers[rhs].get_owned_value();
|
||||
|
||||
// Fast path for integers
|
||||
if matches!(lhs_value, Value::Integer(_)) && matches!(rhs_value, Value::Integer(_)) {
|
||||
if lhs_value == rhs_value {
|
||||
state.pc = target_pc.to_offset_int();
|
||||
} else {
|
||||
state.pc += 1;
|
||||
}
|
||||
}
|
||||
(Value::Text(lhs), Value::Text(rhs)) => {
|
||||
let order = collation.compare_strings(lhs.as_str(), rhs.as_str());
|
||||
if order.is_eq() {
|
||||
state.pc = target_pc.to_offset_int();
|
||||
} else {
|
||||
state.pc += 1;
|
||||
}
|
||||
}
|
||||
(lhs, rhs) => {
|
||||
if *lhs == *rhs {
|
||||
state.pc = target_pc.to_offset_int();
|
||||
} else {
|
||||
state.pc += 1;
|
||||
}
|
||||
}
|
||||
return Ok(InsnFunctionStepResult::Step);
|
||||
}
|
||||
|
||||
// Handle NULL values
|
||||
if matches!(lhs_value, Value::Null) || matches!(rhs_value, Value::Null) {
|
||||
let cond = lhs_value == rhs_value; // Both NULL
|
||||
if (nulleq && cond) || (!nulleq && jump_if_null) {
|
||||
state.pc = target_pc.to_offset_int();
|
||||
} else {
|
||||
state.pc += 1;
|
||||
}
|
||||
return Ok(InsnFunctionStepResult::Step);
|
||||
}
|
||||
|
||||
let mut lhs_temp_reg = state.registers[lhs].clone();
|
||||
let mut rhs_temp_reg = state.registers[rhs].clone();
|
||||
|
||||
let lhs_converted = apply_numeric_affinity(&mut lhs_temp_reg, false);
|
||||
let rhs_converted = apply_numeric_affinity(&mut rhs_temp_reg, false);
|
||||
|
||||
let should_jump = match (
|
||||
lhs_temp_reg.get_owned_value(),
|
||||
rhs_temp_reg.get_owned_value(),
|
||||
) {
|
||||
(Value::Text(lhs_text), Value::Text(rhs_text)) => {
|
||||
let order = collation.compare_strings(lhs_text.as_str(), rhs_text.as_str());
|
||||
order.is_eq()
|
||||
}
|
||||
(lhs, rhs) => *lhs == *rhs,
|
||||
};
|
||||
|
||||
if lhs_converted {
|
||||
state.registers[lhs] = lhs_temp_reg;
|
||||
}
|
||||
if rhs_converted {
|
||||
state.registers[rhs] = rhs_temp_reg;
|
||||
}
|
||||
|
||||
if should_jump {
|
||||
state.pc = target_pc.to_offset_int();
|
||||
} else {
|
||||
state.pc += 1;
|
||||
}
|
||||
|
||||
Ok(InsnFunctionStepResult::Step)
|
||||
}
|
||||
|
||||
@@ -607,37 +634,64 @@ pub fn op_ne(
|
||||
let lhs = *lhs;
|
||||
let rhs = *rhs;
|
||||
let target_pc = *target_pc;
|
||||
let cond = *state.registers[lhs].get_owned_value() != *state.registers[rhs].get_owned_value();
|
||||
let nulleq = flags.has_nulleq();
|
||||
let jump_if_null = flags.has_jump_if_null();
|
||||
let collation = collation.unwrap_or_default();
|
||||
match (
|
||||
state.registers[lhs].get_owned_value(),
|
||||
state.registers[rhs].get_owned_value(),
|
||||
) {
|
||||
(_, Value::Null) | (Value::Null, _) => {
|
||||
if (nulleq && cond) || (!nulleq && jump_if_null) {
|
||||
|
||||
let lhs_value = state.registers[lhs].get_owned_value();
|
||||
let rhs_value = state.registers[rhs].get_owned_value();
|
||||
|
||||
// Fast path for integers
|
||||
if matches!(lhs_value, Value::Integer(_)) && matches!(rhs_value, Value::Integer(_)) {
|
||||
if lhs_value != rhs_value {
|
||||
state.pc = target_pc.to_offset_int();
|
||||
} else {
|
||||
state.pc += 1;
|
||||
}
|
||||
}
|
||||
(Value::Text(lhs), Value::Text(rhs)) => {
|
||||
let order = collation.compare_strings(lhs.as_str(), rhs.as_str());
|
||||
if order.is_ne() {
|
||||
state.pc = target_pc.to_offset_int();
|
||||
} else {
|
||||
state.pc += 1;
|
||||
}
|
||||
}
|
||||
(lhs, rhs) => {
|
||||
if *lhs != *rhs {
|
||||
state.pc = target_pc.to_offset_int();
|
||||
} else {
|
||||
state.pc += 1;
|
||||
}
|
||||
}
|
||||
return Ok(InsnFunctionStepResult::Step);
|
||||
}
|
||||
|
||||
// Handle NULL values
|
||||
if matches!(lhs_value, Value::Null) || matches!(rhs_value, Value::Null) {
|
||||
let cond = lhs_value != rhs_value; // At least one NULL
|
||||
if (nulleq && cond) || (!nulleq && jump_if_null) {
|
||||
state.pc = target_pc.to_offset_int();
|
||||
} else {
|
||||
state.pc += 1;
|
||||
}
|
||||
return Ok(InsnFunctionStepResult::Step);
|
||||
}
|
||||
|
||||
let mut lhs_temp_reg = state.registers[lhs].clone();
|
||||
let mut rhs_temp_reg = state.registers[rhs].clone();
|
||||
|
||||
let lhs_converted = apply_numeric_affinity(&mut lhs_temp_reg, false);
|
||||
let rhs_converted = apply_numeric_affinity(&mut rhs_temp_reg, false);
|
||||
|
||||
let should_jump = match (
|
||||
lhs_temp_reg.get_owned_value(),
|
||||
rhs_temp_reg.get_owned_value(),
|
||||
) {
|
||||
(Value::Text(lhs_text), Value::Text(rhs_text)) => {
|
||||
let order = collation.compare_strings(lhs_text.as_str(), rhs_text.as_str());
|
||||
order.is_ne()
|
||||
}
|
||||
(lhs, rhs) => *lhs != *rhs,
|
||||
};
|
||||
|
||||
if lhs_converted {
|
||||
state.registers[lhs] = lhs_temp_reg;
|
||||
}
|
||||
if rhs_converted {
|
||||
state.registers[rhs] = rhs_temp_reg;
|
||||
}
|
||||
|
||||
if should_jump {
|
||||
state.pc = target_pc.to_offset_int();
|
||||
} else {
|
||||
state.pc += 1;
|
||||
}
|
||||
|
||||
Ok(InsnFunctionStepResult::Step)
|
||||
}
|
||||
|
||||
@@ -664,33 +718,60 @@ pub fn op_lt(
|
||||
let target_pc = *target_pc;
|
||||
let jump_if_null = flags.has_jump_if_null();
|
||||
let collation = collation.unwrap_or_default();
|
||||
match (
|
||||
state.registers[lhs].get_owned_value(),
|
||||
state.registers[rhs].get_owned_value(),
|
||||
) {
|
||||
(_, Value::Null) | (Value::Null, _) => {
|
||||
if jump_if_null {
|
||||
|
||||
let lhs_value = state.registers[lhs].get_owned_value();
|
||||
let rhs_value = state.registers[rhs].get_owned_value();
|
||||
|
||||
// Fast path for integers
|
||||
if matches!(lhs_value, Value::Integer(_)) && matches!(rhs_value, Value::Integer(_)) {
|
||||
if lhs_value < rhs_value {
|
||||
state.pc = target_pc.to_offset_int();
|
||||
} else {
|
||||
state.pc += 1;
|
||||
}
|
||||
}
|
||||
(Value::Text(lhs), Value::Text(rhs)) => {
|
||||
let order = collation.compare_strings(lhs.as_str(), rhs.as_str());
|
||||
if order.is_lt() {
|
||||
state.pc = target_pc.to_offset_int();
|
||||
} else {
|
||||
state.pc += 1;
|
||||
}
|
||||
}
|
||||
(lhs, rhs) => {
|
||||
if *lhs < *rhs {
|
||||
state.pc = target_pc.to_offset_int();
|
||||
} else {
|
||||
state.pc += 1;
|
||||
}
|
||||
}
|
||||
return Ok(InsnFunctionStepResult::Step);
|
||||
}
|
||||
|
||||
// Handle NULL values
|
||||
if matches!(lhs_value, Value::Null) || matches!(rhs_value, Value::Null) {
|
||||
if jump_if_null {
|
||||
state.pc = target_pc.to_offset_int();
|
||||
} else {
|
||||
state.pc += 1;
|
||||
}
|
||||
return Ok(InsnFunctionStepResult::Step);
|
||||
}
|
||||
|
||||
let mut lhs_temp_reg = state.registers[lhs].clone();
|
||||
let mut rhs_temp_reg = state.registers[rhs].clone();
|
||||
|
||||
let lhs_converted = apply_numeric_affinity(&mut lhs_temp_reg, false);
|
||||
let rhs_converted = apply_numeric_affinity(&mut rhs_temp_reg, false);
|
||||
|
||||
let should_jump = match (
|
||||
lhs_temp_reg.get_owned_value(),
|
||||
rhs_temp_reg.get_owned_value(),
|
||||
) {
|
||||
(Value::Text(lhs_text), Value::Text(rhs_text)) => {
|
||||
let order = collation.compare_strings(lhs_text.as_str(), rhs_text.as_str());
|
||||
order.is_lt()
|
||||
}
|
||||
(lhs, rhs) => *lhs < *rhs,
|
||||
};
|
||||
|
||||
if lhs_converted {
|
||||
state.registers[lhs] = lhs_temp_reg;
|
||||
}
|
||||
if rhs_converted {
|
||||
state.registers[rhs] = rhs_temp_reg;
|
||||
}
|
||||
|
||||
if should_jump {
|
||||
state.pc = target_pc.to_offset_int();
|
||||
} else {
|
||||
state.pc += 1;
|
||||
}
|
||||
|
||||
Ok(InsnFunctionStepResult::Step)
|
||||
}
|
||||
|
||||
@@ -717,33 +798,60 @@ pub fn op_le(
|
||||
let target_pc = *target_pc;
|
||||
let jump_if_null = flags.has_jump_if_null();
|
||||
let collation = collation.unwrap_or_default();
|
||||
match (
|
||||
state.registers[lhs].get_owned_value(),
|
||||
state.registers[rhs].get_owned_value(),
|
||||
) {
|
||||
(_, Value::Null) | (Value::Null, _) => {
|
||||
if jump_if_null {
|
||||
|
||||
let lhs_value = state.registers[lhs].get_owned_value();
|
||||
let rhs_value = state.registers[rhs].get_owned_value();
|
||||
|
||||
// Fast path for integers
|
||||
if matches!(lhs_value, Value::Integer(_)) && matches!(rhs_value, Value::Integer(_)) {
|
||||
if lhs_value <= rhs_value {
|
||||
state.pc = target_pc.to_offset_int();
|
||||
} else {
|
||||
state.pc += 1;
|
||||
}
|
||||
}
|
||||
(Value::Text(lhs), Value::Text(rhs)) => {
|
||||
let order = collation.compare_strings(lhs.as_str(), rhs.as_str());
|
||||
if order.is_le() {
|
||||
state.pc = target_pc.to_offset_int();
|
||||
} else {
|
||||
state.pc += 1;
|
||||
}
|
||||
}
|
||||
(lhs, rhs) => {
|
||||
if *lhs <= *rhs {
|
||||
state.pc = target_pc.to_offset_int();
|
||||
} else {
|
||||
state.pc += 1;
|
||||
}
|
||||
}
|
||||
return Ok(InsnFunctionStepResult::Step);
|
||||
}
|
||||
|
||||
// Handle NULL values
|
||||
if matches!(lhs_value, Value::Null) || matches!(rhs_value, Value::Null) {
|
||||
if jump_if_null {
|
||||
state.pc = target_pc.to_offset_int();
|
||||
} else {
|
||||
state.pc += 1;
|
||||
}
|
||||
return Ok(InsnFunctionStepResult::Step);
|
||||
}
|
||||
|
||||
let mut lhs_temp_reg = state.registers[lhs].clone();
|
||||
let mut rhs_temp_reg = state.registers[rhs].clone();
|
||||
|
||||
let lhs_converted = apply_numeric_affinity(&mut lhs_temp_reg, false);
|
||||
let rhs_converted = apply_numeric_affinity(&mut rhs_temp_reg, false);
|
||||
|
||||
let should_jump = match (
|
||||
lhs_temp_reg.get_owned_value(),
|
||||
rhs_temp_reg.get_owned_value(),
|
||||
) {
|
||||
(Value::Text(lhs_text), Value::Text(rhs_text)) => {
|
||||
let order = collation.compare_strings(lhs_text.as_str(), rhs_text.as_str());
|
||||
order.is_le()
|
||||
}
|
||||
(lhs, rhs) => *lhs <= *rhs,
|
||||
};
|
||||
|
||||
if lhs_converted {
|
||||
state.registers[lhs] = lhs_temp_reg;
|
||||
}
|
||||
if rhs_converted {
|
||||
state.registers[rhs] = rhs_temp_reg;
|
||||
}
|
||||
|
||||
if should_jump {
|
||||
state.pc = target_pc.to_offset_int();
|
||||
} else {
|
||||
state.pc += 1;
|
||||
}
|
||||
|
||||
Ok(InsnFunctionStepResult::Step)
|
||||
}
|
||||
|
||||
@@ -770,33 +878,59 @@ pub fn op_gt(
|
||||
let target_pc = *target_pc;
|
||||
let jump_if_null = flags.has_jump_if_null();
|
||||
let collation = collation.unwrap_or_default();
|
||||
match (
|
||||
state.registers[lhs].get_owned_value(),
|
||||
state.registers[rhs].get_owned_value(),
|
||||
) {
|
||||
(_, Value::Null) | (Value::Null, _) => {
|
||||
if jump_if_null {
|
||||
|
||||
let lhs_value = state.registers[lhs].get_owned_value();
|
||||
let rhs_value = state.registers[rhs].get_owned_value();
|
||||
|
||||
// Fast path for integers
|
||||
if matches!(lhs_value, Value::Integer(_)) && matches!(rhs_value, Value::Integer(_)) {
|
||||
if lhs_value > rhs_value {
|
||||
state.pc = target_pc.to_offset_int();
|
||||
} else {
|
||||
state.pc += 1;
|
||||
}
|
||||
}
|
||||
(Value::Text(lhs), Value::Text(rhs)) => {
|
||||
let order = collation.compare_strings(lhs.as_str(), rhs.as_str());
|
||||
if order.is_gt() {
|
||||
state.pc = target_pc.to_offset_int();
|
||||
} else {
|
||||
state.pc += 1;
|
||||
}
|
||||
}
|
||||
(lhs, rhs) => {
|
||||
if *lhs > *rhs {
|
||||
state.pc = target_pc.to_offset_int();
|
||||
} else {
|
||||
state.pc += 1;
|
||||
}
|
||||
}
|
||||
return Ok(InsnFunctionStepResult::Step);
|
||||
}
|
||||
|
||||
// Handle NULL values
|
||||
if matches!(lhs_value, Value::Null) || matches!(rhs_value, Value::Null) {
|
||||
if jump_if_null {
|
||||
state.pc = target_pc.to_offset_int();
|
||||
} else {
|
||||
state.pc += 1;
|
||||
}
|
||||
return Ok(InsnFunctionStepResult::Step);
|
||||
}
|
||||
|
||||
let mut lhs_temp_reg = state.registers[lhs].clone();
|
||||
let mut rhs_temp_reg = state.registers[rhs].clone();
|
||||
|
||||
let lhs_converted = apply_numeric_affinity(&mut lhs_temp_reg, false);
|
||||
let rhs_converted = apply_numeric_affinity(&mut rhs_temp_reg, false);
|
||||
|
||||
let should_jump = match (
|
||||
lhs_temp_reg.get_owned_value(),
|
||||
rhs_temp_reg.get_owned_value(),
|
||||
) {
|
||||
(Value::Text(lhs_text), Value::Text(rhs_text)) => {
|
||||
let order = collation.compare_strings(lhs_text.as_str(), rhs_text.as_str());
|
||||
order.is_gt()
|
||||
}
|
||||
(lhs, rhs) => *lhs > *rhs,
|
||||
};
|
||||
|
||||
if lhs_converted {
|
||||
state.registers[lhs] = lhs_temp_reg;
|
||||
}
|
||||
if rhs_converted {
|
||||
state.registers[rhs] = rhs_temp_reg;
|
||||
}
|
||||
|
||||
if should_jump {
|
||||
state.pc = target_pc.to_offset_int();
|
||||
} else {
|
||||
state.pc += 1;
|
||||
}
|
||||
Ok(InsnFunctionStepResult::Step)
|
||||
}
|
||||
|
||||
@@ -815,41 +949,86 @@ pub fn op_ge(
|
||||
collation,
|
||||
} = insn
|
||||
else {
|
||||
unreachable!("unexpected Insn {:?}", insn)
|
||||
unreachable!("unexpected Insn: {:?}", insn)
|
||||
};
|
||||
|
||||
assert!(target_pc.is_offset());
|
||||
|
||||
let lhs = *lhs;
|
||||
let rhs = *rhs;
|
||||
let target_pc = *target_pc;
|
||||
let jump_if_null = flags.has_jump_if_null();
|
||||
let collation = collation.unwrap_or_default();
|
||||
match (
|
||||
state.registers[lhs].get_owned_value(),
|
||||
state.registers[rhs].get_owned_value(),
|
||||
|
||||
let lhs_value = state.registers[lhs].get_owned_value();
|
||||
let rhs_value = state.registers[rhs].get_owned_value();
|
||||
|
||||
println!("lhs_value: {:?}, rhs_value: {:?}", lhs_value, rhs_value);
|
||||
println!("jump_if_null: {}", jump_if_null);
|
||||
|
||||
if matches!(lhs_value, Value::Integer(_)) && matches!(rhs_value, Value::Integer(_)) {
|
||||
if lhs_value >= rhs_value {
|
||||
state.pc = target_pc.to_offset_int();
|
||||
} else {
|
||||
state.pc += 1;
|
||||
}
|
||||
return Ok(InsnFunctionStepResult::Step);
|
||||
}
|
||||
|
||||
if matches!(lhs_value, Value::Null) || matches!(rhs_value, Value::Null) {
|
||||
if jump_if_null {
|
||||
state.pc = target_pc.to_offset_int();
|
||||
} else {
|
||||
state.pc += 1;
|
||||
}
|
||||
return Ok(InsnFunctionStepResult::Step);
|
||||
}
|
||||
|
||||
let mut lhs_temp_reg = state.registers[lhs].clone();
|
||||
let mut rhs_temp_reg = state.registers[rhs].clone();
|
||||
|
||||
let lhs_converted = apply_numeric_affinity(&mut lhs_temp_reg, false);
|
||||
let rhs_converted = apply_numeric_affinity(&mut rhs_temp_reg, false);
|
||||
println!(
|
||||
"lhs_converted: {}, rhs_converted: {}",
|
||||
lhs_converted, rhs_converted
|
||||
);
|
||||
println!(
|
||||
"converted_lhs: {:?}, converted_rhs: {:?}",
|
||||
lhs_temp_reg.get_owned_value(),
|
||||
rhs_temp_reg.get_owned_value()
|
||||
);
|
||||
let should_jump = match (
|
||||
lhs_temp_reg.get_owned_value(),
|
||||
rhs_temp_reg.get_owned_value(),
|
||||
) {
|
||||
(_, Value::Null) | (Value::Null, _) => {
|
||||
if jump_if_null {
|
||||
state.pc = target_pc.to_offset_int();
|
||||
} else {
|
||||
state.pc += 1;
|
||||
}
|
||||
}
|
||||
(Value::Text(lhs), Value::Text(rhs)) => {
|
||||
let order = collation.compare_strings(lhs.as_str(), rhs.as_str());
|
||||
if order.is_ge() {
|
||||
state.pc = target_pc.to_offset_int();
|
||||
} else {
|
||||
state.pc += 1;
|
||||
}
|
||||
(Value::Text(lhs_text), Value::Text(rhs_text)) => {
|
||||
let order = collation.compare_strings(lhs_text.as_str(), rhs_text.as_str());
|
||||
order.is_ge()
|
||||
}
|
||||
|
||||
(lhs, rhs) => {
|
||||
if *lhs >= *rhs {
|
||||
state.pc = target_pc.to_offset_int();
|
||||
true
|
||||
} else {
|
||||
state.pc += 1;
|
||||
false
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if lhs_converted {
|
||||
state.registers[lhs] = lhs_temp_reg;
|
||||
}
|
||||
if rhs_converted {
|
||||
state.registers[rhs] = rhs_temp_reg;
|
||||
}
|
||||
|
||||
if should_jump {
|
||||
state.pc = target_pc.to_offset_int();
|
||||
} else {
|
||||
state.pc += 1;
|
||||
}
|
||||
|
||||
Ok(InsnFunctionStepResult::Step)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user