Big restructure pt.1

This commit is contained in:
Mia
2026-02-26 19:40:27 +01:00
parent 02f2ddfc67
commit f4334e79f6
32 changed files with 905 additions and 842 deletions
+10
View File
@@ -0,0 +1,10 @@
[package]
name = "leaf_compiler"
version = "0.1.0"
edition = "2024"
[dependencies]
leaf_parser = { path = "../parser" }
leaf_assembly = { path = "../assembly" }
leaf_allocators = { path = "../allocators" }
arcstr = "1.2.0"
+52
View File
@@ -0,0 +1,52 @@
use leaf_parser::{LineCol, ParseError};
use std::ops::Range;
use crate::SourceFile;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Kind {
Unknown = 0x0000,
Parsing = 0x0100,
SymbolNotFound = 0x0200,
UninitializedSymbol = 0x0201,
NotAType = 0x0202,
FunctionCompilationFailed = 0x0301,
}
#[derive(Debug, Clone)]
pub enum Location {
None,
Range {
file: SourceFile,
range: Range<usize>,
},
Position {
file: SourceFile,
position: LineCol,
},
}
#[derive(Debug)]
pub struct CompilationError {
pub kind: Kind,
pub message: String,
pub location: Location,
pub cause: Option<Box<CompilationError>>,
}
impl CompilationError {
pub fn parsing(file: SourceFile, err: ParseError<LineCol>) -> Self {
Self {
kind: Kind::Parsing,
message: err.to_string(),
location: Location::Position {
file,
position: err.location,
},
cause: None,
}
}
}
+87
View File
@@ -0,0 +1,87 @@
use crate::{error::CompilationError, scope::Scope};
use arcstr::literal_substr;
use leaf_allocators::SyncAllocator;
use leaf_assembly::{
assembly::{Assembly, AssemblyIdentifier, Context},
values::Value,
};
use leaf_parser::SourceCode;
use std::{collections::HashMap, sync::Arc};
mod error;
mod scope;
pub type SourceFile = Arc<SourceCode>;
pub struct CompilationContext<'l> {
ctx: &'l Context<'l>,
alloc: &'l dyn SyncAllocator,
}
impl<'l> CompilationContext<'l> {
pub fn new(alloc: &'l dyn SyncAllocator) -> Self {
Self {
alloc,
ctx: Context::new(alloc),
}
}
pub fn get_assembly(&self, ident: &AssemblyIdentifier) -> Option<&'l Assembly<'l>> {
self.ctx.get_assembly(ident)
}
pub fn extend(
&'l self,
ident: AssemblyIdentifier,
sources: &[Arc<SourceCode>],
) -> Result<(), CompilationError> {
let assembly = self.ctx.get_or_create_assembly(ident.clone());
let mut units = Vec::with_capacity(sources.len());
for src in sources {
match leaf_parser::parse(src) {
Ok(unit) => units.push(unit),
Err(err) => return Err(CompilationError::parsing(src.clone(), err)),
}
}
let mut scopes: Vec<_> = sources
.iter()
.map(|src| {
let mut scope = Scope::new(assembly, src.clone());
scope.insert(literal_substr!("void"), Value::Type(self.ctx.void_t()));
scope.insert(literal_substr!("i8"), Value::Type(self.ctx.i8_t()));
scope.insert(literal_substr!("i16"), Value::Type(self.ctx.i16_t()));
scope.insert(literal_substr!("i32"), Value::Type(self.ctx.i32_t()));
scope.insert(literal_substr!("i64"), Value::Type(self.ctx.i64_t()));
scope.insert(literal_substr!("i128"), Value::Type(self.ctx.i128_t()));
scope.insert(literal_substr!("isize"), Value::Type(self.ctx.isize_t()));
scope.insert(literal_substr!("u8"), Value::Type(self.ctx.u8_t()));
scope.insert(literal_substr!("u16"), Value::Type(self.ctx.u16_t()));
scope.insert(literal_substr!("u32"), Value::Type(self.ctx.u32_t()));
scope.insert(literal_substr!("u64"), Value::Type(self.ctx.u64_t()));
scope.insert(literal_substr!("u128"), Value::Type(self.ctx.u128_t()));
scope.insert(literal_substr!("usize"), Value::Type(self.ctx.usize_t()));
scope.insert(literal_substr!("f16"), Value::Type(self.ctx.f16_t()));
scope.insert(literal_substr!("f32"), Value::Type(self.ctx.f32_t()));
scope.insert(literal_substr!("f64"), Value::Type(self.ctx.f64_t()));
scope.insert(literal_substr!("type"), Value::Type(self.ctx.type_t()));
scope
})
.collect();
for i in 0..sources.len() {
let unit = &units[i];
let scope = &mut scopes[i];
scope.declare_constants(&unit.decls);
}
for i in 0..sources.len() {
let unit = &units[i];
let scope = &mut scopes[i];
scope.define_constants(&unit.decls)?;
}
Ok(())
}
}
+26
View File
@@ -0,0 +1,26 @@
use arcstr::ArcStr;
use leaf_allocators::SyncArenaAllocator;
use leaf_assembly::assembly::{AssemblyIdentifier, Version};
use leaf_compiler::CompilationContext;
use leaf_parser::SourceCode;
use std::{path::PathBuf, sync::Arc};
fn main() {
let alloc = SyncArenaAllocator::default();
let context = CompilationContext::new(&alloc);
let ident = AssemblyIdentifier {
version: Version::default(),
name: std::borrow::Cow::Borrowed("leaf_test"),
};
if let Err(err) = context.extend(
ident.clone(),
&[Arc::new(SourceCode {
text: ArcStr::from(std::fs::read_to_string("../test.leaf").unwrap()),
file: PathBuf::from("../test.leaf"),
})],
) {
println!("{}", err.message);
} else {
println!("{:#?}", context.get_assembly(&ident));
}
}
+108
View File
@@ -0,0 +1,108 @@
use arcstr::Substr;
use leaf_assembly::{
assembly::Assembly,
types::{Type, derivations::MakeTypeDerivations},
values::Value,
};
use leaf_parser::{
SourceCode,
ast::{self, ConstDecl, Expr, Ident},
};
use std::{collections::HashMap, sync::Arc};
use crate::error::*;
#[derive(Clone)]
pub struct Scope<'l> {
assembly: &'l Assembly<'l>,
source: Arc<SourceCode>,
values: HashMap<Substr, Option<Value<'l>>>,
}
impl<'l> Scope<'l> {
pub fn new(assembly: &'l Assembly<'l>, source: Arc<SourceCode>) -> Self {
Self {
assembly,
source,
values: HashMap::default(),
}
}
pub fn insert(&mut self, name: Substr, value: Value<'l>) {
self.values.insert(name, Some(value));
}
pub fn declare_constants(&mut self, decl: &[ConstDecl]) {
for val in decl {
for Ident(name) in val.names.as_slice() {
self.values.insert(name.clone(), None);
}
}
}
pub fn define_constants(&mut self, decl: &[ConstDecl]) -> Result<(), CompilationError> {
for val in decl {
let expr = self.compile_expression(&val.value)?;
}
Ok(())
}
pub fn compile_expression(&self, expr: &Expr) -> Result<Value<'l>, CompilationError> {
match expr {
Expr::Ident(Ident(name)) => match self.values.get(name) {
None => Err(CompilationError {
kind: Kind::SymbolNotFound,
message: format!("Symbol `{name}` does not exist in the current scope."),
location: Location::Range {
file: self.source.clone(),
range: name.range(),
},
cause: None,
}),
Some(None) => Err(CompilationError {
kind: Kind::UninitializedSymbol,
message: format!("Symbol `{name}` is not initialized at this time."),
location: Location::Range {
file: self.source.clone(),
range: name.range(),
},
cause: None,
}),
Some(Some(value)) => Ok(*value),
},
Expr::Func(func) => self.compile_function(func).map_err(|err| CompilationError {
kind: Kind::FunctionCompilationFailed,
message: format!("Could not compile function."),
location: Location::Range {
file: self.source.clone(),
range: func.text.range(),
},
cause: Some(Box::new(err)),
}),
_ => todo!("{expr:#?}"),
}
}
fn compile_function(&self, func: &ast::Function) -> Result<Value<'l>, CompilationError> {
let ret_ty = self.assert_type(self.compile_expression(&func.ret)?)?;
let mut par_ty = Vec::with_capacity(func.args.len());
for arg in &func.args {
let ty = self.assert_type(self.compile_expression(&arg.r#type)?)?;
par_ty.push(ty);
}
let fn_ty = ret_ty.make_fn(par_ty);
Ok(Value::Func(self.assembly.create_function(fn_ty)))
}
fn assert_type(&self, val: Value<'l>) -> Result<Type<'l>, CompilationError> {
match val {
Value::Type(ty) => Ok(ty),
_ => Err(CompilationError {
kind: Kind::NotAType,
message: format!("Value is not a type."),
location: Location::None,
cause: None,
}),
}
}
}