Share host-aware completion across runtimes

This commit is contained in:
2026-08-13 18:55:03 +09:00
parent e862e53f3e
commit d28edcf041
25 changed files with 2836 additions and 578 deletions
+36
View File
@@ -107,6 +107,42 @@ impl<L: ImportLoader> Engine<L> {
thunk
}
/// Returns the values installed in the host-owned global environment.
///
/// Language tooling uses this after [`crate::HostEnvironment`] configures a
/// fresh engine, so editor-visible globals cannot drift from evaluation.
pub fn global_values(&mut self) -> Result<Vec<(String, RuntimeValue)>> {
let bindings = self.envs[self.prelude_env.0 as usize].bindings.clone();
bindings
.into_iter()
.map(|binding| Ok((binding.name, self.force(binding.value)?)))
.collect()
}
/// Returns the immediately visible fields of an object runtime value.
pub fn value_fields(
&mut self,
value: &RuntimeValue,
) -> Result<Option<Vec<(String, RuntimeValue)>>> {
let object = match value {
RuntimeValue::Concrete(crate::runtime::ConcreteValue::Object(object)) => object,
RuntimeValue::Abstract(abstract_value) => {
let Some(default) = abstract_value.default else {
return Ok(None);
};
let default = self.force(default)?;
return self.value_fields(&default);
}
_ => return Ok(None),
};
let fields = object.fields.clone();
fields
.into_iter()
.map(|field| Ok((field.name, self.force(field.value)?)))
.collect::<Result<Vec<_>>>()
.map(Some)
}
pub fn add_root_source(
&mut self,
key: impl Into<String>,
+3 -1
View File
@@ -23,7 +23,9 @@ pub use diagnostic::{Diagnostic, DiagnosticKind, Result};
pub use embedding::{HostField, HostValue};
pub use environment::HostEnvironment;
pub use eval::{Engine, format_diagnostic_with};
pub use module::{EmptyLoader, ImportLoader, LoadedImport, LoadedSource, LoadedValue, Module};
pub use module::{
EmptyLoader, ImportCandidate, ImportLoader, LoadedImport, LoadedSource, LoadedValue, Module,
};
pub use parser::{ParseOutput, Parser, SourceForm, parse_source, parse_source_with_source_id};
pub use runtime::{Constraint, Data, ExprRef, LiteralValue, ModuleId, PrimitiveType, RuntimeValue};
pub use span::{SourceId, Span};
+35 -1
View File
@@ -1,4 +1,4 @@
use alloc::string::String;
use alloc::{string::String, vec::Vec};
use crate::{
Ast, ExprId, HostValue, SourceForm, SourceId,
@@ -36,6 +36,27 @@ pub enum LoadedImport {
Value(LoadedValue),
}
/// An import specifier offered by host-owned language tooling.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ImportCandidate {
pub specifier: String,
pub detail: Option<String>,
}
impl ImportCandidate {
pub fn new(specifier: impl Into<String>) -> Self {
Self {
specifier: specifier.into(),
detail: None,
}
}
pub fn with_detail(mut self, detail: impl Into<String>) -> Self {
self.detail = Some(detail.into());
self
}
}
impl LoadedImport {
pub fn source(
key: impl Into<String>,
@@ -59,6 +80,19 @@ impl LoadedImport {
pub trait ImportLoader {
fn load(&mut self, current_key: Option<&str>, specifier: &str) -> crate::Result<LoadedImport>;
/// Returns host-resolvable import specifiers matching an unfinished prefix.
///
/// Runtime-only loaders may keep the default implementation. Hosts that
/// provide an editor should implement this from the same namespace used by
/// [`ImportLoader::load`].
fn complete_import(
&mut self,
_current_key: Option<&str>,
_prefix: &str,
) -> crate::Result<Vec<ImportCandidate>> {
Ok(Vec::new())
}
}
#[derive(Debug, Clone, Copy, Default)]