From 19cba2a7b3564f586aca7bbbc09280b226b913ee Mon Sep 17 00:00:00 2001 From: Araozu Date: Mon, 6 May 2024 10:13:21 -0500 Subject: [PATCH] Split Number into Int & Float --- CHANGELOG.md | 4 +- src/codegen/binding.rs | 2 +- src/codegen/expression.rs | 5 ++- src/codegen/module_ast.rs | 2 +- src/lexic/mod.rs | 56 +++++++++++++------------- src/lexic/scanner/number.rs | 44 ++++++++++---------- src/lexic/token.rs | 15 +++++-- src/semantic/types/expression.rs | 4 +- src/syntax/ast/mod.rs | 3 +- src/syntax/expression/primary.rs | 5 ++- src/syntax/expression/unary.rs | 2 +- src/syntax/functions/arguments_list.rs | 6 +-- 12 files changed, 80 insertions(+), 68 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d56cd2e..bf3241f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,11 +26,11 @@ ## v0.0.12 - [x] Infer datatype of an identifier -- [ ] Infer datatype of a binary operatior +- [x] Infer datatype of a binary operatior - [ ] Infer datatype of unary operator - [ ] Infer datatype of a function call expression - [ ] Infer datatype of binary operators -- [ ] Infer Int & Float as different types +- [x] Infer Int & Float as different types - [ ] Execute semantic analysis on the function's block - [ ] Write tests - [ ] Abstract the parsing of datatypes, such that in the future generics can be implemented in a single place diff --git a/src/codegen/binding.rs b/src/codegen/binding.rs index e94421a..da5531f 100644 --- a/src/codegen/binding.rs +++ b/src/codegen/binding.rs @@ -30,7 +30,7 @@ mod tests { let binding = Binding { datatype: None, identifier: &id_token, - expression: Expression::Number(&value), + expression: Expression::Int(&value), is_mutable: false, }; diff --git a/src/codegen/expression.rs b/src/codegen/expression.rs index 1bc9dc8..5752adb 100644 --- a/src/codegen/expression.rs +++ b/src/codegen/expression.rs @@ -11,7 +11,8 @@ impl Transpilable for Expression<'_> { /// - Identifier fn transpile(&self) -> String { match self { - Expression::Number(value) => format!("{}", value), + Expression::Int(value) => format!("{}", value), + Expression::Float(value) => format!("{}", value), Expression::String(value) => { format!("{}", *value) } @@ -41,7 +42,7 @@ mod tests { #[test] fn should_transpile_number() { let str = String::from("42"); - let exp = Expression::Number(&str); + let exp = Expression::Int(&str); let result = exp.transpile(); assert_eq!("42", result); diff --git a/src/codegen/module_ast.rs b/src/codegen/module_ast.rs index 2cae2b5..492d2f7 100644 --- a/src/codegen/module_ast.rs +++ b/src/codegen/module_ast.rs @@ -35,7 +35,7 @@ mod tests { let binding = Binding { datatype: None, identifier: &id_token, - expression: Expression::Number(&value), + expression: Expression::Int(&value), is_mutable: false, }; diff --git a/src/lexic/mod.rs b/src/lexic/mod.rs index 46f6de3..377382e 100755 --- a/src/lexic/mod.rs +++ b/src/lexic/mod.rs @@ -256,15 +256,15 @@ mod tests { let tokens = get_tokens(&input).unwrap(); let t1 = tokens.get(0).unwrap(); - assert_eq!(TokenType::Number, t1.token_type); + assert_eq!(TokenType::Int, t1.token_type); assert_eq!("126", t1.value); let t2 = tokens.get(1).unwrap(); - assert_eq!(TokenType::Number, t2.token_type); + assert_eq!(TokenType::Float, t2.token_type); assert_eq!("278.98", t2.value); let t3 = tokens.get(2).unwrap(); - assert_eq!(TokenType::Number, t3.token_type); + assert_eq!(TokenType::Float, t3.token_type); assert_eq!("0.282398", t3.value); assert_eq!("1789e+1", tokens.get(3).unwrap().value); @@ -324,7 +324,7 @@ mod tests { let tokens = get_tokens(&input).unwrap(); assert_eq!(TokenType::NewLine, tokens[1].token_type); - assert_eq!(TokenType::Number, tokens[2].token_type); + assert_eq!(TokenType::Int, tokens[2].token_type); } #[test] @@ -333,7 +333,7 @@ mod tests { let tokens = get_tokens(&input).unwrap(); assert_eq!(TokenType::NewLine, tokens[1].token_type); - assert_eq!(TokenType::Number, tokens[2].token_type); + assert_eq!(TokenType::Int, tokens[2].token_type); } #[test] @@ -341,10 +341,10 @@ mod tests { let input = String::from("3\n \n 22"); let tokens = get_tokens(&input).unwrap(); - assert_eq!(TokenType::Number, tokens[0].token_type); + assert_eq!(TokenType::Int, tokens[0].token_type); assert_eq!(TokenType::NewLine, tokens[1].token_type); assert_eq!(TokenType::INDENT, tokens[2].token_type); - assert_eq!(TokenType::Number, tokens[3].token_type); + assert_eq!(TokenType::Int, tokens[3].token_type); } #[test] @@ -352,13 +352,13 @@ mod tests { let input = String::from("3\n \n 22\n 111"); let tokens = get_tokens(&input).unwrap(); - assert_eq!(TokenType::Number, tokens[0].token_type); + assert_eq!(TokenType::Int, tokens[0].token_type); assert_eq!(TokenType::NewLine, tokens[1].token_type); assert_eq!(TokenType::INDENT, tokens[2].token_type); - assert_eq!(TokenType::Number, tokens[3].token_type); + assert_eq!(TokenType::Int, tokens[3].token_type); assert_eq!(TokenType::NewLine, tokens[4].token_type); assert_eq!(TokenType::INDENT, tokens[5].token_type); - assert_eq!(TokenType::Number, tokens[6].token_type); + assert_eq!(TokenType::Int, tokens[6].token_type); } #[test] @@ -366,12 +366,12 @@ mod tests { let input = String::from("3\n \n 22\n 111"); let tokens = get_tokens(&input).unwrap(); - assert_eq!(TokenType::Number, tokens[0].token_type); + assert_eq!(TokenType::Int, tokens[0].token_type); assert_eq!(TokenType::NewLine, tokens[1].token_type); assert_eq!(TokenType::INDENT, tokens[2].token_type); - assert_eq!(TokenType::Number, tokens[3].token_type); + assert_eq!(TokenType::Int, tokens[3].token_type); assert_eq!(TokenType::NewLine, tokens[4].token_type); - assert_eq!(TokenType::Number, tokens[5].token_type); + assert_eq!(TokenType::Int, tokens[5].token_type); } #[test] @@ -379,13 +379,13 @@ mod tests { let input = String::from("3\n \n 22\n111"); let tokens = get_tokens(&input).unwrap(); - assert_eq!(TokenType::Number, tokens[0].token_type); + assert_eq!(TokenType::Int, tokens[0].token_type); assert_eq!(TokenType::NewLine, tokens[1].token_type); assert_eq!(TokenType::INDENT, tokens[2].token_type); - assert_eq!(TokenType::Number, tokens[3].token_type); + assert_eq!(TokenType::Int, tokens[3].token_type); assert_eq!(TokenType::NewLine, tokens[4].token_type); assert_eq!(TokenType::DEDENT, tokens[5].token_type); - assert_eq!(TokenType::Number, tokens[6].token_type); + assert_eq!(TokenType::Int, tokens[6].token_type); } #[test] @@ -393,16 +393,16 @@ mod tests { let input = String::from("1\n 2\n 3\n 4\n5"); let tokens = get_tokens(&input).unwrap(); - assert_eq!(TokenType::Number, tokens[0].token_type); + assert_eq!(TokenType::Int, tokens[0].token_type); assert_eq!(TokenType::NewLine, tokens[1].token_type); assert_eq!(TokenType::INDENT, tokens[2].token_type); - assert_eq!(TokenType::Number, tokens[3].token_type); + assert_eq!(TokenType::Int, tokens[3].token_type); assert_eq!(TokenType::NewLine, tokens[4].token_type); assert_eq!(TokenType::INDENT, tokens[5].token_type); - assert_eq!(TokenType::Number, tokens[6].token_type); + assert_eq!(TokenType::Int, tokens[6].token_type); assert_eq!(TokenType::NewLine, tokens[7].token_type); assert_eq!(TokenType::DEDENT, tokens[8].token_type); - assert_eq!(TokenType::Number, tokens[9].token_type); + assert_eq!(TokenType::Int, tokens[9].token_type); assert_eq!(TokenType::NewLine, tokens[10].token_type); assert_eq!(TokenType::DEDENT, tokens[11].token_type); } @@ -412,13 +412,13 @@ mod tests { let input = String::from("1\n 2\n 3\n4"); let tokens = get_tokens(&input).unwrap(); - assert_eq!(TokenType::Number, tokens[0].token_type); + assert_eq!(TokenType::Int, tokens[0].token_type); assert_eq!(TokenType::NewLine, tokens[1].token_type); assert_eq!(TokenType::INDENT, tokens[2].token_type); - assert_eq!(TokenType::Number, tokens[3].token_type); + assert_eq!(TokenType::Int, tokens[3].token_type); assert_eq!(TokenType::NewLine, tokens[4].token_type); assert_eq!(TokenType::INDENT, tokens[5].token_type); - assert_eq!(TokenType::Number, tokens[6].token_type); + assert_eq!(TokenType::Int, tokens[6].token_type); assert_eq!(TokenType::NewLine, tokens[7].token_type); assert_eq!(TokenType::DEDENT, tokens[8].token_type); assert_eq!(TokenType::DEDENT, tokens[9].token_type); @@ -435,10 +435,10 @@ mod indentation_tests { let input = String::from("1\n 2"); let tokens = get_tokens(&input).unwrap(); - assert_eq!(TokenType::Number, tokens[0].token_type); + assert_eq!(TokenType::Int, tokens[0].token_type); assert_eq!(TokenType::NewLine, tokens[1].token_type); assert_eq!(TokenType::INDENT, tokens[2].token_type); - assert_eq!(TokenType::Number, tokens[3].token_type); + assert_eq!(TokenType::Int, tokens[3].token_type); assert_eq!(TokenType::DEDENT, tokens[4].token_type); assert_eq!(TokenType::EOF, tokens[5].token_type); } @@ -448,13 +448,13 @@ mod indentation_tests { let input = String::from("1\n 2\n 3"); let tokens = get_tokens(&input).unwrap(); - assert_eq!(TokenType::Number, tokens[0].token_type); + assert_eq!(TokenType::Int, tokens[0].token_type); assert_eq!(TokenType::NewLine, tokens[1].token_type); assert_eq!(TokenType::INDENT, tokens[2].token_type); - assert_eq!(TokenType::Number, tokens[3].token_type); + assert_eq!(TokenType::Int, tokens[3].token_type); assert_eq!(TokenType::NewLine, tokens[4].token_type); assert_eq!(TokenType::INDENT, tokens[5].token_type); - assert_eq!(TokenType::Number, tokens[6].token_type); + assert_eq!(TokenType::Int, tokens[6].token_type); assert_eq!(TokenType::DEDENT, tokens[7].token_type); assert_eq!(TokenType::DEDENT, tokens[8].token_type); assert_eq!(TokenType::EOF, tokens[9].token_type); diff --git a/src/lexic/scanner/number.rs b/src/lexic/scanner/number.rs index a0d48ac..73ad748 100755 --- a/src/lexic/scanner/number.rs +++ b/src/lexic/scanner/number.rs @@ -1,7 +1,7 @@ use crate::error_handling::LexError; use crate::lexic::{token::Token, utils, LexResult}; -/// Function to scan a number +/// Function to scan an int/float /// /// This function assumes that the character at `start_pos` is a number [0-9], /// if not it will panic @@ -36,7 +36,7 @@ fn scan_decimal(chars: &Vec, start_pos: usize, current: String) -> LexResu let current_len = current.len(); LexResult::Some( - Token::new_number(current, start_pos - current_len), + Token::new_int(current, start_pos - current_len), start_pos, ) } @@ -98,7 +98,7 @@ fn scan_double_impl(chars: &Vec, start_pos: usize, current: String) -> Lex let current_len = current.len(); LexResult::Some( - Token::new_number(current, start_pos - current_len), + Token::new_float(current, start_pos - current_len), start_pos, ) } @@ -144,7 +144,7 @@ fn scan_digits(chars: &Vec, start_pos: usize, current: String) -> (Token, let current_len = current.len(); ( - Token::new_number(current, start_pos - current_len), + Token::new_float(current, start_pos - current_len), start_pos, ) } @@ -163,7 +163,7 @@ fn scan_hex_digits(chars: &Vec, start_pos: usize, current: String) -> (Tok let current_len = current.len(); ( - Token::new_number(current, start_pos - current_len), + Token::new_int(current, start_pos - current_len), start_pos, ) } @@ -187,7 +187,7 @@ mod tests { if let LexResult::Some(token, next) = scan(&input, start_pos) { assert_eq!(3, next); - assert_eq!(TokenType::Number, token.token_type); + assert_eq!(TokenType::Int, token.token_type); assert_eq!("123", token.value); assert_eq!(0, token.position); } else { @@ -199,7 +199,7 @@ mod tests { if let LexResult::Some(token, next) = scan(&input, start_pos) { assert_eq!(4, next); - assert_eq!(TokenType::Number, token.token_type); + assert_eq!(TokenType::Int, token.token_type); assert_eq!("0123", token.value); assert_eq!(0, token.position); } else { @@ -211,7 +211,7 @@ mod tests { if let LexResult::Some(token, next) = scan(&input, start_pos) { assert_eq!(8, next); - assert_eq!(TokenType::Number, token.token_type); + assert_eq!(TokenType::Int, token.token_type); assert_eq!("123456", token.value); assert_eq!(2, token.position); } else { @@ -227,7 +227,7 @@ mod tests { if let LexResult::Some(token, next) = scan(&input, start_pos) { assert_eq!(3, next); - assert_eq!(TokenType::Number, token.token_type); + assert_eq!(TokenType::Int, token.token_type); assert_eq!("123", token.value); } else { panic!() @@ -241,7 +241,7 @@ mod tests { if let LexResult::Some(token, next) = scan(&input, start_pos) { assert_eq!(4, next); - assert_eq!(TokenType::Number, token.token_type); + assert_eq!(TokenType::Int, token.token_type); assert_eq!("0x20", token.value); assert_eq!(0, token.position); } else { @@ -253,7 +253,7 @@ mod tests { if let LexResult::Some(token, next) = scan(&input, start_pos) { assert_eq!(12, next); - assert_eq!(TokenType::Number, token.token_type); + assert_eq!(TokenType::Int, token.token_type); assert_eq!("0xff23DA", token.value); assert_eq!(4, token.position); } else { @@ -277,7 +277,7 @@ mod tests { let input = str_to_vec("0 x20 "); let start_pos = 0; if let LexResult::Some(token, _) = scan(&input, start_pos) { - assert_eq!(TokenType::Number, token.token_type); + assert_eq!(TokenType::Int, token.token_type); assert_eq!("0", token.value); } else { panic!() @@ -290,7 +290,7 @@ mod tests { let input = str_to_vec("1x20"); let start_pos = 0; if let LexResult::Some(token, _) = scan(&input, start_pos) { - assert_eq!(TokenType::Number, token.token_type); + assert_eq!(TokenType::Int, token.token_type); assert_eq!("1", token.value); } else { panic!() @@ -304,7 +304,7 @@ mod tests { let start_pos = 0; if let LexResult::Some(token, next) = scan(&input, start_pos) { assert_eq!(4, next); - assert_eq!(TokenType::Number, token.token_type); + assert_eq!(TokenType::Float, token.token_type); assert_eq!("3.22", token.value); assert_eq!(0, token.position); } else { @@ -315,7 +315,7 @@ mod tests { let start_pos = 0; if let LexResult::Some(token, next) = scan(&input, start_pos) { assert_eq!(11, next); - assert_eq!(TokenType::Number, token.token_type); + assert_eq!(TokenType::Float, token.token_type); assert_eq!("123456.7890", token.value); assert_eq!(0, token.position); } else { @@ -356,7 +356,7 @@ mod tests { if let LexResult::Some(token, next) = scan(&input, start_pos) { assert_eq!("1e+0", token.value); assert_eq!(4, next); - assert_eq!(TokenType::Number, token.token_type); + assert_eq!(TokenType::Float, token.token_type); assert_eq!(0, token.position); } else { panic!() @@ -366,7 +366,7 @@ mod tests { let start_pos = 0; if let LexResult::Some(token, next) = scan(&input, start_pos) { assert_eq!(4, next); - assert_eq!(TokenType::Number, token.token_type); + assert_eq!(TokenType::Float, token.token_type); assert_eq!("1e-0", token.value); assert_eq!(0, token.position); } else { @@ -377,7 +377,7 @@ mod tests { let start_pos = 0; if let LexResult::Some(token, next) = scan(&input, start_pos) { assert_eq!(4, next); - assert_eq!(TokenType::Number, token.token_type); + assert_eq!(TokenType::Float, token.token_type); assert_eq!("0e+0", token.value); assert_eq!(0, token.position); } else { @@ -388,7 +388,7 @@ mod tests { let start_pos = 0; if let LexResult::Some(token, next) = scan(&input, start_pos) { assert_eq!(19, next); - assert_eq!(TokenType::Number, token.token_type); + assert_eq!(TokenType::Float, token.token_type); assert_eq!("123498790e+12349870", token.value); assert_eq!(0, token.position); } else { @@ -404,7 +404,7 @@ mod tests { if let LexResult::Some(token, next) = scan(&input, start_pos) { assert_eq!("1.24e+1", token.value); assert_eq!(7, next); - assert_eq!(TokenType::Number, token.token_type); + assert_eq!(TokenType::Float, token.token_type); assert_eq!(0, token.position); } else { panic!() @@ -415,7 +415,7 @@ mod tests { if let LexResult::Some(token, next) = scan(&input, start_pos) { assert_eq!("0.00000000000001e+1", token.value); assert_eq!(19, next); - assert_eq!(TokenType::Number, token.token_type); + assert_eq!(TokenType::Float, token.token_type); assert_eq!(0, token.position); } else { panic!() @@ -429,7 +429,7 @@ mod tests { if let LexResult::Some(token, next) = scan(&input, start_pos) { assert_eq!(5, next); - assert_eq!(TokenType::Number, token.token_type); + assert_eq!(TokenType::Int, token.token_type); assert_eq!("123", token.value); assert_eq!(2, token.position); } else { diff --git a/src/lexic/token.rs b/src/lexic/token.rs index 55eb00c..a8975e0 100755 --- a/src/lexic/token.rs +++ b/src/lexic/token.rs @@ -2,7 +2,8 @@ pub enum TokenType { Identifier, Datatype, - Number, + Int, + Float, String, Operator, LeftParen, @@ -47,9 +48,17 @@ impl Token { } } - pub fn new_number(value: String, position: usize) -> Token { + pub fn new_int(value: String, position: usize) -> Token { Token { - token_type: TokenType::Number, + token_type: TokenType::Int, + value, + position, + } + } + + pub fn new_float(value: String, position: usize) -> Token { + Token { + token_type: TokenType::Float, value, position, } diff --git a/src/semantic/types/expression.rs b/src/semantic/types/expression.rs index 89d64a3..1572a80 100644 --- a/src/semantic/types/expression.rs +++ b/src/semantic/types/expression.rs @@ -10,8 +10,8 @@ impl Typed for Expression<'_> { /// Attempts to get the datatype for an expression. fn get_type(&self, scope: &SymbolTable) -> Result { match self { - // TODO: Distinguish between Int & Float - Expression::Number(_) => Ok("Int".into()), + Expression::Int(_) => Ok("Int".into()), + Expression::Float(_) => Ok("Float".into()), Expression::String(_) => Ok("String".into()), Expression::Boolean(_) => Ok("Bool".into()), Expression::Identifier(identifier) => { diff --git a/src/syntax/ast/mod.rs b/src/syntax/ast/mod.rs index 76c8685..c1c473a 100644 --- a/src/syntax/ast/mod.rs +++ b/src/syntax/ast/mod.rs @@ -43,7 +43,8 @@ pub struct Parameter<'a> { #[derive(Debug)] pub enum Expression<'a> { - Number(&'a String), + Int(&'a String), + Float(&'a String), String(&'a String), Boolean(bool), Identifier(&'a String), diff --git a/src/syntax/expression/primary.rs b/src/syntax/expression/primary.rs index dda70ab..5174784 100644 --- a/src/syntax/expression/primary.rs +++ b/src/syntax/expression/primary.rs @@ -12,7 +12,8 @@ use crate::{ pub fn try_parse(tokens: &Vec, pos: usize) -> ParsingResult { match tokens.get_significant(pos) { Some((token, token_pos)) => match token.token_type { - TokenType::Number => Ok((Expression::Number(&token.value), token_pos + 1)), + TokenType::Int => Ok((Expression::Int(&token.value), token_pos + 1)), + TokenType::Float => Ok((Expression::Float(&token.value), token_pos + 1)), TokenType::String => Ok((Expression::String(&token.value), token_pos + 1)), TokenType::Identifier if token.value == "true" || token.value == "false" => { Ok((Expression::Boolean(token.value == "true"), token_pos + 1)) @@ -50,7 +51,7 @@ mod tests { let expression = try_parse(&tokens, 0); match expression { - Ok((Expression::Number(value), _)) => { + Ok((Expression::Int(value), _)) => { assert_eq!("40", format!("{}", value)) } _ => panic!(), diff --git a/src/syntax/expression/unary.rs b/src/syntax/expression/unary.rs index b7ba49e..b55d61c 100644 --- a/src/syntax/expression/unary.rs +++ b/src/syntax/expression/unary.rs @@ -52,7 +52,7 @@ mod tests { match expression { Ok((Expression::UnaryOperator(operator, expression), _)) => { match (operator, *expression) { - (op, Expression::Number(value)) => { + (op, Expression::Int(value)) => { assert_eq!(*op, "-"); assert_eq!(*value, "10"); } diff --git a/src/syntax/functions/arguments_list.rs b/src/syntax/functions/arguments_list.rs index a873dd8..b31a21e 100644 --- a/src/syntax/functions/arguments_list.rs +++ b/src/syntax/functions/arguments_list.rs @@ -135,7 +135,7 @@ mod tests { let first_argument = arguments_list.arguments.get(0).unwrap(); - let Expression::Number(_) = first_argument else { + let Expression::Int(_) = first_argument else { panic!("Expected a number") }; } @@ -153,7 +153,7 @@ mod tests { assert_eq!(arguments_list.arguments.len(), 1); let first_argument = arguments_list.arguments.get(0).unwrap(); - let Expression::Number(_) = first_argument else { + let Expression::Int(_) = first_argument else { panic!("Expected a number") }; } @@ -175,7 +175,7 @@ mod tests { }; let second_argument = arguments_list.arguments.get(1).unwrap(); - let Expression::Number(_) = second_argument else { + let Expression::Int(_) = second_argument else { panic!("Expected a number") }; }