From 3c06ddadde9a8d5508b8704d0d31cba503a4a18b Mon Sep 17 00:00:00 2001 From: Anton Harniakou Date: Mon, 14 Apr 2025 21:04:56 +0300 Subject: [PATCH 1/3] Parse hex integers in unary operators Unary operators ~ and - should work with hex integers --- core/translate/expr.rs | 24 +++++++++++++++++++----- testing/math.test | 6 +++++- testing/select.test | 4 ++++ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/core/translate/expr.rs b/core/translate/expr.rs index d49254f03..3f82940bb 100644 --- a/core/translate/expr.rs +++ b/core/translate/expr.rs @@ -1941,14 +1941,23 @@ pub fn translate_expr( // Special case: if we're negating "9223372036854775808", this is exactly MIN_INT64 // If we don't do this -1 * 9223372036854775808 will overflow and parse will fail // and trigger conversion to Real. - if numeric_value == "9223372036854775808" { + if numeric_value == "9223372036854775808" + || numeric_value == "0x7fffffffffffffff" + || numeric_value == "0x7FFFFFFFFFFFFFFF" + { program.emit_insn(Insn::Integer { value: i64::MIN, dest: target_register, }); } else { - let maybe_int = numeric_value.parse::(); - if let Ok(value) = maybe_int { + if numeric_value.starts_with("0x") { + // must be a hex decimal + let int_value = i64::from_str_radix(&numeric_value[2..], 16)?; + program.emit_insn(Insn::Integer { + value: -int_value, + dest: target_register, + }); + } else if let Ok(value) = numeric_value.parse::() { program.emit_insn(Insn::Integer { value: value * -1, dest: target_register, @@ -1982,8 +1991,13 @@ pub fn translate_expr( Ok(target_register) } (UnaryOperator::BitwiseNot, ast::Expr::Literal(ast::Literal::Numeric(num_val))) => { - let maybe_int = num_val.parse::(); - if let Ok(val) = maybe_int { + if num_val.starts_with("0x") { + let int_value = i64::from_str_radix(&num_val[2..], 16)?; + program.emit_insn(Insn::Integer { + value: !int_value, + dest: target_register, + }); + } else if let Ok(val) = num_val.parse::() { program.emit_insn(Insn::Integer { value: !val, dest: target_register, diff --git a/testing/math.test b/testing/math.test index c5e85186a..18183006e 100755 --- a/testing/math.test +++ b/testing/math.test @@ -612,10 +612,14 @@ do_execsql_test bitwise-not-text-float { SELECT ~'823.34' } {-824} -do_execsql_test bitwise-not-text-int { +do_execsql_test bitwise-not-text-int-1 { SELECT ~'1234' } {-1235} +do_execsql_test bitwise-not-text-int-2 { + SELECT ~0xA +} {-11} + do_execsql_test bitwise-not-scalar-float { SELECT ~abs(693.9) } {-694} diff --git a/testing/select.test b/testing/select.test index e9d119f51..6f0c6997d 100755 --- a/testing/select.test +++ b/testing/select.test @@ -15,6 +15,10 @@ do_execsql_test select-const-3 { SELECT 0xDEAF } {57007} +do_execsql_test select-const-4 { + SELECT -0xA +} {-10} + do_execsql_test select-true { SELECT true } {1} From 0cebeef2ff921c09c3ec8c77d2aecb313bd32b78 Mon Sep 17 00:00:00 2001 From: Anton Harniakou Date: Mon, 14 Apr 2025 21:23:04 +0300 Subject: [PATCH 2/3] Support hex integers beginning with uppercase notation like 0Xfff or 0XFFF --- core/translate/expr.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/core/translate/expr.rs b/core/translate/expr.rs index 3f82940bb..6520a8b14 100644 --- a/core/translate/expr.rs +++ b/core/translate/expr.rs @@ -1850,7 +1850,7 @@ pub fn translate_expr( } ast::Expr::Literal(lit) => match lit { ast::Literal::Numeric(val) => { - if val.starts_with("0x") { + if val.starts_with("0x") || val.starts_with("0X") { // must be a hex decimal let int_value = i64::from_str_radix(&val[2..], 16)?; program.emit_insn(Insn::Integer { @@ -1942,15 +1942,14 @@ pub fn translate_expr( // If we don't do this -1 * 9223372036854775808 will overflow and parse will fail // and trigger conversion to Real. if numeric_value == "9223372036854775808" - || numeric_value == "0x7fffffffffffffff" - || numeric_value == "0x7FFFFFFFFFFFFFFF" + || numeric_value.to_lowercase() == "0x7fffffffffffffff" { program.emit_insn(Insn::Integer { value: i64::MIN, dest: target_register, }); } else { - if numeric_value.starts_with("0x") { + if numeric_value.starts_with("0x") || numeric_value.starts_with("0X") { // must be a hex decimal let int_value = i64::from_str_radix(&numeric_value[2..], 16)?; program.emit_insn(Insn::Integer { @@ -1991,7 +1990,7 @@ pub fn translate_expr( Ok(target_register) } (UnaryOperator::BitwiseNot, ast::Expr::Literal(ast::Literal::Numeric(num_val))) => { - if num_val.starts_with("0x") { + if num_val.starts_with("0x") || num_val.starts_with("0X") { let int_value = i64::from_str_radix(&num_val[2..], 16)?; program.emit_insn(Insn::Integer { value: !int_value, From 8c797a9bd1969e18495b7cd9674adef3e169a445 Mon Sep 17 00:00:00 2001 From: Anton Harniakou Date: Tue, 15 Apr 2025 21:48:53 +0300 Subject: [PATCH 3/3] Use eq_ignore_ascii_case to compare strings --- core/translate/expr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/translate/expr.rs b/core/translate/expr.rs index 6520a8b14..77758cc8f 100644 --- a/core/translate/expr.rs +++ b/core/translate/expr.rs @@ -1942,7 +1942,7 @@ pub fn translate_expr( // If we don't do this -1 * 9223372036854775808 will overflow and parse will fail // and trigger conversion to Real. if numeric_value == "9223372036854775808" - || numeric_value.to_lowercase() == "0x7fffffffffffffff" + || numeric_value.eq_ignore_ascii_case("0x7fffffffffffffff") { program.emit_insn(Insn::Integer { value: i64::MIN,