From f7e62ab5b75baba542edd6966ec18387dc3ade05 Mon Sep 17 00:00:00 2001 From: ychenfo Date: Tue, 8 Mar 2022 02:30:04 +0800 Subject: [PATCH] nac3ast/parser/core: use i128 for u64 constants --- nac3ast/src/constant.rs | 6 +- nac3core/src/codegen/expr.rs | 4 +- nac3core/src/toplevel/helper.rs | 70 ++++-------- nac3core/src/typecheck/type_inferencer/mod.rs | 100 ++++++++---------- nac3parser/src/lexer.rs | 12 +-- nac3parser/src/python.lalrpop | 4 +- nac3parser/src/token.rs | 4 +- 7 files changed, 80 insertions(+), 120 deletions(-) diff --git a/nac3ast/src/constant.rs b/nac3ast/src/constant.rs index af8a85175..d9b0d338f 100644 --- a/nac3ast/src/constant.rs +++ b/nac3ast/src/constant.rs @@ -4,7 +4,7 @@ pub enum Constant { Bool(bool), Str(String), Bytes(Vec), - Int(Option), + Int(i128), Tuple(Vec), Float(f64), Complex { real: f64, imag: f64 }, @@ -28,12 +28,12 @@ impl From for Constant { } impl From for Constant { fn from(i: i32) -> Constant { - Self::Int(Some(i as i64)) + Self::Int(i as i128) } } impl From for Constant { fn from(i: i64) -> Constant { - Self::Int(Some(i)) + Self::Int(i as i128) } } diff --git a/nac3core/src/codegen/expr.rs b/nac3core/src/codegen/expr.rs index 3885804ef..09d0afb0b 100644 --- a/nac3core/src/codegen/expr.rs +++ b/nac3core/src/codegen/expr.rs @@ -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"); }; diff --git a/nac3core/src/toplevel/helper.rs b/nac3core/src/toplevel/helper.rs index 58ba9fa63..a76e7b3a7 100644 --- a/nac3core/src/toplevel/helper.rs +++ b/nac3core/src/toplevel/helper.rs @@ -463,16 +463,13 @@ pub fn parse_parameter_default_value( ) -> Result { fn handle_constant(val: &Constant, loc: &Location) -> Result { 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 = (*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 = (*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 = (*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 diff --git a/nac3core/src/typecheck/type_inferencer/mod.rs b/nac3core/src/typecheck/type_inferencer/mod.rs index d3bae33a9..c012f2ed5 100644 --- a/nac3core/src/typecheck/type_inferencer/mod.rs +++ b/nac3core/src/typecheck/type_inferencer/mod.rs @@ -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 = (*val).try_into(); - v.is_ok() - } => {}, - _ => return report_error("Integer out of bound", args[0].location) + let v: Result = (*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 = (*val).try_into(); - v.is_ok() - } => {}, - _ => return report_error("Integer out of bound", args[0].location) + let v: Result = (*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 = (*val).try_into(); - v.is_ok() - } => {}, - _ => return report_error("Integer out of bound", args[0].location) + let v: Result = (*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 = (*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 = (*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 = match val { - Some(val) => (*val).try_into().ok(), - None => None, - }; + let ind: Option = (*val).try_into().ok(); let ind = ind.ok_or_else(|| "Index must be int32".to_string())?; let map = once(( ind.into(), diff --git a/nac3parser/src/lexer.rs b/nac3parser/src/lexer.rs index 7b04891df..36c593732 100644 --- a/nac3parser/src/lexer.rs +++ b/nac3parser/src/lexer.rs @@ -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::().ok(); + let value = value_text.parse::().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)) } } } diff --git a/nac3parser/src/python.lalrpop b/nac3parser/src/python.lalrpop index 41420ab5c..32775f185 100644 --- a/nac3parser/src/python.lalrpop +++ b/nac3parser/src/python.lalrpop @@ -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: > }, + int => lexer::Tok::Int { value: }, float => lexer::Tok::Float { value: }, complex => lexer::Tok::Complex { real: , imag: }, string => lexer::Tok::String { value: , is_fstring: }, diff --git a/nac3parser/src/token.rs b/nac3parser/src/token.rs index c82ad1537..214262a06 100644 --- a/nac3parser/src/token.rs +++ b/nac3parser/src/token.rs @@ -7,7 +7,7 @@ use crate::ast; #[derive(Clone, Debug, PartialEq)] pub enum Tok { Name { name: ast::StrRef }, - Int { value: Option }, + 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 } => {