lang: module resolvin

This commit is contained in:
Schrottkatze 2024-06-05 21:10:52 +02:00
parent d6bc644fb6
commit 7bc603f7e7
No known key found for this signature in database
5 changed files with 148 additions and 156 deletions

8
Cargo.lock generated
View file

@ -850,9 +850,9 @@ checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
[[package]]
name = "rayon"
version = "1.8.0"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1"
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
dependencies = [
"either",
"rayon-core",
@ -860,9 +860,9 @@ dependencies = [
[[package]]
name = "rayon-core"
version = "1.12.0"
version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed"
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",

View file

@ -1,10 +1,10 @@
use std::{collections::HashMap, path::PathBuf, sync::Arc};
use std::{collections::HashMap, path::PathBuf};
use rowan::ast::{AstNode, AstPtr};
use self::{
error::{Error, WorldCreationError},
mod_tree::{Module, ModuleTree},
mod_tree::ModuleTree,
source_file::SourceFile,
};
@ -42,7 +42,7 @@ impl World {
Err(e) => return Err(WorldCreationError::FailedToOpenEntryPoint(entry_point, e)),
};
let (src, mut errors) = SourceFile::parse_from(entry_point.clone(), source);
let (src, mut errors) = SourceFile::parse_from(&entry_point, source);
let (module_tree, mut files, new_errors) = ModuleTree::parse_from_main(&entry_point, &src);
errors.extend(new_errors);

View file

@ -1,10 +1,12 @@
use std::{
collections::{HashMap, HashSet},
path::PathBuf,
cell::RefCell,
collections::HashMap,
path::{Path, PathBuf},
rc::Rc,
sync::Arc,
};
use rowan::ast::{AstNode, AstPtr};
use rowan::ast::AstNode;
use crate::{lst_parser::syntax_kind::SyntaxKind, SyntaxNode};
@ -16,7 +18,80 @@ use super::{
};
pub struct ModuleTree {
modules: HashMap<String, Arc<Module>>,
modules: Rc<HashMap<String, Module>>,
}
#[derive(Clone)]
struct ModuleParsingContext {
files: Rc<RefCell<HashMap<PathBuf, SourceFile>>>,
errors: Rc<RefCell<Vec<Error>>>,
proj_dir: Rc<PathBuf>,
cur_path: Vec<String>,
cur_file: PathBuf,
}
impl ModuleParsingContext {
fn new(entry_path: &Path) -> Self {
let proj_dir = entry_path.parent().unwrap().to_owned();
Self {
files: Rc::new(RefCell::new(HashMap::new())),
errors: Rc::new(RefCell::new(Vec::new())),
proj_dir: Rc::new(entry_path.to_owned()),
cur_path: Vec::new(),
cur_file: entry_path.to_owned(),
}
}
fn entry_path(&self) -> PathBuf {
self.proj_dir.to_path_buf()
}
fn make_mod_file_path(&self, mod_path: &[String], mod_name: &str) -> PathBuf {
let mut entry_path = self.entry_path();
for el in mod_path {
entry_path.push(format!("{el}/"));
}
entry_path.push(format!("{mod_name}.owo"));
entry_path
}
fn push_cur_path(&mut self, name_to_add: String) {
self.cur_path.push(name_to_add);
}
fn set_cur_file(&mut self, new: PathBuf) {
self.cur_file = new;
}
fn push_errs(&self, errs: Vec<Error>) {
self.errors.borrow_mut().extend(errs);
}
fn parse_child_modules(
&self,
node: &SyntaxNode,
name: Option<String>,
) -> HashMap<String, Module> {
let mut ctx = self.clone();
if let Some(name) = name {
ctx.push_cur_path(name)
}
node.children()
.filter_map(Mod::cast)
.filter_map(|m| match Module::parse_mod(m, self.clone()) {
Ok(module) => Some((module.name(), module)),
Err(error) => {
self.errors.borrow_mut().push(error);
None
}
})
.collect::<HashMap<String, Module>>()
}
fn dissolve(self) -> (HashMap<PathBuf, SourceFile>, Vec<Error>) {
let Self { files, errors, .. } = self;
(files.take(), errors.take())
}
}
impl ModuleTree {
@ -24,37 +99,18 @@ impl ModuleTree {
path: &PathBuf,
main_file: &SourceFile,
) -> (Self, HashMap<PathBuf, SourceFile>, Vec<Error>) {
let tree = main_file.tree();
let mut files = HashMap::new();
let mut errors = Vec::new();
let entry_path = path.parent().unwrap().to_owned();
let modules = main_file
.top_level_modules()
.into_iter()
.filter_map(|m| {
let module =
Module::parse_mod(m.to_node(tree.syntax()), Vec::new(), &path, &entry_path);
match module {
Ok(module) => {
files.extend(module.1);
errors.extend(module.2);
Some((module.0.name(), Arc::new(module.0)))
}
Err(err) => {
errors.push(err);
None
}
}
})
.collect::<HashMap<String, Arc<Module>>>();
let ctx = ModuleParsingContext::new(&entry_path);
let modules = Rc::new(ctx.parse_child_modules(main_file.tree().syntax(), None));
let (files, errors) = ctx.dissolve();
(Self { modules }, files, errors)
}
pub fn print_tree(&self, lst: &Root) {
let name = "main";
print_tree(&name, &self.modules, 0)
print_tree(&name, self.modules.clone(), 0)
}
}
@ -62,19 +118,12 @@ pub struct Module {
path: Vec<String>,
name: String,
kind: ModuleKind,
children: HashMap<String, Arc<Module>>,
children: Rc<HashMap<String, Module>>,
parent: Option<Arc<Module>>,
}
impl Module {
fn parse_mod(
module: Mod,
cur_path: Vec<String>,
cur_file: &PathBuf,
entry_path: &PathBuf,
) -> Result<(Self, HashMap<PathBuf, SourceFile>, Vec<Error>), Error> {
dbg!(cur_file);
dbg!(entry_path);
fn parse_mod(module: Mod, ctx: ModuleParsingContext) -> Result<Self, Error> {
let children = module
.syntax()
.children()
@ -86,138 +135,77 @@ impl Module {
assert_eq!(name.kind(), SyntaxKind::MODULE_NAME);
return Self::parse_file_mod(
name.text().to_string(),
Loc::new(cur_file.clone(), &module),
cur_path,
entry_path,
ctx.clone(),
Loc::new(ctx.cur_file.clone(), &module),
);
} else if children.len() == 2 {
let name = &children[0];
assert_eq!(name.kind(), SyntaxKind::MODULE_NAME);
let body = &children[1];
assert_eq!(body.kind(), SyntaxKind::MODULE_BODY);
return Ok(Self::parse_inline_mod(
module, cur_path, cur_file, entry_path,
));
return Ok(Self::parse_inline_mod(module, ctx.clone()));
}
todo!()
}
fn parse_file_mod(
name: String,
mut ctx: ModuleParsingContext,
decl: Loc<Mod>,
mut cur_path: Vec<String>,
entry_path: &PathBuf,
) -> Result<(Self, HashMap<PathBuf, SourceFile>, Vec<Error>), Error> {
let mut mod_file_path = entry_path.to_owned();
) -> Result<Self, Error> {
ctx.set_cur_file(ctx.make_mod_file_path(&ctx.cur_path, &name));
for el in &cur_path {
mod_file_path.push(format!("{el}/"));
}
mod_file_path.push(format!("{name}.owo"));
let mut files = HashMap::new();
let mut errors = Vec::new();
let source = match std::fs::read_to_string(dbg!(&mod_file_path)) {
let source = match std::fs::read_to_string(&ctx.cur_file) {
Ok(f) => f,
Err(e) => return Err(Error::FailedToOpenFileMod(mod_file_path, e)),
Err(e) => return Err(Error::FailedToOpenFileMod(ctx.cur_file, e)),
};
let (source_file, file_errors) = SourceFile::parse_from(mod_file_path.clone(), source);
errors.extend(file_errors);
let (source_file, file_errors) = SourceFile::parse_from(&ctx.cur_file, source);
let tree = source_file.tree();
let old_path = cur_path.clone();
cur_path.push(name.clone());
let children = source_file
.top_level_modules()
.into_iter()
.filter_map(|m| {
let module = Module::parse_mod(
m.to_node(tree.syntax()),
cur_path.clone(),
&mod_file_path,
&entry_path,
);
match module {
Ok(module) => {
files.extend(module.1);
errors.extend(module.2);
Some((module.0.name(), Arc::new(module.0)))
}
Err(err) => {
errors.push(err);
None
}
}
})
.collect::<HashMap<String, Arc<Module>>>();
let old_path = ctx.cur_path.clone();
ctx.push_cur_path(name.clone());
ctx.push_errs(file_errors);
files.insert(mod_file_path.clone(), source_file);
let children =
Rc::new(ctx.parse_child_modules(source_file.tree().syntax(), Some(name.clone())));
Ok((
Self {
ctx.files
.borrow_mut()
.insert(ctx.cur_file.clone(), source_file);
Ok(Self {
path: old_path,
name,
kind: ModuleKind::File {
declaration: decl,
file_id: mod_file_path,
file_id: ctx.cur_file.clone(),
},
children,
parent: None,
},
files,
errors,
))
})
}
fn parse_inline_mod(
module: Mod,
mut cur_path: Vec<String>,
cur_file: &PathBuf,
entry_path: &PathBuf,
) -> (Self, HashMap<PathBuf, SourceFile>, Vec<Error>) {
fn parse_inline_mod(module: Mod, mut ctx: ModuleParsingContext) -> Self {
let mut children = module.syntax().children().collect::<Vec<_>>();
let body = ModBody::cast(children.pop().unwrap()).unwrap();
let name = ModName::cast(children.pop().unwrap()).unwrap();
let mut files = HashMap::new();
let mut errors = Vec::new();
let old_path = cur_path.clone();
cur_path.push(name.syntax().to_string());
let children = body
let name = ModName::cast(children.pop().unwrap())
.unwrap()
.syntax()
.children()
.filter_map(|node| Mod::cast(node))
.filter_map(|m| {
let m = Self::parse_mod(m, cur_path.clone(), cur_file, entry_path);
match m {
Ok(module) => {
files.extend(module.1);
errors.extend(module.2);
Some((module.0.name(), Arc::new(module.0)))
}
Err(err) => {
errors.push(err);
None
}
}
})
.collect::<HashMap<String, Arc<Module>>>();
.text()
.to_string();
let old_path = ctx.cur_path.clone();
ctx.push_cur_path(name.clone());
let children = Rc::new(ctx.parse_child_modules(body.syntax(), Some(name.clone())));
(
Self {
name: name.syntax().text().to_string(),
kind: ModuleKind::Inline(Loc::new(cur_file.to_owned(), &module)),
name,
kind: ModuleKind::Inline(Loc::new(ctx.cur_file.to_owned(), &module)),
children,
parent: None,
path: old_path,
},
files,
errors,
)
}
}
pub fn name(&self) -> String {
@ -226,7 +214,7 @@ impl Module {
}
}
fn print_tree(name: &str, children: &HashMap<String, Arc<Module>>, level: u32) {
fn print_tree(name: &str, children: Rc<HashMap<String, Module>>, level: u32) {
const INDENT_STR: &str = " ";
for _ in 0..level {
@ -234,9 +222,12 @@ fn print_tree(name: &str, children: &HashMap<String, Arc<Module>>, level: u32) {
}
print!("{name}\n");
for (name, module) in children {
print_tree(name, &module.children, level + 1);
}
// for (name, module) in children.iter() {
// ;
// }
children
.iter()
.for_each(|(name, m)| print_tree(name, m.children.clone(), level + 1))
}
enum ModuleKind {

View file

@ -4,7 +4,7 @@ use rowan::Language;
macro_rules! ast_nodes {
($($ast:ident, $kind:ident);+) => {
$(
#[derive(PartialEq, Eq, Hash)]
#[derive(Debug, PartialEq, Eq, Hash)]
#[repr(transparent)]
pub struct $ast(SyntaxNode);
impl rowan::ast::AstNode for $ast {

View file

@ -1,4 +1,4 @@
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use rowan::ast::{AstNode, AstPtr};
@ -15,6 +15,7 @@ use super::{
nodes::{Def, Mod, Root, Use},
};
#[derive(Debug)]
pub struct SourceFile {
lst: Root,
modules: Vec<AstPtr<Mod>>,
@ -23,7 +24,7 @@ pub struct SourceFile {
}
impl SourceFile {
pub fn parse_from(path: PathBuf, source_text: String) -> (Self, Vec<Error>) {
pub fn parse_from(path: &Path, source_text: String) -> (Self, Vec<Error>) {
let toks = syntax_kind::lex(&source_text);
let input = Input::new(&toks);
let mut parser = Parser::new(input);
@ -57,7 +58,7 @@ impl SourceFile {
},
out.errors()
.into_iter()
.map(|err| Error::from_syntax(path.clone(), err))
.map(|err| Error::from_syntax(path.to_owned(), err))
.collect(),
)
}