diff --git a/src/language_frontend/abstract_syntax_tree/ast.rs b/src/language_frontend/abstract_syntax_tree/ast.rs index a8d4bfa..241df70 100644 --- a/src/language_frontend/abstract_syntax_tree/ast.rs +++ b/src/language_frontend/abstract_syntax_tree/ast.rs @@ -3,28 +3,43 @@ use crate::language_frontend::abstract_syntax_tree::definitions::*; // Option and Result -> define in Std #[derive(Clone, Debug, PartialEq)] pub enum Expr { - Ident(String), + // var/fun_name + Ident(Identifier), + // 4 IntLiteral(i64), + // 12.5 FloatLiteral(f64), + // "eepy" StringLiteral(String), + // true BoolLiteral(bool), + // 'c' CharLiteral(char), + // var x = intPlusOne(12) CallExpr(Call), + // !x UnaryExpr(Unary), + // 1 + 11 BinaryExpr(Binary), + // x = 64 AssignmentExpr(Assignment), + // var foo = "bar" VarExpr(Var), + // if(...) { ... } else { ... } + Condition(Condition), + + // fun helloWorld() { ... } FunctionExpr(Function), Error, diff --git a/src/language_frontend/abstract_syntax_tree/definitions.rs b/src/language_frontend/abstract_syntax_tree/definitions.rs index 1dc04d9..33b14fd 100644 --- a/src/language_frontend/abstract_syntax_tree/definitions.rs +++ b/src/language_frontend/abstract_syntax_tree/definitions.rs @@ -2,23 +2,21 @@ use std::{ops::Range, rc::Rc}; use crate::language_frontend::abstract_syntax_tree::ast::Expr; -/// Abstract Syntax Tree -pub type BlockStatement = Vec; +// Abstract Syntax Tree + +pub type BlockExpression = Vec; pub type Span = Range; -#[derive(Clone, Debug, PartialEq)] -pub enum Statement { - Var(Ident, Option), -} - #[derive(Clone, Debug, PartialEq)] pub enum BinaryOp { + // Arithmetic Multiply, Divide, Add, Substract, + // Comparision Equals, NotEquals, Less, @@ -26,15 +24,16 @@ pub enum BinaryOp { Greater, GreaterEquals, + // Logical And, Or, + // todo: bitwise } #[derive(Clone, Debug, PartialEq)] pub enum UnaryOp { Not, - Minus, - Plus, + Negate, } #[derive(Clone, Debug, PartialEq)] @@ -82,19 +81,20 @@ impl Value { // Structs //--------------------------------------- #[derive(Clone, Debug, PartialEq)] -pub struct Ident(pub Rc); +pub struct Identifier(pub String); #[derive(Clone, Debug, PartialEq)] pub struct While { - pub condition: Expr, - pub body: BlockStatement, + pub condition: Box, + pub body: BlockExpression, } +/// Example: `if (a > 12) { ... }` #[derive(Clone, Debug, PartialEq)] pub struct Condition { - pub condition: Expr, - pub if_body: BlockStatement, - pub else_body: Option, + pub condition: Box, + pub if_body: BlockExpression, + pub else_body: Option, } /// Example: `x = y` @@ -108,7 +108,7 @@ pub struct Assignment { #[derive(Clone, Debug, PartialEq)] pub struct Var { pub ty: Option, - pub ident: String, + pub ident: Identifier, pub value: Box, } @@ -145,14 +145,17 @@ pub struct Binary { #[derive(Clone, Debug, PartialEq)] pub struct Function { pub name: String, - pub params: Option>, + pub params: Option>, pub return_type: Option, - pub body: Option>, - pub body_expr: Option>, + pub body: Option, + pub body_expr: Option>, // ' -> (return)' } #[derive(Clone, Debug, PartialEq)] pub struct Call { - pub callee: Box, + /// name of the function being called + pub name: Box, + + /// arguments supplied pub arguments: Vec, } diff --git a/src/language_frontend/abstract_syntax_tree/parser.rs b/src/language_frontend/abstract_syntax_tree/parser.rs index 17a242a..ca4b7b2 100644 --- a/src/language_frontend/abstract_syntax_tree/parser.rs +++ b/src/language_frontend/abstract_syntax_tree/parser.rs @@ -115,7 +115,7 @@ where .map(|(name, rhs)| { Expr::VarExpr(Var { ty: None, - ident: name, + ident: Identifier(String::from(name)), value: Box::new(rhs), }) }); @@ -157,12 +157,12 @@ mod tests { #[test] fn test_unary_expr() { - let negate_two = parse("-2"); + let negate_two = parse("!2"); assert!(negate_two.is_ok()); assert_eq!( negate_two.clone().unwrap(), vec![Expr::UnaryExpr(Unary { - operator: UnaryOp::Minus, + operator: UnaryOp::Negate, operand: Box::new(Expr::IntLiteral(2)), })] ) @@ -176,7 +176,7 @@ mod tests { var_bool.clone().unwrap(), vec![Expr::VarExpr(Var { ty: None, - ident: String::from("isUwU"), + ident: Identifier(String::from("isUwU")), value: Box::new(Expr::BoolLiteral(true)) })] ) @@ -204,7 +204,7 @@ mod tests { var_without_expl_type.clone().unwrap(), vec![Expr::VarExpr(Var { ty: None, - ident: String::from("x"), + ident: Identifier(String::from("x")), value: Box::new(Expr::IntLiteral(12)) })] ) @@ -225,6 +225,7 @@ mod tests { #[test] fn test_function_decl() { + // test without a body or args let empty_fun = parse("fun helloWorld() { }"); assert!(empty_fun.is_ok()); assert_eq!( @@ -238,6 +239,7 @@ mod tests { })] ); + // tests if empty new lines within a function works let empty_fun_with_new_lines = parse( r"fun emptyMulLines() { @@ -255,6 +257,7 @@ mod tests { })] ); + // tests for return expr in functions let fun_that_returns_int = parse( r"fun returnsInt(): int { -> 12 diff --git a/src/llvm_backend/llvm.rs b/src/llvm_backend/llvm.rs new file mode 100644 index 0000000..f7c1d42 --- /dev/null +++ b/src/llvm_backend/llvm.rs @@ -0,0 +1,37 @@ +use chumsky::prelude::todo; +use inkwell::{ + OptimizationLevel, + builder::{self, Builder}, + context::Context, + execution_engine::ExecutionEngine, + module::Module, + types::BasicTypeEnum, + values::{BasicValueEnum, FunctionValue}, +}; + +use crate::language_frontend::abstract_syntax_tree::{ + ast::Expr, + definitions::{Function, Type}, +}; + +pub struct CodeGen<'ctx> { + pub(crate) context: &'ctx Context, + pub(crate) module: Module<'ctx>, + pub(crate) builder: Builder<'ctx>, + pub(crate) exec_engine: ExecutionEngine<'ctx>, +} + +impl<'ctx> CodeGen<'ctx> { + pub fn new(context: &'ctx Context, module_name: &str, opt_level: OptimizationLevel) -> Self { + let module = context.create_module(module_name); + let exec_engine = module.create_jit_execution_engine(opt_level).unwrap(); + let builder = context.create_builder(); + + CodeGen { + context, + module, + builder, + exec_engine, + } + } +} diff --git a/src/llvm_backend/mod.rs b/src/llvm_backend/mod.rs new file mode 100644 index 0000000..cd44a09 --- /dev/null +++ b/src/llvm_backend/mod.rs @@ -0,0 +1 @@ +pub mod llvm; diff --git a/src/main.rs b/src/main.rs index cfa7a42..8881300 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ use chumsky::input::{Input, Stream}; use logos::Logos; mod language_frontend; +mod llvm_backend; use crate::{ language_frontend::abstract_syntax_tree::parser::parse, language_frontend::lexer::tokens::Token,