Skip to content

Commit 9e39a96

Browse files
committed
[Compiler v2] support signed integers
1 parent 17cfb51 commit 9e39a96

File tree

120 files changed

+32995
-231
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

120 files changed

+32995
-231
lines changed

third_party/move/move-command-line-common/src/parser.rs

Lines changed: 97 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ use crate::{
77
values::{ParsableValue, ParsedValue, ValueToken},
88
};
99
use anyhow::{anyhow, bail, Result};
10-
use move_core_types::{account_address::AccountAddress, int256::U256};
10+
use move_core_types::{
11+
account_address::AccountAddress,
12+
int256::{I256, U256},
13+
};
1114
use num_bigint::BigUint;
1215
use std::{collections::BTreeMap, fmt::Display, iter::Peekable, num::ParseIntError};
1316

@@ -137,6 +140,12 @@ impl<'a, I: Iterator<Item = (TypeToken, &'a str)>> Parser<'a, TypeToken, I> {
137140
(TypeToken::Ident, "u64") => ParsedType::U64,
138141
(TypeToken::Ident, "u128") => ParsedType::U128,
139142
(TypeToken::Ident, "u256") => ParsedType::U256,
143+
(TypeToken::Ident, "i8") => ParsedType::I8,
144+
(TypeToken::Ident, "i16") => ParsedType::I16,
145+
(TypeToken::Ident, "i32") => ParsedType::I32,
146+
(TypeToken::Ident, "i64") => ParsedType::I64,
147+
(TypeToken::Ident, "i128") => ParsedType::I128,
148+
(TypeToken::Ident, "i256") => ParsedType::I256,
140149
(TypeToken::Ident, "bool") => ParsedType::Bool,
141150
(TypeToken::Ident, "address") => ParsedType::Address,
142151
(TypeToken::Ident, "signer") => ParsedType::Signer,
@@ -191,8 +200,13 @@ impl<'a, I: Iterator<Item = (ValueToken, &'a str)>> Parser<'a, ValueToken, I> {
191200
let (tok, contents) = self.advance_any()?;
192201
Ok(match tok {
193202
ValueToken::Number if !matches!(self.peek_tok(), Some(ValueToken::ColonColon)) => {
194-
let u = parse_u256(contents)?;
195-
ParsedValue::InferredNum(u)
203+
if contents.starts_with('-') {
204+
let i = parse_i256(contents)?;
205+
ParsedValue::InferredNegNum(i)
206+
} else {
207+
let u = parse_u256(contents)?;
208+
ParsedValue::InferredNum(u)
209+
}
196210
},
197211
ValueToken::NumberTyped => {
198212
if let Some(s) = contents.strip_suffix("u8") {
@@ -210,9 +224,27 @@ impl<'a, I: Iterator<Item = (ValueToken, &'a str)>> Parser<'a, ValueToken, I> {
210224
} else if let Some(s) = contents.strip_suffix("u128") {
211225
let (u, _) = parse_u128(s)?;
212226
ParsedValue::U128(u)
213-
} else {
214-
let u = parse_u256(contents.strip_suffix("u256").unwrap())?;
227+
} else if let Some(s) = contents.strip_suffix("u256") {
228+
let u = parse_u256(s)?;
215229
ParsedValue::U256(u)
230+
} else if let Some(s) = contents.strip_suffix("i8") {
231+
let (i, _) = parse_i8(s)?;
232+
ParsedValue::I8(i)
233+
} else if let Some(s) = contents.strip_suffix("i16") {
234+
let (i, _) = parse_i16(s)?;
235+
ParsedValue::I16(i)
236+
} else if let Some(s) = contents.strip_suffix("i32") {
237+
let (i, _) = parse_i32(s)?;
238+
ParsedValue::I32(i)
239+
} else if let Some(s) = contents.strip_suffix("i64") {
240+
let (i, _) = parse_i64(s)?;
241+
ParsedValue::I64(i)
242+
} else if let Some(s) = contents.strip_suffix("i128") {
243+
let (i, _) = parse_i128(s)?;
244+
ParsedValue::I128(i)
245+
} else {
246+
let i = parse_i256(contents.strip_suffix("i256").unwrap())?;
247+
ParsedValue::I256(i)
216248
}
217249
},
218250
ValueToken::True => ParsedValue::Bool(true),
@@ -342,10 +374,14 @@ pub enum NumberFormat {
342374
}
343375

344376
// Determines the base of the number literal, depending on the prefix
345-
pub(crate) fn determine_num_text_and_base(s: &str) -> (&str, NumberFormat) {
346-
match s.strip_prefix("0x") {
347-
Some(s_hex) => (s_hex, NumberFormat::Hex),
348-
None => (s, NumberFormat::Decimal),
377+
pub(crate) fn determine_num_text_and_base(s: &str) -> (String, NumberFormat) {
378+
if let Some(s_hex) = s.strip_prefix("0x") {
379+
(s_hex.to_string(), NumberFormat::Hex)
380+
} else if let Some(s_hex) = s.strip_prefix("-0x") {
381+
// if negative hex, need to add the '-' back
382+
(format!("-{}", s_hex), NumberFormat::Hex)
383+
} else {
384+
(s.to_string(), NumberFormat::Decimal)
349385
}
350386
}
351387

@@ -400,7 +436,58 @@ pub fn parse_u256(s: &str) -> anyhow::Result<U256> {
400436
U256::from_str_radix(&txt.replace('_', ""), base as u32)
401437
}
402438

403-
// Parse an address from a decimal or hex encoding
439+
/// Parse an i8 from a decimal or hex encoding and return its value in i8
440+
pub fn parse_i8(s: &str) -> Result<(i8, NumberFormat), ParseIntError> {
441+
let (txt, base) = determine_num_text_and_base(s);
442+
Ok((
443+
i8::from_str_radix(&txt.replace('_', ""), base as u32)?,
444+
base,
445+
))
446+
}
447+
448+
/// Parse an i16 from a decimal or hex encoding and return its value in i16
449+
pub fn parse_i16(s: &str) -> Result<(i16, NumberFormat), ParseIntError> {
450+
let (txt, base) = determine_num_text_and_base(s);
451+
Ok((
452+
i16::from_str_radix(&txt.replace('_', ""), base as u32)?,
453+
base,
454+
))
455+
}
456+
457+
/// Parse an i32 from a decimal or hex encoding and return its value in i32
458+
pub fn parse_i32(s: &str) -> Result<(i32, NumberFormat), ParseIntError> {
459+
let (txt, base) = determine_num_text_and_base(s);
460+
Ok((
461+
i32::from_str_radix(&txt.replace('_', ""), base as u32)?,
462+
base,
463+
))
464+
}
465+
466+
/// Parse an i64 from a decimal or hex encoding and return its value in i64
467+
pub fn parse_i64(s: &str) -> Result<(i64, NumberFormat), ParseIntError> {
468+
let (txt, base) = determine_num_text_and_base(s);
469+
Ok((
470+
i64::from_str_radix(&txt.replace('_', ""), base as u32)?,
471+
base,
472+
))
473+
}
474+
475+
/// Parse an i128 from a decimal or hex encoding and return its value in i128
476+
pub fn parse_i128(s: &str) -> Result<(i128, NumberFormat), ParseIntError> {
477+
let (txt, base) = determine_num_text_and_base(s);
478+
Ok((
479+
i128::from_str_radix(&txt.replace('_', ""), base as u32)?,
480+
base,
481+
))
482+
}
483+
484+
/// Parse an i256 from a decimal or hex encoding and return its value in I256
485+
pub fn parse_i256(s: &str) -> anyhow::Result<I256> {
486+
let (txt, base) = determine_num_text_and_base(s);
487+
I256::from_str_radix(&txt.replace('_', ""), base as u32)
488+
}
489+
490+
/// Parse an address from a decimal or hex encoding
404491
pub fn parse_address_number(s: &str) -> Option<([u8; AccountAddress::LENGTH], NumberFormat)> {
405492
let (txt, base) = determine_num_text_and_base(s);
406493
let parsed = BigUint::parse_bytes(txt.as_bytes(), match base {

third_party/move/move-command-line-common/src/types.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ pub enum ParsedType {
3737
U64,
3838
U128,
3939
U256,
40+
I8,
41+
I16,
42+
I32,
43+
I64,
44+
I128,
45+
I256,
4046
Bool,
4147
Address,
4248
Signer,
@@ -149,6 +155,12 @@ impl ParsedType {
149155
ParsedType::U64 => TypeTag::U64,
150156
ParsedType::U128 => TypeTag::U128,
151157
ParsedType::U256 => TypeTag::U256,
158+
ParsedType::I8 => TypeTag::I8,
159+
ParsedType::I16 => TypeTag::I16,
160+
ParsedType::I32 => TypeTag::I32,
161+
ParsedType::I64 => TypeTag::I64,
162+
ParsedType::I128 => TypeTag::I128,
163+
ParsedType::I256 => TypeTag::I256,
152164
ParsedType::Bool => TypeTag::Bool,
153165
ParsedType::Address => TypeTag::Address,
154166
ParsedType::Signer => TypeTag::Signer,

third_party/move/move-command-line-common/src/values.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,19 @@ pub enum ValueToken {
4343
pub enum ParsedValue<Extra: ParsableValue = ()> {
4444
Address(ParsedAddress),
4545
InferredNum(move_core_types::int256::U256),
46+
InferredNegNum(move_core_types::int256::I256),
4647
U8(u8),
4748
U16(u16),
4849
U32(u32),
4950
U64(u64),
5051
U128(u128),
5152
U256(move_core_types::int256::U256),
53+
I8(i8),
54+
I16(i16),
55+
I32(i32),
56+
I64(i64),
57+
I128(i128),
58+
I256(move_core_types::int256::I256),
5259
Bool(bool),
5360
Vector(Vec<ParsedValue<Extra>>),
5461
Struct(
@@ -321,6 +328,14 @@ impl<Extra: ParsableValue> ParsedValue<Extra> {
321328
ParsedValue::InferredNum(u) | ParsedValue::U256(u) => {
322329
Extra::move_value_into_concrete(MoveValue::U256(u))
323330
},
331+
ParsedValue::I8(i) => Extra::move_value_into_concrete(MoveValue::I8(i)),
332+
ParsedValue::I16(i) => Extra::move_value_into_concrete(MoveValue::I16(i)),
333+
ParsedValue::I32(i) => Extra::move_value_into_concrete(MoveValue::I32(i)),
334+
ParsedValue::I64(i) => Extra::move_value_into_concrete(MoveValue::I64(i)),
335+
ParsedValue::I128(i) => Extra::move_value_into_concrete(MoveValue::I128(i)),
336+
ParsedValue::InferredNegNum(i) | ParsedValue::I256(i) => {
337+
Extra::move_value_into_concrete(MoveValue::I256(i))
338+
},
324339
ParsedValue::Bool(b) => Extra::move_value_into_concrete(MoveValue::Bool(b)),
325340
ParsedValue::Vector(values) => Extra::concrete_vector(
326341
values

third_party/move/move-compiler-v2/legacy-move-compiler/src/expansion/ast.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,8 @@ pub enum Value_ {
476476
Address(Address),
477477
// <num>
478478
InferredNum(move_core_types::int256::U256),
479+
// <num>
480+
InferredNegNum(move_core_types::int256::I256),
479481
// <num>u8
480482
U8(u8),
481483
// <num>u16
@@ -488,6 +490,18 @@ pub enum Value_ {
488490
U128(u128),
489491
// <num>u256
490492
U256(move_core_types::int256::U256),
493+
// <num>i8
494+
I8(i8),
495+
// <num>i16
496+
I16(i16),
497+
// <num>i32
498+
I32(i32),
499+
// <num>i64
500+
I64(i64),
501+
// <num>i128
502+
I128(i128),
503+
// <num>i256
504+
I256(move_core_types::int256::I256),
491505
// true
492506
// false
493507
Bool(bool),
@@ -1596,6 +1610,13 @@ impl AstDebug for Value_ {
15961610
V::U64(u) => w.write(&format!("{}u64", u)),
15971611
V::U128(u) => w.write(&format!("{}u128", u)),
15981612
V::U256(u) => w.write(&format!("{}u256", u)),
1613+
V::InferredNegNum(i) => w.write(&format!("{}", i)),
1614+
V::I8(i) => w.write(&format!("{}i8", i)),
1615+
V::I16(i) => w.write(&format!("{}i16", i)),
1616+
V::I32(i) => w.write(&format!("{}i32", i)),
1617+
V::I64(i) => w.write(&format!("{}i64", i)),
1618+
V::I128(i) => w.write(&format!("{}i128", i)),
1619+
V::I256(i) => w.write(&format!("{}i256", i)),
15991620
V::Bool(b) => w.write(&format!("{}", b)),
16001621
V::Bytearray(v) => w.write(&format!("{:?}", v)),
16011622
}

third_party/move/move-compiler-v2/legacy-move-compiler/src/expansion/translate.rs

Lines changed: 65 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,15 @@ use crate::{
2323
shared::{
2424
builtins,
2525
known_attributes::{AttributeKind, AttributePosition, KnownAttribute},
26-
parse_u128, parse_u64, parse_u8,
2726
unique_map::UniqueMap,
2827
CompilationEnv, Identifier, Name, NamedAddressMap, NamedAddressMaps, NumericalAddress,
2928
},
3029
FullyCompiledProgram,
3130
};
32-
use move_command_line_common::parser::{parse_u16, parse_u256, parse_u32};
31+
use move_command_line_common::parser::{
32+
parse_i128, parse_i16, parse_i256, parse_i32, parse_i64, parse_i8, parse_u128, parse_u16,
33+
parse_u256, parse_u32, parse_u64, parse_u8,
34+
};
3335
use move_ir_types::location::*;
3436
use move_symbol_pool::Symbol;
3537
use once_cell::sync::Lazy;
@@ -2829,50 +2831,100 @@ fn value(context: &mut Context, sp!(loc, pvalue_): P::Value) -> Option<E::Value>
28292831
PV::Num(s) if s.ends_with("u8") => match parse_u8(&s[..s.len() - 2]) {
28302832
Ok((u, _format)) => EV::U8(u),
28312833
Err(_) => {
2832-
context.env.add_diag(num_too_big_error(loc, "'u8'"));
2834+
context.env.add_diag(num_cannot_fit_error(loc, "'u8'"));
28332835
return None;
28342836
},
28352837
},
28362838
PV::Num(s) if s.ends_with("u16") => match parse_u16(&s[..s.len() - 3]) {
28372839
Ok((u, _format)) => EV::U16(u),
28382840
Err(_) => {
2839-
context.env.add_diag(num_too_big_error(loc, "'u16'"));
2841+
context.env.add_diag(num_cannot_fit_error(loc, "'u16'"));
28402842
return None;
28412843
},
28422844
},
28432845
PV::Num(s) if s.ends_with("u32") => match parse_u32(&s[..s.len() - 3]) {
28442846
Ok((u, _format)) => EV::U32(u),
28452847
Err(_) => {
2846-
context.env.add_diag(num_too_big_error(loc, "'u32'"));
2848+
context.env.add_diag(num_cannot_fit_error(loc, "'u32'"));
28472849
return None;
28482850
},
28492851
},
28502852
PV::Num(s) if s.ends_with("u64") => match parse_u64(&s[..s.len() - 3]) {
28512853
Ok((u, _format)) => EV::U64(u),
28522854
Err(_) => {
2853-
context.env.add_diag(num_too_big_error(loc, "'u64'"));
2855+
context.env.add_diag(num_cannot_fit_error(loc, "'u64'"));
28542856
return None;
28552857
},
28562858
},
28572859
PV::Num(s) if s.ends_with("u128") => match parse_u128(&s[..s.len() - 4]) {
28582860
Ok((u, _format)) => EV::U128(u),
28592861
Err(_) => {
2860-
context.env.add_diag(num_too_big_error(loc, "'u128'"));
2862+
context.env.add_diag(num_cannot_fit_error(loc, "'u128'"));
28612863
return None;
28622864
},
28632865
},
28642866
PV::Num(s) if s.ends_with("u256") => match parse_u256(&s[..s.len() - 4]) {
28652867
Ok(u) => EV::U256(u),
28662868
Err(_) => {
2867-
context.env.add_diag(num_too_big_error(loc, "'u256'"));
2869+
context.env.add_diag(num_cannot_fit_error(loc, "'u256'"));
28682870
return None;
28692871
},
28702872
},
2871-
2873+
PV::Num(s) if s.ends_with("i8") => match parse_i8(&s[..s.len() - 2]) {
2874+
Ok((i, _format)) => EV::I8(i),
2875+
Err(_) => {
2876+
context.env.add_diag(num_cannot_fit_error(loc, "'i8'"));
2877+
return None;
2878+
},
2879+
},
2880+
PV::Num(s) if s.ends_with("i16") => match parse_i16(&s[..s.len() - 3]) {
2881+
Ok((i, _format)) => EV::I16(i),
2882+
Err(_) => {
2883+
context.env.add_diag(num_cannot_fit_error(loc, "'i16'"));
2884+
return None;
2885+
},
2886+
},
2887+
PV::Num(s) if s.ends_with("i32") => match parse_i32(&s[..s.len() - 3]) {
2888+
Ok((i, _format)) => EV::I32(i),
2889+
Err(_) => {
2890+
context.env.add_diag(num_cannot_fit_error(loc, "'i32'"));
2891+
return None;
2892+
},
2893+
},
2894+
PV::Num(s) if s.ends_with("i64") => match parse_i64(&s[..s.len() - 3]) {
2895+
Ok((i, _format)) => EV::I64(i),
2896+
Err(_) => {
2897+
context.env.add_diag(num_cannot_fit_error(loc, "'i64'"));
2898+
return None;
2899+
},
2900+
},
2901+
PV::Num(s) if s.ends_with("i128") => match parse_i128(&s[..s.len() - 4]) {
2902+
Ok((i, _format)) => EV::I128(i),
2903+
Err(_) => {
2904+
context.env.add_diag(num_cannot_fit_error(loc, "'i128'"));
2905+
return None;
2906+
},
2907+
},
2908+
PV::Num(s) if s.ends_with("i256") => match parse_i256(&s[..s.len() - 4]) {
2909+
Ok(i) => EV::I256(i),
2910+
Err(_) => {
2911+
context.env.add_diag(num_cannot_fit_error(loc, "'i256'"));
2912+
return None;
2913+
},
2914+
},
2915+
// non-typed negative number literal
2916+
PV::Num(s) if s.starts_with("-") => match parse_i256(&s) {
2917+
Ok(i) => EV::InferredNegNum(i),
2918+
Err(_) => {
2919+
context.env.add_diag(num_cannot_fit_error(loc, "'i256'"));
2920+
return None;
2921+
},
2922+
},
2923+
// non-typed number literal
28722924
PV::Num(s) => match parse_u256(&s) {
28732925
Ok(u) => EV::InferredNum(u),
28742926
Err(_) => {
2875-
context.env.add_diag(num_too_big_error(
2927+
context.env.add_diag(num_cannot_fit_error(
28762928
loc,
28772929
"the largest possible integer type, 'u256'",
28782930
));
@@ -2898,15 +2950,15 @@ fn value(context: &mut Context, sp!(loc, pvalue_): P::Value) -> Option<E::Value>
28982950
Some(sp(loc, value_))
28992951
}
29002952

2901-
// Create an error for an integer literal that is too big to fit in its type.
2953+
// Create an error for an integer literal that cannot fit in its type.
29022954
// This assumes that the literal is the current token.
2903-
fn num_too_big_error(loc: Loc, type_description: &'static str) -> Diagnostic {
2955+
fn num_cannot_fit_error(loc: Loc, type_description: &'static str) -> Diagnostic {
29042956
diag!(
29052957
Syntax::InvalidNumber,
29062958
(
29072959
loc,
29082960
format!(
2909-
"Invalid number literal. The given literal is too large to fit into {}",
2961+
"Invalid number literal. The given literal cannot fit into {}",
29102962
type_description
29112963
)
29122964
),

0 commit comments

Comments
 (0)