1
0
forked from M-Labs/nac3

nac3ast/parser/core: use i128 for u64 constants

This commit is contained in:
ychenfo 2022-03-08 02:30:04 +08:00
parent 9f6c7b3359
commit f7e62ab5b7
7 changed files with 80 additions and 120 deletions

View File

@ -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)
}
}

View File

@ -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");
};

View File

@ -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) => {
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,
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)),
}
}
} => {
if args.len() == 1 {
match &args[0].node {
ast::ExprKind::Constant { value: Constant::Int(Some(v)), .. } =>
Ok(SymbolValue::I64(*v)),
_ => 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

View File

@ -781,13 +781,8 @@ 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)
}
if v.is_ok() {
return Ok(Located {
location: args[0].location,
custom,
@ -796,6 +791,9 @@ impl<'a> Inferencer<'a> {
kind: kind.clone(),
},
});
} else {
return report_error("Integer out of bound", args[0].location)
}
}
}
if id == "uint32".into() && args.len() == 1 {
@ -803,13 +801,8 @@ 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)
}
if v.is_ok() {
return Ok(Located {
location: args[0].location,
custom,
@ -818,6 +811,9 @@ impl<'a> Inferencer<'a> {
kind: kind.clone(),
},
});
} else {
return report_error("Integer out of bound", args[0].location)
}
}
}
if id == "uint64".into() && args.len() == 1 {
@ -825,13 +821,8 @@ 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)
}
if v.is_ok() {
return Ok(Located {
location: args[0].location,
custom,
@ -840,6 +831,9 @@ impl<'a> Inferencer<'a> {
kind: kind.clone(),
},
});
} else {
return report_error("Integer out of bound", args[0].location)
}
}
}
Located { location: func_location, custom, node: ExprKind::Name { id, ctx } }
@ -923,8 +917,6 @@ 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() {
@ -933,9 +925,6 @@ impl<'a> Inferencer<'a> {
report_error("Integer out of bound", *loc)
}
}
None => report_error("Integer out of bound", *loc),
}
}
ast::Constant::Float(_) => Ok(self.primitives.float),
ast::Constant::Tuple(vals) => {
let ty: Result<Vec<_>, _> =
@ -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(),

View File

@ -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))
}
}
}

View File

@ -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> },

View File

@ -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 } => {