From e7febd0a391d026317d55448a359c6af8aa30b0e Mon Sep 17 00:00:00 2001 From: IsaacShelton Date: Tue, 10 Sep 2024 20:36:05 -0500 Subject: [PATCH] Finished initial support for parsing for generics / compile-time arguments --- src/ast/expr/call.rs | 3 +- src/interpreter_env/mod.rs | 1 + src/parser/error.rs | 8 ++-- src/parser/parse_expr/post/member.rs | 5 ++- src/parser/parse_expr/primary/call.rs | 16 ++++--- .../parse_expr/primary/declare_assign.rs | 12 +++--- .../parse_expr/primary/enum_member_literal.rs | 15 ++++--- src/parser/parse_expr/primary/mod.rs | 42 +++++++++++-------- src/resolve/expr/call.rs | 7 ++++ 9 files changed, 66 insertions(+), 43 deletions(-) diff --git a/src/ast/expr/call.rs b/src/ast/expr/call.rs index cb480a0d..348156a7 100644 --- a/src/ast/expr/call.rs +++ b/src/ast/expr/call.rs @@ -1,9 +1,10 @@ use super::Expr; -use crate::ast::Type; +use crate::ast::{CompileTimeArgument, Type}; #[derive(Clone, Debug)] pub struct Call { pub function_name: String, pub arguments: Vec, pub expected_to_return: Option, + pub generics: Vec, } diff --git a/src/interpreter_env/mod.rs b/src/interpreter_env/mod.rs index 87abbad1..85d0ae83 100644 --- a/src/interpreter_env/mod.rs +++ b/src/interpreter_env/mod.rs @@ -59,6 +59,7 @@ pub fn setup_build_system_interpreter_symbols(file: &mut AstFile) { function_name: "main".into(), arguments: vec![], expected_to_return: Some(void.clone()), + generics: vec![], })) .at(Source::internal()); diff --git a/src/parser/error.rs b/src/parser/error.rs index fcd606b7..9228d1c9 100644 --- a/src/parser/error.rs +++ b/src/parser/error.rs @@ -69,7 +69,6 @@ pub enum ParseErrorKind { DefineHasMultipleDefinitions { name: String, }, - ExpectedEnumName, ExpectedEnumMemberName, Lexical { message: String, @@ -84,6 +83,7 @@ pub enum ParseErrorKind { name: String, word_for_nth: String, }, + GenericsNotSupportedHere, Other { message: String, }, @@ -180,9 +180,6 @@ impl Display for ParseErrorKind { ParseErrorKind::DefineHasMultipleDefinitions { name } => { write!(f, "Define '{}' has multiple definitions", name)?; } - ParseErrorKind::ExpectedEnumName => { - write!(f, "Expected enum name")?; - } ParseErrorKind::ExpectedEnumMemberName => { write!(f, "Expected enum member name")?; } @@ -207,6 +204,9 @@ impl Display for ParseErrorKind { word_for_nth, name )?; } + ParseErrorKind::GenericsNotSupportedHere => { + write!(f, "Generics not supported here")?; + } ParseErrorKind::Other { message } | ParseErrorKind::Lexical { message } => { write!(f, "{}", message)?; } diff --git a/src/parser/parse_expr/post/member.rs b/src/parser/parse_expr/post/member.rs index df467291..5284447e 100644 --- a/src/parser/parse_expr/post/member.rs +++ b/src/parser/parse_expr/post/member.rs @@ -14,8 +14,9 @@ impl<'a, I: Inflow> Parser<'a, I> { let source = self.parse_token(TokenKind::Member, Some("for member expression"))?; let member_name = self.parse_identifier(Some("for member name"))?; - if self.input.peek_is(TokenKind::OpenParen) { - self.parse_call_with(member_name, vec![subject], source) + if self.input.peek_is(TokenKind::OpenParen) || self.input.peek_is(TokenKind::OpenAngle) { + let generics = self.parse_generics()?; + self.parse_call_with(member_name, generics, vec![subject], source) } else { Ok(ExprKind::Member(Box::new(subject), member_name).at(source)) } diff --git a/src/parser/parse_expr/primary/call.rs b/src/parser/parse_expr/primary/call.rs index 1c067061..1edf4bcb 100644 --- a/src/parser/parse_expr/primary/call.rs +++ b/src/parser/parse_expr/primary/call.rs @@ -1,6 +1,6 @@ use super::Parser; use crate::{ - ast::{Call, Expr, ExprKind}, + ast::{Call, CompileTimeArgument, Expr, ExprKind}, inflow::Inflow, parser::error::ParseError, source_files::Source, @@ -8,19 +8,22 @@ use crate::{ }; impl<'a, I: Inflow> Parser<'a, I> { - pub fn parse_call(&mut self) -> Result { + pub fn parse_call( + &mut self, + function_name: String, + generics: Vec, + source: Source, + ) -> Result { // function_name(arg1, arg2, arg3) // ^ - let (function_name, source) = - self.parse_identifier_keep_location(Some("for function call"))?; - - self.parse_call_with(function_name, vec![], source) + self.parse_call_with(function_name, generics, vec![], source) } pub fn parse_call_with( &mut self, function_name: String, + generics: Vec, prefix_args: Vec, source: Source, ) -> Result { @@ -45,6 +48,7 @@ impl<'a, I: Inflow> Parser<'a, I> { function_name, arguments: args, expected_to_return: None, + generics, })) .at(source)) } diff --git a/src/parser/parse_expr/primary/declare_assign.rs b/src/parser/parse_expr/primary/declare_assign.rs index 225f49db..90664106 100644 --- a/src/parser/parse_expr/primary/declare_assign.rs +++ b/src/parser/parse_expr/primary/declare_assign.rs @@ -3,16 +3,18 @@ use crate::{ ast::{DeclareAssign, Expr, ExprKind}, inflow::Inflow, parser::error::ParseError, + source_files::Source, token::{Token, TokenKind}, }; impl<'a, I: Inflow> Parser<'a, I> { - pub fn parse_declare_assign(&mut self) -> Result { + pub fn parse_declare_assign( + &mut self, + variable_name: String, + source: Source, + ) -> Result { // variable_name := value - // ^ - - let (variable_name, source) = - self.parse_identifier_keep_location(Some("for function call"))?; + // ^ self.parse_token( TokenKind::DeclareAssign, diff --git a/src/parser/parse_expr/primary/enum_member_literal.rs b/src/parser/parse_expr/primary/enum_member_literal.rs index f6b668a3..4c462092 100644 --- a/src/parser/parse_expr/primary/enum_member_literal.rs +++ b/src/parser/parse_expr/primary/enum_member_literal.rs @@ -3,27 +3,26 @@ use crate::{ ast::{EnumMemberLiteral, Expr, ExprKind}, inflow::Inflow, parser::error::{ParseError, ParseErrorKind}, + source_files::Source, token::{Token, TokenKind}, }; impl<'a, I: Inflow> Parser<'a, I> { - pub fn parse_enum_member_literal(&mut self) -> Result { + pub fn parse_enum_member_literal( + &mut self, + enum_name: String, + source: Source, + ) -> Result { // EnumName::EnumVariant // ^ - let source = self.source_here(); - let enum_name = self - .input - .eat_identifier() - .ok_or_else(|| ParseErrorKind::ExpectedEnumName.at(source))?; - self.parse_token(TokenKind::Namespace, Some("for enum member literal"))?; let variant_source = self.source_here(); let variant_name = self .input .eat_identifier() - .ok_or_else(|| ParseErrorKind::ExpectedEnumName.at(variant_source))?; + .ok_or_else(|| ParseErrorKind::ExpectedEnumMemberName.at(variant_source))?; Ok(ExprKind::EnumMemberLiteral(Box::new(EnumMemberLiteral { enum_name, diff --git a/src/parser/parse_expr/primary/mod.rs b/src/parser/parse_expr/primary/mod.rs index b99e9ce3..4650e928 100644 --- a/src/parser/parse_expr/primary/mod.rs +++ b/src/parser/parse_expr/primary/mod.rs @@ -70,24 +70,23 @@ impl<'a, I: Inflow> Parser<'a, I> { // TODO: CLEANUP: This should be cleaned up once we have proper // namespaces and generic parsing that applies to all cases - match self.input.peek_nth(1).kind { - TokenKind::Namespace => self.parse_enum_member_literal(), - TokenKind::OpenAngle => { - let name = self.input.eat_identifier().unwrap(); - let generics = self.parse_generics()?; + let name = self.input.eat_identifier().unwrap(); + let generics = self.parse_generics()?; + match self.input.peek().kind { + TokenKind::Namespace => { if !generics.is_empty() { - todo!("generics in expressions not implemented yet"); + return Err(ParseErrorKind::GenericsNotSupportedHere.at(source)); } - let ast_type = self.parse_type_from_parts(name, vec![], source)?; - self.parse_structure_literal_with(ast_type) + self.parse_enum_member_literal(name, source) } TokenKind::OpenCurly => { - let peek = &self.input.peek_nth(2).kind; + let ast_type = self.parse_type_from_parts(name, generics, source)?; + let peek = &self.input.peek_nth(1).kind; if peek.is_extend() || peek.is_colon() { - self.parse_structure_literal() + self.parse_structure_literal_with(ast_type) } else { let next_three = array_last::<3, 5, _>(self.input.peek_n()).map(|token| &token.kind); @@ -95,7 +94,7 @@ impl<'a, I: Inflow> Parser<'a, I> { match &next_three[..] { [TokenKind::Identifier(_), TokenKind::Colon, ..] | [TokenKind::Newline, TokenKind::Identifier(_), TokenKind::Colon, ..] => { - self.parse_structure_literal() + self.parse_structure_literal_with(ast_type) } _ => Ok(Expr::new( ExprKind::Variable( @@ -106,12 +105,21 @@ impl<'a, I: Inflow> Parser<'a, I> { } } } - TokenKind::OpenParen => self.parse_call(), - TokenKind::DeclareAssign => self.parse_declare_assign(), - _ => Ok(Expr::new( - ExprKind::Variable(self.input.advance().kind.unwrap_identifier()), - source, - )), + TokenKind::OpenParen => self.parse_call(name, generics, source), + TokenKind::DeclareAssign => { + if !generics.is_empty() { + return Err(ParseErrorKind::GenericsNotSupportedHere.at(source)); + } + + self.parse_declare_assign(name, source) + } + _ => { + if !generics.is_empty() { + return Err(ParseErrorKind::GenericsNotSupportedHere.at(source)); + } + + Ok(Expr::new(ExprKind::Variable(name), source)) + } } } TokenKind::Not | TokenKind::BitComplement | TokenKind::Subtract => { diff --git a/src/resolve/expr/call.rs b/src/resolve/expr/call.rs index caeff760..ffdf3d97 100644 --- a/src/resolve/expr/call.rs +++ b/src/resolve/expr/call.rs @@ -15,6 +15,13 @@ pub fn resolve_call_expr( call: &ast::Call, source: Source, ) -> Result { + if !call.generics.is_empty() { + return Err(ResolveErrorKind::Other { + message: "Resolution of calls with generics is not implemented yet".into(), + } + .at(source)); + } + let function_ref = ctx .function_search_ctx .find_function_or_error(&call.function_name, source)?;