bitwise #15
@@ -2162,14 +2162,36 @@ impl<'a> Compiler<'a> {
|
|||||||
scope: &mut VariableScope<'a, '_>,
|
scope: &mut VariableScope<'a, '_>,
|
||||||
) -> Result<CompileLocation<'a>, Error<'a>> {
|
) -> Result<CompileLocation<'a>, Error<'a>> {
|
||||||
fn fold_binary_expression<'a>(expr: &BinaryExpression<'a>) -> Option<Number> {
|
fn fold_binary_expression<'a>(expr: &BinaryExpression<'a>) -> Option<Number> {
|
||||||
|
fn number_to_i64(n: Number) -> Option<i64> {
|
||||||
|
match n {
|
||||||
|
Number::Integer(i, _) => i64::try_from(i).ok(),
|
||||||
|
Number::Decimal(d, _) => {
|
||||||
|
// Convert decimal to i64 by truncating
|
||||||
|
let int_part = d.trunc();
|
||||||
|
i64::try_from(int_part.mantissa() / 10_i128.pow(int_part.scale())).ok()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn i64_to_number(i: i64) -> Number {
|
||||||
|
Number::Integer(i as i128, Unit::None)
|
||||||
|
}
|
||||||
|
|
||||||
let (lhs, rhs) = match &expr {
|
let (lhs, rhs) = match &expr {
|
||||||
BinaryExpression::Add(l, r)
|
BinaryExpression::Add(l, r)
|
||||||
| BinaryExpression::Subtract(l, r)
|
| BinaryExpression::Subtract(l, r)
|
||||||
| BinaryExpression::Multiply(l, r)
|
| BinaryExpression::Multiply(l, r)
|
||||||
| BinaryExpression::Divide(l, r)
|
| BinaryExpression::Divide(l, r)
|
||||||
| BinaryExpression::Exponent(l, r)
|
| BinaryExpression::Exponent(l, r)
|
||||||
| BinaryExpression::Modulo(l, r) => (fold_expression(l)?, fold_expression(r)?),
|
| BinaryExpression::Modulo(l, r)
|
||||||
_ => return None,
|
| BinaryExpression::BitwiseAnd(l, r)
|
||||||
|
| BinaryExpression::BitwiseOr(l, r)
|
||||||
|
| BinaryExpression::BitwiseXor(l, r)
|
||||||
|
| BinaryExpression::LeftShift(l, r)
|
||||||
|
| BinaryExpression::RightShiftArithmetic(l, r)
|
||||||
|
| BinaryExpression::RightShiftLogical(l, r) => {
|
||||||
|
(fold_expression(l)?, fold_expression(r)?)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
match expr {
|
match expr {
|
||||||
@@ -2178,7 +2200,37 @@ impl<'a> Compiler<'a> {
|
|||||||
BinaryExpression::Multiply(..) => Some(lhs * rhs),
|
BinaryExpression::Multiply(..) => Some(lhs * rhs),
|
||||||
BinaryExpression::Divide(..) => Some(lhs / rhs), // Watch out for div by zero panics!
|
BinaryExpression::Divide(..) => Some(lhs / rhs), // Watch out for div by zero panics!
|
||||||
BinaryExpression::Modulo(..) => Some(lhs % rhs),
|
BinaryExpression::Modulo(..) => Some(lhs % rhs),
|
||||||
_ => None, // Handle Exponent separately or implement pow
|
BinaryExpression::BitwiseAnd(..) => {
|
||||||
|
let lhs_int = number_to_i64(lhs)?;
|
||||||
|
let rhs_int = number_to_i64(rhs)?;
|
||||||
|
Some(i64_to_number(lhs_int & rhs_int))
|
||||||
|
}
|
||||||
|
BinaryExpression::BitwiseOr(..) => {
|
||||||
|
let lhs_int = number_to_i64(lhs)?;
|
||||||
|
let rhs_int = number_to_i64(rhs)?;
|
||||||
|
Some(i64_to_number(lhs_int | rhs_int))
|
||||||
|
}
|
||||||
|
BinaryExpression::BitwiseXor(..) => {
|
||||||
|
let lhs_int = number_to_i64(lhs)?;
|
||||||
|
let rhs_int = number_to_i64(rhs)?;
|
||||||
|
Some(i64_to_number(lhs_int ^ rhs_int))
|
||||||
|
}
|
||||||
|
BinaryExpression::LeftShift(..) => {
|
||||||
|
let lhs_int = number_to_i64(lhs)?;
|
||||||
|
let rhs_int = number_to_i64(rhs)?;
|
||||||
|
Some(i64_to_number(lhs_int << rhs_int))
|
||||||
|
}
|
||||||
|
BinaryExpression::RightShiftArithmetic(..) => {
|
||||||
|
let lhs_int = number_to_i64(lhs)?;
|
||||||
|
let rhs_int = number_to_i64(rhs)?;
|
||||||
|
Some(i64_to_number(lhs_int >> rhs_int))
|
||||||
|
}
|
||||||
|
BinaryExpression::RightShiftLogical(..) => {
|
||||||
|
let lhs_int = number_to_i64(lhs)?;
|
||||||
|
let rhs_int = number_to_i64(rhs)?;
|
||||||
|
Some(i64_to_number(lhs_int >> rhs_int))
|
||||||
|
}
|
||||||
|
_ => None, // Exponent not handled in compile-time folding
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -135,6 +135,9 @@ pub enum TokenType<'a> {
|
|||||||
/// Represents a string token
|
/// Represents a string token
|
||||||
String(Cow<'a, str>),
|
String(Cow<'a, str>),
|
||||||
|
|
||||||
|
#[regex(r"0[xX][0-9a-fA-F][0-9a-fA-F_]*([cfk])?", parse_number)]
|
||||||
|
#[regex(r"0[oO][0-7][0-7_]*([cfk])?", parse_number)]
|
||||||
|
#[regex(r"0[bB][01][01_]*([cfk])?", parse_number)]
|
||||||
#[regex(r"[0-9][0-9_]*(\.[0-9][0-9_]*)?([cfk])?", parse_number)]
|
#[regex(r"[0-9][0-9_]*(\.[0-9][0-9_]*)?([cfk])?", parse_number)]
|
||||||
/// Represents a number token
|
/// Represents a number token
|
||||||
Number(Number),
|
Number(Number),
|
||||||
@@ -254,7 +257,33 @@ fn parse_number<'a>(lexer: &mut Lexer<'a, TokenType<'a>>) -> Result<Number, LexE
|
|||||||
_ => Unit::None,
|
_ => Unit::None,
|
||||||
};
|
};
|
||||||
|
|
||||||
if clean_str.contains('.') {
|
// Determine the base and parse accordingly
|
||||||
|
if clean_str.starts_with("0x") || clean_str.starts_with("0X") {
|
||||||
|
// Hexadecimal
|
||||||
|
let hex_part = &clean_str[2..];
|
||||||
|
Ok(Number::Integer(
|
||||||
|
i128::from_str_radix(hex_part, 16)
|
||||||
|
.map_err(|_| LexError::NumberParse(line, span, slice.to_string()))?,
|
||||||
|
unit,
|
||||||
|
))
|
||||||
|
} else if clean_str.starts_with("0o") || clean_str.starts_with("0O") {
|
||||||
|
// Octal
|
||||||
|
let octal_part = &clean_str[2..];
|
||||||
|
Ok(Number::Integer(
|
||||||
|
i128::from_str_radix(octal_part, 8)
|
||||||
|
.map_err(|_| LexError::NumberParse(line, span, slice.to_string()))?,
|
||||||
|
unit,
|
||||||
|
))
|
||||||
|
} else if clean_str.starts_with("0b") || clean_str.starts_with("0B") {
|
||||||
|
// Binary
|
||||||
|
let binary_part = &clean_str[2..];
|
||||||
|
Ok(Number::Integer(
|
||||||
|
i128::from_str_radix(binary_part, 2)
|
||||||
|
.map_err(|_| LexError::NumberParse(line, span, slice.to_string()))?,
|
||||||
|
unit,
|
||||||
|
))
|
||||||
|
} else if clean_str.contains('.') {
|
||||||
|
// Decimal floating point
|
||||||
Ok(Number::Decimal(
|
Ok(Number::Decimal(
|
||||||
clean_str
|
clean_str
|
||||||
.parse::<Decimal>()
|
.parse::<Decimal>()
|
||||||
@@ -262,6 +291,7 @@ fn parse_number<'a>(lexer: &mut Lexer<'a, TokenType<'a>>) -> Result<Number, LexE
|
|||||||
unit,
|
unit,
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
|
// Decimal integer
|
||||||
Ok(Number::Integer(
|
Ok(Number::Integer(
|
||||||
clean_str
|
clean_str
|
||||||
.parse::<i128>()
|
.parse::<i128>()
|
||||||
|
|||||||
Reference in New Issue
Block a user