lang: current state for archival purposes

This commit is contained in:
Schrottkatze 2024-06-23 20:32:10 +02:00
parent 37651a83bc
commit 1c6180aabc
No known key found for this signature in database
10 changed files with 775 additions and 59 deletions

328
Cargo.lock generated
View file

@ -82,6 +82,133 @@ dependencies = [
"yansi", "yansi",
] ]
[[package]]
name = "async-channel"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a"
dependencies = [
"concurrent-queue",
"event-listener-strategy",
"futures-core",
"pin-project-lite",
]
[[package]]
name = "async-executor"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8828ec6e544c02b0d6691d21ed9f9218d0384a82542855073c2a3f58304aaf0"
dependencies = [
"async-task",
"concurrent-queue",
"fastrand",
"futures-lite",
"slab",
]
[[package]]
name = "async-fs"
version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a"
dependencies = [
"async-lock",
"blocking",
"futures-lite",
]
[[package]]
name = "async-io"
version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d6baa8f0178795da0e71bc42c9e5d13261aac7ee549853162e66a241ba17964"
dependencies = [
"async-lock",
"cfg-if",
"concurrent-queue",
"futures-io",
"futures-lite",
"parking",
"polling",
"rustix",
"slab",
"tracing",
"windows-sys 0.52.0",
]
[[package]]
name = "async-lock"
version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18"
dependencies = [
"event-listener",
"event-listener-strategy",
"pin-project-lite",
]
[[package]]
name = "async-net"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b948000fad4873c1c9339d60f2623323a0cfd3816e5181033c6a5cb68b2accf7"
dependencies = [
"async-io",
"blocking",
"futures-lite",
]
[[package]]
name = "async-process"
version = "2.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7eda79bbd84e29c2b308d1dc099d7de8dcc7035e48f4bf5dc4a531a44ff5e2a"
dependencies = [
"async-channel",
"async-io",
"async-lock",
"async-signal",
"async-task",
"blocking",
"cfg-if",
"event-listener",
"futures-lite",
"rustix",
"tracing",
"windows-sys 0.52.0",
]
[[package]]
name = "async-signal"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "794f185324c2f00e771cd9f1ae8b5ac68be2ca7abb129a87afd6e86d228bc54d"
dependencies = [
"async-io",
"async-lock",
"atomic-waker",
"cfg-if",
"futures-core",
"futures-io",
"rustix",
"signal-hook-registry",
"slab",
"windows-sys 0.52.0",
]
[[package]]
name = "async-task"
version = "4.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de"
[[package]]
name = "atomic-waker"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.1.0" version = "1.1.0"
@ -121,6 +248,19 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "blocking"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea"
dependencies = [
"async-channel",
"async-task",
"futures-io",
"futures-lite",
"piper",
]
[[package]] [[package]]
name = "bytemuck" name = "bytemuck"
version = "1.14.0" version = "1.14.0"
@ -191,6 +331,15 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "concurrent-queue"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
dependencies = [
"crossbeam-utils",
]
[[package]] [[package]]
name = "countme" name = "countme"
version = "3.0.1" version = "3.0.1"
@ -366,6 +515,12 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bda8e21c04aca2ae33ffc2fd8c23134f3cac46db123ba97bd9d3f3b8a4a85e1" checksum = "9bda8e21c04aca2ae33ffc2fd8c23134f3cac46db123ba97bd9d3f3b8a4a85e1"
[[package]]
name = "easy-parallel"
version = "3.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2afbb9b0aef60e4f0d2b18129b6c0dff035a6f7dbbd17c2f38c1432102ee223c"
[[package]] [[package]]
name = "ego-tree" name = "ego-tree"
version = "0.6.2" version = "0.6.2"
@ -405,6 +560,16 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "errno"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
dependencies = [
"libc",
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "eval" name = "eval"
version = "0.1.0" version = "0.1.0"
@ -415,6 +580,27 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "event-listener"
version = "5.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba"
dependencies = [
"concurrent-queue",
"parking",
"pin-project-lite",
]
[[package]]
name = "event-listener-strategy"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1"
dependencies = [
"event-listener",
"pin-project-lite",
]
[[package]] [[package]]
name = "exr" name = "exr"
version = "1.71.0" version = "1.71.0"
@ -431,6 +617,12 @@ dependencies = [
"zune-inflate", "zune-inflate",
] ]
[[package]]
name = "fastrand"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a"
[[package]] [[package]]
name = "fdeflate" name = "fdeflate"
version = "0.3.3" version = "0.3.3"
@ -471,6 +663,31 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "futures-core"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
[[package]]
name = "futures-io"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
[[package]]
name = "futures-lite"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5"
dependencies = [
"fastrand",
"futures-core",
"futures-io",
"parking",
"pin-project-lite",
]
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.12" version = "0.2.12"
@ -610,8 +827,10 @@ dependencies = [
"crossbeam", "crossbeam",
"dashmap", "dashmap",
"drop_bomb", "drop_bomb",
"easy-parallel",
"ego-tree", "ego-tree",
"enumset", "enumset",
"futures-lite",
"indexmap", "indexmap",
"indoc", "indoc",
"logos", "logos",
@ -619,6 +838,7 @@ dependencies = [
"owo-colors", "owo-colors",
"petgraph", "petgraph",
"rowan", "rowan",
"smol",
] ]
[[package]] [[package]]
@ -650,6 +870,12 @@ dependencies = [
"redox_syscall 0.4.1", "redox_syscall 0.4.1",
] ]
[[package]]
name = "linux-raw-sys"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
[[package]] [[package]]
name = "lock_api" name = "lock_api"
version = "0.4.11" version = "0.4.11"
@ -788,6 +1014,12 @@ dependencies = [
"supports-color", "supports-color",
] ]
[[package]]
name = "parking"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae"
[[package]] [[package]]
name = "parking_lot_core" name = "parking_lot_core"
version = "0.9.10" version = "0.9.10"
@ -853,6 +1085,23 @@ dependencies = [
"siphasher", "siphasher",
] ]
[[package]]
name = "pin-project-lite"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
[[package]]
name = "piper"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae1d5c74c9876f070d3e8fd503d748c7d974c3e48da8f41350fa5222ef9b4391"
dependencies = [
"atomic-waker",
"fastrand",
"futures-io",
]
[[package]] [[package]]
name = "png" name = "png"
version = "0.17.10" version = "0.17.10"
@ -866,6 +1115,21 @@ dependencies = [
"miniz_oxide", "miniz_oxide",
] ]
[[package]]
name = "polling"
version = "3.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e6a007746f34ed64099e88783b0ae369eaa3da6392868ba262e2af9b8fbaea1"
dependencies = [
"cfg-if",
"concurrent-queue",
"hermit-abi",
"pin-project-lite",
"rustix",
"tracing",
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "powerfmt" name = "powerfmt"
version = "0.2.0" version = "0.2.0"
@ -1010,6 +1274,19 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustix"
version = "0.38.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
dependencies = [
"bitflags 2.4.1",
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.16" version = "1.0.16"
@ -1053,6 +1330,15 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "signal-hook-registry"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "simd-adler32" name = "simd-adler32"
version = "0.3.7" version = "0.3.7"
@ -1065,12 +1351,38 @@ version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
[[package]]
name = "slab"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
"autocfg",
]
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "1.11.2" version = "1.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
[[package]]
name = "smol"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e635339259e51ef85ac7aa29a1cd991b957047507288697a690e80ab97d07cad"
dependencies = [
"async-channel",
"async-executor",
"async-fs",
"async-io",
"async-lock",
"async-net",
"async-process",
"blocking",
"futures-lite",
]
[[package]] [[package]]
name = "spin" name = "spin"
version = "0.9.8" version = "0.9.8"
@ -1174,6 +1486,22 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]]
name = "tracing"
version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
dependencies = [
"pin-project-lite",
"tracing-core",
]
[[package]]
name = "tracing-core"
version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.12" version = "1.0.12"

View file

@ -20,6 +20,9 @@ num_cpus = "1.16"
dashmap = "5.5.3" dashmap = "5.5.3"
crossbeam = "0.8.4" crossbeam = "0.8.4"
owo-colors = {version = "4", features = ["supports-colors"]} owo-colors = {version = "4", features = ["supports-colors"]}
smol = "2"
futures-lite = "2.3"
easy-parallel = "3.3.1"
[lints] [lints]
workspace = true workspace = true

View file

@ -1,4 +1,4 @@
#![feature(type_alias_impl_trait, lint_reasons)] #![feature(type_alias_impl_trait, lint_reasons, box_into_inner)]
use crate::lst_parser::syntax_kind::SyntaxKind; use crate::lst_parser::syntax_kind::SyntaxKind;

View file

@ -209,4 +209,9 @@ impl Output {
pub fn errors(&self) -> Vec<SyntaxError> { pub fn errors(&self) -> Vec<SyntaxError> {
self.errors.clone() self.errors.clone()
} }
pub fn dissolve(self) -> (GreenNode, Vec<SyntaxError>) {
let Self { green_node, errors } = self;
(green_node, errors)
}
} }

View file

@ -1,11 +1,19 @@
use std::{ use std::{
fmt::Display, fmt::Display,
path::{Path, PathBuf}, path::{Path, PathBuf},
sync::{Arc, Mutex},
}; };
use crate::world::world_creation_pool::WorldCreationPool; use crate::world::world_creation_pool::WorldCreationPool;
use self::{files::Files, registry::Registry}; use easy_parallel::Parallel;
use futures_lite::future;
use smol::{
channel::{unbounded, Sender},
Executor,
};
use self::{error::Error, files::Files, registry::Registry};
pub mod error; pub mod error;
pub mod files; pub mod files;

View file

@ -7,50 +7,55 @@ use std::{
use dashmap::DashMap; use dashmap::DashMap;
use rowan::ast::{AstNode, AstPtr}; use rowan::ast::{AstNode, AstPtr};
use crate::lst_parser::{ use crate::{
lst_parser::{
error::SyntaxError, grammar::source_file, input::Input, output::Output, syntax_kind, Parser, error::SyntaxError, grammar::source_file, input::Input, output::Output, syntax_kind, Parser,
},
Lang,
}; };
use super::{error::Error, modules::Module, nodes}; use super::{error::Error, modules::Module, nodes};
pub struct Loc<N: AstNode> { #[derive(Clone)]
pub struct Loc<N: AstNode<Language = Lang>> {
file: FileId, file: FileId,
syntax: AstPtr<N>, syntax: AstPtr<N>,
} }
#[derive(Clone)] impl<N: AstNode<Language = Lang>> Loc<N> {
pub struct Files(Arc<FilesInner>); pub fn new(node: N, file: FileId) -> Self {
Self {
impl Files { file,
pub fn new() -> Self { syntax: AstPtr::new(&node),
Self(Arc::new(FilesInner::new())) }
} }
pub fn add_and_parse(&self, file: &Path) -> Result<(FileId, Vec<Error>), std::io::Error> { pub fn file(&self) -> FileId {
self.0.add_and_parse(file) self.file
} }
pub fn get(&self, id: FileId) -> Arc<SourceFile> { pub fn syntax(&self) -> AstPtr<N> {
self.0.get(id) self.syntax.clone()
} }
} }
/// global file store /// global file store
/// contains all known files etc. /// contains all known files etc.
struct FilesInner { #[derive(Clone)]
paths: Mutex<Vec<PathBuf>>, pub struct Files {
store: DashMap<PathBuf, Arc<SourceFile>>, paths: Arc<Mutex<Vec<PathBuf>>>,
store: Arc<DashMap<PathBuf, Arc<SourceFile>>>,
} }
impl FilesInner { impl Files {
fn new() -> Self { pub fn new() -> Self {
Self { Self {
paths: Mutex::new(Vec::new()), paths: Arc::new(Mutex::new(Vec::new())),
store: DashMap::new(), store: Arc::new(DashMap::new()),
} }
} }
fn add_and_parse(&self, path: &Path) -> Result<(FileId, Vec<Error>), std::io::Error> { pub fn add_and_parse(&self, path: &Path) -> Result<(FileId, Vec<Error>), std::io::Error> {
let (file, errors) = SourceFile::read_and_parse(&path)?; let (file, errors) = SourceFile::read_and_parse(&path)?;
// add file to paths and unlock again // add file to paths and unlock again
@ -73,7 +78,7 @@ impl FilesInner {
)) ))
} }
fn get(&self, id: FileId) -> Arc<SourceFile> { pub fn get(&self, id: FileId) -> Arc<SourceFile> {
let path = { let path = {
let paths = self.paths.lock().unwrap(); let paths = self.paths.lock().unwrap();
paths[id.0].clone() paths[id.0].clone()
@ -81,10 +86,19 @@ impl FilesInner {
self.store.get(&path).unwrap().clone() self.store.get(&path).unwrap().clone()
} }
pub fn get_path(&self, id: FileId) -> PathBuf {
let paths = self.paths.lock().unwrap();
paths[id.0].clone()
}
pub fn path_store(&self) -> Arc<Mutex<Vec<PathBuf>>> {
self.paths.clone()
}
} }
pub struct SourceFile { pub struct SourceFile {
pub lst: Mutex<nodes::Root>, pub lst: RwLock<rowan::GreenNode>,
root_module: Option<Arc<Module>>, root_module: Option<Arc<Module>>,
} }
@ -100,14 +114,15 @@ impl SourceFile {
let events = parser.finish(); let events = parser.finish();
let out = Output::from_parser_output(toks, events); let out = Output::from_parser_output(toks, events);
let lst = out.syntax(); // let lst = out.syntax();
let (lst, errors) = out.dissolve();
Ok(( Ok((
Self { Self {
lst: Mutex::new(nodes::Root::cast(lst).unwrap()), lst: RwLock::new(lst),
root_module: None, root_module: None,
}, },
out.errors(), errors,
)) ))
} }
} }

View file

@ -1,14 +1,18 @@
use std::sync::Arc; use std::{
string::String,
sync::{Arc, Mutex},
};
use dashmap::{DashMap, DashSet}; use dashmap::{DashMap, DashSet};
use rowan::ast::AstNode; use rowan::ast::{AstNode, AstPtr};
use crate::SyntaxNode;
use super::{ use super::{
files::{FileId, Loc}, files::{FileId, Loc},
nodes, nodes,
registry::ItemPath, registry::ItemPath,
world_creation_pool::WorkerCtx, world_creation_pool::{wait_blocker::WaitBlocker, Task, WorkerCtx},
// world_creation_pool::WorkerCtx,
}; };
pub struct Module { pub struct Module {
@ -21,18 +25,151 @@ pub struct Module {
} }
impl Module { impl Module {
pub fn parse_file(ctx: WorkerCtx, file: FileId, decl: Option<Loc<nodes::Mod>>) { pub fn parse_mod_body(
let f = ctx.files.get(file); ctx: &WorkerCtx,
tree: SyntaxNode,
path: ItemPath,
file: FileId,
) -> (DashMap<String, Arc<Mutex<Option<Arc<Module>>>>>, Vec<Task>) {
let children: Vec<(String, Arc<Mutex<Option<Arc<Module>>>>, nodes::Mod)> = tree
.children()
.filter_map(|c| nodes::Mod::cast(c))
.map(|m| {
let name = nodes::ModName::cast(m.syntax().first_child().unwrap())
.expect("ModName should always be first child of Mod");
(
name.syntax().text().to_string(),
Arc::new(Mutex::new(None)),
m,
)
})
.collect();
let retv: DashMap<String, Arc<Mutex<Option<Arc<Module>>>>> = children
.iter()
.map(|(name, mod_r, _)| (name.to_owned(), mod_r.clone()))
.collect();
let tasks = children
.into_iter()
.map(|(name, mod_r, loc)| {
let mut path = path.clone();
path.push(name);
Task::ParseMod(Loc::new(loc, file), mod_r, path)
})
.collect::<Vec<_>>();
let tree = f.lst.lock().unwrap(); (retv, tasks)
}
pub fn parse_file0(
ctx: &mut WorkerCtx,
file: FileId,
path: ItemPath,
decl: Option<Loc<nodes::Mod>>,
) {
let tree = ctx.get_tree(file);
let children = (&*tree).syntax().children(); let (retv, tasks) = Self::parse_mod_body(ctx, tree, path.clone(), file);
ctx.send_tasks(
Task::ParseFileMod1 {
file,
decl,
ret: retv.into(),
path,
},
tasks,
)
}
pub fn parse_mod(
ctx: &mut WorkerCtx,
loc: Loc<nodes::Mod>,
path: ItemPath,
ret: Arc<Mutex<Option<Module>>>,
blocker: WaitBlocker,
) {
let mod_decl = ctx.resolve_loc(loc);
let children = mod_decl.syntax().children().collect::<Vec<_>>();
if children.len() == 1 {
// TODO: file mod
todo!()
} else if children.len() == 2 {
// inline mod
}
}
pub fn parse_inline_mod(
ctx: &mut WorkerCtx,
decl: Loc<nodes::Mod>,
path: ItemPath,
ret: Arc<Mutex<Option<Arc<Module>>>>,
blocker: WaitBlocker,
) {
let mod_decl_children = ctx
.resolve_loc(decl.clone())
.syntax()
.children()
.collect::<Vec<_>>();
assert_eq!(mod_decl_children.len(), 2);
let name = nodes::ModName::cast(mod_decl_children[0].clone()).unwrap();
let body = nodes::ModBody::cast(mod_decl_children[1].clone()).unwrap();
let (retv, tasks) =
Self::parse_mod_body(ctx, body.syntax().clone(), path.clone(), decl.file());
ctx.send_tasks(
Task::CompleteMod {
ret_self: ret,
body: ModuleBody::Inline(Loc::new(body, decl.file())),
decl: Some(decl),
path,
child_mods: retv.into(),
blocker,
},
tasks,
)
}
pub fn complete_mod(
ctx: &mut WorkerCtx,
decl: Option<Loc<nodes::Mod>>,
ret_self: Arc<Mutex<Option<Arc<Module>>>>,
body: ModuleBody,
path: ItemPath,
child_mods: Arc<DashMap<String, Arc<Mutex<Option<Arc<Module>>>>>>,
blocker: WaitBlocker,
) {
assert!(child_mods
.iter()
.all(|item| item.value().lock().unwrap().is_some()));
let module = Arc::new(Module {
decl,
body,
own_path: path,
child_modules: Arc::new(
Arc::<_>::unwrap_or_clone(child_mods)
.into_iter()
.map(|(name, module)| {
let module = module.lock().unwrap().take().unwrap();
(name, module)
})
.collect(),
),
child_defs: Arc::default(),
});
let mut ret_self = ret_self.lock().unwrap();
*ret_self = Some(module);
drop(blocker);
} }
} }
struct Def; struct Def;
enum ModuleBody { pub enum ModuleBody {
InLine(Loc<nodes::ModBody>), Inline(Loc<nodes::ModBody>),
File(FileId), File(FileId),
} }

View file

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

View file

@ -1,14 +1,28 @@
use std::{path::PathBuf, thread}; use std::{
collections::HashMap,
path::PathBuf,
sync::{Arc, Mutex},
thread,
};
use crossbeam::channel::{Receiver, Sender}; use crossbeam::channel::{Receiver, Sender};
use dashmap::DashMap;
use rowan::ast::{AstNode, AstPtr};
use crate::{Lang, SyntaxNode};
use self::wait_blocker::WaitBlocker;
use super::{ use super::{
error::Error, error::Error,
files::{FileId, Files, Loc}, files::{FileId, Files, Loc},
modules::{Module, ModuleBody},
nodes, nodes,
registry::Registry, registry::{ItemPath, Registry},
}; };
pub mod wait_blocker;
pub(super) struct WorldCreationPool { pub(super) struct WorldCreationPool {
workers: Vec<Worker>, workers: Vec<Worker>,
tx: Sender<Job>, tx: Sender<Job>,
@ -24,7 +38,7 @@ impl WorldCreationPool {
i, i,
files.clone(), files.clone(),
reg.clone(), reg.clone(),
JobSender(tx.clone()), tx.clone(),
rx.clone(), rx.clone(),
)) ))
} }
@ -33,12 +47,31 @@ impl WorldCreationPool {
} }
} }
pub struct JobSender(Sender<Job>);
enum Job { enum Job {
ParseFileMod { WaitingFor(WaitBlocker, Task),
Awaited(WaitBlocker, Task),
}
pub enum Task {
ParseMod(Loc<nodes::Mod>, Arc<Mutex<Option<Arc<Module>>>>, ItemPath),
ParseFileMod0 {
file: FileId, file: FileId,
decl: Option<Loc<nodes::Mod>>, decl: Option<Loc<nodes::Mod>>,
path: ItemPath,
},
ParseFileMod1 {
file: FileId,
decl: Option<Loc<nodes::Mod>>,
path: ItemPath,
ret: Arc<DashMap<String, Arc<Mutex<Option<Arc<Module>>>>>>,
},
CompleteMod {
ret_self: Arc<Mutex<Option<Arc<Module>>>>,
decl: Option<Loc<nodes::Mod>>,
body: ModuleBody,
path: ItemPath,
child_mods: Arc<DashMap<String, Arc<Mutex<Option<Arc<Module>>>>>>,
blocker: WaitBlocker,
}, },
OpenFile(PathBuf), OpenFile(PathBuf),
} }
@ -51,26 +84,104 @@ struct Worker {
pub struct WorkerCtx { pub struct WorkerCtx {
errors: Vec<Error>, errors: Vec<Error>,
pub files: Files, files: Files,
local_files: HashMap<PathBuf, SyntaxNode>,
pub reg: Registry, pub reg: Registry,
pub tx: JobSender, tx: Sender<Job>,
}
impl WorkerCtx {
pub fn get_tree(&mut self, id: FileId) -> SyntaxNode {
let p = self.files.get_path(id);
if self.local_files.contains_key(&p) {
self.local_files[&p].clone()
} else {
let f = self.files.get(id);
let lst = SyntaxNode::new_root(f.lst.read().unwrap().clone());
self.local_files.insert(p, lst.clone());
lst
}
}
pub fn resolve_loc<N: AstNode<Language = Lang>>(&mut self, loc: Loc<N>) -> N {
let f = self.get_tree(loc.file());
loc.syntax().to_node(&f)
}
pub fn send_tasks(&self, task: Task, dependencies: Vec<Task>) {
let blocker = WaitBlocker::new();
for dep_task in dependencies {
self.tx
.send(Job::Awaited(blocker.clone(), dep_task))
.unwrap();
}
self.tx.send(Job::WaitingFor(blocker, task)).unwrap();
}
} }
impl Worker { impl Worker {
fn new(id: usize, files: Files, reg: Registry, sender: JobSender, rx: Receiver<Job>) -> Self { fn new(id: usize, files: Files, reg: Registry, sender: Sender<Job>, rx: Receiver<Job>) -> Self {
let thread_handle = thread::spawn(move || {
let ctx = WorkerCtx { let ctx = WorkerCtx {
errors: Vec::new(), errors: Vec::new(),
local_files: HashMap::new(),
files, files,
reg, reg,
tx: sender, tx: sender,
}; };
let thread_handle = thread::spawn(move || { for job in &rx {
for msg in rx { // if matches!(job, Job::WithCond(_, _)) {
match msg {
Job::ParseFileMod { file, decl } => todo!(), // }
Job::OpenFile(path) => todo!(), match job {
Job::WaitingFor(blocker, task) => {
if blocker.is_ready() {
Self::do_task(&ctx, task, None)
} else if rx.is_empty() {
if let Some(blocker) =
blocker.wait_for(std::time::Duration::from_millis(50))
{
ctx.tx.send(Job::WaitingFor(blocker, task)).unwrap();
} else {
Self::do_task(&ctx, task, None)
} }
} else {
ctx.tx.send(Job::WaitingFor(blocker, task)).unwrap();
}
}
Job::Awaited(blocker, task) => {
Self::do_task(&ctx, task, Some(blocker.clone()));
drop(blocker)
}
}
// if let Job::WithCond(blocker, job_inner) = job_msg {
// if blocker.is_ready() {
// job = Box::<Job>::into_inner(job_inner);
// } else if rx.is_empty() {
// if let Some(blocker) =
// blocker.wait_for(std::time::Duration::from_millis(50))
// {
// job = Job::WithCond(blocker, job_inner);
// } else {
// job = Box::<Job>::into_inner(job_inner);
// }
// } else {
// job = Job::WithCond(blocker, job_inner);
// }
// } else {
// job = job_msg;
// }
// match job {
// Job::ParseFileMod { file, decl } => todo!(),
// Job::OpenFile(path) => todo!(),
// Job::WithCond(blocker, job) => {
// ctx.tx.send(Job::WithCond(blocker, job)).unwrap()
// }
// }
} }
}); });
@ -79,4 +190,26 @@ impl Worker {
thread: thread_handle, thread: thread_handle,
} }
} }
fn do_task(ctx: &WorkerCtx, task: Task, blocker: Option<WaitBlocker>) {
match task {
Task::ParseMod(_, _, _) => todo!(),
Task::ParseFileMod0 { file, decl, path } => todo!(),
Task::ParseFileMod1 {
file,
decl,
path,
ret,
} => todo!(),
Task::CompleteMod {
ret_self,
decl,
body,
path,
child_mods,
blocker,
} => todo!(),
Task::OpenFile(_) => todo!(),
}
}
} }

View file

@ -0,0 +1,87 @@
use std::{
sync::{Arc, Condvar, Mutex},
time::Duration,
};
/// like a WaitGroup from crossbeam, but can also just check if it's the last one
pub struct WaitBlocker {
inner: Arc<Inner>,
}
struct Inner {
waiting: Mutex<usize>,
cvar: Condvar,
}
impl WaitBlocker {
pub fn new() -> Self {
Self {
inner: Arc::new(Inner {
waiting: Mutex::new(1),
cvar: Condvar::new(),
}),
}
}
pub fn wait(self) {
if *self.inner.waiting.lock().unwrap() == 1 {
return;
}
let inner = self.inner.clone();
drop(self);
inner
.cvar
.wait_while(inner.waiting.lock().unwrap(), |w| *w > 0);
}
pub fn wait_for(self, dur: Duration) -> Option<Self> {
if *self.inner.waiting.lock().unwrap() == 1 {
return None;
}
let inner = self.inner.clone();
drop(self);
let (_, timeout_res) = inner
.cvar
.wait_timeout_while(inner.waiting.lock().unwrap(), dur, |w| *w > 0)
.unwrap();
if timeout_res.timed_out() {
None
} else {
{
let mut w = inner.waiting.lock().unwrap();
*w += 1;
}
Some(Self { inner })
}
}
pub fn is_ready(&self) -> bool {
*self.inner.waiting.lock().unwrap() == 1
}
}
impl Clone for WaitBlocker {
fn clone(&self) -> Self {
let mut w = self.inner.waiting.lock().unwrap();
*w += 1;
drop(w);
Self {
inner: self.inner.clone(),
}
}
}
impl Drop for WaitBlocker {
fn drop(&mut self) {
let mut w = self.inner.waiting.lock().unwrap();
*w -= 1;
if *w == 0 {
self.inner.cvar.notify_all()
}
}
}