Skip to content

Commit 277bdd5

Browse files
committed
feat(hir, lsp): rewrite to support multiple modules (wip)
1 parent 2388ac7 commit 277bdd5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+4115
-1522
lines changed

crates/hir/Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@ enum-as-inner = "0.3.3"
1111
indexmap = { version = "1.7.0", features = ["serde"] }
1212
itertools = "0.10.1"
1313
rhai-rowan = { path = "../rowan" }
14-
serde = "1"
15-
serde_json = "1"
1614
slotmap = { version = "1.0.6", features = ["serde"] }
1715
static_assertions = "1.1.0"
1816
thiserror = "1.0.30"
1917
tracing = "0.1.29"
2018
strum_macros = "0.22.0"
2119
strsim = "0.10.0"
20+
url = "2.2.2"
21+
salsa = "0.16.1"
2222

2323
[dev-dependencies]
2424
insta = "1.8.0"

crates/hir/benches/create.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ use rhai_rowan::{parser::Parser, syntax::SyntaxNode};
55

66
fn create_hir(syntax: &SyntaxNode) -> Hir {
77
let mut hir = Hir::new();
8-
hir.add_module_from_syntax("bench", syntax);
8+
hir.add_source(&"mem://bench".parse().unwrap(), syntax);
99
hir
1010
}
1111

1212
fn create_hir_full(syntax: &SyntaxNode) -> Hir {
1313
let mut hir = Hir::new();
14-
hir.add_module_from_syntax("bench", syntax);
14+
hir.add_source(&"mem://bench".parse().unwrap(), syntax);
1515
hir.resolve_references();
1616
hir
1717
}

crates/hir/benches/query.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};
2-
use itertools::Itertools;
32
use pprof::criterion::{Output, PProfProfiler};
43
use rhai_hir::{Hir, Module, Symbol};
54
use rhai_rowan::parser::Parser;
@@ -36,7 +35,7 @@ fn bench(c: &mut Criterion) {
3635
let mut hir = Hir::new();
3736

3837
for (name, syntax) in modules {
39-
hir.add_module_from_syntax(&name, &syntax);
38+
hir.add_source(&name, &syntax);
4039
}
4140

4241
const MIN_SYMBOLS: usize = 10;

crates/hir/src/eval.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
use serde::{Deserialize, Serialize};
2-
3-
#[derive(Debug, Clone, Serialize, Deserialize)]
1+
#[derive(Debug, Clone)]
42
pub enum Value {
53
Int(i64),
64
Float(f64),

crates/hir/src/hir.rs

+99-95
Original file line numberDiff line numberDiff line change
@@ -1,145 +1,149 @@
1-
use crate::{scope::ScopeData, symbol::*, HashMap, Module, Scope};
1+
mod add;
2+
pub mod query;
3+
pub mod resolve;
24

35
use core::ops;
6+
7+
use crate::{
8+
module::{ModuleData, ModuleKind},
9+
scope::ScopeData,
10+
source::{Source, SourceData},
11+
symbol::*,
12+
Module, Scope,
13+
};
14+
415
use rhai_rowan::syntax::SyntaxNode;
5-
use serde::{Deserialize, Serialize};
16+
use slotmap::{Key, SlotMap};
17+
use url::Url;
618

7-
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
19+
#[derive(Debug, Default, Clone)]
820
pub struct Hir {
9-
modules: HashMap<String, Module>,
21+
static_module: Module,
22+
modules: SlotMap<Module, ModuleData>,
23+
scopes: SlotMap<Scope, ScopeData>,
24+
symbols: SlotMap<Symbol, SymbolData>,
25+
sources: SlotMap<Source, SourceData>,
1026
}
1127

1228
static_assertions::assert_impl_all!(Hir: Send, Sync);
1329

14-
impl ops::Index<Scope> for Hir {
15-
type Output = ScopeData;
16-
17-
fn index(&self, index: Scope) -> &Self::Output {
18-
for (_, m) in self.modules() {
19-
if m.contains_scope(index) {
20-
return &m[index];
21-
}
22-
}
23-
24-
panic!(
25-
r#"scope "{:?}" does not exist in any of the modules"#,
26-
index
27-
)
30+
impl Hir {
31+
#[must_use]
32+
pub fn new() -> Self {
33+
Self::default()
2834
}
2935
}
3036

31-
impl ops::Index<Symbol> for Hir {
32-
type Output = SymbolData;
37+
impl Hir {
38+
pub fn clear(&mut self) {
39+
self.symbols.clear();
40+
self.scopes.clear();
41+
self.modules.clear();
42+
self.sources.clear();
43+
self.static_module = Module::default();
44+
}
3345

34-
fn index(&self, index: Symbol) -> &Self::Output {
35-
for (_, m) in self.modules() {
36-
if m.contains_symbol(index) {
37-
return &m[index];
38-
}
39-
}
46+
#[must_use]
47+
pub fn symbol(&self, symbol: Symbol) -> Option<&SymbolData> {
48+
self.symbols.get(symbol)
49+
}
4050

41-
panic!(
42-
r#"symbol "{:?}" does not exist in any of the modules"#,
43-
index
44-
)
51+
pub fn symbols(&self) -> impl Iterator<Item = (Symbol, &SymbolData)> {
52+
self.symbols.iter()
4553
}
46-
}
4754

48-
impl Hir {
4955
#[must_use]
50-
pub fn new() -> Self {
51-
Self::default()
56+
pub fn scope(&self, scope: Scope) -> Option<&ScopeData> {
57+
self.scopes.get(scope)
58+
}
59+
60+
pub fn scopes(&self) -> impl Iterator<Item = (Scope, &ScopeData)> {
61+
self.scopes.iter()
5262
}
5363

5464
#[must_use]
55-
pub fn get_module(&self, name: &str) -> Option<&Module> {
56-
self.modules.get(name)
65+
pub fn module(&self, module: Module) -> Option<&ModuleData> {
66+
self.modules.get(module)
5767
}
5868

59-
pub fn modules(&self) -> impl Iterator<Item = (&String, &Module)> {
69+
pub fn modules(&self) -> impl Iterator<Item = (Module, &ModuleData)> {
6070
self.modules.iter()
6171
}
6272

63-
pub fn remove_module(&mut self, name: &str) {
64-
self.modules.remove(name);
65-
// TODO: module references
73+
pub fn sources(&self) -> impl Iterator<Item = (Source, &SourceData)> {
74+
self.sources.iter()
6675
}
6776

6877
#[must_use]
69-
pub fn contains_module(&self, module: &str) -> bool {
70-
self.modules.contains_key(module)
78+
pub fn source_for(&self, url: &Url) -> Option<Source> {
79+
self.sources()
80+
.find_map(|(s, data)| if data.url == *url { Some(s) } else { None })
7181
}
7282

73-
#[must_use]
74-
pub fn module_count(&self) -> usize {
75-
self.modules.len()
83+
fn symbol_mut(&mut self, symbol: Symbol) -> &mut SymbolData {
84+
self.symbols.get_mut(symbol).unwrap()
7685
}
7786

78-
#[must_use]
79-
pub fn contains_scope(&self, scope: Scope) -> bool {
80-
for (_, m) in self.modules() {
81-
if m.contains_scope(scope) {
82-
return true;
83-
}
84-
}
87+
fn scope_mut(&mut self, scope: Scope) -> &mut ScopeData {
88+
self.scopes.get_mut(scope).unwrap()
89+
}
8590

86-
false
91+
#[allow(dead_code)]
92+
fn module_mut(&mut self, module: Module) -> &mut ModuleData {
93+
self.modules.get_mut(module).unwrap()
8794
}
8895

89-
#[must_use]
90-
pub fn scope_count(&self) -> usize {
91-
self.modules()
92-
.fold(0, |count, (_, m)| count + m.scope_count())
96+
fn source_mut(&mut self, source: Source) -> &mut SourceData {
97+
self.sources.get_mut(source).unwrap()
9398
}
9499

95-
#[must_use]
96-
pub fn contains_symbol(&self, symbol: Symbol) -> bool {
97-
for (_, m) in self.modules() {
98-
if m.contains_symbol(symbol) {
99-
return true;
100-
}
101-
}
100+
// pub fn resolve_references(&mut self) {
101+
// for (_, m) in self.modules.iter_mut() {
102+
// m.resolve_references();
103+
// }
104+
// }
102105

103-
false
104-
}
106+
// pub fn resolve_references_in_module(&mut self, name: &str) {
107+
// if let Some(m) = self.modules.get_mut(name) {
108+
// m.resolve_references();
109+
// }
110+
// }
105111

106-
#[must_use]
107-
pub fn symbol_count(&self) -> usize {
108-
self.modules()
109-
.fold(0, |count, (_, m)| count + m.symbol_count())
110-
}
112+
// pub fn infer_types(&mut self) {
113+
// for (_, m) in self.modules.iter_mut() {
114+
// m.infer_types();
115+
// }
116+
// }
111117
}
112118

113-
impl Hir {
114-
pub fn add_module_from_syntax(&mut self, name: &str, syntax: &SyntaxNode) {
115-
self.remove_module(name);
119+
impl ops::Index<Scope> for Hir {
120+
type Output = ScopeData;
116121

117-
if let Some(m) = Module::new_from_syntax(name, syntax) {
118-
self.modules.insert(name.into(), m);
119-
}
122+
fn index(&self, index: Scope) -> &Self::Output {
123+
self.scopes.get(index).unwrap()
120124
}
125+
}
121126

122-
pub fn resolve_references(&mut self) {
123-
for (_, m) in self.modules.iter_mut() {
124-
m.resolve_references();
125-
}
126-
}
127+
impl ops::Index<Symbol> for Hir {
128+
type Output = SymbolData;
127129

128-
pub fn resolve_references_in_module(&mut self, name: &str) {
129-
if let Some(m) = self.modules.get_mut(name) {
130-
m.resolve_references();
131-
}
130+
fn index(&self, index: Symbol) -> &Self::Output {
131+
self.symbols.get(index).unwrap()
132132
}
133+
}
134+
135+
impl ops::Index<Module> for Hir {
136+
type Output = ModuleData;
133137

134-
pub fn infer_types(&mut self) {
135-
for (_, m) in self.modules.iter_mut() {
136-
m.infer_types();
137-
}
138+
fn index(&self, index: Module) -> &Self::Output {
139+
self.modules.get(index).unwrap()
138140
}
141+
}
139142

140-
pub fn infer_types_in_module(&mut self, name: &str) {
141-
if let Some(m) = self.modules.get_mut(name) {
142-
m.infer_types();
143-
}
144-
}
143+
impl ops::Index<Source> for Hir {
144+
type Output = SourceData;
145+
146+
fn index(&self, index: Source) -> &Self::Output {
147+
self.sources.get(index).unwrap()
148+
}
145149
}

crates/hir/src/hir/add.rs

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
mod def;
2+
mod script;
3+
4+
use super::*;
5+
use crate::{module::ModuleKind, scope::ScopeParent, source::SourceKind, Type};
6+
use rhai_rowan::ast::{AstNode, Rhai, RhaiDef};
7+
8+
impl Hir {
9+
pub fn add_source(&mut self, url: &Url, syntax: &SyntaxNode) {
10+
if let Some(def) = Rhai::cast(syntax.clone()) {
11+
let source = self.sources.insert(SourceData {
12+
kind: SourceKind::Def,
13+
url: url.clone(),
14+
module: Module::default(),
15+
});
16+
17+
let m = self.ensure_module(ModuleKind::Dynamic(url.clone()));
18+
self.source_mut(source).module = m;
19+
20+
self.add_script(source, self[m].scope, &def);
21+
}
22+
23+
if let Some(def) = RhaiDef::cast(syntax.clone()) {
24+
let source = self.sources.insert(SourceData {
25+
kind: SourceKind::Def,
26+
url: url.clone(),
27+
module: Module::default(),
28+
});
29+
30+
self.add_def(source, &def);
31+
}
32+
33+
// TODO: error
34+
}
35+
}
36+
37+
impl Hir {
38+
fn ensure_static_module(&mut self) {
39+
if self.static_module.is_null() {
40+
let scope = self.scopes.insert(ScopeData::default());
41+
self.static_module = self.modules.insert(ModuleData {
42+
kind: ModuleKind::Static,
43+
scope,
44+
});
45+
}
46+
}
47+
48+
fn ensure_module(&mut self, kind: ModuleKind) -> Module {
49+
match &kind {
50+
ModuleKind::Static => {
51+
self.ensure_static_module();
52+
self.static_module
53+
}
54+
_ => self
55+
.modules
56+
.iter()
57+
.find_map(|(m, data)| if data.kind == kind { Some(m) } else { None })
58+
.unwrap_or_else(|| {
59+
let scope = self.scopes.insert(ScopeData::default());
60+
self.modules.insert(ModuleData { kind, scope })
61+
}),
62+
}
63+
}
64+
}
65+
66+
impl Scope {
67+
pub(crate) fn add_symbol(self, hir: &mut Hir, symbol: Symbol, hoist: bool) {
68+
let s = hir.scope_mut(self);
69+
debug_assert!(!s.symbols.contains(&symbol));
70+
debug_assert!(!s.hoisted_symbols.contains(&symbol));
71+
72+
if hoist {
73+
s.hoisted_symbols.insert(symbol);
74+
} else {
75+
s.symbols.insert(symbol);
76+
}
77+
78+
let sym_data = hir.symbol_mut(symbol);
79+
80+
debug_assert!(sym_data.parent_scope == Scope::default());
81+
82+
sym_data.parent_scope = self;
83+
84+
tracing::debug!(
85+
symbol_kind = Into::<&'static str>::into(&sym_data.kind),
86+
hoist,
87+
?self,
88+
?symbol,
89+
"added symbol to scope"
90+
);
91+
}
92+
93+
pub(crate) fn set_parent(self, hir: &mut Hir, parent: impl Into<ScopeParent>) {
94+
let s = hir.scope_mut(self);
95+
debug_assert!(s.parent.is_none());
96+
s.parent = Some(parent.into());
97+
}
98+
}

0 commit comments

Comments
 (0)