Skip to content

Commit 14e8f1d

Browse files
MarwesMarkus Westerlind
authored andcommitted
feat: Make the query code compatible with the language server
1 parent fedb732 commit 14e8f1d

File tree

2 files changed

+181
-58
lines changed

2 files changed

+181
-58
lines changed

src/import.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ pub struct Import<I = DefaultImporter> {
234234
pub paths: RwLock<Vec<PathBuf>>,
235235
pub importer: I,
236236

237-
compiler: Mutex<CompilerDatabase>,
237+
pub compiler: Mutex<CompilerDatabase>,
238238
}
239239

240240
#[derive(Debug)]

src/query.rs

Lines changed: 180 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,19 @@ impl crate::query::CompilationBase for CompilerDatabase {
208208
.peek(&(key.into(), None))
209209
.and_then(|r| r.ok())
210210
}
211+
212+
fn peek_module_type(&self, key: &str) -> Option<ArcType> {
213+
self.query(ModuleTypeQuery)
214+
.peek(&(key.into(), None))
215+
.and_then(|r| r.ok())
216+
}
217+
218+
fn peek_module_metadata(&self, key: &str) -> Option<Arc<Metadata>> {
219+
self.query(ModuleMetadataQuery)
220+
.peek(&(key.into(), None))
221+
.and_then(|r| r.ok())
222+
}
223+
211224
fn peek_core_expr(&self, key: &str) -> Option<interpreter::Global<CoreExpr>> {
212225
self.query(CoreExprQuery)
213226
.peek(&(key.into(), None))
@@ -326,6 +339,8 @@ pub trait CompilationBase: Send {
326339
fn add_module(&mut self, module: String, contents: &str);
327340

328341
fn peek_typechecked_module(&self, key: &str) -> Option<TypecheckValue<Arc<OwnedExpr<Symbol>>>>;
342+
fn peek_module_type(&self, key: &str) -> Option<ArcType>;
343+
fn peek_module_metadata(&self, key: &str) -> Option<Arc<Metadata>>;
329344
fn peek_core_expr(&self, key: &str) -> Option<interpreter::Global<CoreExpr>>;
330345
fn peek_global(&self, key: &str) -> Option<DatabaseGlobal>;
331346
}
@@ -362,6 +377,18 @@ pub trait Compilation: CompilationBase {
362377
(Option<TypecheckValue<Arc<OwnedExpr<Symbol>>>>, Error),
363378
>;
364379

380+
async fn module_type(
381+
&self,
382+
module: String,
383+
expected_type: Option<ArcType>,
384+
) -> StdResult<ArcType, Error>;
385+
386+
async fn module_metadata(
387+
&self,
388+
module: String,
389+
expected_type: Option<ArcType>,
390+
) -> StdResult<Arc<Metadata>, Error>;
391+
365392
#[salsa::cycle(recover_cycle_expected_type)]
366393
async fn core_expr(
367394
&self,
@@ -497,6 +524,36 @@ async fn typechecked_module(
497524
Ok(value.map(Arc::new))
498525
}
499526

527+
async fn module_type(
528+
db: &mut (impl Compilation + salsa::Database),
529+
name: String,
530+
expected_type: Option<ArcType>,
531+
) -> StdResult<ArcType, Error> {
532+
if db.compiler().query(ExternLoaderQuery).peek(&name).is_some() {
533+
let (_id, module) = &*db.extern_module(name).await?;
534+
return Ok(module.typ.clone());
535+
}
536+
db.typechecked_module(name, expected_type)
537+
.await
538+
.map(|module| module.typ)
539+
.map_err(|(_, err)| err)
540+
}
541+
542+
async fn module_metadata(
543+
db: &mut (impl Compilation + salsa::Database),
544+
name: String,
545+
expected_type: Option<ArcType>,
546+
) -> StdResult<Arc<Metadata>, Error> {
547+
if db.compiler().query(ExternLoaderQuery).peek(&name).is_some() {
548+
let (_id, module) = &*db.extern_module(name.clone()).await?;
549+
return Ok(Arc::new(module.metadata.clone()));
550+
}
551+
db.typechecked_module(name, expected_type)
552+
.await
553+
.map(|module| module.metadata)
554+
.map_err(|(_, err)| err)
555+
}
556+
500557
async fn core_expr(
501558
db: &mut (impl Compilation + salsa::Database),
502559
module: String,
@@ -505,9 +562,15 @@ async fn core_expr(
505562
db.salsa_runtime_mut().report_untracked_read();
506563

507564
let value = db
508-
.typechecked_module(module.clone(), expected_type)
565+
.typechecked_module(module.clone(), expected_type.clone())
509566
.await
510567
.map_err(|(_, err)| err)?;
568+
569+
// Ensure the type is stored in the database so we can collect typechecked_module later
570+
db.module_type(module.clone(), expected_type.clone())
571+
.await?;
572+
db.module_metadata(module.clone(), expected_type).await?;
573+
511574
let settings = db.compiler_settings();
512575

513576
let env = env(db.compiler());
@@ -612,6 +675,11 @@ async fn global_inner(db: &mut dyn Compilation, name: String) -> Result<Unrooted
612675
.typechecked_module(name.clone(), None)
613676
.await
614677
.map_err(|(_, err)| err)?;
678+
679+
// Ensure the type is stored in the database so we can collect typechecked_module later
680+
db.module_type(name.clone(), None).await?;
681+
db.module_metadata(name.clone(), None).await?;
682+
615683
let closure = db.compiled_module(name.clone(), None).await?;
616684

617685
let module_id = closure.function.name.clone();
@@ -745,7 +813,15 @@ where
745813

746814
fn find_type(&self, id: &SymbolRef) -> Option<ArcType> {
747815
if id.is_global() {
748-
self.get_global(id.definition_name()).map(|g| g.typ.clone())
816+
self.0
817+
.borrow_mut()
818+
.get_binding_inner(id.definition_name(), |self_, module| {
819+
self_
820+
.get_extern_global(module.as_str())
821+
.map(|global| global.typ)
822+
.or_else(|| self_.peek_module_type(module.as_str().into()))
823+
})
824+
.ok()
749825
} else {
750826
let name = id.definition_name();
751827

@@ -831,10 +907,81 @@ where
831907
}
832908
}
833909

910+
fn get_scoped_global<'n, T>(
911+
name: &'n str,
912+
mut lookup: impl FnMut(&Name) -> Option<T>,
913+
) -> Option<(&'n Name, T)> {
914+
let mut module = Name::new(name.trim_start_matches('@'));
915+
// Try to find a global by successively reducing the module path
916+
// Input: "x.y.z.w"
917+
// Test: "x.y.z"
918+
// Test: "x.y"
919+
// Test: "x"
920+
// Test: -> Error
921+
let global = loop {
922+
if module.as_str() == "" {
923+
return None;
924+
}
925+
if let Some(g) = lookup(module) {
926+
break g;
927+
}
928+
module = module.module();
929+
};
930+
let remaining_offset = ::std::cmp::min(name.len(), module.as_str().len() + 1); //Add 1 byte for the '.'
931+
let remaining_fields = Name::new(&name[remaining_offset..]);
932+
Some((remaining_fields, global))
933+
}
934+
935+
use crate::base::resolve;
936+
trait Extract: Sized {
937+
// type Output;
938+
fn extract(&self, db: &mut CompilerDatabase, field_name: &str) -> Option<Self>;
939+
fn typ(&self) -> &ArcType;
940+
// fn output(&self) -> Self::Output;
941+
}
942+
943+
impl Extract for ArcType {
944+
fn extract(&self, db: &mut CompilerDatabase, field_name: &str) -> Option<Self> {
945+
let typ = resolve::remove_aliases_cow(&env(db), &mut NullInterner, self);
946+
typ.row_iter()
947+
.find(|field| field.name.as_ref() == field_name)
948+
.map(|field| field.typ.clone())
949+
}
950+
fn typ(&self) -> &ArcType {
951+
self
952+
}
953+
}
954+
impl Extract for (RootedValue<RootedThread>, ArcType) {
955+
fn extract(&self, db: &mut CompilerDatabase, field_name: &str) -> Option<Self> {
956+
let (value, typ) = self;
957+
let typ = resolve::remove_aliases_cow(&env(db), &mut NullInterner, typ);
958+
typ.row_iter()
959+
.enumerate()
960+
.find(|&(_, field)| field.name.as_ref() == field_name)
961+
.map(|(index, field)| match value.get_variants().as_ref() {
962+
ValueRef::Data(data) => (
963+
db.thread().root_value(data.get_variant(index).unwrap()),
964+
field.typ.clone(),
965+
),
966+
_ => ice!("Unexpected value {:?}", value),
967+
})
968+
}
969+
fn typ(&self) -> &ArcType {
970+
&self.1
971+
}
972+
}
973+
834974
impl CompilerDatabase {
835975
pub fn find_type_info(&mut self, name: &str) -> Result<Alias<Symbol, ArcType>> {
836976
let name = Name::new(name);
837-
let (_, typ) = self.get_binding(name.module().as_str())?;
977+
978+
let typ = self.get_binding_inner(name.module().as_str(), |self_, module| {
979+
self_
980+
.get_extern_global(module.as_str())
981+
.map(|global| global.typ)
982+
.or_else(|| self_.peek_module_type(module.as_str().into()))
983+
})?;
984+
838985
let maybe_type_info = {
839986
let field_name = name.name();
840987
typ.type_field_iter()
@@ -846,49 +993,31 @@ impl CompilerDatabase {
846993
.ok_or_else(move || vm::Error::UndefinedField(typ, name.name().as_str().into()).into())
847994
}
848995

849-
fn get_scoped_global<'s, 'n>(
850-
&'s mut self,
851-
name: &'n str,
852-
) -> Option<(&'n Name, DatabaseGlobal)> {
853-
let mut module = Name::new(name.trim_start_matches('@'));
854-
// Try to find a global by successively reducing the module path
855-
// Input: "x.y.z.w"
856-
// Test: "x.y.z"
857-
// Test: "x.y"
858-
// Test: "x"
859-
// Test: -> Error
860-
let global = loop {
861-
if module.as_str() == "" {
862-
return None;
863-
}
864-
if let Some(g) = self
865-
.get_extern_global(name)
866-
.or_else(|| self.peek_global(module.as_str().into()))
867-
{
868-
break g;
869-
}
870-
module = module.module();
871-
};
872-
let remaining_offset = ::std::cmp::min(name.len(), module.as_str().len() + 1); //Add 1 byte for the '.'
873-
let remaining_fields = Name::new(&name[remaining_offset..]);
874-
Some((remaining_fields, global))
875-
}
876-
877996
pub fn get_binding(&mut self, name: &str) -> Result<(RootedValue<RootedThread>, ArcType)> {
878-
use crate::base::resolve;
997+
self.get_binding_inner(name, |self_, module| {
998+
self_
999+
.get_extern_global(module.as_str())
1000+
.or_else(|| self_.peek_global(module.as_str().into()))
1001+
.map(|global| (global.value, global.typ))
1002+
})
1003+
}
8791004

880-
let (remaining_fields, global) = self
881-
.get_scoped_global(name)
1005+
fn get_binding_inner<T>(
1006+
&mut self,
1007+
name: &str,
1008+
mut lookup: impl FnMut(&mut Self, &Name) -> Option<T>,
1009+
) -> Result<T>
1010+
where
1011+
T: Extract,
1012+
{
1013+
let (remaining_fields, mut value) = get_scoped_global(name, |n| lookup(self, n))
8821014
.ok_or_else(|| vm::Error::UndefinedBinding(name.into()))?;
8831015

8841016
if remaining_fields.as_str().is_empty() {
8851017
// No fields left
886-
return Ok((global.value, global.typ.clone()));
1018+
return Ok(value);
8871019
}
8881020

889-
let mut typ = global.typ;
890-
let mut value = global.value.get_variant();
891-
8921021
for mut field_name in remaining_fields.components() {
8931022
if field_name.starts_with('(') && field_name.ends_with(')') {
8941023
field_name = &field_name[1..field_name.len() - 1];
@@ -902,24 +1031,13 @@ impl CompilerDatabase {
9021031
))
9031032
.into());
9041033
}
905-
typ = resolve::remove_aliases(&env(self), &mut NullInterner, typ);
906-
let next_type = {
907-
typ.row_iter()
908-
.enumerate()
909-
.find(|&(_, field)| field.name.as_ref() == field_name)
910-
.map(|(index, field)| match value.as_ref() {
911-
ValueRef::Data(data) => {
912-
value = data.get_variant(index).unwrap();
913-
&field.typ
914-
}
915-
_ => ice!("Unexpected value {:?}", value),
916-
})
917-
.cloned()
918-
};
919-
typ =
920-
next_type.ok_or_else(move || vm::Error::UndefinedField(typ, field_name.into()))?;
1034+
1035+
value = value.extract(self, field_name).ok_or_else(move || {
1036+
vm::Error::UndefinedField(value.typ().clone(), field_name.into())
1037+
})?;
9211038
}
922-
Ok((self.thread().root_value(value), typ))
1039+
1040+
Ok(value)
9231041
}
9241042

9251043
pub fn get_metadata(&mut self, name_str: &str) -> Result<Arc<Metadata>> {
@@ -928,9 +1046,14 @@ impl CompilerDatabase {
9281046
}
9291047

9301048
fn get_metadata_(&mut self, name_str: &str) -> Option<Arc<Metadata>> {
931-
let (remaining, global) = self.get_scoped_global(name_str)?;
1049+
let (remaining, metadata) = get_scoped_global(name_str, |module| {
1050+
self.get_extern_global(module.as_str())
1051+
.map(|global| global.metadata)
1052+
.or_else(|| self.peek_module_metadata(module.as_str().into()))
1053+
})?;
1054+
1055+
let mut metadata = &metadata;
9321056

933-
let mut metadata = &global.metadata;
9341057
for field_name in remaining.components() {
9351058
metadata = metadata.module.get(field_name)?
9361059
}

0 commit comments

Comments
 (0)