diff --git a/src/macros/macros.rs b/src/macros/macros.rs index c8d1bd5..cc42c74 100644 --- a/src/macros/macros.rs +++ b/src/macros/macros.rs @@ -1,17 +1,75 @@ -use std::ffi::{c_char, CStr}; - +use crate::lexer; use libloading::Symbol; +use std::ffi::{c_char, CStr, CString}; #[repr(C)] -pub enum Literal { - String(*const i8), - Int(i64), - UInt(u64), -} - -#[repr(C)] +#[derive(Debug)] pub enum Token { - Literal(Literal), + Ident(*mut c_char), + Integer(*mut c_char), + String(*mut c_char), + + Assign, + Plus, + Minus, + Bang, + Asterisk, + Slash, + Arrow, + Period, + Tilde, + Ampersand, + Bar, + Equal, + NotEqual, + LessThan, + GreaterThan, + LessEqual, + GreaterEqual, + And, + Or, + Shl, + Shr, + Comma, + Semicolon, + Colon, + LParen, + RParen, + LBrace, + RBrace, + LBracket, + RBracket, + + Const, + True, + False, + Let, + Fn, + Enum, + Struct, + If, + While, + For, + Else, + Return, + As, + Continue, + Break, + + U8, + U16, + U32, + U64, + I8, + I16, + I32, + I64, + Usize, + Isize, + Bool, + Void, + + Null, } #[repr(C)] @@ -50,3 +108,171 @@ pub fn symbol_to_macros<'lib>(symbol: Symbol<'lib, *const Slice>) -> &'li std::slice::from_raw_parts(slice.ptr, slice.len) } } + +impl Into for lexer::Token { + fn into(self) -> Token { + match self { + Self::Ident(ident) => { + let ident = Box::leak(Box::new(CString::new(ident).unwrap())); + + Token::Ident(ident.as_ptr() as *mut c_char) + } + Self::String(string) => { + let string = Box::leak(Box::new(CString::new(string).unwrap())); + + Token::String(string.as_ptr() as *mut c_char) + } + Self::Integer(integer) => { + let integer = Box::leak(Box::new(CString::new(integer).unwrap())); + + Token::Integer(integer.as_ptr() as *mut c_char) + } + + Self::Assign => Token::Assign, + Self::Plus => Token::Plus, + Self::Minus => Token::Minus, + Self::Bang => Token::Bang, + Self::Asterisk => Token::Asterisk, + Self::Slash => Token::Slash, + Self::Arrow => Token::Arrow, + Self::Period => Token::Period, + Self::Tilde => Token::Tilde, + Self::Ampersand => Token::Ampersand, + Self::Bar => Token::Bar, + Self::Equal => Token::Equal, + Self::NotEqual => Token::NotEqual, + Self::LessThan => Token::LessThan, + Self::GreaterThan => Token::GreaterThan, + Self::LessEqual => Token::LessEqual, + Self::GreaterEqual => Token::GreaterEqual, + Self::And => Token::And, + Self::Or => Token::Or, + Self::Shl => Token::Shl, + Self::Shr => Token::Shr, + Self::Comma => Token::Comma, + Self::Semicolon => Token::Semicolon, + Self::Colon => Token::Colon, + Self::LParen => Token::LParen, + Self::RParen => Token::RParen, + Self::LBrace => Token::LBrace, + Self::RBrace => Token::RBrace, + Self::LBracket => Token::LBracket, + Self::RBracket => Token::RBracket, + + Self::Const => Token::Const, + Self::True => Token::True, + Self::False => Token::False, + Self::Let => Token::Let, + Self::Fn => Token::Fn, + Self::Enum => Token::Enum, + Self::Struct => Token::Struct, + Self::If => Token::If, + Self::While => Token::While, + Self::For => Token::For, + Self::Else => Token::Else, + Self::Return => Token::Return, + Self::As => Token::As, + Self::Continue => Token::Continue, + Self::Break => Token::Break, + + Self::U8 => Token::U8, + Self::U16 => Token::U16, + Self::U32 => Token::U32, + Self::U64 => Token::U64, + Self::I8 => Token::I8, + Self::I16 => Token::I16, + Self::I32 => Token::I32, + Self::I64 => Token::I64, + Self::Usize => Token::Usize, + Self::Isize => Token::Isize, + Self::Bool => Token::Bool, + Self::Void => Token::Void, + + Self::Null => Token::Null, + } + } +} + +impl Into for Token { + fn into(self) -> lexer::Token { + match self { + Self::Ident(ptr) => { + let ident = unsafe { CString::from_raw(ptr) }.into_string().unwrap(); + + lexer::Token::Ident(ident) + } + Self::String(ptr) => { + let string = unsafe { CString::from_raw(ptr) }.into_string().unwrap(); + + lexer::Token::String(string) + } + Self::Integer(ptr) => { + let integer = unsafe { CString::from_raw(ptr) }.into_string().unwrap(); + + lexer::Token::Integer(integer) + } + + Self::Assign => lexer::Token::Assign, + Self::Plus => lexer::Token::Plus, + Self::Minus => lexer::Token::Minus, + Self::Bang => lexer::Token::Bang, + Self::Asterisk => lexer::Token::Asterisk, + Self::Slash => lexer::Token::Slash, + Self::Arrow => lexer::Token::Arrow, + Self::Period => lexer::Token::Period, + Self::Tilde => lexer::Token::Tilde, + Self::Ampersand => lexer::Token::Ampersand, + Self::Bar => lexer::Token::Bar, + Self::Equal => lexer::Token::Equal, + Self::NotEqual => lexer::Token::NotEqual, + Self::LessThan => lexer::Token::LessThan, + Self::GreaterThan => lexer::Token::GreaterThan, + Self::LessEqual => lexer::Token::LessEqual, + Self::GreaterEqual => lexer::Token::GreaterEqual, + Self::And => lexer::Token::And, + Self::Or => lexer::Token::Or, + Self::Shl => lexer::Token::Shl, + Self::Shr => lexer::Token::Shr, + Self::Comma => lexer::Token::Comma, + Self::Semicolon => lexer::Token::Semicolon, + Self::Colon => lexer::Token::Colon, + Self::LParen => lexer::Token::LParen, + Self::RParen => lexer::Token::RParen, + Self::LBrace => lexer::Token::LBrace, + Self::RBrace => lexer::Token::RBrace, + Self::LBracket => lexer::Token::LBracket, + Self::RBracket => lexer::Token::RBracket, + + Self::Const => lexer::Token::Const, + Self::True => lexer::Token::True, + Self::False => lexer::Token::False, + Self::Let => lexer::Token::Let, + Self::Fn => lexer::Token::Fn, + Self::Enum => lexer::Token::Enum, + Self::Struct => lexer::Token::Struct, + Self::If => lexer::Token::If, + Self::While => lexer::Token::While, + Self::For => lexer::Token::For, + Self::Else => lexer::Token::Else, + Self::Return => lexer::Token::Return, + Self::As => lexer::Token::As, + Self::Continue => lexer::Token::Continue, + Self::Break => lexer::Token::Break, + + Self::U8 => lexer::Token::U8, + Self::U16 => lexer::Token::U16, + Self::U32 => lexer::Token::U32, + Self::U64 => lexer::Token::U64, + Self::I8 => lexer::Token::I8, + Self::I16 => lexer::Token::I16, + Self::I32 => lexer::Token::I32, + Self::I64 => lexer::Token::I64, + Self::Usize => lexer::Token::Usize, + Self::Isize => lexer::Token::Isize, + Self::Bool => lexer::Token::Bool, + Self::Void => lexer::Token::Void, + + Self::Null => lexer::Token::Null, + } + } +} diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 5ec0ad0..0ac61b7 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -9,4 +9,5 @@ pub use error::ParserError; pub use expr::*; pub use op::{BinOp, BitwiseOp, CmpOp, OpParseError, UnOp}; pub use parser::Parser; +pub use precedence::Precedence; pub use stmt::{Block, Stmt, StmtFor, StmtFunction, StmtIf, StmtReturn, StmtVarDecl, StmtWhile}; diff --git a/src/parser/parser.rs b/src/parser/parser.rs index 6893f5e..0f25ce8 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -133,7 +133,7 @@ impl>> Parser { Ok(stmts) } - fn expr(&mut self, precedence: Precedence) -> Result { + pub fn expr(&mut self, precedence: Precedence) -> Result { let token = match self.cur_token.as_ref().unwrap() { Token::Ident(_) => Token::Ident(Default::default()), Token::Integer(_) => Token::Integer(Default::default()), @@ -149,6 +149,7 @@ impl>> Parser { }; while !self.cur_token_is(&Token::Semicolon) + && self.cur_token.is_some() && precedence < Precedence::from(self.cur_token.as_ref().unwrap()) { left = match self.infix_fns.get(self.cur_token.as_ref().unwrap()) { @@ -247,6 +248,36 @@ impl>> Parser { Ok(()) } + fn stmt(&mut self) -> Result, ParserError> { + match self.cur_token.as_ref().unwrap() { + Token::Return => Ok(Some(self.parse_return()?)), + Token::If => Ok(Some(self.if_stmt()?)), + Token::While => Ok(Some(self.while_stmt()?)), + Token::For => Ok(Some(self.for_stmt()?)), + Token::Let => Ok(Some(self.var_decl()?)), + Token::Continue => { + self.expect(&Token::Continue)?; + self.expect(&Token::Semicolon)?; + + Ok(Some(Stmt::Continue)) + } + Token::Break => { + self.expect(&Token::Break)?; + self.expect(&Token::Semicolon)?; + + Ok(Some(Stmt::Break)) + } + Token::Fn => self.function(true), + _ => { + let expr = Stmt::Expr(self.expr(Precedence::default())?); + + self.expect(&Token::Semicolon)?; + + Ok(Some(expr)) + } + } + } + fn compound_statement(&mut self, scope_kind: ScopeKind) -> Result { let mut stmts = Vec::new(); @@ -254,34 +285,8 @@ impl>> Parser { self.expect(&Token::LBrace)?; while !self.cur_token_is(&Token::RBrace) { - match self.cur_token.as_ref().unwrap() { - Token::Return => stmts.push(self.parse_return()?), - Token::If => stmts.push(self.if_stmt()?), - Token::While => stmts.push(self.while_stmt()?), - Token::For => stmts.push(self.for_stmt()?), - Token::Let => stmts.push(self.var_decl()?), - Token::Continue => { - self.expect(&Token::Continue)?; - self.expect(&Token::Semicolon)?; - stmts.push(Stmt::Continue); - } - Token::Break => { - self.expect(&Token::Break)?; - self.expect(&Token::Semicolon)?; - stmts.push(Stmt::Break); - } - Token::Fn => { - if let Some(stmt) = self.function(true)? { - stmts.push(stmt) - } - } - _ => { - let expr = Stmt::Expr(self.expr(Precedence::default())?); - - self.expect(&Token::Semicolon)?; - - stmts.push(expr); - } + if let Some(stmt) = self.stmt()? { + stmts.push(stmt); } } @@ -293,6 +298,19 @@ impl>> Parser { }) } + // This function is used only by macro expansion + pub fn parse_stmts(&mut self) -> Result, ParserError> { + let mut stmts = Vec::new(); + + while self.cur_token.is_some() { + if let Some(stmt) = self.stmt()? { + stmts.push(stmt); + } + } + + Ok(stmts) + } + fn parse_type(&mut self) -> Result { let mut n = 0; while self.cur_token_is(&Token::Asterisk) { diff --git a/src/passes/macro_expansion.rs b/src/passes/macro_expansion.rs index 2520ab8..f88699a 100644 --- a/src/passes/macro_expansion.rs +++ b/src/passes/macro_expansion.rs @@ -1,7 +1,8 @@ use super::Pass; use crate::{ - macros::{symbol_to_macros, Macro, MacroFn, Slice}, - parser::Stmt, + lexer::{self, LexerError}, + macros::{self, symbol_to_macros, Macro, MacroFn, Slice}, + parser::{Block, Expr, Parser, Precedence, Stmt}, scope::Scope, }; use libloading::Library; @@ -24,8 +25,8 @@ impl Pass for MacroExpansion { } } - fn run_pass(self, stmts: &mut Vec, scope: &mut Scope) -> Self::Output { - () + fn run_pass(self, stmts: &mut Vec, _: &mut Scope) -> Self::Output { + (0..stmts.len()).for_each(|i| self.check_stmt(stmts, i)); } } @@ -52,4 +53,133 @@ impl MacroExpansion { None } + + fn call_macro( + &self, + func: &MacroFn, + tokens: &mut Vec, + ) -> Vec> { + let token_tree = std::mem::take(tokens) + .into_iter() + .map(|token| token.into()) + .collect::>() + .leak(); + let token_tree = func(Slice { + ptr: token_tree.as_ptr(), + len: token_tree.len(), + }); + + unsafe { + Vec::from_raw_parts( + token_tree.ptr as *mut macros::Token, + token_tree.len, + token_tree.len, + ) + } + .into_iter() + .map(|token_tree| Ok(token_tree.into())) + .collect() + } + + fn check_stmt(&self, stmts: &mut Vec, i: usize) { + match &mut stmts[i] { + Stmt::VarDecl(stmt) => { + if let Some(expr) = &mut stmt.value { + self.check_expr(expr); + } + } + Stmt::Expr(expr) => match expr { + Expr::MacroCall(call) => match self.get_macro(&call.name) { + Some(func) => { + let tokens = self.call_macro(func, &mut call.tokens); + let mut parser = Parser::new(tokens.into_iter()).unwrap(); + // TODO: assert that all tokens were parsed + let parsed_stmts = parser.parse_stmts().unwrap(); + + stmts.splice(i..=i, parsed_stmts); + } + None => panic!("Macro {} doesn't exist", &call.name), + }, + expr => self.check_expr(expr), + }, + Stmt::Function(stmt) => self.check_block(&mut stmt.block), + Stmt::Return(stmt) => { + if let Some(expr) = &mut stmt.expr { + self.check_expr(expr) + } + } + Stmt::If(stmt) => { + self.check_expr(&mut stmt.condition); + self.check_block(&mut stmt.consequence); + if let Some(block) = &mut stmt.alternative { + self.check_block(block); + } + } + Stmt::While(stmt) => { + self.check_expr(&mut stmt.condition); + self.check_block(&mut stmt.block); + } + Stmt::For(stmt) => { + // What to do here? + if let Some(stmt) = &mut stmt.initializer {} + if let Some(expr) = &mut stmt.condition { + self.check_expr(expr); + } + if let Some(expr) = &mut stmt.increment { + self.check_expr(expr); + } + self.check_block(&mut stmt.block); + } + Stmt::Continue | Stmt::Break => (), + }; + } + + fn check_expr(&self, expr: &mut Expr) { + match expr { + Expr::Binary(expr) => { + self.check_expr(&mut expr.left); + self.check_expr(&mut expr.right); + } + Expr::Unary(expr) => self.check_expr(&mut expr.expr), + Expr::Cast(expr) => self.check_expr(&mut expr.expr), + Expr::Lit(_) | Expr::Ident(_) => (), + Expr::Struct(expr) => expr + .fields + .iter_mut() + .for_each(|(_, expr)| self.check_expr(expr)), + Expr::Array(expr) => expr.0.iter_mut().for_each(|expr| self.check_expr(expr)), + Expr::StructAccess(expr) => self.check_expr(&mut expr.expr), + Expr::StructMethod(expr) => { + self.check_expr(&mut expr.expr); + expr.arguments + .iter_mut() + .for_each(|expr| self.check_expr(expr)); + } + Expr::ArrayAccess(expr) => { + self.check_expr(&mut expr.expr); + self.check_expr(&mut expr.index); + } + Expr::FunctionCall(expr) => { + self.check_expr(&mut expr.expr); + expr.arguments + .iter_mut() + .for_each(|expr| self.check_expr(expr)); + } + Expr::MacroCall(call) => match self.get_macro(&call.name) { + Some(func) => { + let tokens = self.call_macro(func, &mut call.tokens); + let mut parser = Parser::new(tokens.into_iter()).unwrap(); + // TODO: assert that all tokens were parsed + let parsed_expr = parser.expr(Precedence::default()).unwrap(); + + *expr = parsed_expr; + } + None => panic!("Macro {} doesn't exist", &call.name), + }, + } + } + + fn check_block(&self, block: &mut Block) { + (0..block.statements.len()).for_each(|i| self.check_stmt(&mut block.statements, i)); + } }