From 8be56292390fd56c1ef6617dafa951ab343fe042 Mon Sep 17 00:00:00 2001 From: "[ Taha. Dostifam ]" Date: Mon, 10 Feb 2025 23:34:54 +0330 Subject: [PATCH] extern variadic funcs works now --- ast/src/ast.rs | 6 +++++- ast/src/tests.rs | 4 ++-- ast/src/token.rs | 4 ++++ compiler/src/funcs.rs | 42 ++++++++++++++++++++-------------------- compiler/src/import.rs | 6 +++--- compiler/src/structs.rs | 8 ++++---- examples/main.cy | 5 ++--- lexer/src/lib.rs | 23 +++++++++++++++++++++- parser/src/statements.rs | 34 +++++++++++++++++++++++++++----- parser/src/tests.rs | 2 +- stdlib/io.cy | 6 +++--- 11 files changed, 96 insertions(+), 44 deletions(-) diff --git a/ast/src/ast.rs b/ast/src/ast.rs index b9186f2..961c55c 100644 --- a/ast/src/ast.rs +++ b/ast/src/ast.rs @@ -374,7 +374,11 @@ pub struct FunctionParam { pub loc: Location, } -pub type FunctionParams = Vec; +#[derive(Debug, Clone)] +pub struct FunctionParams { + pub list: Vec, + pub is_variadic: bool +} #[derive(Debug, Clone)] pub struct If { diff --git a/ast/src/tests.rs b/ast/src/tests.rs index 3c81d48..70361fc 100644 --- a/ast/src/tests.rs +++ b/ast/src/tests.rs @@ -195,7 +195,7 @@ mod tests { let func = FuncDef { name: "add".to_string(), - params: vec![param.clone()], + params: FunctionParams { list: vec![param.clone()], is_variadic: false }, body: Box::new(BlockStatement { body: vec![], span: Span::default(), @@ -208,7 +208,7 @@ mod tests { }; assert_eq!(func.name, "add"); - assert_eq!(func.params[0].identifier.name, "a"); + assert_eq!(func.params.list[0].identifier.name, "a"); } #[test] diff --git a/ast/src/token.rs b/ast/src/token.rs index 36801b3..0f4ff80 100644 --- a/ast/src/token.rs +++ b/ast/src/token.rs @@ -36,6 +36,8 @@ pub enum TokenKind { Comma, Hashtag, Dot, + DoubleDot, + TripleDot, DoubleQuote, SingleQuote, Pipe, @@ -114,6 +116,8 @@ impl fmt::Display for TokenKind { Self::RightBracket => write!(f, "]]"), Self::Comma => write!(f, ","), Self::Hashtag => write!(f, "#"), + Self::DoubleDot => write!(f, ".."), + Self::TripleDot => write!(f, "..."), Self::Dot => write!(f, "."), Self::DoubleQuote => write!(f, "\""), Self::SingleQuote => write!(f, "'"), diff --git a/compiler/src/funcs.rs b/compiler/src/funcs.rs index 8d3dc01..f20e7dd 100644 --- a/compiler/src/funcs.rs +++ b/compiler/src/funcs.rs @@ -14,7 +14,7 @@ pub struct FuncMetadata { pub(crate) func_type: VisType, pub(crate) ptr: *mut gcc_jit_function, pub(crate) return_type: TokenKind, - pub(crate) params: Vec, + pub(crate) params: FunctionParams, } #[derive(Debug, Clone)] @@ -26,15 +26,15 @@ pub struct FuncParamRecord { pub type FuncParamsRecords = Vec; impl Compiler { - fn declare_function(&mut self, declare_function: FuncDecl) -> (*mut gcc_jit_function, FuncParamsRecords) { - let func_type = match declare_function.vis_type { + fn declare_function(&mut self, func_decl: FuncDecl) -> (*mut gcc_jit_function, FuncParamsRecords) { + let func_type = match func_decl.vis_type { VisType::Extern => gcc_jit_function_kind::GCC_JIT_FUNCTION_IMPORTED, // imported function VisType::Pub => gcc_jit_function_kind::GCC_JIT_FUNCTION_EXPORTED, VisType::Internal => gcc_jit_function_kind::GCC_JIT_FUNCTION_INTERNAL, VisType::Inline => gcc_jit_function_kind::GCC_JIT_FUNCTION_ALWAYS_INLINE, }; - let return_type_token = declare_function + let return_type_token = func_decl .return_type .clone() .unwrap_or(Token { @@ -48,7 +48,7 @@ impl Compiler { let mut params: Vec<*mut gcc_jit_param> = Vec::new(); let mut func_params = FuncParamsRecords::new(); - for (idx, func_def_param) in declare_function.params.iter().enumerate() { + for (idx, func_def_param) in func_decl.params.list.iter().enumerate() { let name = CString::new(func_def_param.identifier.name.clone()).unwrap(); let ty_token = if let Some(user_def) = &func_def_param.ty { @@ -76,17 +76,17 @@ impl Compiler { }); } - let func_name = CString::new(declare_function.name.clone()).unwrap(); + let func_name = CString::new(func_decl.name.clone()).unwrap(); let func = unsafe { gcc_jit_context_new_function( self.context, - self.gccjit_location(declare_function.loc.clone()), + self.gccjit_location(func_decl.loc.clone()), func_type, return_type.clone(), func_name.as_ptr(), params.len().try_into().unwrap(), params.as_mut_ptr(), - 0, + self.cbool(func_decl.params.is_variadic), ) }; @@ -210,18 +210,18 @@ impl Compiler { let mut expr = self.compile_expression(Rc::clone(&scope), expr.clone()); if let Some(ref func_params) = func_params { - let param = func_params[idx].clone(); - - if let Some(var_token_type) = param.ty { - if self.auto_castable_data_types(var_token_type.clone()) { - expr = unsafe { - gcc_jit_context_new_cast( - self.context, - self.gccjit_location(param.loc.clone()), - expr, - self.token_as_data_type(self.context, var_token_type), - ) - }; + if let Some(param) = func_params.get(idx) { + if let Some(var_token_type) = ¶m.ty { + if self.auto_castable_data_types(var_token_type.clone()) { + expr = unsafe { + gcc_jit_context_new_cast( + self.context, + self.gccjit_location(param.loc.clone()), + expr, + self.token_as_data_type(self.context, var_token_type.clone()), + ) + }; + } } } } @@ -247,7 +247,7 @@ impl Compiler { }; let mut args = - self.compile_func_arguments(Rc::clone(&scope), Some(metadata.params.clone()), func_call.arguments); + self.compile_func_arguments(Rc::clone(&scope), Some(metadata.params.list.clone()), func_call.arguments); let rvalue = unsafe { gcc_jit_context_new_call( diff --git a/compiler/src/import.rs b/compiler/src/import.rs index c43efd1..f797e8d 100644 --- a/compiler/src/import.rs +++ b/compiler/src/import.rs @@ -149,7 +149,7 @@ impl Compiler { fn define_imported_func_as_extern_decl( &mut self, func_name: String, - params: Vec, + params: FunctionParams, return_type: Option, loc: Location, ) -> *mut gcc_jit_function { @@ -160,7 +160,7 @@ impl Compiler { }) .kind; - let mut func_params = self.compile_func_params(func_name.clone(), params.clone(), loc.clone()); + let mut func_params = self.compile_func_params(func_name.clone(), params.list.clone(), loc.clone()); let func_name_cstr = CString::new(func_name.clone()).unwrap(); let decl_func = unsafe { gcc_jit_context_new_function( @@ -171,7 +171,7 @@ impl Compiler { func_name_cstr.as_ptr(), func_params.len().try_into().unwrap(), func_params.as_mut_ptr(), - 0, // FIXME Variadic + self.cbool(params.is_variadic) ) }; diff --git a/compiler/src/structs.rs b/compiler/src/structs.rs index 3ca5db4..806052e 100644 --- a/compiler/src/structs.rs +++ b/compiler/src/structs.rs @@ -133,7 +133,7 @@ impl Compiler { // Isolate the mutable borrow to avoid conflict with immutable borrows. self.compile_func_arguments( Rc::clone(&scope), - Some(method_def.params), + Some(method_def.params.list), method_call.arguments, ) }; @@ -176,11 +176,11 @@ impl Compiler { // Inserting self argument let mut arguments = self.compile_func_arguments( Rc::clone(&scope), - Some(method_def.params.clone()), + Some(method_def.params.list.clone()), method_call.arguments, ); let self_param = method_def - .params + .params.list .iter() .find(|&key| key.identifier.name == "self") .unwrap(); @@ -363,7 +363,7 @@ impl Compiler { for item in methods.clone() { let mut is_static = true; - if let Some(self_param) = item.params.iter().find(|&key| key.identifier.name == "self") { + if let Some(self_param) = item.params.list.iter().find(|&key| key.identifier.name == "self") { is_static = false; if !self.struct_self_param_valid(struct_name.clone(), self_param.ty.clone().unwrap()) { diff --git a/examples/main.cy b/examples/main.cy index 1f3b07b..5b607df 100644 --- a/examples/main.cy +++ b/examples/main.cy @@ -1,6 +1,5 @@ -pub fn _sum() { +import io; -} pub fn main() { - _sum(); + printf("Hello: %s %s\n", "adad", "aasd"); } \ No newline at end of file diff --git a/lexer/src/lib.rs b/lexer/src/lib.rs index 87c5007..d6ecd5d 100644 --- a/lexer/src/lib.rs +++ b/lexer/src/lib.rs @@ -172,7 +172,28 @@ impl Lexer { '[' => TokenKind::LeftBracket, ']' => TokenKind::RightBracket, ',' => TokenKind::Comma, - '.' => TokenKind::Dot, + '.' => { + self.read_char(); + + let mut kind = TokenKind::Dot; + + if self.ch == '.' && self.peek_char() == '.' { + self.read_char(); + self.read_char(); + kind = TokenKind::TripleDot; + } else if self.ch == '.' { + self.read_char(); + kind = TokenKind::DoubleDot; + } + + return Token { + kind, + span: Span { + start: self.pos - 1, + end: self.pos - 1, + }, + }; + }, '#' => TokenKind::Hashtag, '"' => return self.read_string(), '\'' => return self.read_char_literal(), diff --git a/parser/src/statements.rs b/parser/src/statements.rs index bc2d73f..c1670fc 100644 --- a/parser/src/statements.rs +++ b/parser/src/statements.rs @@ -342,15 +342,39 @@ impl<'a> Parser<'a> { } } - pub fn parse_func_params(&mut self) -> Result { + pub fn parse_func_params(&mut self, func_def_start: usize) -> Result { let params_start = self.current_token.span.start; self.expect_current(TokenKind::LeftParen)?; - let mut params: Vec = Vec::new(); + let mut triple_dots_count = 0; + let mut is_variadic = false; + let mut list: Vec = Vec::new(); while self.current_token.kind != TokenKind::RightParen { match self.current_token.kind.clone() { + TokenKind::TripleDot => { + if triple_dots_count >= 1 { + return Err(CompileTimeError { + location: self.current_location(), + etype: ParserErrorType::InvalidToken(self.current_token.kind.clone()), + file_name: Some(self.lexer.file_name.clone()), + code_raw: Some(self.lexer.select(func_def_start..self.current_token.span.end + 1)), + verbose: Some(String::from( + "Only one triple_dot is allowed in func decl and it must be positioned as final param.", + )), + caret: true, + }); + } + self.next_token(); + is_variadic = true; + triple_dots_count += 1; + + if self.current_token_is(TokenKind::Comma) { + self.next_token(); + continue; + } + } TokenKind::Identifier { name } => { self.next_token(); // consume the identifier @@ -375,7 +399,7 @@ impl<'a> Parser<'a> { self.next_token(); // consume the expression } - params.push(FunctionParam { + list.push(FunctionParam { identifier: Identifier { name: name, span: self.current_token.span.clone(), @@ -428,7 +452,7 @@ impl<'a> Parser<'a> { self.expect_current(TokenKind::RightParen)?; - Ok(params) + Ok(FunctionParams { list, is_variadic }) } pub fn parse_for_loop(&mut self) -> Result { @@ -687,7 +711,7 @@ impl<'a> Parser<'a> { }; // export the name of the function self.next_token(); // consume the name of the identifier - let params = self.parse_func_params()?; + let params = self.parse_func_params(start)?; let mut return_type: Option = None; diff --git a/parser/src/tests.rs b/parser/src/tests.rs index 4436faa..1bb087b 100644 --- a/parser/src/tests.rs +++ b/parser/src/tests.rs @@ -83,7 +83,7 @@ mod tests { fn test_parse_function_params() { let mut lexer = Lexer::new(String::from("(a: i32, b: u32 = 1, c: string)"), String::from("parser_test.cy")); let mut parser = Parser::new(&mut lexer); - let params = parser.parse_func_params().unwrap(); + let params = parser.parse_func_params(0).unwrap().list; assert_eq!(params.index(0).identifier.name, "a"); assert_eq!(params.index(0).default_value.is_none(), true); diff --git a/stdlib/io.cy b/stdlib/io.cy index 5cfea5b..55e034c 100644 --- a/stdlib/io.cy +++ b/stdlib/io.cy @@ -1,5 +1,5 @@ -extern fn printf(fmt: string): void as local_printf; +extern fn printf(fmt: string, ...): void as _printf; -pub fn printf(fmt: string) { - local_printf(fmt); +pub fn printf(fmt: string, ...) { + _printf(fmt); }