diff --git a/asg/src/const_value.rs b/asg/src/const_value.rs index 2316604925..f093a65559 100644 --- a/asg/src/const_value.rs +++ b/asg/src/const_value.rs @@ -186,7 +186,7 @@ macro_rules! const_int_bimap { impl ConstInt { const_int_op!(raw_value, String, x, format!("{}", x)); - const_int_map!(value_negate, x, x.overflowing_neg().0); + const_int_map!(value_negate, x, x.checked_neg()?); const_int_map!(value_bit_negate, x, !x); @@ -267,61 +267,18 @@ impl ConstInt { Type::Integer(self.get_int_type()) } - fn parse_signed(int_type: &IntegerType, raw: u128) -> Option { - Some(match int_type { - IntegerType::I8 => ConstInt::I8(raw.try_into().ok()?), - IntegerType::I16 => ConstInt::I16(raw.try_into().ok()?), - IntegerType::I32 => ConstInt::I32(raw.try_into().ok()?), - IntegerType::I64 => ConstInt::I64(raw.try_into().ok()?), - IntegerType::I128 => ConstInt::I128(raw.try_into().ok()?), - _ => panic!("illegal type passed to parse_signed"), - }) - } - pub fn parse(int_type: &IntegerType, value: &str, span: &Span) -> Result { - let raw: u128 = value.parse().map_err(|_| AsgConvertError::invalid_int(&value, span))?; Ok(match int_type { - // IntegerType::I8 => ConstInt::I8(raw.try_into().map_err(|_| AsgConvertError::overflowed_const_int(&value, span))?), - // IntegerType::I16 => ConstInt::I16(raw.try_into().map_err(|_| AsgConvertError::overflowed_const_int(&value, span))?), - // IntegerType::I32 => ConstInt::I32(raw.try_into().map_err(|_| AsgConvertError::overflowed_const_int(&value, span))?), - // IntegerType::I64 => ConstInt::I64(raw.try_into().map_err(|_| AsgConvertError::overflowed_const_int(&value, span))?), - // IntegerType::I128 => ConstInt::I128(raw.try_into().map_err(|_| AsgConvertError::overflowed_const_int(&value, span))?), - IntegerType::U8 => ConstInt::U8( - raw.try_into() - .map_err(|_| AsgConvertError::overflowed_const_int(&value, span))?, - ), - IntegerType::U16 => ConstInt::U16( - raw.try_into() - .map_err(|_| AsgConvertError::overflowed_const_int(&value, span))?, - ), - IntegerType::U32 => ConstInt::U32( - raw.try_into() - .map_err(|_| AsgConvertError::overflowed_const_int(&value, span))?, - ), - IntegerType::U64 => ConstInt::U64( - raw.try_into() - .map_err(|_| AsgConvertError::overflowed_const_int(&value, span))?, - ), - IntegerType::U128 => ConstInt::U128( - raw.try_into() - .map_err(|_| AsgConvertError::overflowed_const_int(&value, span))?, - ), - signed_type => { - if let Some(parsed) = Self::parse_signed(signed_type, raw) { - parsed - } else if let Some(_parsed) = Self::parse_signed(signed_type, raw - 1) { - match int_type { - IntegerType::I8 => ConstInt::I8(raw as i8), - IntegerType::I16 => ConstInt::I16(raw as i16), - IntegerType::I32 => ConstInt::I32(raw as i32), - IntegerType::I64 => ConstInt::I64(raw as i64), - IntegerType::I128 => ConstInt::I128(raw as i128), - _ => panic!("illegal type passed to parse_signed"), - } - } else { - return Err(AsgConvertError::overflowed_const_int(&value, span)); - } - } + IntegerType::I8 => ConstInt::I8(value.parse().map_err(|_| AsgConvertError::invalid_int(&value, span))?), + IntegerType::I16 => ConstInt::I16(value.parse().map_err(|_| AsgConvertError::invalid_int(&value, span))?), + IntegerType::I32 => ConstInt::I32(value.parse().map_err(|_| AsgConvertError::invalid_int(&value, span))?), + IntegerType::I64 => ConstInt::I64(value.parse().map_err(|_| AsgConvertError::invalid_int(&value, span))?), + IntegerType::I128 => ConstInt::I128(value.parse().map_err(|_| AsgConvertError::invalid_int(&value, span))?), + IntegerType::U8 => ConstInt::U8(value.parse().map_err(|_| AsgConvertError::invalid_int(&value, span))?), + IntegerType::U16 => ConstInt::U16(value.parse().map_err(|_| AsgConvertError::invalid_int(&value, span))?), + IntegerType::U32 => ConstInt::U32(value.parse().map_err(|_| AsgConvertError::invalid_int(&value, span))?), + IntegerType::U64 => ConstInt::U64(value.parse().map_err(|_| AsgConvertError::invalid_int(&value, span))?), + IntegerType::U128 => ConstInt::U128(value.parse().map_err(|_| AsgConvertError::invalid_int(&value, span))?), }) } } diff --git a/asg/src/error/mod.rs b/asg/src/error/mod.rs index 1cb3ef346e..87040a58fa 100644 --- a/asg/src/error/mod.rs +++ b/asg/src/error/mod.rs @@ -244,10 +244,6 @@ impl AsgConvertError { Self::new_from_span(format!("failed to parse int value '{}'", value), span) } - pub fn overflowed_const_int(value: &str, span: &Span) -> Self { - Self::new_from_span(format!("const int value is overflowed for type '{}'", value), span) - } - pub fn unsigned_negation(span: &Span) -> Self { Self::new_from_span("cannot negate unsigned integer".to_string(), span) } diff --git a/ast/src/common/span.rs b/ast/src/common/span.rs index 33879b364f..1f672f9889 100644 --- a/ast/src/common/span.rs +++ b/ast/src/common/span.rs @@ -67,6 +67,7 @@ impl std::ops::Add for &Span { impl std::ops::Add for Span { type Output = Self; + #[allow(clippy::comparison_chain)] fn add(self, other: Self) -> Self { if self.line_start == other.line_stop { Span { diff --git a/ast/src/types/integer_type.rs b/ast/src/types/integer_type.rs index 2319c51769..579ca2c6c0 100644 --- a/ast/src/types/integer_type.rs +++ b/ast/src/types/integer_type.rs @@ -42,10 +42,7 @@ pub enum IntegerType { impl IntegerType { pub fn is_signed(&self) -> bool { use IntegerType::*; - match self { - I8 | I16 | I32 | I64 | I128 => true, - _ => false, - } + matches!(self, I8 | I16 | I32 | I64 | I128) } } diff --git a/parser/src/parser/expression.rs b/parser/src/parser/expression.rs index 299368b5c3..257cb30852 100644 --- a/parser/src/parser/expression.rs +++ b/parser/src/parser/expression.rs @@ -365,14 +365,25 @@ impl ParserContext { } let mut inner = self.parse_access_expression()?; for op in ops.into_iter().rev() { + let operation = match op.token { + Token::Not => UnaryOperation::Not, + Token::Minus => UnaryOperation::Negate, + Token::BitNot => UnaryOperation::BitNot, + _ => unimplemented!(), + }; + // hack for const signed integer overflow issues + if matches!(operation, UnaryOperation::Negate) { + if let Expression::Value(ValueExpression::Integer(type_, value, span)) = inner { + inner = Expression::Value(ValueExpression::Integer(type_, format!("-{}", value), &op.span + &span)); + continue; + } else if let Expression::Value(ValueExpression::Implicit(value, span)) = inner { + inner = Expression::Value(ValueExpression::Implicit(format!("-{}", value), &op.span + &span)); + continue; + } + } inner = Expression::Unary(UnaryExpression { span: &op.span + inner.span(), - op: match op.token { - Token::Not => UnaryOperation::Not, - Token::Minus => UnaryOperation::Negate, - Token::BitNot => UnaryOperation::BitNot, - _ => unimplemented!(), - }, + op: operation, inner: Box::new(inner), }); }