Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions crates/ast/src/ast/lit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ impl fmt::Display for Lit<'_> {
let Self { ref kind, symbol, span: _ } = *self;
match kind {
LitKind::Str(s, ..) => write!(f, "{}\"{symbol}\"", s.prefix()),
LitKind::Number(_)
LitKind::Number(..)
| LitKind::Rational(_)
| LitKind::Err(_)
| LitKind::Address(_)
Expand Down Expand Up @@ -97,7 +97,8 @@ pub enum LitKind<'ast> {
/// This list is only present in the AST, and is discarded after.
Str(StrKind, ByteSymbol, &'ast [(Span, Symbol)]),
/// A decimal or hexadecimal number literal.
Number(U256),
/// The boolean indicates if the number is negative.
Number(U256, bool),
/// A rational number literal.
///
/// Note that rational literals that evaluate to integers are represented as
Expand Down Expand Up @@ -127,7 +128,13 @@ impl fmt::Debug for LitKind<'_> {
}
f.write_str(")")
}
Self::Number(value) => write!(f, "Number({value:?})"),
Self::Number(value, negative) => {
if *negative {
write!(f, "Number(-{value:?})")
} else {
write!(f, "Number({value:?})")
}
}
Self::Rational(value) => write!(f, "Rational({value:?})"),
Self::Address(value) => write!(f, "Address({value:?})"),
Self::Bool(value) => write!(f, "Bool({value:?})"),
Expand All @@ -141,7 +148,7 @@ impl LitKind<'_> {
pub fn description(&self) -> &'static str {
match self {
Self::Str(kind, ..) => kind.description(),
Self::Number(_) => "number",
Self::Number(..) => "number",
Self::Rational(_) => "rational",
Self::Address(_) => "address",
Self::Bool(_) => "boolean",
Expand Down
12 changes: 6 additions & 6 deletions crates/parse/src/parser/lit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ fn parse_integer<'ast>(
if let Some(subdenomination) = subdenomination {
n = n.checked_mul(U256::from(subdenomination.value())).ok_or(LitError::IntegerTooLarge)?;
}
Ok(LitKind::Number(n))
Ok(LitKind::Number(n, false))
}

fn parse_rational<'ast>(
Expand Down Expand Up @@ -347,7 +347,7 @@ fn parse_rational<'ast>(

// 0E... is always zero.
if number.is_zero() {
return Ok(LitKind::Number(U256::ZERO));
return Ok(LitKind::Number(U256::ZERO, false));
}

if let Some(exp) = exp {
Expand Down Expand Up @@ -377,7 +377,7 @@ fn parse_rational<'ast>(
}

if number.is_integer() {
big_to_u256(number.to_integer(), true).map(LitKind::Number)
big_to_u256(number.to_integer(), true).map(|n| LitKind::Number(n, false))
} else {
let (numer, denom) = number.into_raw();
Ok(LitKind::Rational(Ratio::new(big_to_u256(numer, true)?, big_to_u256(denom, true)?)))
Expand Down Expand Up @@ -539,7 +539,7 @@ mod tests {
fn check_int(src: &str, expected: Result<&str, LitError>) {
lex_literal(src, false, |sess, symbol| {
let res = match parse_integer(sess, symbol, None) {
Ok(LitKind::Number(n)) => Ok(n),
Ok(LitKind::Number(n, _)) => Ok(n),
Ok(x) => panic!("not a number: {x:?} ({src:?})"),
Err(e) => Err(e),
};
Expand All @@ -559,7 +559,7 @@ mod tests {
e => panic!("not an address: {e:?} ({src:?})"),
},
Err(int) => match parse_integer(sess, symbol, None) {
Ok(LitKind::Number(n)) => {
Ok(LitKind::Number(n, _)) => {
assert_eq!(n, U256::from_str_radix(int, 10).unwrap(), "{src:?}")
}
e => panic!("not an integer: {e:?} ({src:?})"),
Expand Down Expand Up @@ -636,7 +636,7 @@ mod tests {
fn check_int_full(src: &str, should_fail_lexing: bool, expected: Result<&str, LitError>) {
lex_literal(src, should_fail_lexing, |sess, symbol| {
let res = match parse_rational(sess, symbol, None) {
Ok(LitKind::Number(r)) => Ok(r),
Ok(LitKind::Number(r, _)) => Ok(r),
Ok(x) => panic!("not a number: {x:?} ({src:?})"),
Err(e) => Err(e),
};
Expand Down
20 changes: 19 additions & 1 deletion crates/sema/src/ast_lowering/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1084,7 +1084,25 @@ impl<'gcx> ResolveContext<'gcx> {
)),
ast::ExprKind::TypeCall(ty) => hir::ExprKind::TypeCall(self.lower_type(ty)),
ast::ExprKind::Type(ty) => hir::ExprKind::Type(self.lower_type(ty)),
ast::ExprKind::Unary(op, expr) => hir::ExprKind::Unary(*op, self.lower_expr(expr)),
ast::ExprKind::Unary(op, expr) => {
// Special handling for negation of numeric literals: fold to negative integer
// literal
let expr_span = op.span.with_hi(expr.span.hi());
if op.kind == ast::UnOpKind::Neg
&& let ast::ExprKind::Lit(ast::Lit { span: _, symbol, kind }, _) =
&expr.peel_parens().kind
&& let ast::LitKind::Number(number, negative) = kind
{
let neg_int_lit = self.arena.alloc(ast::Lit {
span: expr_span,
symbol: *symbol,
kind: ast::LitKind::Number(*number, !negative),
});
hir::ExprKind::Lit(neg_int_lit)
} else {
hir::ExprKind::Unary(*op, self.lower_expr(expr))
}
}
};
self.hir_builder().expr_owned(self.next_id(), kind, expr.span)
}
Expand Down
4 changes: 2 additions & 2 deletions crates/sema/src/ast_passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ impl<'sess> AstValidator<'sess, '_> {
}

fn check_underscores_in_number_literals(&self, lit: &ast::Lit<'_>) {
let (ast::LitKind::Number(_) | ast::LitKind::Rational(_)) = lit.kind else {
let (ast::LitKind::Number(..) | ast::LitKind::Rational(_)) = lit.kind else {
return;
};
let value = lit.symbol.as_str();
Expand Down Expand Up @@ -109,7 +109,7 @@ impl<'sess> AstValidator<'sess, '_> {
return;
};

let (ast::LitKind::Number(_) | ast::LitKind::Rational(_)) = lit.kind else {
let (ast::LitKind::Number(..) | ast::LitKind::Rational(_)) = lit.kind else {
panic!("non-number literal with denomination {:?}", lit.kind)
};

Expand Down
4 changes: 3 additions & 1 deletion crates/sema/src/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,9 @@ impl<'gcx> ConstantEvaluator<'gcx> {
fn eval_lit(&mut self, lit: &hir::Lit<'_>) -> EvalResult<'gcx> {
match lit.kind {
// LitKind::Str(str_kind, arc) => todo!(),
LitKind::Number(n) => Ok(IntScalar::new(n)),
LitKind::Number(n, negative) => {
Ok(if negative { IntScalar::new(n.wrapping_neg()) } else { IntScalar::new(n) })
}
// LitKind::Rational(ratio) => todo!(),
LitKind::Address(address) => Ok(IntScalar::from_be_bytes(address.as_slice())),
LitKind::Bool(bool) => Ok(IntScalar::from_be_bytes(&[bool as u8])),
Expand Down
4 changes: 2 additions & 2 deletions crates/sema/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -634,8 +634,8 @@ impl<'gcx> Gcx<'gcx> {
pub fn type_of_lit(self, lit: &'gcx hir::Lit<'gcx>) -> Ty<'gcx> {
match &lit.kind {
solar_ast::LitKind::Str(_, s, _) => self.mk_ty_string_literal(s.as_byte_str()),
solar_ast::LitKind::Number(int) => {
self.mk_ty_int_literal(false, int.bit_len() as _).unwrap_or_else(|| {
solar_ast::LitKind::Number(int, negative) => {
self.mk_ty_int_literal(*negative, int.bit_len() as _).unwrap_or_else(|| {
self.mk_ty_err(
self.dcx()
.err("integer literal is greater than 2**256")
Expand Down
Loading