forked from M-Labs/nac3
nac3ast/parser/core: use i128 for u64 constants
This commit is contained in:
parent
9f6c7b3359
commit
f7e62ab5b7
@ -4,7 +4,7 @@ pub enum Constant {
|
||||
Bool(bool),
|
||||
Str(String),
|
||||
Bytes(Vec<u8>),
|
||||
Int(Option<i64>),
|
||||
Int(i128),
|
||||
Tuple(Vec<Constant>),
|
||||
Float(f64),
|
||||
Complex { real: f64, imag: f64 },
|
||||
@ -28,12 +28,12 @@ impl From<bool> for Constant {
|
||||
}
|
||||
impl From<i32> for Constant {
|
||||
fn from(i: i32) -> Constant {
|
||||
Self::Int(Some(i as i64))
|
||||
Self::Int(i as i128)
|
||||
}
|
||||
}
|
||||
impl From<i64> for Constant {
|
||||
fn from(i: i64) -> Constant {
|
||||
Self::Int(Some(i))
|
||||
Self::Int(i as i128)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,7 +153,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
||||
let ty = self.ctx.bool_type();
|
||||
ty.const_int(if *v { 1 } else { 0 }, false).into()
|
||||
}
|
||||
Constant::Int(Some(val)) => {
|
||||
Constant::Int(val) => {
|
||||
let ty = if self.unifier.unioned(ty, self.primitives.int32)
|
||||
|| self.unifier.unioned(ty, self.primitives.uint32)
|
||||
{
|
||||
@ -1315,7 +1315,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
||||
.into_struct_value();
|
||||
let index: u32 =
|
||||
if let ExprKind::Constant { value: ast::Constant::Int(v), .. } = &slice.node {
|
||||
v.unwrap().try_into().unwrap()
|
||||
(*v).try_into().unwrap()
|
||||
} else {
|
||||
unreachable!("tuple subscript must be const int after type check");
|
||||
};
|
||||
|
@ -463,16 +463,13 @@ pub fn parse_parameter_default_value(
|
||||
) -> Result<SymbolValue, String> {
|
||||
fn handle_constant(val: &Constant, loc: &Location) -> Result<SymbolValue, String> {
|
||||
match val {
|
||||
Constant::Int(v) => match v {
|
||||
Some(v) => {
|
||||
if let Ok(v) = (*v).try_into() {
|
||||
Ok(SymbolValue::I32(v))
|
||||
} else {
|
||||
Err(format!("integer value out of range at {}", loc))
|
||||
}
|
||||
Constant::Int(v) => {
|
||||
if let Ok(v) = (*v).try_into() {
|
||||
Ok(SymbolValue::I32(v))
|
||||
} else {
|
||||
Err(format!("integer value out of range at {}", loc))
|
||||
}
|
||||
None => Err(format!("integer value out of range at {}", loc)),
|
||||
},
|
||||
}
|
||||
Constant::Float(v) => Ok(SymbolValue::Double(*v)),
|
||||
Constant::Bool(v) => Ok(SymbolValue::Bool(*v)),
|
||||
Constant::Tuple(tuple) => Ok(SymbolValue::Tuple(
|
||||
@ -483,62 +480,39 @@ pub fn parse_parameter_default_value(
|
||||
}
|
||||
match &default.node {
|
||||
ast::ExprKind::Constant { value, .. } => handle_constant(value, &default.location),
|
||||
ast::ExprKind::Call { func, args, .. } if {
|
||||
ast::ExprKind::Call { func, args, .. } if args.len() == 1 => {
|
||||
match &func.node {
|
||||
ast::ExprKind::Name { id, .. } => *id == "int64".into(),
|
||||
_ => false,
|
||||
}
|
||||
} => {
|
||||
if args.len() == 1 {
|
||||
match &args[0].node {
|
||||
ast::ExprKind::Constant { value: Constant::Int(Some(v)), .. } =>
|
||||
Ok(SymbolValue::I64(*v)),
|
||||
ast::ExprKind::Name { id, .. } if *id == "int64".into() => match &args[0].node {
|
||||
ast::ExprKind::Constant { value: Constant::Int(v), .. } => {
|
||||
let v: Result<i64, _> = (*v).try_into();
|
||||
match v {
|
||||
Ok(v) => Ok(SymbolValue::I64(v)),
|
||||
_ => Err(format!("default param value out of range at {}", default.location)),
|
||||
}
|
||||
}
|
||||
_ => Err(format!("only allow constant integer here at {}", default.location))
|
||||
}
|
||||
} else {
|
||||
Err(format!("only allow constant integer here at {}", default.location))
|
||||
}
|
||||
}
|
||||
ast::ExprKind::Call { func, args, .. } if {
|
||||
match &func.node {
|
||||
ast::ExprKind::Name { id, .. } => *id == "uint32".into(),
|
||||
_ => false,
|
||||
}
|
||||
} => {
|
||||
if args.len() == 1 {
|
||||
match &args[0].node {
|
||||
ast::ExprKind::Constant { value: Constant::Int(Some(v)), .. } => {
|
||||
ast::ExprKind::Name { id, .. } if *id == "uint32".into() => match &args[0].node {
|
||||
ast::ExprKind::Constant { value: Constant::Int(v), .. } => {
|
||||
let v: Result<u32, _> = (*v).try_into();
|
||||
match v {
|
||||
Ok(v) => Ok(SymbolValue::U32(v)),
|
||||
_ => Err(format!("default param value out of range at {}", default.location))
|
||||
_ => Err(format!("default param value out of range at {}", default.location)),
|
||||
}
|
||||
}
|
||||
_ => Err(format!("only allow constant integer here at {}", default.location))
|
||||
}
|
||||
} else {
|
||||
Err(format!("only allow constant integer here at {}", default.location))
|
||||
}
|
||||
}
|
||||
ast::ExprKind::Call { func, args, .. } if {
|
||||
match &func.node {
|
||||
ast::ExprKind::Name { id, .. } => *id == "uint64".into(),
|
||||
_ => false,
|
||||
}
|
||||
} => {
|
||||
if args.len() == 1 {
|
||||
match &args[0].node {
|
||||
ast::ExprKind::Constant { value: Constant::Int(Some(v)), .. } => {
|
||||
ast::ExprKind::Name { id, .. } if *id == "uint64".into() => match &args[0].node {
|
||||
ast::ExprKind::Constant { value: Constant::Int(v), .. } => {
|
||||
let v: Result<u64, _> = (*v).try_into();
|
||||
match v {
|
||||
Ok(v) => Ok(SymbolValue::U64(v)),
|
||||
_ => Err(format!("default param value out of range at {}", default.location))
|
||||
_ => Err(format!("default param value out of range at {}", default.location)),
|
||||
}
|
||||
}
|
||||
_ => Err(format!("only allow constant integer here at {}", default.location))
|
||||
}
|
||||
} else {
|
||||
Err(format!("only allow constant integer here at {}", default.location))
|
||||
_ => Err(format!("unsupported default parameter at {}", default.location)),
|
||||
}
|
||||
}
|
||||
ast::ExprKind::Tuple { elts, .. } => Ok(SymbolValue::Tuple(elts
|
||||
|
@ -781,21 +781,19 @@ impl<'a> Inferencer<'a> {
|
||||
&args[0].node
|
||||
{
|
||||
let custom = Some(self.primitives.int64);
|
||||
match val {
|
||||
Some(val) if {
|
||||
let v: Result<i64, _> = (*val).try_into();
|
||||
v.is_ok()
|
||||
} => {},
|
||||
_ => return report_error("Integer out of bound", args[0].location)
|
||||
let v: Result<i64, _> = (*val).try_into();
|
||||
if v.is_ok() {
|
||||
return Ok(Located {
|
||||
location: args[0].location,
|
||||
custom,
|
||||
node: ExprKind::Constant {
|
||||
value: ast::Constant::Int(*val),
|
||||
kind: kind.clone(),
|
||||
},
|
||||
});
|
||||
} else {
|
||||
return report_error("Integer out of bound", args[0].location)
|
||||
}
|
||||
return Ok(Located {
|
||||
location: args[0].location,
|
||||
custom,
|
||||
node: ExprKind::Constant {
|
||||
value: ast::Constant::Int(*val),
|
||||
kind: kind.clone(),
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
if id == "uint32".into() && args.len() == 1 {
|
||||
@ -803,21 +801,19 @@ impl<'a> Inferencer<'a> {
|
||||
&args[0].node
|
||||
{
|
||||
let custom = Some(self.primitives.uint32);
|
||||
match val {
|
||||
Some(val) if {
|
||||
let v: Result<u32, _> = (*val).try_into();
|
||||
v.is_ok()
|
||||
} => {},
|
||||
_ => return report_error("Integer out of bound", args[0].location)
|
||||
let v: Result<u32, _> = (*val).try_into();
|
||||
if v.is_ok() {
|
||||
return Ok(Located {
|
||||
location: args[0].location,
|
||||
custom,
|
||||
node: ExprKind::Constant {
|
||||
value: ast::Constant::Int(*val),
|
||||
kind: kind.clone(),
|
||||
},
|
||||
});
|
||||
} else {
|
||||
return report_error("Integer out of bound", args[0].location)
|
||||
}
|
||||
return Ok(Located {
|
||||
location: args[0].location,
|
||||
custom,
|
||||
node: ExprKind::Constant {
|
||||
value: ast::Constant::Int(*val),
|
||||
kind: kind.clone(),
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
if id == "uint64".into() && args.len() == 1 {
|
||||
@ -825,21 +821,19 @@ impl<'a> Inferencer<'a> {
|
||||
&args[0].node
|
||||
{
|
||||
let custom = Some(self.primitives.uint64);
|
||||
match val {
|
||||
Some(val) if {
|
||||
let v: Result<u64, _> = (*val).try_into();
|
||||
v.is_ok()
|
||||
} => {},
|
||||
_ => return report_error("Integer out of bound", args[0].location)
|
||||
let v: Result<u64, _> = (*val).try_into();
|
||||
if v.is_ok() {
|
||||
return Ok(Located {
|
||||
location: args[0].location,
|
||||
custom,
|
||||
node: ExprKind::Constant {
|
||||
value: ast::Constant::Int(*val),
|
||||
kind: kind.clone(),
|
||||
},
|
||||
});
|
||||
} else {
|
||||
return report_error("Integer out of bound", args[0].location)
|
||||
}
|
||||
return Ok(Located {
|
||||
location: args[0].location,
|
||||
custom,
|
||||
node: ExprKind::Constant {
|
||||
value: ast::Constant::Int(*val),
|
||||
kind: kind.clone(),
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
Located { location: func_location, custom, node: ExprKind::Name { id, ctx } }
|
||||
@ -923,17 +917,12 @@ impl<'a> Inferencer<'a> {
|
||||
match constant {
|
||||
ast::Constant::Bool(_) => Ok(self.primitives.bool),
|
||||
ast::Constant::Int(val) => {
|
||||
match val {
|
||||
Some(val) => {
|
||||
let int32: Result<i32, _> = (*val).try_into();
|
||||
// int64 and unsigned integers are handled separately in functions
|
||||
if int32.is_ok() {
|
||||
Ok(self.primitives.int32)
|
||||
} else {
|
||||
report_error("Integer out of bound", *loc)
|
||||
}
|
||||
}
|
||||
None => report_error("Integer out of bound", *loc),
|
||||
let int32: Result<i32, _> = (*val).try_into();
|
||||
// int64 and unsigned integers are handled separately in functions
|
||||
if int32.is_ok() {
|
||||
Ok(self.primitives.int32)
|
||||
} else {
|
||||
report_error("Integer out of bound", *loc)
|
||||
}
|
||||
}
|
||||
ast::Constant::Float(_) => Ok(self.primitives.float),
|
||||
@ -1066,10 +1055,7 @@ impl<'a> Inferencer<'a> {
|
||||
}
|
||||
ast::ExprKind::Constant { value: ast::Constant::Int(val), .. } => {
|
||||
// the index is a constant, so value can be a sequence.
|
||||
let ind: Option<i32> = match val {
|
||||
Some(val) => (*val).try_into().ok(),
|
||||
None => None,
|
||||
};
|
||||
let ind: Option<i32> = (*val).try_into().ok();
|
||||
let ind = ind.ok_or_else(|| "Index must be int32".to_string())?;
|
||||
let map = once((
|
||||
ind.into(),
|
||||
|
@ -285,11 +285,11 @@ where
|
||||
fn lex_number_radix(&mut self, start_pos: Location, radix: u32) -> LexResult {
|
||||
let value_text = self.radix_run(radix);
|
||||
let end_pos = self.get_pos();
|
||||
let value = match i64::from_str_radix(&value_text, radix) {
|
||||
Ok(value) => Some(value),
|
||||
let value = match i128::from_str_radix(&value_text, radix) {
|
||||
Ok(value) => value,
|
||||
Err(e) => {
|
||||
match e.kind() {
|
||||
IntErrorKind::PosOverflow | IntErrorKind::NegOverflow => None,
|
||||
IntErrorKind::PosOverflow | IntErrorKind::NegOverflow => i128::MAX,
|
||||
_ => return Err(LexicalError {
|
||||
error: LexicalErrorType::OtherError(format!("{:?}", e)),
|
||||
location: start_pos,
|
||||
@ -361,9 +361,9 @@ where
|
||||
let end_pos = self.get_pos();
|
||||
// assumption: value_text contains a valid integer.
|
||||
// parse should only fail because of overflow.
|
||||
let value = value_text.parse::<i64>().ok();
|
||||
let value = value_text.parse::<i128>().ok();
|
||||
let nonzero = match value {
|
||||
Some(value) => value != 0i64,
|
||||
Some(value) => value != 0i128,
|
||||
None => true
|
||||
};
|
||||
if start_is_zero && nonzero {
|
||||
@ -372,7 +372,7 @@ where
|
||||
location: self.get_pos(),
|
||||
});
|
||||
}
|
||||
Ok((start_pos, Tok::Int { value }, end_pos))
|
||||
Ok((start_pos, Tok::Int { value: value.unwrap_or(i128::MAX) }, end_pos))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -919,7 +919,7 @@ Factor: ast::Expr = {
|
||||
match (&op, &e.node) {
|
||||
(ast::Unaryop::USub, ast::ExprKind::Constant { value: Constant::Int(val), kind }) => {
|
||||
ast::ExprKind::Constant {
|
||||
value: if let Some(val) = val { Constant::Int(Some(-val)) } else { Constant::Int(None) },
|
||||
value: if i128::MAX == *val { Constant::Int(*val) } else { Constant::Int(-val) },
|
||||
kind: kind.clone()
|
||||
}
|
||||
}
|
||||
@ -1361,7 +1361,7 @@ extern {
|
||||
"True" => lexer::Tok::True,
|
||||
"False" => lexer::Tok::False,
|
||||
"None" => lexer::Tok::None,
|
||||
int => lexer::Tok::Int { value: <Option<i64>> },
|
||||
int => lexer::Tok::Int { value: <i128> },
|
||||
float => lexer::Tok::Float { value: <f64> },
|
||||
complex => lexer::Tok::Complex { real: <f64>, imag: <f64> },
|
||||
string => lexer::Tok::String { value: <String>, is_fstring: <bool> },
|
||||
|
@ -7,7 +7,7 @@ use crate::ast;
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum Tok {
|
||||
Name { name: ast::StrRef },
|
||||
Int { value: Option<i64> },
|
||||
Int { value: i128 },
|
||||
Float { value: f64 },
|
||||
Complex { real: f64, imag: f64 },
|
||||
String { value: String, is_fstring: bool },
|
||||
@ -112,7 +112,7 @@ impl fmt::Display for Tok {
|
||||
use Tok::*;
|
||||
match self {
|
||||
Name { name } => write!(f, "'{}'", ast::get_str_from_ref(&ast::get_str_ref_lock(), *name)),
|
||||
Int { value } => if let Some(value) = value { write!(f, "'{}'", value) } else { write!(f, "'#OFL#'") },
|
||||
Int { value } => if *value != i128::MAX { write!(f, "'{}'", value) } else { write!(f, "'#OFL#'") },
|
||||
Float { value } => write!(f, "'{}'", value),
|
||||
Complex { real, imag } => write!(f, "{}j{}", real, imag),
|
||||
String { value, is_fstring } => {
|
||||
|
Loading…
Reference in New Issue
Block a user