Skip to content

Commit

Permalink
literal_to_literal working
Browse files Browse the repository at this point in the history
  • Loading branch information
xunilrj committed Jul 12, 2023
1 parent 09ba6c6 commit 86d7f6d
Show file tree
Hide file tree
Showing 15 changed files with 172 additions and 3 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions sway-ast/src/literal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,14 @@ pub enum LitIntType {
U16,
U32,
U64,
U128,
U256,
I8,
I16,
I32,
I64,
I128,
I256,
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash, Serialize)]
Expand Down
1 change: 1 addition & 0 deletions sway-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ im = "15.0"
itertools = "0.10"
lazy_static = "1.4"
miden-core = "0.3.0"
num-bigint = { version = "0.4.3", features = ["serde"] }
pest = "2.1.3"
pest_derive = "2.1"
petgraph = "0.6"
Expand Down
4 changes: 4 additions & 0 deletions sway-core/src/ir_generation/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ pub(super) fn convert_literal_to_value(context: &mut Context, ast_literal: &Lite
Literal::U16(n) => Constant::get_uint(context, 64, *n as u64),
Literal::U32(n) => Constant::get_uint(context, 64, *n as u64),
Literal::U64(n) => Constant::get_uint(context, 64, *n),
Literal::U128(_) => todo!(),
Literal::U256(_) => todo!(),
Literal::Numeric(n) => Constant::get_uint(context, 64, *n),
Literal::String(s) => Constant::get_string(context, s.as_str().as_bytes().to_vec()),
Literal::Boolean(b) => Constant::get_bool(context, *b),
Expand All @@ -42,6 +44,8 @@ pub(super) fn convert_literal_to_constant(
Literal::U16(n) => Constant::new_uint(context, 64, *n as u64),
Literal::U32(n) => Constant::new_uint(context, 64, *n as u64),
Literal::U64(n) => Constant::new_uint(context, 64, *n),
Literal::U128(_) => todo!(),
Literal::U256(_) => todo!(),
Literal::Numeric(n) => Constant::new_uint(context, 64, *n),
Literal::String(s) => Constant::new_string(context, s.as_str().as_bytes().to_vec()),
Literal::Boolean(b) => Constant::new_bool(context, *b),
Expand Down
11 changes: 11 additions & 0 deletions sway-core/src/language/literal.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{type_system::*, Engines};

use num_bigint::BigUint;
use sway_error::error::CompileError;
use sway_types::{integer_bits::IntegerBits, span};

Expand All @@ -15,6 +16,8 @@ pub enum Literal {
U16(u16),
U32(u32),
U64(u64),
U128(u128),
U256(BigUint),
String(span::Span),
Numeric(u64),
Boolean(bool),
Expand All @@ -41,6 +44,8 @@ impl Hash for Literal {
state.write_u8(4);
x.hash(state);
}
U128(_) => todo!(),
U256(_) => todo!(),
Numeric(x) => {
state.write_u8(5);
x.hash(state);
Expand Down Expand Up @@ -68,6 +73,8 @@ impl PartialEq for Literal {
(Self::U16(l0), Self::U16(r0)) => l0 == r0,
(Self::U32(l0), Self::U32(r0)) => l0 == r0,
(Self::U64(l0), Self::U64(r0)) => l0 == r0,
(Self::U128(l0), Self::U128(r0)) => l0 == r0,
(Self::U256(l0), Self::U256(r0)) => l0 == r0,
(Self::String(l0), Self::String(r0)) => *l0.as_str() == *r0.as_str(),
(Self::Numeric(l0), Self::Numeric(r0)) => l0 == r0,
(Self::Boolean(l0), Self::Boolean(r0)) => l0 == r0,
Expand All @@ -84,6 +91,8 @@ impl fmt::Display for Literal {
Literal::U16(content) => content.to_string(),
Literal::U32(content) => content.to_string(),
Literal::U64(content) => content.to_string(),
Literal::U128(_) => todo!(),
Literal::U256(_) => todo!(),
Literal::Numeric(content) => content.to_string(),
Literal::String(content) => content.as_str().to_string(),
Literal::Boolean(content) => content.to_string(),
Expand Down Expand Up @@ -132,6 +141,8 @@ impl Literal {
Literal::U16(_) => TypeInfo::UnsignedInteger(IntegerBits::Sixteen),
Literal::U32(_) => TypeInfo::UnsignedInteger(IntegerBits::ThirtyTwo),
Literal::U64(_) => TypeInfo::UnsignedInteger(IntegerBits::SixtyFour),
Literal::U128(_) => todo!(),
Literal::U256(_) => todo!(),
Literal::Boolean(_) => TypeInfo::Boolean,
Literal::B256(_) => TypeInfo::B256,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,8 @@ impl Pattern {
Literal::U16(x) => Pattern::U16(Range::from_single(x)),
Literal::U32(x) => Pattern::U32(Range::from_single(x)),
Literal::U64(x) => Pattern::U64(Range::from_single(x)),
Literal::U128(_) => todo!(),
Literal::U256(_) => todo!(),
Literal::B256(x) => Pattern::B256(x),
Literal::Boolean(b) => Pattern::Boolean(b),
Literal::Numeric(x) => Pattern::Numeric(Range::from_single(x)),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,8 @@ impl ty::TyExpression {
Literal::U16(_) => TypeInfo::UnsignedInteger(IntegerBits::Sixteen),
Literal::U32(_) => TypeInfo::UnsignedInteger(IntegerBits::ThirtyTwo),
Literal::U64(_) => TypeInfo::UnsignedInteger(IntegerBits::SixtyFour),
Literal::U128(_) => todo!(),
Literal::U256(_) => todo!(),
Literal::Boolean(_) => TypeInfo::Boolean,
Literal::B256(_) => TypeInfo::B256,
};
Expand Down
84 changes: 81 additions & 3 deletions sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::{
};

use itertools::Itertools;
use num_bigint::BigUint;
use sway_ast::{
attribute::Annotated,
expr::{LoopControlFlow, ReassignmentOp, ReassignmentOpVariant},
Expand Down Expand Up @@ -1773,7 +1774,7 @@ fn expr_to_expression(
},
Expr::Path(path_expr) => path_expr_to_expression(context, handler, engines, path_expr)?,
Expr::Literal(literal) => Expression {
kind: ExpressionKind::Literal(literal_to_literal(context, handler, literal)?),
kind: ExpressionKind::Literal(literal_to_literal(handler, literal)?),
span,
},
Expr::AbiCast { args, .. } => {
Expand Down Expand Up @@ -2774,7 +2775,6 @@ fn path_root_opt_to_bool_and_qualified_path_root(
}

fn literal_to_literal(
_context: &mut Context,
handler: &Handler,
literal: sway_ast::Literal,
) -> Result<Literal, ErrorEmitted> {
Expand Down Expand Up @@ -2887,10 +2887,38 @@ fn literal_to_literal(
};
Literal::U64(value)
}
LitIntType::U128 => {
let value = match u128::try_from(parsed) {
Ok(value) => value,
Err(..) => {
let error = ConvertParseTreeError::U128LiteralOutOfRange { span };
return Err(handler.emit_err(error.into()));
}
};
Literal::U128(value)
}
LitIntType::U256 => {
let mut bytes = parsed.to_bytes_le();

// Normalize removing zeros from the most signicants positions
if let Some(&0) = bytes.last() {
let len = bytes.iter().rposition(|&d| d != 0).map_or(0, |i| i + 1);
bytes.truncate(len);
}

if bytes.len() <= 32 {
Literal::U256(BigUint::from_bytes_le(&bytes))
} else {
let error = ConvertParseTreeError::U256LiteralOutOfRange { span };
return Err(handler.emit_err(error.into()));
}
}
LitIntType::I8 | LitIntType::I16 | LitIntType::I32 | LitIntType::I64 => {
let error = ConvertParseTreeError::SignedIntegersNotSupported { span };
return Err(handler.emit_err(error.into()));
}
LitIntType::I128 => todo!(),
LitIntType::I256 => todo!(),
},
}
}
Expand Down Expand Up @@ -3551,7 +3579,7 @@ fn pattern_to_scrutinee(
}
Pattern::AmbiguousSingleIdent(ident) => Scrutinee::AmbiguousSingleIdent(ident),
Pattern::Literal(literal) => Scrutinee::Literal {
value: literal_to_literal(context, handler, literal)?,
value: literal_to_literal(handler, literal)?,
span,
},
Pattern::Constant(path_expr) => {
Expand Down Expand Up @@ -4204,3 +4232,53 @@ pub fn cfg_eval(
}
Ok(true)
}

#[cfg(test)]
mod tests {
use super::*;
use num_bigint::{BigUint, ToBigUint};

fn assert(ty: LitIntType, value: impl ToBigUint, expected: Literal) {
let actual = literal_to_literal(
&Handler::default(),
sway_ast::Literal::Int(LitInt {
span: Span::dummy(),
parsed: value.to_biguint().unwrap(),
ty_opt: Some((ty, Span::dummy())),
}),
);

if !matches!(&actual, Ok(l) if *l == expected) {
dbg!(&actual, &expected);
assert!(matches!(actual, Ok(l) if l == expected));
}
}

#[test]
fn ok_literal_to_literal() {
assert(LitIntType::U8, 0u8, Literal::U8(0));
assert(LitIntType::U8, u8::MAX, Literal::U8(u8::MAX));

assert(LitIntType::U16, 0u16, Literal::U16(0));
assert(LitIntType::U16, u16::MAX, Literal::U16(u16::MAX));

assert(LitIntType::U32, 0u32, Literal::U32(0));
assert(LitIntType::U32, u32::MAX, Literal::U32(u32::MAX));

assert(LitIntType::U64, 0u64, Literal::U64(0));
assert(LitIntType::U64, u64::MAX, Literal::U64(u64::MAX));

assert(LitIntType::U128, 0u128, Literal::U128(0));
assert(LitIntType::U128, u128::MAX, Literal::U128(u128::MAX));

let zero = BigUint::from_bytes_le(&[0u8; 32]);
let max_value = BigUint::from_bytes_le(&[255u8; 32]);
assert(LitIntType::U256, 0, Literal::U256(zero));
assert(
LitIntType::U256,
//115 quattuorvigintillion, if you are curious
max_value.clone(),
Literal::U256(max_value),
);
}
}
6 changes: 6 additions & 0 deletions sway-error/src/convert_parse_tree_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ pub enum ConvertParseTreeError {
U32LiteralOutOfRange { span: Span },
#[error("u64 literal out of range")]
U64LiteralOutOfRange { span: Span },
#[error("u128 literal out of range")]
U128LiteralOutOfRange { span: Span },
#[error("u256 literal out of range")]
U256LiteralOutOfRange { span: Span },
#[error("signed integers are not supported")]
SignedIntegersNotSupported { span: Span },
#[error("ref variables are not supported")]
Expand Down Expand Up @@ -147,6 +151,8 @@ impl Spanned for ConvertParseTreeError {
ConvertParseTreeError::U16LiteralOutOfRange { span } => span.clone(),
ConvertParseTreeError::U32LiteralOutOfRange { span } => span.clone(),
ConvertParseTreeError::U64LiteralOutOfRange { span } => span.clone(),
ConvertParseTreeError::U128LiteralOutOfRange { span } => span.clone(),
ConvertParseTreeError::U256LiteralOutOfRange { span } => span.clone(),
ConvertParseTreeError::SignedIntegersNotSupported { span } => span.clone(),
ConvertParseTreeError::RefVariablesNotSupported { span } => span.clone(),
ConvertParseTreeError::LiteralPatternsNotSupportedHere { span } => span.clone(),
Expand Down
5 changes: 5 additions & 0 deletions sway-parse/src/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,7 @@ fn lex_int_ty_opt(l: &mut Lexer<'_>) -> Result<Option<(LitIntType, Span)>> {
None => break l.src.len(),
}
};

// Parse the suffix to a known one, or if unknown, recover by throwing it away.
let ty = match parse_int_suffix(&suffix) {
Some(s) => s,
Expand All @@ -726,10 +727,14 @@ pub fn parse_int_suffix(suffix: &str) -> Option<LitIntType> {
"u16" => LitIntType::U16,
"u32" => LitIntType::U32,
"u64" => LitIntType::U64,
"u128" => LitIntType::U128,
"u256" => LitIntType::U256,
"i8" => LitIntType::I8,
"i16" => LitIntType::I16,
"i32" => LitIntType::I32,
"i64" => LitIntType::I64,
"i128" => LitIntType::I128,
"i256" => LitIntType::I256,
_ => return None,
})
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[[package]]
name = 'b256_ops'
source = 'member'
dependencies = ['std']

[[package]]
name = 'core'
source = 'path+from-root-963ABD293AAA1DE4'

[[package]]
name = 'std'
source = 'path+from-root-963ABD293AAA1DE4'
dependencies = ['core']
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[project]
authors = ["Fuel Labs <[email protected]>"]
license = "Apache-2.0"
name = "b256_ops"
entry = "main.sw"

[dependencies]
std = { path = "../../../../../../../sway-lib-std" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"configurables": [],
"functions": [
{
"attributes": null,
"inputs": [],
"name": "main",
"output": {
"name": "",
"type": 0,
"typeArguments": null
}
}
],
"loggedTypes": [],
"messagesTypes": [],
"types": [
{
"components": null,
"type": "u64",
"typeId": 0,
"typeParameters": null
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
script;

fn main() -> u64 {
let aaaa = 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaau256;
0
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
category = "run"
expected_result = { action = "return", value = 100 }
validate_abi = true

0 comments on commit 86d7f6d

Please sign in to comment.