pub struct Executor { /* private fields */ }Expand description
Lua execution engine.
Holds a shared VM for lightweight stateless operations (eval_simple)
and spawns per-session VMs for coroutine-based execution (start_session).
Per-session VMs eliminate global namespace pollution between concurrent
sessions — each session’s alc, ctx, and package.loaded are fully
isolated.
Implementations§
Source§impl Executor
impl Executor
pub async fn new(lib_paths: Vec<PathBuf>) -> Result<Self>
Sourcepub async fn eval_simple(&self, code: String) -> Result<Value, String>
pub async fn eval_simple(&self, code: String) -> Result<Value, String>
Evaluate Lua code without LLM bridge. For lightweight operations like reading package metadata.
Uses the shared VM. extra_lib_paths must be empty — use
Self::eval_simple_with_paths when project-local paths are needed.
Sourcepub async fn eval_simple_with_paths(
&self,
code: String,
extra_lib_paths: Vec<PathBuf>,
variant_pkgs: Vec<VariantPkg>,
) -> Result<Value, String>
pub async fn eval_simple_with_paths( &self, code: String, extra_lib_paths: Vec<PathBuf>, variant_pkgs: Vec<VariantPkg>, ) -> Result<Value, String>
Evaluate Lua code without LLM bridge, with optional extra package paths and variant pkgs.
When both extra_lib_paths and variant_pkgs are empty, reuses the
shared VM (cheap). When either is non-empty, spawns a dedicated VM so
the extra resolvers are active (slightly more expensive, but pkg_list
is the only caller and it is low-frequency).
The fast path does not register alc.* bridge primitives, so the
state_store / card_store / scenarios_dir handles that
Self::start_session requires are not threaded through here —
callers that need them go through start_session.
Sourcepub async fn start_session(
&self,
code: String,
ctx: Value,
extra_lib_paths: Vec<PathBuf>,
variant_pkgs: Vec<VariantPkg>,
state_store: Arc<JsonFileStore>,
card_store: Arc<FileCardStore>,
scenarios_dir: PathBuf,
) -> Result<Session, String>
pub async fn start_session( &self, code: String, ctx: Value, extra_lib_paths: Vec<PathBuf>, variant_pkgs: Vec<VariantPkg>, state_store: Arc<JsonFileStore>, card_store: Arc<FileCardStore>, scenarios_dir: PathBuf, ) -> Result<Session, String>
Start a new Lua execution session on a dedicated VM.
Each session gets its own Lua VM (OS thread + mlua instance) so concurrent sessions cannot interfere with each other’s globals. The VM is cleaned up automatically when the session completes or is abandoned (all senders drop → channel closes → thread exits).
extra_lib_paths are prepended to self.lib_paths so project-local
packages take precedence over the global package directory.
variant_pkgs come from alc.local.toml and override both layers
(registered at the highest priority).
state_store / card_store / scenarios_dir are resolved by the
service layer (typically from AppConfig.app_dir()) so the engine
crate never touches HOME. They flow through bridge::BridgeConfig
to back alc.state.* / alc.card.* / alc._dirs.scenarios.
Sourcepub async fn start_session_with_env(
&self,
env_map: Arc<HashMap<String, String>>,
code: String,
ctx: Value,
extra_lib_paths: Vec<PathBuf>,
variant_pkgs: Vec<VariantPkg>,
state_store: Arc<JsonFileStore>,
card_store: Arc<FileCardStore>,
scenarios_dir: PathBuf,
) -> Result<Session, String>
pub async fn start_session_with_env( &self, env_map: Arc<HashMap<String, String>>, code: String, ctx: Value, extra_lib_paths: Vec<PathBuf>, variant_pkgs: Vec<VariantPkg>, state_store: Arc<JsonFileStore>, card_store: Arc<FileCardStore>, scenarios_dir: PathBuf, ) -> Result<Session, String>
Like [start_session] but registers alc.env inside the setup closure
with a pre-built, frozen env snapshot.
The env_map must be fully populated from all sources (inject / dotenv /
os.env) before this call — the TIME boundary freeze happens at the
call site (i.e. alc_run invocation in the service layer).
Existing start_session call sites remain untouched (out-of-scope wave
zero design). Service layer code that resolves env calls this wrapper
instead.
Auto Trait Implementations§
impl !RefUnwindSafe for Executor
impl !UnwindSafe for Executor
impl Freeze for Executor
impl Send for Executor
impl Sync for Executor
impl Unpin for Executor
impl UnsafeUnpin for Executor
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreimpl<T> MaybeSend for Twhere
T: Send,
Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.