forked from katzen-cafe/iowo
lang: module resolvin
This commit is contained in:
parent
d6bc644fb6
commit
7bc603f7e7
5 changed files with 148 additions and 156 deletions
8
Cargo.lock
generated
8
Cargo.lock
generated
|
@ -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",
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
path: old_path,
|
||||
name,
|
||||
kind: ModuleKind::File {
|
||||
declaration: decl,
|
||||
file_id: mod_file_path,
|
||||
},
|
||||
children,
|
||||
parent: None,
|
||||
ctx.files
|
||||
.borrow_mut()
|
||||
.insert(ctx.cur_file.clone(), source_file);
|
||||
|
||||
Ok(Self {
|
||||
path: old_path,
|
||||
name,
|
||||
kind: ModuleKind::File {
|
||||
declaration: decl,
|
||||
file_id: ctx.cur_file.clone(),
|
||||
},
|
||||
files,
|
||||
errors,
|
||||
))
|
||||
children,
|
||||
parent: None,
|
||||
})
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
(
|
||||
Self {
|
||||
name: name.syntax().text().to_string(),
|
||||
kind: ModuleKind::Inline(Loc::new(cur_file.to_owned(), &module)),
|
||||
children,
|
||||
parent: None,
|
||||
path: old_path,
|
||||
},
|
||||
files,
|
||||
errors,
|
||||
)
|
||||
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,
|
||||
kind: ModuleKind::Inline(Loc::new(ctx.cur_file.to_owned(), &module)),
|
||||
children,
|
||||
parent: None,
|
||||
path: old_path,
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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(),
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue