Repurpose module map and rename old to ErrorModules

This commit is contained in:
Sofia 2025-07-22 17:32:37 +03:00
parent fa6b7bdf87
commit f35f1ef701
11 changed files with 116 additions and 125 deletions

View File

@ -3,7 +3,7 @@
//! used for unwrapping syntax sugar, and then be transformed into Reid MIR.
use std::path::PathBuf;
use crate::token_stream::TokenRange;
use crate::{lexer::FullToken, token_stream::TokenRange};
pub mod parse;
pub mod process;
@ -206,6 +206,7 @@ pub enum TopLevelStatement {
#[derive(Debug)]
pub struct Module {
pub name: String,
pub tokens: Vec<FullToken>,
pub top_level_statements: Vec<TopLevelStatement>,
pub path: Option<PathBuf>,
pub is_main: bool,

View File

@ -1,18 +1,25 @@
use std::{path::PathBuf, process};
use std::path::PathBuf;
use crate::{
ast::{self},
mir::{self, NamedVariableRef, SourceModuleId, StmtKind, StructField, StructType, TypeKey},
mir::{
self, ModuleMap, NamedVariableRef, SourceModuleId, StmtKind, StructField, StructType,
TypeKey,
},
};
impl mir::Context {
pub fn from(modules: Vec<mir::Module>, base: PathBuf) -> mir::Context {
mir::Context { modules, base }
let mut map = ModuleMap::new();
for module in modules {
map.insert(module.module_id, module);
}
mir::Context { modules: map, base }
}
}
impl ast::Module {
pub fn process(&self, module_id: SourceModuleId) -> mir::Module {
pub fn process(self, module_id: SourceModuleId) -> mir::Module {
let mut imports = Vec::new();
let mut functions = Vec::new();
let mut typedefs = Vec::new();
@ -100,6 +107,7 @@ impl ast::Module {
functions,
path: self.path.clone(),
is_main: self.is_main,
tokens: self.tokens,
typedefs,
}
}

View File

@ -15,7 +15,7 @@ use reid_lib::{
};
use crate::{
error_raporting::ModuleMap,
error_raporting::ErrorModules,
lexer::{FullToken, Position},
mir::{
self, implement::TypeCategory, Metadata, NamedVariableRef, SourceModuleId, StructField,
@ -40,24 +40,10 @@ impl<'ctx> CodegenContext<'ctx> {
impl mir::Context {
/// Compile MIR [`Context`] into [`CodegenContext`] containing LLIR.
pub fn codegen<'ctx>(
&self,
context: &'ctx Context,
mod_map: &ModuleMap,
) -> CodegenContext<'ctx> {
pub fn codegen<'ctx>(&self, context: &'ctx Context) -> CodegenContext<'ctx> {
let mut modules = Vec::new();
for module in &self.modules {
modules.push(
module.codegen(
context,
mod_map
.module(&module.module_id)
.unwrap()
.tokens
.as_ref()
.unwrap(),
),
);
for (_, module) in &self.modules {
modules.push(module.codegen(context));
}
CodegenContext { context }
}
@ -198,12 +184,9 @@ impl Default for State {
}
impl mir::Module {
fn codegen<'ctx>(
&self,
context: &'ctx Context,
tokens: &Vec<FullToken>,
) -> ModuleCodegen<'ctx> {
fn codegen<'ctx>(&self, context: &'ctx Context) -> ModuleCodegen<'ctx> {
let mut module = context.module(&self.name, self.is_main);
let tokens = &self.tokens;
let (debug, compile_unit) = if let Some(path) = &self.path {
module.create_debug_info(DebugFileData {
@ -252,19 +235,24 @@ impl mir::Module {
insert_debug!(&TypeKind::Char);
for typedef in &self.typedefs {
let type_key = TypeKey(typedef.name.clone(), self.module_id);
let type_value = match &typedef.kind {
TypeDefinitionKind::Struct(StructType(fields)) => {
module.custom_type(CustomTypeKind::NamedStruct(NamedStruct(
typedef.name.clone(),
fields
.iter()
// TODO: Reorder custom-type definitions such that
// inner types get evaluated first. Otherwise this
// will cause a panic!
.map(|StructField(_, t, _)| t.get_type(&type_values, &types))
.collect(),
)))
let type_key = TypeKey(typedef.name.clone(), typedef.source_module);
let type_value = if typedef.source_module != self.module_id {
todo!()
} else {
match &typedef.kind {
TypeDefinitionKind::Struct(StructType(fields)) => {
module.custom_type(CustomTypeKind::NamedStruct(NamedStruct(
typedef.name.clone(),
fields
.iter()
// TODO: Reorder custom-type definitions such that
// inner types get evaluated first. Otherwise this
// will cause a panic!
.map(|StructField(_, t, _)| t.get_type(&type_values, &types))
.collect(),
)))
}
}
};
types.insert(type_value, typedef.clone());
@ -891,6 +879,7 @@ impl mir::Expression {
mir::ExprKind::Accessed(expression, type_kind, field) => {
let struct_val = expression.codegen(scope, &state.load(false)).unwrap();
dbg!(&expression);
let TypeKind::CodegenPtr(inner) = &struct_val.1 else {
panic!("tried accessing non-pointer");
};
@ -1034,7 +1023,13 @@ impl mir::Expression {
panic!("Variable was not a pointer?!?")
}
} else {
StackValue(v.0.derive(var_ptr_instr), *ptr_inner.clone())
let TypeKind::Borrow(borrow_inner, mutable) = *ptr_inner.clone() else {
panic!();
};
StackValue(
StackValueKind::mutable(mutable, var_ptr_instr),
*borrow_inner.clone(),
)
}
})
}

View File

@ -63,24 +63,24 @@ impl PartialOrd for ErrorKind {
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Module {
pub struct ErrorModule {
pub name: String,
pub tokens: Option<Vec<FullToken>>,
pub source: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct ModuleMap {
module_map: HashMap<mir::SourceModuleId, Module>,
pub struct ErrorModules {
module_map: HashMap<mir::SourceModuleId, ErrorModule>,
module_counter: mir::SourceModuleId,
}
impl ModuleMap {
impl ErrorModules {
pub fn add_module<T: Into<String>>(&mut self, name: T) -> Option<mir::SourceModuleId> {
let id = self.module_counter.increment();
self.module_map.insert(
id,
Module {
ErrorModule {
name: name.into(),
tokens: None,
source: None,
@ -101,21 +101,21 @@ impl ModuleMap {
}
}
pub fn module(&self, id: &mir::SourceModuleId) -> Option<&Module> {
pub fn module(&self, id: &mir::SourceModuleId) -> Option<&ErrorModule> {
self.module_map.get(id)
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct ReidError {
map: ModuleMap,
map: ErrorModules,
errors: Vec<ErrorKind>,
}
impl ReidError {
pub fn from_lexer<U>(
result: Result<U, lexer::Error>,
map: ModuleMap,
map: ErrorModules,
module: SourceModuleId,
) -> Result<U, ReidError> {
result.map_err(|error| {
@ -136,7 +136,7 @@ impl ReidError {
pub fn from_parser<U>(
result: Result<U, token_stream::Error>,
map: ModuleMap,
map: ErrorModules,
module: SourceModuleId,
) -> Result<U, ReidError> {
result.map_err(|error| {
@ -155,7 +155,7 @@ impl ReidError {
})
}
pub fn from_kind<U>(errors: Vec<ErrorKind>, map: ModuleMap) -> ReidError {
pub fn from_kind<U>(errors: Vec<ErrorKind>, map: ErrorModules) -> ReidError {
ReidError { map, errors }
}
}

View File

@ -43,7 +43,7 @@
use std::path::PathBuf;
use error_raporting::{ErrorKind as ErrorRapKind, ModuleMap, ReidError};
use error_raporting::{ErrorKind as ErrorRapKind, ErrorModules, ReidError};
use lexer::FullToken;
use mir::{
linker::LinkerPass, typecheck::TypeCheck, typeinference::TypeInference, typerefs::TypeRefs,
@ -64,7 +64,7 @@ mod util;
pub fn parse_module<'map, T: Into<String>>(
source: &str,
name: T,
map: &'map mut ModuleMap,
map: &'map mut ErrorModules,
) -> Result<(mir::SourceModuleId, Vec<FullToken>), ReidError> {
let id = map.add_module(name.into()).unwrap();
map.set_source(id, source.to_owned());
@ -81,8 +81,8 @@ pub fn parse_module<'map, T: Into<String>>(
pub fn compile_module<'map>(
module_id: mir::SourceModuleId,
tokens: &Vec<FullToken>,
map: &'map mut ModuleMap,
tokens: Vec<FullToken>,
map: &'map mut ErrorModules,
path: Option<PathBuf>,
is_main: bool,
) -> Result<mir::Module, ReidError> {
@ -101,8 +101,11 @@ pub fn compile_module<'map>(
statements.push(statement);
}
drop(token_stream);
let ast_module = ast::Module {
name: module.name,
tokens: tokens,
top_level_statements: statements,
path,
is_main,
@ -113,7 +116,7 @@ pub fn compile_module<'map>(
pub fn perform_all_passes<'map>(
context: &mut mir::Context,
module_map: &'map mut ModuleMap,
module_map: &'map mut ErrorModules,
) -> Result<(), ReidError> {
#[cfg(debug_assertions)]
dbg!(&context);
@ -193,13 +196,13 @@ pub fn perform_all_passes<'map>(
pub fn compile_and_pass<'map>(
source: &str,
path: PathBuf,
module_map: &'map mut ModuleMap,
module_map: &'map mut ErrorModules,
) -> Result<CompileOutput, ReidError> {
let path = path.canonicalize().unwrap();
let name = path.file_name().unwrap().to_str().unwrap().to_owned();
let (id, tokens) = parse_module(source, name, module_map)?;
let module = compile_module(id, &tokens, module_map, Some(path.clone()), true)?;
let module = compile_module(id, tokens, module_map, Some(path.clone()), true)?;
let mut mir_context = mir::Context::from(vec![module], path.parent().unwrap().to_owned());
@ -211,7 +214,7 @@ pub fn compile_and_pass<'map>(
println!("{}", &mir_context);
let mut context = Context::new(format!("Reid ({})", env!("CARGO_PKG_VERSION")));
let codegen_modules = mir_context.codegen(&mut context, &module_map);
let codegen_modules = mir_context.codegen(&mut context);
#[cfg(debug_assertions)]
println!("{}", &codegen_modules.context);
@ -221,6 +224,6 @@ pub fn compile_and_pass<'map>(
}
pub fn compile_simple(source: &str, path: PathBuf) -> Result<CompileOutput, ReidError> {
let mut map = ModuleMap::default();
let mut map = ErrorModules::default();
compile_and_pass(source, path, &mut map)
}

View File

@ -6,7 +6,7 @@ use super::*;
impl Display for Context {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for module in &self.modules {
for (_, module) in &self.modules {
Display::fmt(&module, f)?;
}
Ok(())

View File

@ -9,8 +9,7 @@ use std::{
use crate::{
compile_module,
error_raporting::{ModuleMap, ReidError},
lexer::FullToken,
error_raporting::{ErrorModules, ReidError},
mir::{SourceModuleId, TypeDefinition, TypeKey, TypeKind},
parse_module,
};
@ -47,22 +46,21 @@ pub enum ErrorKind {
FunctionIsPrivate(String, String),
}
pub fn compile_std(
module_map: &mut ModuleMap,
) -> Result<(super::Module, Vec<FullToken>), ReidError> {
pub fn compile_std(module_map: &mut ErrorModules) -> Result<Module, ReidError> {
let (id, tokens) = parse_module(STD_SOURCE, "standard_library", module_map)?;
let module = compile_module(id, &tokens, module_map, None, false)?;
let module = compile_module(id, tokens, module_map, None, false)?;
let module_id = module.module_id;
let mut mir_context = super::Context::from(vec![module], Default::default());
let std_compiled = mir_context.modules.remove(0);
Ok((std_compiled, tokens))
let std_compiled = mir_context.modules.remove(&module_id).unwrap();
Ok(std_compiled)
}
/// Struct used to implement a type-checking pass that can be performed on the
/// MIR.
pub struct LinkerPass<'map> {
pub module_map: &'map mut ModuleMap,
pub module_map: &'map mut ErrorModules,
pub is_lib: bool,
}
@ -72,16 +70,15 @@ impl<'map> Pass for LinkerPass<'map> {
type Data = ();
type TError = ErrorKind;
fn context(&mut self, context: &mut Context, mut state: LinkerPassState) -> PassResult {
let mains = context
.modules
.iter_mut()
.filter(|m| m.is_main)
let mains = (&mut context.modules)
.into_iter()
.filter(|(_, module)| module.is_main)
.collect::<Vec<_>>();
if mains.len() > 1 {
state.note_errors(&vec![ErrorKind::MultipleMainsAtStart], Metadata::default());
return Ok(());
}
if let Some(main) = mains.first() {
if let Some((_, main)) = mains.first() {
if let None = main.functions.iter().find(|f| f.name == "main") {
if !self.is_lib {
state.note_errors(&vec![ErrorKind::NoMainFunction], Metadata::default());
@ -95,26 +92,19 @@ impl<'map> Pass for LinkerPass<'map> {
}
};
let mut modules = HashMap::<String, Rc<RefCell<_>>>::new();
let mut modules = HashMap::<SourceModuleId, Rc<RefCell<_>>>::new();
let mut module_ids = HashMap::<String, SourceModuleId>::new();
for module in context.modules.drain(..) {
let tokens = self
.module_map
.module(&module.module_id)
.unwrap()
.tokens
.clone()
.unwrap();
modules.insert(module.name.clone(), Rc::new(RefCell::new((module, tokens))));
for (mod_id, module) in context.modules.drain() {
modules.insert(mod_id, Rc::new(RefCell::new(module)));
}
let mut modules_to_process: Vec<Rc<RefCell<(Module, Vec<FullToken>)>>> =
modules.values().cloned().collect();
let mut modules_to_process: Vec<Rc<RefCell<_>>> = modules.values().cloned().collect();
while let Some(module) = modules_to_process.pop() {
let mut importer_module = module.borrow_mut();
for import in importer_module.0.imports.clone() {
for import in importer_module.imports.clone() {
let Import(path, _) = &import;
if path.len() != 2 {
state.ok::<_, Infallible>(
@ -125,14 +115,18 @@ impl<'map> Pass for LinkerPass<'map> {
let module_name = unsafe { path.get_unchecked(0) };
let mut imported = if let Some(module) = modules.get_mut(module_name) {
let mut imported = if let Some(module) =
modules.get_mut(module_ids.get(module_name).unwrap())
{
module
} else if module_name == "std" {
let std = compile_std(&mut self.module_map)?;
modules.insert(
"std".to_owned(),
std.module_id,
Rc::new(RefCell::new(compile_std(&mut self.module_map)?)),
);
modules.get("std").unwrap()
module_ids.insert(std.name, std.module_id);
modules.get(&std.module_id).unwrap()
} else {
let file_path =
PathBuf::from(&context.base.clone()).join(module_name.to_owned() + ".reid");
@ -160,8 +154,7 @@ impl<'map> Pass for LinkerPass<'map> {
}
};
match compile_module(id, &tokens, &mut self.module_map, Some(file_path), false)
{
match compile_module(id, tokens, &mut self.module_map, Some(file_path), false) {
Ok(imported_module) => {
if imported_module.is_main {
state.ok::<_, Infallible>(
@ -170,12 +163,11 @@ impl<'map> Pass for LinkerPass<'map> {
);
continue;
}
let module_name = imported_module.name.clone();
modules.insert(
module_name.clone(),
Rc::new(RefCell::new((imported_module, tokens))),
);
let imported = modules.get_mut(&module_name).unwrap();
let module_id = imported_module.module_id;
module_ids
.insert(imported_module.name.clone(), imported_module.module_id);
modules.insert(module_id, Rc::new(RefCell::new(imported_module)));
let imported = modules.get_mut(&module_id).unwrap();
modules_to_process.push(imported.clone());
imported
}
@ -194,13 +186,9 @@ impl<'map> Pass for LinkerPass<'map> {
.borrow_mut();
let func_name = unsafe { path.get_unchecked(1) };
let imported_mod_name = imported.0.name.clone();
let imported_mod_name = imported.name.clone();
let Some(func) = imported
.0
.functions
.iter_mut()
.find(|f| f.name == *func_name)
let Some(func) = imported.functions.iter_mut().find(|f| f.name == *func_name)
else {
state.ok::<_, Infallible>(
Err(ErrorKind::NoSuchFunctionInModule(
@ -228,7 +216,6 @@ impl<'map> Pass for LinkerPass<'map> {
func.is_imported = true;
if let Some(existing) = importer_module
.0
.functions
.iter()
.find(|f| f.name == *func_name)
@ -304,8 +291,8 @@ impl<'map> Pass for LinkerPass<'map> {
let mut seen = HashSet::new();
seen.extend(imported_types.clone());
let imported_mod_id = imported.0.module_id;
let imported_mod_typedefs = &mut imported.0.typedefs;
let imported_mod_id = imported.module_id;
let imported_mod_typedefs = &mut imported.typedefs;
for typekey in imported_types.clone() {
let typedef = imported_mod_typedefs
@ -323,10 +310,10 @@ impl<'map> Pass for LinkerPass<'map> {
.unwrap()
.clone();
importer_module.0.typedefs.push(typedef.clone());
importer_module.typedefs.push(typedef.clone());
}
importer_module.0.functions.push(FunctionDefinition {
importer_module.functions.push(FunctionDefinition {
name: func_name,
is_pub: false,
is_imported: false,
@ -337,9 +324,9 @@ impl<'map> Pass for LinkerPass<'map> {
}
}
context.modules = modules
let modules: Vec<Module> = modules
.into_values()
.map(|v| Rc::into_inner(v).unwrap().into_inner().0)
.map(|v| Rc::into_inner(v).unwrap().into_inner())
.collect();
Ok(())

View File

@ -354,11 +354,14 @@ pub struct Module {
pub functions: Vec<FunctionDefinition>,
pub typedefs: Vec<TypeDefinition>,
pub path: Option<PathBuf>,
pub tokens: Vec<FullToken>,
pub is_main: bool,
}
pub type ModuleMap = HashMap<SourceModuleId, Module>;
#[derive(Debug)]
pub struct Context {
pub modules: Vec<Module>,
pub modules: ModuleMap,
pub base: PathBuf,
}

View File

@ -277,7 +277,7 @@ impl Context {
let mut state = State::new();
let mut scope = Scope::default();
pass.context(self, PassState::from(&mut state, &mut scope, None))?;
for module in &mut self.modules {
for (_, module) in (&mut self.modules).into_iter() {
module.pass(pass, &mut state, &mut scope.inner())?;
}
Ok(state)

View File

@ -10,13 +10,10 @@ mod util;
fn test(source: &str, name: &str) {
let mut map = Default::default();
let (id, tokens) = assert_err(parse_module(source, name, &mut map));
let module = assert_err(compile_module(id, &tokens, &mut map, None, true));
let module = assert_err(compile_module(id, tokens, &mut map, None, true));
assert_err(perform_all_passes(
&mut mir::Context {
modules: vec![module],
base: Default::default(),
},
&mut mir::Context::from(vec![module], Default::default()),
&mut map,
));
}

View File

@ -14,7 +14,7 @@ fn compiles() {
#[test]
fn passes_all_passes() {
let mut map = Default::default();
let Ok((mut std, _)) = compile_std(&mut map) else {
let Ok(mut std) = compile_std(&mut map) else {
panic!()
};
@ -22,10 +22,7 @@ fn passes_all_passes() {
std.is_main = true;
assert_err(perform_all_passes(
&mut mir::Context {
modules: vec![std],
base: Default::default(),
},
&mut mir::Context::from(vec![std], Default::default()),
&mut map,
));
}