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