This commit is contained in:
LunarAkai 2025-08-10 09:51:27 +02:00
commit 42e6b66eb5
6 changed files with 86 additions and 26 deletions

View file

@ -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,

View file

@ -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<Statement>;
// Abstract Syntax Tree
pub type BlockExpression = Vec<Expr>;
pub type Span = Range<usize>;
#[derive(Clone, Debug, PartialEq)]
pub enum Statement {
Var(Ident, Option<Type>),
}
#[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<str>);
pub struct Identifier(pub String);
#[derive(Clone, Debug, PartialEq)]
pub struct While {
pub condition: Expr,
pub body: BlockStatement,
pub condition: Box<Expr>,
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<BlockStatement>,
pub condition: Box<Expr>,
pub if_body: BlockExpression,
pub else_body: Option<BlockExpression>,
}
/// Example: `x = y`
@ -108,7 +108,7 @@ pub struct Assignment {
#[derive(Clone, Debug, PartialEq)]
pub struct Var {
pub ty: Option<Type>,
pub ident: String,
pub ident: Identifier,
pub value: Box<Expr>,
}
@ -145,14 +145,17 @@ pub struct Binary {
#[derive(Clone, Debug, PartialEq)]
pub struct Function {
pub name: String,
pub params: Option<Vec<(Ident, Type)>>,
pub params: Option<Vec<(Identifier, Type)>>,
pub return_type: Option<Type>,
pub body: Option<Vec<Expr>>,
pub body_expr: Option<Box<Expr>>,
pub body: Option<BlockExpression>,
pub body_expr: Option<Box<Expr>>, // ' -> (return)'
}
#[derive(Clone, Debug, PartialEq)]
pub struct Call {
pub callee: Box<Expr>,
/// name of the function being called
pub name: Box<Identifier>,
/// arguments supplied
pub arguments: Vec<Expr>,
}

View file

@ -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

37
src/llvm_backend/llvm.rs Normal file
View file

@ -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,
}
}
}

1
src/llvm_backend/mod.rs Normal file
View file

@ -0,0 +1 @@
pub mod llvm;

View file

@ -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,