implement import & scopedImport (WIP, ResolvePath resolves to string)

This commit is contained in:
2026-05-05 15:18:31 +08:00
parent eb59f4fb67
commit c1c5681d13
11 changed files with 452 additions and 102 deletions
+52 -11
View File
@@ -34,6 +34,9 @@ pub struct CodeState {
pub spans: Vec<(usize, rnix::TextRange)>,
pub thunk_count: usize,
pub global_env: HashMap<StringId, MaybeThunk>,
/// Set during a compilation pass when the code is being compiled under a
/// `scopedImport` scope. Read by [`CompilerCtx::current_scope_slot`].
pub current_scope_slot: Option<u32>,
}
pub struct Evaluator {
@@ -67,6 +70,7 @@ impl Evaluator {
thunk_count: 0,
bytecode,
global_env,
current_scope_slot: None,
},
}
}
@@ -150,16 +154,22 @@ impl VmCode for CodeState {
fn bytecode(&self) -> &[u8] {
&self.bytecode
}
fn compile(
fn compile_with_scope(
&mut self,
source: Source,
extra_scope: Option<fix_vm::ExtraScope>,
runtime: &mut impl VmRuntimeCtx,
) -> Result<InstructionPtr> {
let mut compiler = CompilerCtx {
code: self,
runtime,
};
compiler.compile_bytecode(source, None)
let extra = extra_scope.map(|s| match s {
fix_vm::ExtraScope::ScopedImport { keys, slot_id } => {
ExtraScope::ScopedImport { keys, slot_id }
}
});
compiler.compile_bytecode(source, extra)
}
}
@@ -180,9 +190,18 @@ impl<'a, R: VmRuntimeCtx> CompilerCtx<'a, R> {
source: Source,
extra_scope: Option<ExtraScope>,
) -> Result<InstructionPtr> {
let root = self.downgrade(source, extra_scope)?;
let ip = fix_codegen::compile_bytecode(root.as_ref(), self);
Ok(ip)
let prev_scope_slot = self.code.current_scope_slot;
self.code.current_scope_slot = match &extra_scope {
Some(ExtraScope::ScopedImport { slot_id, .. }) => Some(*slot_id),
_ => None,
};
let result = (|| -> Result<InstructionPtr> {
let root = self.downgrade(source, extra_scope)?;
let ip = fix_codegen::compile_bytecode(root.as_ref(), self);
Ok(ip)
})();
self.code.current_scope_slot = prev_scope_slot;
result
}
fn downgrade(&mut self, source: Source, extra_scope: Option<ExtraScope>) -> Result<OwnedIr> {
@@ -258,6 +277,22 @@ impl<'a, R: VmRuntimeCtx> BytecodeContext for CompilerCtx<'a, R> {
};
self.runtime.add_const(val)
}
fn current_source_dir(&mut self) -> StringId {
let dir = self
.code
.sources
.last()
.expect("current_source not set")
.get_dir()
.to_string_lossy()
.into_owned();
self.runtime.intern_string(dir)
}
fn current_scope_slot(&self) -> Option<u32> {
self.code.current_scope_slot
}
}
#[derive(Default)]
@@ -410,8 +445,8 @@ impl<'ctx: 'ir, 'id, 'ir, R: VmRuntimeCtx> DowngradeContext<'id, 'ir>
.alloc(GhostCell::new(MaybeThunk::ReplBinding(sym)).into()));
}
}
Scope::ScopedImport(scoped_bindings) => {
if scoped_bindings.contains(&sym) {
Scope::ScopedImport { keys, .. } => {
if keys.contains(&sym) {
return Ok(self
.bump
.alloc(GhostCell::new(MaybeThunk::ScopedImportBinding(sym)).into()));
@@ -598,21 +633,27 @@ impl<'id, 'ir> ThunkScope<'id, 'ir> {
enum Scope<'ctx, 'id, 'ir> {
Global(&'ctx HashMap<StringId, MaybeThunk>),
Repl(&'ctx HashSet<StringId>),
ScopedImport(HashSet<StringId>),
ScopedImport {
keys: HashSet<StringId>,
slot_id: u32,
},
Let(HashMap<StringId, GhostMaybeThunkRef<'id, 'ir>>),
Param { sym: StringId, abs_layer: u8 },
}
enum ExtraScope<'ctx> {
pub enum ExtraScope<'ctx> {
Repl(&'ctx HashSet<StringId>),
ScopedImport(HashSet<StringId>),
ScopedImport {
keys: HashSet<StringId>,
slot_id: u32,
},
}
impl<'ctx> From<ExtraScope<'ctx>> for Scope<'ctx, '_, '_> {
fn from(value: ExtraScope<'ctx>) -> Self {
use ExtraScope::*;
match value {
ScopedImport(scope) => Scope::ScopedImport(scope),
ScopedImport { keys, slot_id } => Scope::ScopedImport { keys, slot_id },
Repl(scope) => Scope::Repl(scope),
}
}