diff --git a/package/origlang-ast/src/lib.rs b/package/origlang-ast/src/lib.rs index edd2b88b..52e92188 100644 --- a/package/origlang-ast/src/lib.rs +++ b/package/origlang-ast/src/lib.rs @@ -80,7 +80,6 @@ impl Identifier { } #[must_use = "If you don't use it, it will drop entire String"] - #[allow(clippy::missing_const_for_fn)] // see https://github.com/rust-lang/rust-clippy/issues/10617 pub fn name(self) -> String { self.0 } diff --git a/package/origlang-cli/src/args.rs b/package/origlang-cli/src/args.rs index bfc3ec1e..87da28d4 100644 --- a/package/origlang-cli/src/args.rs +++ b/package/origlang-cli/src/args.rs @@ -1,8 +1,6 @@ // clap issue?: https://github.com/clap-rs/clap/issues/4733 #![warn(clippy::almost_swapped)] -use std::fs::File; -use std::io::{BufReader, Read}; use std::path::PathBuf; use std::string::FromUtf8Error; use clap::{Parser, Subcommand}; diff --git a/package/origlang-ir-optimizer/src/ir1.rs b/package/origlang-ir-optimizer/src/ir1.rs index 3b616b7d..14e7d0aa 100644 --- a/package/origlang-ir-optimizer/src/ir1.rs +++ b/package/origlang-ir-optimizer/src/ir1.rs @@ -36,23 +36,6 @@ impl> OutputCompareResultAsSelf f } } -trait Continue { - fn continue_value(self) -> Option; -} - -impl Continue for Option { - #[allow(clippy::use_self)] - fn continue_value(self) -> Option { - self - } -} - -impl Continue for bool { - fn continue_value(self) -> Option { - self.then_some(true) - } -} - /// 二項演算子についての定数畳み込みを行う。 // TODO: 左端以外に畳み込みが行える定数項があっても、それらの項が畳み込まれない。 // すなわち、オーバーフローがないものとして`a * 2 / 2`を最適化するとき、`a`に最適化出来ない。 diff --git a/package/origlang-lexer/src/boundary.rs b/package/origlang-lexer/src/boundary.rs index a559c0d9..be2e9b4c 100644 --- a/package/origlang-lexer/src/boundary.rs +++ b/package/origlang-lexer/src/boundary.rs @@ -56,9 +56,3 @@ impl From for Utf8CharStride { } } } - -#[derive(Error, Debug)] -#[error("invalid value for UTF-8 codepoint stride: {given_value}")] -pub struct InvalidUtf8CharStrideError { - given_value: u8 -} diff --git a/package/origlang-parser/src/parser.rs b/package/origlang-parser/src/parser.rs index 2f6abcde..7967a189 100644 --- a/package/origlang-parser/src/parser.rs +++ b/package/origlang-parser/src/parser.rs @@ -42,7 +42,7 @@ pub enum TokenKind { } impl TokenKind { - fn only(token: Token) -> Self { + fn only(token: &Token) -> Self { Self::Only(token.display()) } } @@ -142,7 +142,7 @@ impl Parser { unmatch: aliased.data }, aliased.position)) }; - self.read_and_consume_or_report_unexpected_token(Token::SymEq)?; + self.read_and_consume_or_report_unexpected_token(&Token::SymEq)?; let Ok(replace_with) = self.lexer.parse_fallible(|| self.parse_type()) else { let p = self.lexer.peek_cloned(); return Err(ParserError::new(ParserErrorInner::UnexpectedToken { @@ -218,7 +218,7 @@ impl Parser { Ok(expr_tuple) } else { let inner_expression = self.parse_lowest_precedence_expression()?; - self.read_and_consume_or_report_unexpected_token(Token::SymRightPar)?; + self.read_and_consume_or_report_unexpected_token(&Token::SymRightPar)?; Ok(inner_expression) } } @@ -582,7 +582,7 @@ impl Parser { debug!("type:tuple:accumulator = {vec:?}"); - self.read_and_consume_or_report_unexpected_token(Token::SymRightPar)?; + self.read_and_consume_or_report_unexpected_token(&Token::SymRightPar)?; if vec.len() < 2 { let l = vec.len(); @@ -609,7 +609,7 @@ impl Parser { fn parse_variable_declaration(&self) -> Result { debug!("decl:var"); - self.read_and_consume_or_report_unexpected_token(Token::VarKeyword)?; + self.read_and_consume_or_report_unexpected_token(&Token::VarKeyword)?; let pattern = self.parse_atomic_pattern()?; // optionally, allow type annotation @@ -631,7 +631,7 @@ impl Parser { debug!("decl:var:annotation: {type_annotation:?}"); - self.read_and_consume_or_report_unexpected_token(Token::SymEq)?; + self.read_and_consume_or_report_unexpected_token(&Token::SymEq)?; debug!("decl:var:expr"); let expression = self.parse_lowest_precedence_expression()?; @@ -651,7 +651,7 @@ impl Parser { pat: TokenKind::Identifier, unmatch: ident_token.data }, ident_token.position)) }; - self.read_and_consume_or_report_unexpected_token(Token::SymEq)?; + self.read_and_consume_or_report_unexpected_token(&Token::SymEq)?; debug!("assign:var:expr"); let expression = self.parse_lowest_precedence_expression()?; Ok(Statement::VariableAssignment { @@ -670,9 +670,9 @@ impl Parser { if self.lexer.peek().ok_or_else(|| ParserError::new(ParserErrorInner::EndOfFileError, self.lexer.last_position))?.data == Token::KeywordIf { self.lexer.next(); let condition = self.parse_lowest_precedence_expression()?; - self.read_and_consume_or_report_unexpected_token(Token::KeywordThen)?; + self.read_and_consume_or_report_unexpected_token(&Token::KeywordThen)?; let then_clause_value = self.parse_lowest_precedence_expression()?; - self.read_and_consume_or_report_unexpected_token(Token::KeywordElse)?; + self.read_and_consume_or_report_unexpected_token(&Token::KeywordElse)?; let else_clause_value = self.parse_lowest_precedence_expression()?; Ok(Expression::If { condition: Box::new(condition), @@ -686,7 +686,7 @@ impl Parser { fn parse_block_scope(&self) -> Result { debug!("statement:block"); - self.read_and_consume_or_report_unexpected_token(Token::KeywordBlock)?; + self.read_and_consume_or_report_unexpected_token(&Token::KeywordBlock)?; if self.lexer.peek().ok_or_else(|| ParserError::new(ParserErrorInner::EndOfFileError, self.lexer.last_position))?.data == Token::NewLine { self.lexer.next(); } @@ -695,7 +695,7 @@ impl Parser { while let Ok(v) = self.parse_statement() { statements.push(v); } - self.read_and_consume_or_report_unexpected_token(Token::KeywordEnd)?; + self.read_and_consume_or_report_unexpected_token(&Token::KeywordEnd)?; Ok(Statement::Block { inner_statements: (statements), @@ -706,7 +706,7 @@ impl Parser { debug!("expr:block"); if self.lexer.peek().ok_or_else(|| ParserError::new(ParserErrorInner::EndOfFileError, self.lexer.last_position))?.data == Token::KeywordBlock { self.lexer.next(); - self.read_and_consume_or_report_unexpected_token(Token::NewLine)?; + self.read_and_consume_or_report_unexpected_token(&Token::NewLine)?; let mut statements = vec![]; while let Ok(v) = self.parse_statement() { statements.push(v); @@ -715,7 +715,7 @@ impl Parser { if self.lexer.peek().ok_or_else(|| ParserError::new(ParserErrorInner::EndOfFileError, self.lexer.last_position))?.data == Token::NewLine { self.lexer.next(); } - self.read_and_consume_or_report_unexpected_token(Token::KeywordEnd)?; + self.read_and_consume_or_report_unexpected_token(&Token::KeywordEnd)?; Ok(Expression::Block { intermediate_statements: statements, final_expression @@ -727,7 +727,7 @@ impl Parser { fn parse_tuple_destruct_pattern(&self) -> Result { debug!("pattern:tuple"); - self.read_and_consume_or_report_unexpected_token(Token::SymLeftPar)?; + self.read_and_consume_or_report_unexpected_token(&Token::SymLeftPar)?; let mut v = vec![]; @@ -740,10 +740,10 @@ impl Parser { break } - self.read_and_consume_or_report_unexpected_token(Token::SymComma)?; + self.read_and_consume_or_report_unexpected_token(&Token::SymComma)?; } - self.read_and_consume_or_report_unexpected_token(Token::SymRightPar)?; + self.read_and_consume_or_report_unexpected_token(&Token::SymRightPar)?; Ok(AtomicPattern::Tuple(v)) } @@ -774,11 +774,11 @@ impl Parser { } /// 現在のトークンが指定されたトークンならそのトークンをそのまま返した上でレキサーを1個進める。そうではないなら[`ParseError::UnexpectedToken`]を返す。 - fn read_and_consume_or_report_unexpected_token(&self, token: Token) -> Result { + fn read_and_consume_or_report_unexpected_token(&self, token: &Token) -> Result<(), ParserError> { let peek = self.lexer.peek().ok_or_else(|| ParserError::new(ParserErrorInner::EndOfFileError, self.lexer.last_position))?; - if peek.data == token { + if &peek.data == token { self.lexer.next(); - Ok(token) + Ok(()) } else { Err(ParserError::new(ParserErrorInner::UnexpectedToken { pat: TokenKind::only(token), diff --git a/package/origlang-runtime/src/lib.rs b/package/origlang-runtime/src/lib.rs index 07d319ea..ba0a3a85 100644 --- a/package/origlang-runtime/src/lib.rs +++ b/package/origlang-runtime/src/lib.rs @@ -192,7 +192,6 @@ impl Runtime { } /// Start runtime. Never returns until execution is completed. - #[allow(dead_code)] pub fn start<'s: 'o, 'o>(&'s self, seq: &[IR2]) -> &'o RefCell { // info!("{ast:?}", ast = &ast); let x = seq; @@ -342,6 +341,49 @@ macro_rules! indicate_type_checker_bug { }; } +fn evaluate_bin_op(runtime: &Runtime, lhs: &CompiledTypedExpression, rhs: &CompiledTypedExpression, operator: &BinaryOperatorKind) -> EvaluateResult { + let lhs = lhs.evaluate(runtime)?; + let rhs = rhs.evaluate(runtime)?; + if matches!(operator, BinaryOperatorKind::Equal | BinaryOperatorKind::NotEqual) { + return if lhs.get_type() == rhs.get_type() { + let ret = match operator { + BinaryOperatorKind::Equal => lhs == rhs, + BinaryOperatorKind::NotEqual => lhs != rhs, + _ => unreachable!(), + }; + Ok(ret.into()) + } else { + indicate_type_checker_bug!(context = "type checker must deny equality check between different types") + } + } + + match (lhs, rhs) { + (TypeBox::NonCoercedInteger(lhs), TypeBox::NonCoercedInteger(rhs)) => { + f!(lhs, operator, rhs as NonCoerced) + }, + (TypeBox::Int8(lhs), TypeBox::Int8(rhs)) => { + f!(lhs, operator, rhs) + }, + (TypeBox::Int16(lhs), TypeBox::Int16(rhs)) => { + f!(lhs, operator, rhs) + }, + (TypeBox::Int32(lhs), TypeBox::Int32(rhs)) => { + f!(lhs, operator, rhs) + }, + (TypeBox::Int64(lhs), TypeBox::Int64(rhs)) => { + f!(lhs, operator, rhs as Coerced) + }, + (TypeBox::String(lhs), TypeBox::String(rhs)) => { + let mut ret = lhs; + // give hint to compiler + ret.reserve_exact(rhs.len()); + ret += rhs.as_str(); + Ok(ret.into()) + } + _ => indicate_type_checker_bug!(context = "type checker must deny operator application between different type") + } +} + impl CanBeEvaluated for CompiledTypedExpression { fn evaluate(&self, runtime: &Runtime) -> EvaluateResult { match self { @@ -361,46 +403,7 @@ impl CanBeEvaluated for CompiledTypedExpression { .ok_or(RuntimeError::UndefinedVariable { identifier: ident.clone() }) }, Self::BinaryOperator { lhs, rhs, operator, return_type: _ } => { - let lhs = lhs.as_ref().evaluate(runtime)?; - let rhs = rhs.as_ref().evaluate(runtime)?; - if matches!(operator, BinaryOperatorKind::Equal | BinaryOperatorKind::NotEqual) { - return if lhs.get_type() == rhs.get_type() { - let ret = match operator { - BinaryOperatorKind::Equal => lhs == rhs, - BinaryOperatorKind::NotEqual => lhs != rhs, - _ => unreachable!(), - }; - Ok(ret.into()) - } else { - indicate_type_checker_bug!(context = "type checker must deny equality check between different types") - } - } - - return match (lhs, rhs) { - (TypeBox::NonCoercedInteger(lhs), TypeBox::NonCoercedInteger(rhs)) => { - f!(lhs, operator, rhs as NonCoerced) - }, - (TypeBox::Int8(lhs), TypeBox::Int8(rhs)) => { - f!(lhs, operator, rhs) - }, - (TypeBox::Int16(lhs), TypeBox::Int16(rhs)) => { - f!(lhs, operator, rhs) - }, - (TypeBox::Int32(lhs), TypeBox::Int32(rhs)) => { - f!(lhs, operator, rhs) - }, - (TypeBox::Int64(lhs), TypeBox::Int64(rhs)) => { - f!(lhs, operator, rhs as Coerced) - }, - (TypeBox::String(lhs), TypeBox::String(rhs)) => { - let mut ret = lhs; - // give hint to compiler - ret.reserve_exact(rhs.len()); - ret += rhs.as_str(); - Ok(ret.into()) - } - _ => indicate_type_checker_bug!(context = "type checker must deny operator application between different type") - }; + evaluate_bin_op(runtime, lhs, rhs, operator) } Self::If { condition, then: then_clause_value, els: else_clause_value, return_type: _ } => { let ret = condition.as_ref().evaluate(runtime)?; diff --git a/package/origlang-typecheck/src/lib.rs b/package/origlang-typecheck/src/lib.rs index c8b770ce..1b3436e2 100644 --- a/package/origlang-typecheck/src/lib.rs +++ b/package/origlang-typecheck/src/lib.rs @@ -1,18 +1,5 @@ #![deny(clippy::all)] #![warn(clippy::pedantic, clippy::nursery)] -pub mod type_check; - -pub fn add(left: usize, right: usize) -> usize { - left + right -} -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); - } -} +// TODO: lift up +pub mod type_check; diff --git a/package/origlang-typecheck/src/type_check.rs b/package/origlang-typecheck/src/type_check.rs index 7ee91c09..6a9940cd 100644 --- a/package/origlang-typecheck/src/type_check.rs +++ b/package/origlang-typecheck/src/type_check.rs @@ -493,6 +493,8 @@ impl TypeChecker { } } + #[must_use] + #[allow(clippy::missing_panics_doc)] // do not panic pub fn make_fresh_identifier(&self) -> Identifier { // TODO: this implementation is poor. choice more elegant algorithm. let hello = RandomState::new().hash_one(());