1use super::async_runtime::{
2 signal_pair, AsyncRegistry, AsyncTaskEntry, AsyncTaskQueue, AsyncTaskTarget, AsyncValueFuture,
3 PendingAsyncTask,
4};
5use super::conversions::{
6 FromLustArgs, FromLustValue, FunctionArgs, IntoLustValue, IntoTypedValue,
7};
8use super::native_types::ExternRegistry;
9use super::values::{EnumInstance, FunctionHandle, StructField, StructInstance, TypedValue};
10use crate::ast::{
11 EnumDef, FieldOwnership, FunctionDef, ImplBlock, Item, ItemKind, Span, StructDef, TraitDef,
12 Type, TypeKind,
13};
14use crate::bytecode::{Compiler, NativeCallResult, Value};
15use crate::modules::{ModuleImports, ModuleLoader};
16use crate::typechecker::{FunctionSignature, TypeChecker};
17use crate::vm::VM;
18use crate::{LustConfig, LustError, Result};
19use hashbrown::HashMap;
20use std::cell::RefCell;
21use std::future::Future;
22use std::path::{Path, PathBuf};
23use std::rc::Rc;
24use std::task::{Context, Poll};
25
26pub struct EmbeddedBuilder {
27 base_dir: PathBuf,
28 modules: HashMap<String, String>,
29 entry_module: Option<String>,
30 config: LustConfig,
31 extern_registry: ExternRegistry,
32}
33
34impl Default for EmbeddedBuilder {
35 fn default() -> Self {
36 Self {
37 base_dir: PathBuf::from("__embedded__"),
38 modules: HashMap::new(),
39 entry_module: None,
40 config: LustConfig::default(),
41 extern_registry: ExternRegistry::new(),
42 }
43 }
44}
45
46impl EmbeddedBuilder {
47 pub fn new() -> Self {
48 Self::default()
49 }
50
51 pub fn with_base_dir(self, base_dir: impl Into<PathBuf>) -> Self {
52 self.set_base_dir(base_dir)
53 }
54
55 pub fn set_base_dir(mut self, base_dir: impl Into<PathBuf>) -> Self {
56 self.base_dir = base_dir.into();
57 self
58 }
59
60 pub fn module(mut self, module_path: impl Into<String>, source: impl Into<String>) -> Self {
61 self.modules.insert(module_path.into(), source.into());
62 self
63 }
64
65 pub fn enable_stdlib_module<S: AsRef<str>>(mut self, module: S) -> Self {
66 self.config.enable_module(module);
67 self
68 }
69
70 pub fn add_stdlib_module<S: AsRef<str>>(mut self, module: S) -> Self {
71 self.config.enable_module(module);
72 self
73 }
74
75 pub fn declare_struct(mut self, def: StructDef) -> Self {
76 self.extern_registry.add_struct(def);
77 self
78 }
79
80 pub fn declare_enum(mut self, def: EnumDef) -> Self {
81 self.extern_registry.add_enum(def);
82 self
83 }
84
85 pub fn declare_trait(mut self, def: TraitDef) -> Self {
86 self.extern_registry.add_trait(def);
87 self
88 }
89
90 pub fn declare_impl(mut self, impl_block: ImplBlock) -> Self {
91 self.extern_registry.add_impl(impl_block);
92 self
93 }
94
95 pub fn declare_function(mut self, func: FunctionDef) -> Self {
96 self.extern_registry.add_function(func);
97 self
98 }
99
100 pub fn with_extern_registry(mut self, registry: ExternRegistry) -> Self {
101 self.extern_registry = registry;
102 self
103 }
104
105 pub fn extern_registry_mut(&mut self) -> &mut ExternRegistry {
106 &mut self.extern_registry
107 }
108
109 pub fn with_config(mut self, config: LustConfig) -> Self {
110 self.config = config;
111 self
112 }
113
114 pub fn set_config(mut self, config: LustConfig) -> Self {
115 self.config = config;
116 self
117 }
118
119 pub fn add_module(
120 &mut self,
121 module_path: impl Into<String>,
122 source: impl Into<String>,
123 ) -> &mut Self {
124 self.modules.insert(module_path.into(), source.into());
125 self
126 }
127
128 pub fn entry_module(mut self, module_path: impl Into<String>) -> Self {
129 self.set_entry_module(module_path);
130 self
131 }
132
133 pub fn set_entry_module(&mut self, module_path: impl Into<String>) -> &mut Self {
134 self.entry_module = Some(module_path.into());
135 self
136 }
137
138 pub fn compile(self) -> Result<EmbeddedProgram> {
139 let entry_module = self
140 .entry_module
141 .ok_or_else(|| LustError::Unknown("No entry module configured for embedding".into()))?;
142 let has_entry = self.modules.contains_key(&entry_module);
143 if !has_entry {
144 return Err(LustError::Unknown(format!(
145 "Entry module '{}' was not provided via EmbeddedBuilder::module",
146 entry_module
147 )));
148 }
149
150 let overrides: HashMap<PathBuf, String> = self
151 .modules
152 .into_iter()
153 .map(|(module, source)| (module_path_to_file(&self.base_dir, &module), source))
154 .collect();
155 compile_in_memory(
156 self.base_dir,
157 entry_module,
158 overrides,
159 self.config,
160 self.extern_registry,
161 )
162 }
163}
164
165pub struct EmbeddedProgram {
166 vm: VM,
167 signatures: HashMap<String, FunctionSignature>,
168 struct_defs: HashMap<String, StructDef>,
169 enum_defs: HashMap<String, EnumDef>,
170 entry_script: Option<String>,
171 entry_module: String,
172 async_registry: Rc<RefCell<AsyncRegistry>>,
173}
174
175pub struct AsyncDriver<'a> {
176 program: &'a mut EmbeddedProgram,
177}
178
179impl<'a> AsyncDriver<'a> {
180 pub fn new(program: &'a mut EmbeddedProgram) -> Self {
181 Self { program }
182 }
183
184 pub fn poll(&mut self) -> Result<()> {
185 self.program.poll_async_tasks()
186 }
187
188 pub fn pump_until_idle(&mut self) -> Result<()> {
189 while self.program.has_pending_async_tasks() {
190 self.program.poll_async_tasks()?;
191 }
192 Ok(())
193 }
194
195 pub fn has_pending(&self) -> bool {
196 self.program.has_pending_async_tasks()
197 }
198}
199
200impl EmbeddedProgram {
201 pub fn builder() -> EmbeddedBuilder {
202 EmbeddedBuilder::default()
203 }
204
205 pub fn vm_mut(&mut self) -> &mut VM {
206 &mut self.vm
207 }
208
209 pub(crate) fn vm(&self) -> &VM {
210 &self.vm
211 }
212
213 pub fn global_names(&self) -> Vec<String> {
214 self.vm.global_names()
215 }
216
217 pub fn globals(&self) -> Vec<(String, Value)> {
218 self.vm.globals_snapshot()
219 }
220
221 pub fn signature(&self, function_name: &str) -> Option<&FunctionSignature> {
222 self.find_signature(function_name).map(|(_, sig)| sig)
223 }
224
225 pub fn typed_functions(&self) -> impl Iterator<Item = (&String, &FunctionSignature)> {
226 self.signatures.iter()
227 }
228
229 pub fn struct_definition(&self, type_name: &str) -> Option<&StructDef> {
230 self.struct_defs.get(type_name)
231 }
232
233 pub fn enum_definition(&self, type_name: &str) -> Option<&EnumDef> {
234 self.enum_defs.get(type_name)
235 }
236
237 fn find_signature(&self, name: &str) -> Option<(String, &FunctionSignature)> {
238 if let Some(sig) = self.signatures.get(name) {
239 return Some((name.to_string(), sig));
240 }
241
242 for candidate in self.signature_lookup_candidates(name) {
243 if let Some(sig) = self.signatures.get(&candidate) {
244 return Some((candidate, sig));
245 }
246 }
247
248 let matches = self
249 .signatures
250 .iter()
251 .filter_map(|(key, sig)| {
252 if Self::simple_name(key) == name {
253 Some((key, sig))
254 } else {
255 None
256 }
257 })
258 .collect::<Vec<_>>();
259 if matches.len() == 1 {
260 let (key, sig) = matches[0];
261 return Some((key.clone(), sig));
262 }
263
264 None
265 }
266
267 fn resolve_signature(&self, name: &str) -> Result<(String, &FunctionSignature)> {
268 if let Some(found) = self.find_signature(name) {
269 return Ok(found);
270 }
271
272 let matches = self
273 .signatures
274 .keys()
275 .filter(|key| Self::simple_name(key) == name)
276 .count();
277 if matches > 1 {
278 return Err(LustError::TypeError {
279 message: format!(
280 "Cannot register native '{}': multiple matching functions found; specify a fully qualified name",
281 name
282 ),
283 });
284 }
285
286 Err(LustError::TypeError {
287 message: format!(
288 "Cannot register native '{}': function not declared in Lust source",
289 name
290 ),
291 })
292 }
293
294 fn signature_lookup_candidates(&self, name: &str) -> Vec<String> {
295 let mut candidates: Vec<String> = Vec::new();
296 if name.contains("::") {
297 candidates.push(name.replace("::", "."));
298 }
299
300 if name.contains('.') {
301 candidates.push(name.replace('.', "::"));
302 }
303
304 if !name.contains('.') && !name.contains("::") {
305 let module = &self.entry_module;
306 candidates.push(format!("{}.{}", module, name));
307 candidates.push(format!("{}::{}", module, name));
308 }
309
310 candidates
311 }
312
313 fn simple_name(name: &str) -> &str {
314 name.rsplit(|c| c == '.' || c == ':').next().unwrap_or(name)
315 }
316
317 fn register_native_with_aliases<F>(&mut self, requested_name: &str, canonical: String, func: F)
318 where
319 F: Fn(&[Value]) -> std::result::Result<NativeCallResult, String> + 'static,
320 {
321 let native_fn: Rc<dyn Fn(&[Value]) -> std::result::Result<NativeCallResult, String>> =
322 Rc::new(func);
323 let value = Value::NativeFunction(native_fn);
324 let mut aliases: Vec<String> = Vec::new();
325 aliases.push(canonical.clone());
326 let canonical_normalized = normalize_global_name(&canonical);
327 if canonical_normalized != canonical {
328 aliases.push(canonical_normalized);
329 }
330
331 if requested_name != canonical {
332 aliases.push(requested_name.to_string());
333 let normalized = normalize_global_name(requested_name);
334 if normalized != requested_name {
335 aliases.push(normalized);
336 }
337 }
338
339 aliases.sort();
340 aliases.dedup();
341 #[cfg(debug_assertions)]
342 eprintln!(
343 "register_native_with_aliases requested='{}' canonical='{}' aliases={:?}",
344 requested_name, canonical, aliases
345 );
346 for key in aliases {
347 self.vm.register_native(key, value.clone());
348 }
349 }
350
351 pub fn get_global_value(&self, name: &str) -> Option<Value> {
352 let normalized = normalize_global_name(name);
353 self.vm.get_global(&normalized)
354 }
355
356 pub fn get_typed_global<T: FromLustValue>(&self, name: &str) -> Result<Option<T>> {
357 let normalized = normalize_global_name(name);
358 match self.vm.get_global(&normalized) {
359 Some(value) => T::from_value(value).map(Some),
360 None => Ok(None),
361 }
362 }
363
364 pub fn set_global_value<V: IntoTypedValue>(&mut self, name: impl Into<String>, value: V) {
365 let name_string = name.into();
366 let normalized = normalize_global_name(&name_string);
367 let value = value.into_typed_value().into_value();
368 self.vm.set_global(normalized, value);
369 }
370
371 pub fn struct_instance<I>(
372 &self,
373 type_name: impl Into<String>,
374 fields: I,
375 ) -> Result<StructInstance>
376 where
377 I: IntoIterator,
378 I::Item: Into<StructField>,
379 {
380 let type_name = type_name.into();
381 let def = self
382 .struct_defs
383 .get(&type_name)
384 .ok_or_else(|| LustError::TypeError {
385 message: format!("Unknown struct '{}'", type_name),
386 })?;
387 let mut provided: HashMap<String, TypedValue> = fields
388 .into_iter()
389 .map(|field| {
390 let field: StructField = field.into();
391 field.into_parts()
392 })
393 .collect();
394 let mut ordered_fields: Vec<(Rc<String>, Value)> = Vec::with_capacity(def.fields.len());
395 for field in &def.fields {
396 let typed_value = provided
397 .remove(&field.name)
398 .ok_or_else(|| LustError::TypeError {
399 message: format!(
400 "Struct '{}' is missing required field '{}'",
401 type_name, field.name
402 ),
403 })?;
404
405 let matches_ref_inner = matches!(field.ownership, FieldOwnership::Weak)
406 && matches!(typed_value.as_value(), Value::Struct { .. });
407 if !typed_value.matches(&field.ty) && !matches_ref_inner {
408 return Err(LustError::TypeError {
409 message: format!(
410 "Struct field '{}' expects Rust value of type '{}' but received '{}'",
411 field.name,
412 field.ty,
413 typed_value.description()
414 ),
415 });
416 }
417
418 ordered_fields.push((Rc::new(field.name.clone()), typed_value.into_value()));
419 }
420
421 if !provided.is_empty() {
422 let mut unexpected: Vec<String> = provided.into_keys().collect();
423 unexpected.sort();
424 return Err(LustError::TypeError {
425 message: format!(
426 "Struct '{}' received unexpected field(s): {}",
427 type_name,
428 unexpected.join(", ")
429 ),
430 });
431 }
432
433 let value = self.vm.instantiate_struct(&type_name, ordered_fields)?;
434 Ok(StructInstance::new(type_name.clone(), value))
435 }
436
437 pub fn enum_variant(
438 &self,
439 type_name: impl Into<String>,
440 variant: impl Into<String>,
441 ) -> Result<EnumInstance> {
442 self.enum_variant_with(type_name, variant, std::iter::empty::<Value>())
443 }
444
445 pub fn enum_variant_with<I, V>(
446 &self,
447 type_name: impl Into<String>,
448 variant: impl Into<String>,
449 payload: I,
450 ) -> Result<EnumInstance>
451 where
452 I: IntoIterator<Item = V>,
453 V: IntoTypedValue,
454 {
455 let type_name = type_name.into();
456 let variant_name = variant.into();
457 let def = self
458 .enum_defs
459 .get(&type_name)
460 .ok_or_else(|| LustError::TypeError {
461 message: format!("Unknown enum '{}'", type_name),
462 })?;
463 let enum_variant = def
464 .variants
465 .iter()
466 .find(|v| v.name == variant_name)
467 .ok_or_else(|| LustError::TypeError {
468 message: format!(
469 "Enum '{}' has no variant named '{}'",
470 type_name, variant_name
471 ),
472 })?;
473 let mut values: Vec<TypedValue> =
474 payload.into_iter().map(|v| v.into_typed_value()).collect();
475 let coerced_values: Option<Rc<Vec<Value>>> = match &enum_variant.fields {
476 None => {
477 if !values.is_empty() {
478 return Err(LustError::TypeError {
479 message: format!(
480 "Enum variant '{}.{}' does not accept payload values",
481 type_name, variant_name
482 ),
483 });
484 }
485
486 None
487 }
488
489 Some(field_types) => {
490 if values.len() != field_types.len() {
491 return Err(LustError::TypeError {
492 message: format!(
493 "Enum variant '{}.{}' expects {} value(s) but {} were supplied",
494 type_name,
495 variant_name,
496 field_types.len(),
497 values.len()
498 ),
499 });
500 }
501
502 let mut collected = Vec::with_capacity(field_types.len());
503 for (idx, (typed_value, field_ty)) in
504 values.drain(..).zip(field_types.iter()).enumerate()
505 {
506 if !typed_value.matches(field_ty) {
507 return Err(LustError::TypeError {
508 message: format!(
509 "Enum variant '{}.{}' field {} expects Lust type '{}' but Rust provided '{}'",
510 type_name,
511 variant_name,
512 idx + 1,
513 field_ty,
514 typed_value.description()
515 ),
516 });
517 }
518
519 collected.push(typed_value.into_value());
520 }
521
522 Some(Rc::new(collected))
523 }
524 };
525 Ok(EnumInstance::new(
526 type_name.clone(),
527 variant_name.clone(),
528 Value::Enum {
529 enum_name: type_name,
530 variant: variant_name,
531 values: coerced_values,
532 },
533 ))
534 }
535
536 pub fn register_native_fn<F>(&mut self, name: impl Into<String>, func: F)
537 where
538 F: Fn(&[Value]) -> std::result::Result<NativeCallResult, String> + 'static,
539 {
540 let native = Value::NativeFunction(Rc::new(func));
541 self.vm.register_native(name, native);
542 }
543
544 pub fn register_async_native<F, Fut>(&mut self, name: impl Into<String>, func: F) -> Result<()>
545 where
546 F: Fn(Vec<Value>) -> Fut + 'static,
547 Fut: Future<Output = std::result::Result<Value, String>> + 'static,
548 {
549 let registry = self.async_registry.clone();
550 let name_string = name.into();
551 let handler = move |values: &[Value]| -> std::result::Result<NativeCallResult, String> {
552 let args: Vec<Value> = values.iter().cloned().collect();
553 let future: AsyncValueFuture = Box::pin(func(args));
554 VM::with_current(|vm| {
555 let handle = vm
556 .current_task_handle()
557 .ok_or_else(|| "Async native functions require a running task".to_string())?;
558 let mut registry = registry.borrow_mut();
559 if registry.has_pending_for(handle) {
560 return Err(format!(
561 "Task {} already has a pending async native call",
562 handle.id()
563 ));
564 }
565
566 registry.register(AsyncTaskEntry::new(
567 AsyncTaskTarget::ScriptTask(handle),
568 future,
569 ));
570 Ok(NativeCallResult::Yield(Value::Nil))
571 })
572 };
573 self.register_native_fn(name_string, handler);
574 Ok(())
575 }
576
577 pub fn register_typed_native<Args, R, F>(&mut self, name: &str, func: F) -> Result<()>
578 where
579 Args: FromLustArgs,
580 R: IntoLustValue + FromLustValue,
581 F: Fn(Args) -> std::result::Result<R, String> + 'static,
582 {
583 let (canonical, signature) = self.resolve_signature(name)?;
584 if !Args::matches_signature(&signature.params) {
585 return Err(LustError::TypeError {
586 message: format!(
587 "Native '{}' argument types do not match Lust signature",
588 name
589 ),
590 });
591 }
592
593 ensure_return_type::<R>(name, &signature.return_type)?;
594 let handler = move |values: &[Value]| -> std::result::Result<NativeCallResult, String> {
595 let args = Args::from_values(values)?;
596 let result = func(args)?;
597 Ok(NativeCallResult::Return(result.into_value()))
598 };
599 self.register_native_with_aliases(name, canonical, handler);
600 Ok(())
601 }
602
603 pub fn register_async_typed_native<Args, R, F, Fut>(
604 &mut self,
605 name: &str,
606 func: F,
607 ) -> Result<()>
608 where
609 Args: FromLustArgs,
610 R: IntoLustValue + FromLustValue,
611 F: Fn(Args) -> Fut + 'static,
612 Fut: Future<Output = std::result::Result<R, String>> + 'static,
613 {
614 let (canonical, signature) = self.resolve_signature(name)?;
615 let signature = signature.clone();
616 if !Args::matches_signature(&signature.params) {
617 return Err(LustError::TypeError {
618 message: format!(
619 "Native '{}' argument types do not match Lust signature",
620 name
621 ),
622 });
623 }
624
625 let registry = self.async_registry.clone();
626 let handler = move |values: &[Value]| -> std::result::Result<NativeCallResult, String> {
627 let args = Args::from_values(values)?;
628 let future = func(args);
629 let mapped = async move {
630 match future.await {
631 Ok(result) => Ok(result.into_value()),
632 Err(err) => Err(err),
633 }
634 };
635 let future: AsyncValueFuture = Box::pin(mapped);
636 VM::with_current(|vm| {
637 let handle = vm
638 .current_task_handle()
639 .ok_or_else(|| "Async native functions require a running task".to_string())?;
640 let mut registry = registry.borrow_mut();
641 if registry.has_pending_for(handle) {
642 return Err(format!(
643 "Task {} already has a pending async native call",
644 handle.id()
645 ));
646 }
647
648 registry.register(AsyncTaskEntry::new(
649 AsyncTaskTarget::ScriptTask(handle),
650 future,
651 ));
652 Ok(NativeCallResult::Yield(Value::Nil))
653 })
654 };
655 self.register_native_with_aliases(name, canonical, handler);
656 Ok(())
657 }
658
659 pub fn register_async_task_native<Args, R, F, Fut>(&mut self, name: &str, func: F) -> Result<()>
660 where
661 Args: FromLustArgs,
662 R: IntoLustValue + FromLustValue,
663 F: Fn(Args) -> Fut + 'static,
664 Fut: Future<Output = std::result::Result<R, String>> + 'static,
665 {
666 let (canonical, signature) = self.resolve_signature(name)?;
667 let signature = signature.clone();
668 if !Args::matches_signature(&signature.params) {
669 return Err(LustError::TypeError {
670 message: format!(
671 "Native '{}' argument types do not match Lust signature",
672 name
673 ),
674 });
675 }
676
677 let registry = self.async_registry.clone();
678 let handler = move |values: &[Value]| -> std::result::Result<NativeCallResult, String> {
679 let args = Args::from_values(values)?;
680 let future = func(args);
681 let mapped = async move {
682 match future.await {
683 Ok(result) => Ok(result.into_value()),
684 Err(err) => Err(err),
685 }
686 };
687 let future: AsyncValueFuture = Box::pin(mapped);
688 VM::with_current(|vm| {
689 let mut registry = registry.borrow_mut();
690 let handle = vm.create_native_future_task();
691 let entry = AsyncTaskEntry::new(AsyncTaskTarget::NativeTask(handle), future);
692 registry.register(entry);
693 Ok(NativeCallResult::Return(Value::task(handle)))
694 })
695 };
696 self.register_native_with_aliases(name, canonical, handler);
697 Ok(())
698 }
699
700 pub fn register_async_task_queue<Args, R>(
701 &mut self,
702 name: &str,
703 queue: AsyncTaskQueue<Args, R>,
704 ) -> Result<()>
705 where
706 Args: FromLustArgs + 'static,
707 R: IntoLustValue + FromLustValue + 'static,
708 {
709 let (canonical, signature) = self.resolve_signature(name)?;
710 let signature = signature.clone();
711 if !Args::matches_signature(&signature.params) {
712 return Err(LustError::TypeError {
713 message: format!(
714 "Native '{}' argument types do not match Lust signature",
715 name
716 ),
717 });
718 }
719
720 let registry = self.async_registry.clone();
721 let queue_clone = queue.clone();
722 let handler = move |values: &[Value]| -> std::result::Result<NativeCallResult, String> {
723 let args = Args::from_values(values)?;
724 let (completer, signal_future) = signal_pair::<R>();
725 let future: AsyncValueFuture = Box::pin(async move {
726 match signal_future.await {
727 Ok(result) => Ok(result.into_value()),
728 Err(err) => Err(err),
729 }
730 });
731
732 VM::with_current(|vm| {
733 let mut registry = registry.borrow_mut();
734 let handle = vm.create_native_future_task();
735 let entry = AsyncTaskEntry::new(AsyncTaskTarget::NativeTask(handle), future);
736 registry.register(entry);
737 queue_clone.push(PendingAsyncTask::new(handle, args, completer));
738 Ok(NativeCallResult::Return(Value::task(handle)))
739 })
740 };
741 self.register_native_with_aliases(name, canonical, handler);
742 Ok(())
743 }
744
745 pub fn call_typed<Args, R>(&mut self, function_name: &str, args: Args) -> Result<R>
746 where
747 Args: FunctionArgs,
748 R: FromLustValue,
749 {
750 let signature = self
751 .signatures
752 .get(function_name)
753 .ok_or_else(|| LustError::TypeError {
754 message: format!(
755 "No type information available for function '{}'; \
756 use call_raw if the function is dynamically typed",
757 function_name
758 ),
759 })?;
760 Args::validate_signature(function_name, &signature.params)?;
761 ensure_return_type::<R>(function_name, &signature.return_type)?;
762 let values = args.into_values();
763 let value = self.vm.call(function_name, values)?;
764 R::from_value(value)
765 }
766
767 pub fn call_raw(&mut self, function_name: &str, args: Vec<Value>) -> Result<Value> {
768 self.vm.call(function_name, args)
769 }
770
771 pub fn function_handle(&self, function_name: &str) -> Result<FunctionHandle> {
772 let mut candidates = Vec::new();
773 candidates.push(function_name.to_string());
774 candidates.extend(self.signature_lookup_candidates(function_name));
775 for name in candidates {
776 if let Some(value) = self.vm.function_value(&name) {
777 return FunctionHandle::from_value(value);
778 }
779 }
780 Err(LustError::RuntimeError {
781 message: format!("Function '{}' not found in embedded program", function_name),
782 })
783 }
784
785 pub fn run_entry_script(&mut self) -> Result<()> {
786 let Some(entry) = &self.entry_script else {
787 return Err(LustError::RuntimeError {
788 message: "Embedded program has no entry script".into(),
789 });
790 };
791 let result = self.vm.call(entry, Vec::new())?;
792 match result {
793 Value::Nil => Ok(()),
794 other => Err(LustError::RuntimeError {
795 message: format!(
796 "Entry script '{}' returned non-unit value: {:?}",
797 entry, other
798 ),
799 }),
800 }
801 }
802
803 pub fn poll_async_tasks(&mut self) -> Result<()> {
804 let pending_ids: Vec<u64> = {
805 let registry = self.async_registry.borrow();
806 registry.pending.keys().copied().collect()
807 };
808
809 for id in pending_ids {
810 let mut completion: Option<(AsyncTaskTarget, std::result::Result<Value, String>)> =
811 None;
812 {
813 let mut registry = self.async_registry.borrow_mut();
814 let entry = match registry.pending.get_mut(&id) {
815 Some(entry) => entry,
816 None => continue,
817 };
818
819 if !entry.take_should_poll() {
820 continue;
821 }
822
823 let waker = entry.make_waker();
824 let mut cx = Context::from_waker(&waker);
825 if let Poll::Ready(result) = entry.future.as_mut().poll(&mut cx) {
826 completion = Some((entry.target, result));
827 }
828 }
829
830 if let Some((target, outcome)) = completion {
831 self.async_registry.borrow_mut().pending.remove(&id);
832 match target {
833 AsyncTaskTarget::ScriptTask(handle) => match outcome {
834 Ok(value) => {
835 self.vm.resume_task_handle(handle, Some(value))?;
836 }
837
838 Err(message) => {
839 self.vm
840 .fail_task_handle(handle, LustError::RuntimeError { message })?;
841 }
842 },
843
844 AsyncTaskTarget::NativeTask(handle) => {
845 self.vm.complete_native_future_task(handle, outcome)?;
846 }
847 }
848 }
849 }
850
851 Ok(())
852 }
853
854 pub fn has_pending_async_tasks(&self) -> bool {
855 !self.async_registry.borrow().is_empty()
856 }
857}
858
859fn compile_in_memory(
860 base_dir: PathBuf,
861 entry_module: String,
862 overrides: HashMap<PathBuf, String>,
863 config: LustConfig,
864 extern_registry: ExternRegistry,
865) -> Result<EmbeddedProgram> {
866 let mut loader = ModuleLoader::new(base_dir.clone());
867 loader.set_source_overrides(overrides);
868 let entry_path = module_path_to_file(&base_dir, &entry_module);
869 let entry_path_str = entry_path
870 .to_str()
871 .ok_or_else(|| LustError::Unknown("Entry path contained invalid UTF-8".into()))?
872 .to_string();
873 let program = loader.load_program_from_entry(&entry_path_str)?;
874 let mut imports_map: HashMap<String, ModuleImports> = HashMap::new();
875 for module in &program.modules {
876 imports_map.insert(module.path.clone(), module.imports.clone());
877 }
878
879 let mut wrapped_items: Vec<Item> = Vec::new();
880 for module in &program.modules {
881 wrapped_items.push(Item::new(
882 ItemKind::Module {
883 name: module.path.clone(),
884 items: module.items.clone(),
885 },
886 Span::new(0, 0, 0, 0),
887 ));
888 }
889
890 let mut typechecker = TypeChecker::with_config(&config);
891 typechecker.set_imports_by_module(imports_map.clone());
892 extern_registry.register_with_typechecker(&mut typechecker)?;
893 typechecker.check_program(&program.modules)?;
894 let option_coercions = typechecker.take_option_coercions();
895 let mut struct_defs = typechecker.struct_definitions();
896 for def in extern_registry.structs() {
897 struct_defs.insert(def.name.clone(), def.clone());
898 }
899 let mut enum_defs = typechecker.enum_definitions();
900 for def in extern_registry.enums() {
901 enum_defs.insert(def.name.clone(), def.clone());
902 }
903 let mut signatures = typechecker.function_signatures();
904 let mut compiler = Compiler::new();
905 compiler.set_option_coercions(option_coercions);
906 compiler.configure_stdlib(&config);
907 compiler.set_imports_by_module(imports_map);
908 compiler.set_entry_module(program.entry_module.clone());
909 compiler.set_function_signatures(signatures.clone());
910 let functions = compiler.compile_module(&wrapped_items)?;
911 let trait_impls = compiler.get_trait_impls().to_vec();
912 let mut init_funcs: Vec<(String, String)> = Vec::new();
913 for module in &program.modules {
914 if module.path != program.entry_module {
915 if let Some(init) = &module.init_function {
916 let init_name = module
917 .imports
918 .function_aliases
919 .get(init)
920 .cloned()
921 .unwrap_or_else(|| init.clone());
922 init_funcs.push((module.path.clone(), init_name));
923 }
924 }
925 }
926
927 let function_names: Vec<String> = functions.iter().map(|f| f.name.clone()).collect();
928 let entry_script = function_names
929 .iter()
930 .find(|name| name.as_str() == "__script")
931 .cloned();
932 if let Some(script_name) = &entry_script {
933 signatures
934 .entry(script_name.clone())
935 .or_insert_with(|| FunctionSignature {
936 params: Vec::new(),
937 return_type: Type::new(TypeKind::Unit, Span::new(0, 0, 0, 0)),
938 is_method: false,
939 });
940 }
941
942 let mut vm = VM::with_config(&config);
943 vm.load_functions(functions);
944 vm.register_structs(&struct_defs);
945 extern_registry.register_type_stubs(&mut vm);
946 for (type_name, trait_name) in trait_impls {
947 vm.register_trait_impl(type_name, trait_name);
948 }
949
950 for (module_path, init) in init_funcs {
951 let value = vm.call(&init, Vec::new())?;
952 vm.set_global(module_path, value);
953 }
954
955 Ok(EmbeddedProgram {
956 vm,
957 signatures,
958 struct_defs,
959 enum_defs,
960 entry_script,
961 entry_module: program.entry_module,
962 async_registry: Rc::new(RefCell::new(AsyncRegistry::new())),
963 })
964}
965
966fn module_path_to_file(base_dir: &Path, module_path: &str) -> PathBuf {
967 let mut path = base_dir.to_path_buf();
968 for segment in module_path.split('.') {
969 path.push(segment);
970 }
971
972 path.set_extension("lust");
973 path
974}
975
976pub(crate) fn normalize_global_name(name: &str) -> String {
977 if name.contains("::") {
978 name.to_string()
979 } else if let Some((module, identifier)) = name.rsplit_once('.') {
980 format!("{}::{}", module, identifier)
981 } else {
982 name.to_string()
983 }
984}
985
986pub(crate) fn ensure_return_type<R: FromLustValue>(function_name: &str, ty: &Type) -> Result<()> {
987 if matches!(ty.kind, TypeKind::Unknown) || R::matches_lust_type(ty) {
988 return Ok(());
989 }
990
991 Err(LustError::TypeError {
992 message: format!(
993 "Function '{}' reports return type '{}' which is incompatible with Rust receiver '{}'",
994 function_name,
995 ty,
996 R::type_description()
997 ),
998 })
999}