lust/
embed.rs

1use crate::ast::{EnumDef, FieldOwnership, Item, ItemKind, Span, StructDef, Type, TypeKind};
2use crate::bytecode::{Compiler, FieldStorage, NativeCallResult, TaskHandle, Value, ValueKey};
3use crate::modules::{ModuleImports, ModuleLoader};
4use crate::number::{LustFloat, LustInt};
5use crate::typechecker::{FunctionSignature, TypeChecker};
6use crate::vm::VM;
7use crate::{LustConfig, LustError, Result};
8use hashbrown::HashMap;
9use std::cell::{Ref, RefCell, RefMut};
10use std::future::Future;
11use std::path::{Path, PathBuf};
12use std::pin::Pin;
13use std::rc::Rc;
14use std::sync::atomic::{AtomicBool, Ordering};
15use std::sync::Arc;
16use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
17
18type AsyncValueFuture = Pin<Box<dyn Future<Output = std::result::Result<Value, String>>>>;
19
20struct AsyncRegistry {
21    pending: HashMap<u64, AsyncTaskEntry>,
22}
23
24impl AsyncRegistry {
25    fn new() -> Self {
26        Self {
27            pending: HashMap::new(),
28        }
29    }
30
31    fn register(
32        &mut self,
33        handle: TaskHandle,
34        future: AsyncValueFuture,
35    ) -> std::result::Result<(), String> {
36        let key = handle.id();
37        if self.pending.contains_key(&key) {
38            return Err(format!(
39                "Task {} already has a pending async native call",
40                key
41            ));
42        }
43
44        self.pending
45            .insert(key, AsyncTaskEntry::new(handle, future));
46        Ok(())
47    }
48
49    fn is_empty(&self) -> bool {
50        self.pending.is_empty()
51    }
52}
53
54struct AsyncTaskEntry {
55    handle: TaskHandle,
56    future: AsyncValueFuture,
57    wake_flag: Arc<WakeFlag>,
58    immediate_poll: bool,
59}
60
61impl AsyncTaskEntry {
62    fn new(handle: TaskHandle, future: AsyncValueFuture) -> Self {
63        Self {
64            handle,
65            future,
66            wake_flag: Arc::new(WakeFlag::new()),
67            immediate_poll: true,
68        }
69    }
70
71    fn take_should_poll(&mut self) -> bool {
72        if self.immediate_poll {
73            self.immediate_poll = false;
74            true
75        } else {
76            self.wake_flag.take()
77        }
78    }
79
80    fn make_waker(&self) -> Waker {
81        make_async_waker(&self.wake_flag)
82    }
83}
84
85struct WakeFlag {
86    pending: AtomicBool,
87}
88
89impl WakeFlag {
90    fn new() -> Self {
91        Self {
92            pending: AtomicBool::new(true),
93        }
94    }
95
96    fn take(&self) -> bool {
97        self.pending.swap(false, Ordering::SeqCst)
98    }
99
100    fn wake(&self) {
101        self.pending.store(true, Ordering::SeqCst);
102    }
103}
104
105fn make_async_waker(flag: &Arc<WakeFlag>) -> Waker {
106    unsafe {
107        Waker::from_raw(RawWaker::new(
108            Arc::into_raw(flag.clone()) as *const (),
109            &ASYNC_WAKER_VTABLE,
110        ))
111    }
112}
113
114unsafe fn async_waker_clone(ptr: *const ()) -> RawWaker {
115    let arc = Arc::<WakeFlag>::from_raw(ptr as *const WakeFlag);
116    let cloned = arc.clone();
117    std::mem::forget(arc);
118    RawWaker::new(Arc::into_raw(cloned) as *const (), &ASYNC_WAKER_VTABLE)
119}
120
121unsafe fn async_waker_wake(ptr: *const ()) {
122    let arc = Arc::<WakeFlag>::from_raw(ptr as *const WakeFlag);
123    arc.wake();
124}
125
126unsafe fn async_waker_wake_by_ref(ptr: *const ()) {
127    let arc = Arc::<WakeFlag>::from_raw(ptr as *const WakeFlag);
128    arc.wake();
129    std::mem::forget(arc);
130}
131
132unsafe fn async_waker_drop(ptr: *const ()) {
133    let _ = Arc::<WakeFlag>::from_raw(ptr as *const WakeFlag);
134}
135
136static ASYNC_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(
137    async_waker_clone,
138    async_waker_wake,
139    async_waker_wake_by_ref,
140    async_waker_drop,
141);
142pub struct EmbeddedBuilder {
143    base_dir: PathBuf,
144    modules: HashMap<String, String>,
145    entry_module: Option<String>,
146    config: LustConfig,
147}
148
149impl Default for EmbeddedBuilder {
150    fn default() -> Self {
151        Self {
152            base_dir: PathBuf::from("__embedded__"),
153            modules: HashMap::new(),
154            entry_module: None,
155            config: LustConfig::default(),
156        }
157    }
158}
159
160impl EmbeddedBuilder {
161    pub fn new() -> Self {
162        Self::default()
163    }
164
165    pub fn with_base_dir(self, base_dir: impl Into<PathBuf>) -> Self {
166        self.set_base_dir(base_dir)
167    }
168
169    pub fn set_base_dir(mut self, base_dir: impl Into<PathBuf>) -> Self {
170        self.base_dir = base_dir.into();
171        self
172    }
173
174    pub fn module(mut self, module_path: impl Into<String>, source: impl Into<String>) -> Self {
175        self.modules.insert(module_path.into(), source.into());
176        self
177    }
178
179    pub fn enable_stdlib_module<S: AsRef<str>>(mut self, module: S) -> Self {
180        self.config.enable_module(module);
181        self
182    }
183
184    pub fn add_stdlib_module<S: AsRef<str>>(mut self, module: S) -> Self {
185        self.config.enable_module(module);
186        self
187    }
188
189    pub fn with_config(mut self, config: LustConfig) -> Self {
190        self.config = config;
191        self
192    }
193
194    pub fn set_config(mut self, config: LustConfig) -> Self {
195        self.config = config;
196        self
197    }
198
199    pub fn add_module(
200        &mut self,
201        module_path: impl Into<String>,
202        source: impl Into<String>,
203    ) -> &mut Self {
204        self.modules.insert(module_path.into(), source.into());
205        self
206    }
207
208    pub fn entry_module(mut self, module_path: impl Into<String>) -> Self {
209        self.set_entry_module(module_path);
210        self
211    }
212
213    pub fn set_entry_module(&mut self, module_path: impl Into<String>) -> &mut Self {
214        self.entry_module = Some(module_path.into());
215        self
216    }
217
218    pub fn compile(self) -> Result<EmbeddedProgram> {
219        let entry_module = self
220            .entry_module
221            .ok_or_else(|| LustError::Unknown("No entry module configured for embedding".into()))?;
222        let has_entry = self.modules.contains_key(&entry_module);
223        if !has_entry {
224            return Err(LustError::Unknown(format!(
225                "Entry module '{}' was not provided via EmbeddedBuilder::module",
226                entry_module
227            )));
228        }
229
230        let overrides: HashMap<PathBuf, String> = self
231            .modules
232            .into_iter()
233            .map(|(module, source)| (module_path_to_file(&self.base_dir, &module), source))
234            .collect();
235        compile_in_memory(self.base_dir, entry_module, overrides, self.config)
236    }
237}
238
239pub struct EmbeddedProgram {
240    vm: VM,
241    signatures: HashMap<String, FunctionSignature>,
242    struct_defs: HashMap<String, StructDef>,
243    enum_defs: HashMap<String, EnumDef>,
244    entry_script: Option<String>,
245    entry_module: String,
246    async_registry: Rc<RefCell<AsyncRegistry>>,
247}
248
249impl EmbeddedProgram {
250    pub fn builder() -> EmbeddedBuilder {
251        EmbeddedBuilder::default()
252    }
253
254    pub fn vm_mut(&mut self) -> &mut VM {
255        &mut self.vm
256    }
257
258    pub fn global_names(&self) -> Vec<String> {
259        self.vm.global_names()
260    }
261
262    pub fn globals(&self) -> Vec<(String, Value)> {
263        self.vm.globals_snapshot()
264    }
265
266    pub fn signature(&self, function_name: &str) -> Option<&FunctionSignature> {
267        self.find_signature(function_name).map(|(_, sig)| sig)
268    }
269
270    pub fn typed_functions(&self) -> impl Iterator<Item = (&String, &FunctionSignature)> {
271        self.signatures.iter()
272    }
273
274    pub fn struct_definition(&self, type_name: &str) -> Option<&StructDef> {
275        self.struct_defs.get(type_name)
276    }
277
278    pub fn enum_definition(&self, type_name: &str) -> Option<&EnumDef> {
279        self.enum_defs.get(type_name)
280    }
281
282    fn find_signature(&self, name: &str) -> Option<(String, &FunctionSignature)> {
283        if let Some(sig) = self.signatures.get(name) {
284            return Some((name.to_string(), sig));
285        }
286
287        for candidate in self.signature_lookup_candidates(name) {
288            if let Some(sig) = self.signatures.get(&candidate) {
289                return Some((candidate, sig));
290            }
291        }
292
293        let matches = self
294            .signatures
295            .iter()
296            .filter_map(|(key, sig)| {
297                if Self::simple_name(key) == name {
298                    Some((key, sig))
299                } else {
300                    None
301                }
302            })
303            .collect::<Vec<_>>();
304        if matches.len() == 1 {
305            let (key, sig) = matches[0];
306            return Some((key.clone(), sig));
307        }
308
309        None
310    }
311
312    fn resolve_signature(&self, name: &str) -> Result<(String, &FunctionSignature)> {
313        if let Some(found) = self.find_signature(name) {
314            return Ok(found);
315        }
316
317        let matches = self
318            .signatures
319            .keys()
320            .filter(|key| Self::simple_name(key) == name)
321            .count();
322        if matches > 1 {
323            return Err(LustError::TypeError {
324                message: format!(
325                    "Cannot register native '{}': multiple matching functions found; specify a fully qualified name",
326                    name
327                ),
328            });
329        }
330
331        Err(LustError::TypeError {
332            message: format!(
333                "Cannot register native '{}': function not declared in Lust source",
334                name
335            ),
336        })
337    }
338
339    fn signature_lookup_candidates(&self, name: &str) -> Vec<String> {
340        let mut candidates: Vec<String> = Vec::new();
341        if name.contains("::") {
342            candidates.push(name.replace("::", "."));
343        }
344
345        if name.contains('.') {
346            candidates.push(name.replace('.', "::"));
347        }
348
349        if !name.contains('.') && !name.contains("::") {
350            let module = &self.entry_module;
351            candidates.push(format!("{}.{}", module, name));
352            candidates.push(format!("{}::{}", module, name));
353        }
354
355        candidates
356    }
357
358    fn simple_name(name: &str) -> &str {
359        name.rsplit(|c| c == '.' || c == ':').next().unwrap_or(name)
360    }
361
362    fn register_native_with_aliases<F>(&mut self, requested_name: &str, canonical: String, func: F)
363    where
364        F: Fn(&[Value]) -> std::result::Result<NativeCallResult, String> + 'static,
365    {
366        let native_fn: Rc<dyn Fn(&[Value]) -> std::result::Result<NativeCallResult, String>> =
367            Rc::new(func);
368        let value = Value::NativeFunction(native_fn);
369        let mut aliases: Vec<String> = Vec::new();
370        aliases.push(canonical.clone());
371        let canonical_normalized = normalize_global_name(&canonical);
372        if canonical_normalized != canonical {
373            aliases.push(canonical_normalized);
374        }
375
376        if requested_name != canonical {
377            aliases.push(requested_name.to_string());
378            let normalized = normalize_global_name(requested_name);
379            if normalized != requested_name {
380                aliases.push(normalized);
381            }
382        }
383
384        aliases.sort();
385        aliases.dedup();
386        for key in aliases {
387            self.vm.register_native(key, value.clone());
388        }
389    }
390
391    pub fn get_global_value(&self, name: &str) -> Option<Value> {
392        let normalized = normalize_global_name(name);
393        self.vm.get_global(&normalized)
394    }
395
396    pub fn get_typed_global<T: FromLustValue>(&self, name: &str) -> Result<Option<T>> {
397        let normalized = normalize_global_name(name);
398        match self.vm.get_global(&normalized) {
399            Some(value) => T::from_value(value).map(Some),
400            None => Ok(None),
401        }
402    }
403
404    pub fn set_global_value<V: IntoTypedValue>(&mut self, name: impl Into<String>, value: V) {
405        let name_string = name.into();
406        let normalized = normalize_global_name(&name_string);
407        let value = value.into_typed_value().into_value();
408        self.vm.set_global(normalized, value);
409    }
410
411    pub fn struct_instance<I>(
412        &self,
413        type_name: impl Into<String>,
414        fields: I,
415    ) -> Result<StructInstance>
416    where
417        I: IntoIterator,
418        I::Item: Into<StructField>,
419    {
420        let type_name = type_name.into();
421        let def = self
422            .struct_defs
423            .get(&type_name)
424            .ok_or_else(|| LustError::TypeError {
425                message: format!("Unknown struct '{}'", type_name),
426            })?;
427        let mut provided: HashMap<String, TypedValue> = fields
428            .into_iter()
429            .map(|field| {
430                let field: StructField = field.into();
431                field.into_parts()
432            })
433            .collect();
434        let mut ordered_fields: Vec<(Rc<String>, Value)> = Vec::with_capacity(def.fields.len());
435        for field in &def.fields {
436            let typed_value = provided
437                .remove(&field.name)
438                .ok_or_else(|| LustError::TypeError {
439                    message: format!(
440                        "Struct '{}' is missing required field '{}'",
441                        type_name, field.name
442                    ),
443                })?;
444            let matches_declared = typed_value.matches(&field.ty);
445            let matches_ref_inner = matches!(field.ownership, FieldOwnership::Weak)
446                && field
447                    .weak_target
448                    .as_ref()
449                    .map(|inner| typed_value.matches(inner))
450                    .unwrap_or(false);
451            if !(matches_declared || matches_ref_inner) {
452                return Err(LustError::TypeError {
453                    message: format!(
454                        "Struct '{}' field '{}' expects Lust type '{}' but Rust provided '{}'",
455                        type_name,
456                        field.name,
457                        field.ty,
458                        typed_value.description()
459                    ),
460                });
461            }
462
463            ordered_fields.push((Rc::new(field.name.clone()), typed_value.into_value()));
464        }
465
466        if !provided.is_empty() {
467            let extra = provided.keys().cloned().collect::<Vec<_>>().join(", ");
468            return Err(LustError::TypeError {
469                message: format!(
470                    "Struct '{}' received unknown field(s): {}",
471                    type_name, extra
472                ),
473            });
474        }
475
476        let value = self.vm.instantiate_struct(&type_name, ordered_fields)?;
477        Ok(StructInstance::new(type_name.clone(), value))
478    }
479
480    pub fn enum_variant(
481        &self,
482        type_name: impl Into<String>,
483        variant: impl Into<String>,
484    ) -> Result<EnumInstance> {
485        self.enum_variant_with(type_name, variant, std::iter::empty::<Value>())
486    }
487
488    pub fn enum_variant_with<I, V>(
489        &self,
490        type_name: impl Into<String>,
491        variant: impl Into<String>,
492        payload: I,
493    ) -> Result<EnumInstance>
494    where
495        I: IntoIterator<Item = V>,
496        V: IntoTypedValue,
497    {
498        let type_name = type_name.into();
499        let variant_name = variant.into();
500        let def = self
501            .enum_defs
502            .get(&type_name)
503            .ok_or_else(|| LustError::TypeError {
504                message: format!("Unknown enum '{}'", type_name),
505            })?;
506        let enum_variant = def
507            .variants
508            .iter()
509            .find(|v| v.name == variant_name)
510            .ok_or_else(|| LustError::TypeError {
511                message: format!(
512                    "Enum '{}' has no variant named '{}'",
513                    type_name, variant_name
514                ),
515            })?;
516        let mut values: Vec<TypedValue> =
517            payload.into_iter().map(|v| v.into_typed_value()).collect();
518        let coerced_values: Option<Rc<Vec<Value>>> = match &enum_variant.fields {
519            None => {
520                if !values.is_empty() {
521                    return Err(LustError::TypeError {
522                        message: format!(
523                            "Enum variant '{}.{}' does not accept payload values",
524                            type_name, variant_name
525                        ),
526                    });
527                }
528
529                None
530            }
531
532            Some(field_types) => {
533                if values.len() != field_types.len() {
534                    return Err(LustError::TypeError {
535                        message: format!(
536                            "Enum variant '{}.{}' expects {} value(s) but {} were supplied",
537                            type_name,
538                            variant_name,
539                            field_types.len(),
540                            values.len()
541                        ),
542                    });
543                }
544
545                let mut collected = Vec::with_capacity(field_types.len());
546                for (idx, (typed_value, field_ty)) in
547                    values.drain(..).zip(field_types.iter()).enumerate()
548                {
549                    if !typed_value.matches(field_ty) {
550                        return Err(LustError::TypeError {
551                            message: format!(
552                                "Enum variant '{}.{}' field {} expects Lust type '{}' but Rust provided '{}'",
553                                type_name,
554                                variant_name,
555                                idx + 1,
556                                field_ty,
557                                typed_value.description()
558                            ),
559                        });
560                    }
561
562                    collected.push(typed_value.into_value());
563                }
564
565                Some(Rc::new(collected))
566            }
567        };
568        Ok(EnumInstance::new(
569            type_name.clone(),
570            variant_name.clone(),
571            Value::Enum {
572                enum_name: type_name,
573                variant: variant_name,
574                values: coerced_values,
575            },
576        ))
577    }
578
579    pub fn register_native_fn<F>(&mut self, name: impl Into<String>, func: F)
580    where
581        F: Fn(&[Value]) -> std::result::Result<NativeCallResult, String> + 'static,
582    {
583        let native = Value::NativeFunction(Rc::new(func));
584        self.vm.register_native(name, native);
585    }
586
587    pub fn register_async_native<F, Fut>(&mut self, name: impl Into<String>, func: F) -> Result<()>
588    where
589        F: Fn(Vec<Value>) -> Fut + 'static,
590        Fut: Future<Output = std::result::Result<Value, String>> + 'static,
591    {
592        let registry = self.async_registry.clone();
593        let name_string = name.into();
594        let handler = move |values: &[Value]| -> std::result::Result<NativeCallResult, String> {
595            let args: Vec<Value> = values.iter().cloned().collect();
596            let future: AsyncValueFuture = Box::pin(func(args));
597            VM::with_current(|vm| {
598                let handle = vm
599                    .current_task_handle()
600                    .ok_or_else(|| "Async native functions require a running task".to_string())?;
601                registry.borrow_mut().register(handle, future)?;
602                Ok(NativeCallResult::Yield(Value::Nil))
603            })
604        };
605        self.register_native_fn(name_string, handler);
606        Ok(())
607    }
608
609    pub fn register_typed_native<Args, R, F>(&mut self, name: &str, func: F) -> Result<()>
610    where
611        Args: FromLustArgs,
612        R: IntoLustValue + FromLustValue,
613        F: Fn(Args) -> std::result::Result<R, String> + 'static,
614    {
615        let (canonical, signature) = self.resolve_signature(name)?;
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        ensure_return_type::<R>(name, &signature.return_type)?;
626        let handler = move |values: &[Value]| -> std::result::Result<NativeCallResult, String> {
627            let args = Args::from_values(values)?;
628            let result = func(args)?;
629            Ok(NativeCallResult::Return(result.into_value()))
630        };
631        self.register_native_with_aliases(name, canonical, handler);
632        Ok(())
633    }
634
635    pub fn register_async_typed_native<Args, R, F, Fut>(
636        &mut self,
637        name: &str,
638        func: F,
639    ) -> Result<()>
640    where
641        Args: FromLustArgs,
642        R: IntoLustValue + FromLustValue,
643        F: Fn(Args) -> Fut + 'static,
644        Fut: Future<Output = std::result::Result<R, String>> + 'static,
645    {
646        let (canonical, signature) = self.resolve_signature(name)?;
647        let signature = signature.clone();
648        if !Args::matches_signature(&signature.params) {
649            return Err(LustError::TypeError {
650                message: format!(
651                    "Native '{}' argument types do not match Lust signature",
652                    name
653                ),
654            });
655        }
656
657        ensure_return_type::<R>(name, &signature.return_type)?;
658        let registry = self.async_registry.clone();
659        let handler = move |values: &[Value]| -> std::result::Result<NativeCallResult, String> {
660            let args = Args::from_values(values)?;
661            let future = func(args);
662            let mapped = async move {
663                match future.await {
664                    Ok(result) => Ok(result.into_value()),
665                    Err(err) => Err(err),
666                }
667            };
668            let future: AsyncValueFuture = Box::pin(mapped);
669            VM::with_current(|vm| {
670                let handle = vm
671                    .current_task_handle()
672                    .ok_or_else(|| "Async native functions require a running task".to_string())?;
673                registry.borrow_mut().register(handle, future)?;
674                Ok(NativeCallResult::Yield(Value::Nil))
675            })
676        };
677        self.register_native_with_aliases(name, canonical, handler);
678        Ok(())
679    }
680
681    pub fn call_typed<Args, R>(&mut self, function_name: &str, args: Args) -> Result<R>
682    where
683        Args: FunctionArgs,
684        R: FromLustValue,
685    {
686        let signature = self
687            .signatures
688            .get(function_name)
689            .ok_or_else(|| LustError::TypeError {
690                message: format!(
691                    "No type information available for function '{}'; \
692                     use call_raw if the function is dynamically typed",
693                    function_name
694                ),
695            })?;
696        Args::validate_signature(function_name, &signature.params)?;
697        ensure_return_type::<R>(function_name, &signature.return_type)?;
698        let values = args.into_values();
699        let value = self.vm.call(function_name, values)?;
700        R::from_value(value)
701    }
702
703    pub fn call_raw(&mut self, function_name: &str, args: Vec<Value>) -> Result<Value> {
704        self.vm.call(function_name, args)
705    }
706
707    pub fn run_entry_script(&mut self) -> Result<()> {
708        let Some(entry) = &self.entry_script else {
709            return Err(LustError::RuntimeError {
710                message: "Embedded program has no entry script".into(),
711            });
712        };
713        let result = self.vm.call(entry, Vec::new())?;
714        match result {
715            Value::Nil => Ok(()),
716            other => Err(LustError::RuntimeError {
717                message: format!(
718                    "Entry script '{}' returned non-unit value: {:?}",
719                    entry, other
720                ),
721            }),
722        }
723    }
724
725    pub fn poll_async_tasks(&mut self) -> Result<()> {
726        let pending_ids: Vec<u64> = {
727            let registry = self.async_registry.borrow();
728            registry.pending.keys().copied().collect()
729        };
730
731        let mut completions: Vec<(TaskHandle, std::result::Result<Value, String>)> = Vec::new();
732        for id in pending_ids {
733            let handle = TaskHandle(id);
734            if self.vm.get_task_instance(handle).is_err() {
735                self.async_registry.borrow_mut().pending.remove(&id);
736                continue;
737            }
738
739            let maybe_outcome = {
740                let mut registry = self.async_registry.borrow_mut();
741                let entry = match registry.pending.get_mut(&id) {
742                    Some(entry) => entry,
743                    None => continue,
744                };
745
746                if !entry.take_should_poll() {
747                    continue;
748                }
749
750                let waker = entry.make_waker();
751                let mut cx = Context::from_waker(&waker);
752                match entry.future.as_mut().poll(&mut cx) {
753                    Poll::Ready(result) => {
754                        let handle = entry.handle;
755                        registry.pending.remove(&id);
756                        Some((handle, result))
757                    }
758
759                    Poll::Pending => None,
760                }
761            };
762
763            if let Some(outcome) = maybe_outcome {
764                completions.push(outcome);
765            }
766        }
767
768        for (handle, outcome) in completions {
769            match outcome {
770                Ok(value) => {
771                    self.vm.resume_task_handle(handle, Some(value))?;
772                }
773
774                Err(message) => {
775                    self.vm
776                        .fail_task_handle(handle, LustError::RuntimeError { message })?;
777                }
778            }
779        }
780
781        Ok(())
782    }
783
784    pub fn has_pending_async_tasks(&self) -> bool {
785        !self.async_registry.borrow().is_empty()
786    }
787}
788
789fn compile_in_memory(
790    base_dir: PathBuf,
791    entry_module: String,
792    overrides: HashMap<PathBuf, String>,
793    config: LustConfig,
794) -> Result<EmbeddedProgram> {
795    let mut loader = ModuleLoader::new(base_dir.clone());
796    loader.set_source_overrides(overrides);
797    let entry_path = module_path_to_file(&base_dir, &entry_module);
798    let entry_path_str = entry_path
799        .to_str()
800        .ok_or_else(|| LustError::Unknown("Entry path contained invalid UTF-8".into()))?
801        .to_string();
802    let program = loader.load_program_from_entry(&entry_path_str)?;
803    let mut imports_map: HashMap<String, ModuleImports> = HashMap::new();
804    for module in &program.modules {
805        imports_map.insert(module.path.clone(), module.imports.clone());
806    }
807
808    let mut wrapped_items: Vec<Item> = Vec::new();
809    for module in &program.modules {
810        wrapped_items.push(Item::new(
811            ItemKind::Module {
812                name: module.path.clone(),
813                items: module.items.clone(),
814            },
815            Span::new(0, 0, 0, 0),
816        ));
817    }
818
819    let mut typechecker = TypeChecker::with_config(&config);
820    typechecker.set_imports_by_module(imports_map.clone());
821    typechecker.check_program(&program.modules)?;
822    let option_coercions = typechecker.take_option_coercions();
823    let struct_defs = typechecker.struct_definitions();
824    let enum_defs = typechecker.enum_definitions();
825    let mut signatures = typechecker.function_signatures();
826    let mut compiler = Compiler::new();
827    compiler.set_option_coercions(option_coercions);
828    compiler.configure_stdlib(&config);
829    compiler.set_imports_by_module(imports_map);
830    compiler.set_entry_module(program.entry_module.clone());
831    let functions = compiler.compile_module(&wrapped_items)?;
832    let trait_impls = compiler.get_trait_impls().to_vec();
833    let mut init_funcs = Vec::new();
834    for module in &program.modules {
835        if module.path != program.entry_module {
836            if let Some(init) = &module.init_function {
837                init_funcs.push(init.clone());
838            }
839        }
840    }
841
842    let function_names: Vec<String> = functions.iter().map(|f| f.name.clone()).collect();
843    let entry_script = function_names
844        .iter()
845        .find(|name| name.as_str() == "__script")
846        .cloned();
847    if let Some(script_name) = &entry_script {
848        signatures
849            .entry(script_name.clone())
850            .or_insert_with(|| FunctionSignature {
851                params: Vec::new(),
852                return_type: Type::new(TypeKind::Unit, Span::new(0, 0, 0, 0)),
853                is_method: false,
854            });
855    }
856
857    let mut vm = VM::with_config(&config);
858    vm.load_functions(functions);
859    vm.register_structs(&struct_defs);
860    for (type_name, trait_name) in trait_impls {
861        vm.register_trait_impl(type_name, trait_name);
862    }
863
864    for init in init_funcs {
865        vm.call(&init, Vec::new())?;
866    }
867
868    Ok(EmbeddedProgram {
869        vm,
870        signatures,
871        struct_defs,
872        enum_defs,
873        entry_script,
874        entry_module: program.entry_module,
875        async_registry: Rc::new(RefCell::new(AsyncRegistry::new())),
876    })
877}
878
879fn module_path_to_file(base_dir: &Path, module_path: &str) -> PathBuf {
880    let mut path = base_dir.to_path_buf();
881    for segment in module_path.split('.') {
882        path.push(segment);
883    }
884
885    path.set_extension("lust");
886    path
887}
888
889fn normalize_global_name(name: &str) -> String {
890    if name.contains("::") {
891        name.to_string()
892    } else if let Some((module, identifier)) = name.rsplit_once('.') {
893        format!("{}::{}", module, identifier)
894    } else {
895        name.to_string()
896    }
897}
898
899fn ensure_return_type<R: FromLustValue>(function_name: &str, ty: &Type) -> Result<()> {
900    if matches!(ty.kind, TypeKind::Unknown) || R::matches_lust_type(ty) {
901        return Ok(());
902    }
903
904    Err(LustError::TypeError {
905        message: format!(
906            "Function '{}' reports return type '{}' which is incompatible with Rust receiver '{}'",
907            function_name,
908            ty,
909            R::type_description()
910        ),
911    })
912}
913
914pub struct TypedValue {
915    value: Value,
916    matcher: Box<dyn Fn(&Value, &Type) -> bool>,
917    description: &'static str,
918}
919
920impl TypedValue {
921    fn new<F>(value: Value, matcher: F, description: &'static str) -> Self
922    where
923        F: Fn(&Value, &Type) -> bool + 'static,
924    {
925        Self {
926            value,
927            matcher: Box::new(matcher),
928            description,
929        }
930    }
931
932    fn matches(&self, ty: &Type) -> bool {
933        match &ty.kind {
934            TypeKind::Union(types) => types.iter().any(|alt| (self.matcher)(&self.value, alt)),
935            _ => (self.matcher)(&self.value, ty),
936        }
937    }
938
939    fn description(&self) -> &'static str {
940        self.description
941    }
942
943    fn into_value(self) -> Value {
944        self.value
945    }
946}
947
948pub struct StructField {
949    name: String,
950    value: TypedValue,
951}
952
953impl StructField {
954    pub fn new(name: impl Into<String>, value: impl IntoTypedValue) -> Self {
955        Self {
956            name: name.into(),
957            value: value.into_typed_value(),
958        }
959    }
960
961    pub fn name(&self) -> &str {
962        &self.name
963    }
964
965    fn into_parts(self) -> (String, TypedValue) {
966        (self.name, self.value)
967    }
968}
969
970pub fn struct_field(name: impl Into<String>, value: impl IntoTypedValue) -> StructField {
971    StructField::new(name, value)
972}
973
974impl<K, V> From<(K, V)> for StructField
975where
976    K: Into<String>,
977    V: IntoTypedValue,
978{
979    fn from((name, value): (K, V)) -> Self {
980        StructField::new(name, value)
981    }
982}
983
984#[derive(Clone)]
985pub struct StructInstance {
986    type_name: String,
987    value: Value,
988}
989
990impl StructInstance {
991    fn new(type_name: String, value: Value) -> Self {
992        debug_assert!(matches!(value, Value::Struct { .. }));
993        Self { type_name, value }
994    }
995
996    pub fn type_name(&self) -> &str {
997        &self.type_name
998    }
999
1000    pub fn field<T: FromLustValue>(&self, field: &str) -> Result<T> {
1001        let value_ref = self.borrow_field(field)?;
1002        T::from_value(value_ref.into_owned())
1003    }
1004
1005    pub fn borrow_field(&self, field: &str) -> Result<ValueRef<'_>> {
1006        match &self.value {
1007            Value::Struct { layout, fields, .. } => {
1008                let index = layout
1009                    .index_of_str(field)
1010                    .ok_or_else(|| LustError::RuntimeError {
1011                        message: format!(
1012                            "Struct '{}' has no field named '{}'",
1013                            self.type_name, field
1014                        ),
1015                    })?;
1016                match layout.field_storage(index) {
1017                    FieldStorage::Strong => {
1018                        let slots = fields.borrow();
1019                        if slots.get(index).is_none() {
1020                            return Err(LustError::RuntimeError {
1021                                message: format!(
1022                                    "Struct '{}' field '{}' is unavailable",
1023                                    self.type_name, field
1024                                ),
1025                            });
1026                        }
1027
1028                        Ok(ValueRef::borrowed(Ref::map(slots, move |values| {
1029                            &values[index]
1030                        })))
1031                    }
1032
1033                    FieldStorage::Weak => {
1034                        let stored = {
1035                            let slots = fields.borrow();
1036                            slots
1037                                .get(index)
1038                                .cloned()
1039                                .ok_or_else(|| LustError::RuntimeError {
1040                                    message: format!(
1041                                        "Struct '{}' field '{}' is unavailable",
1042                                        self.type_name, field
1043                                    ),
1044                                })?
1045                        };
1046                        let materialized = layout.materialize_field_value(index, stored);
1047                        Ok(ValueRef::owned(materialized))
1048                    }
1049                }
1050            }
1051
1052            _ => Err(LustError::RuntimeError {
1053                message: "StructInstance does not contain a struct value".to_string(),
1054            }),
1055        }
1056    }
1057
1058    pub fn set_field<V: IntoTypedValue>(&self, field: &str, value: V) -> Result<()> {
1059        match &self.value {
1060            Value::Struct { layout, fields, .. } => {
1061                let index = layout
1062                    .index_of_str(field)
1063                    .ok_or_else(|| LustError::RuntimeError {
1064                        message: format!(
1065                            "Struct '{}' has no field named '{}'",
1066                            self.type_name, field
1067                        ),
1068                    })?;
1069                let typed_value = value.into_typed_value();
1070                let matches_declared = typed_value.matches(layout.field_type(index));
1071                let matches_ref_inner = layout.is_weak(index)
1072                    && layout
1073                        .weak_target(index)
1074                        .map(|inner| typed_value.matches(inner))
1075                        .unwrap_or(false);
1076                if !(matches_declared || matches_ref_inner) {
1077                    return Err(LustError::TypeError {
1078                        message: format!(
1079                            "Struct '{}' field '{}' expects Lust type '{}' but Rust provided '{}'",
1080                            self.type_name,
1081                            field,
1082                            layout.field_type(index),
1083                            typed_value.description()
1084                        ),
1085                    });
1086                }
1087
1088                let canonical_value = layout
1089                    .canonicalize_field_value(index, typed_value.into_value())
1090                    .map_err(|message| LustError::TypeError { message })?;
1091                fields.borrow_mut()[index] = canonical_value;
1092                Ok(())
1093            }
1094
1095            _ => Err(LustError::RuntimeError {
1096                message: "StructInstance does not contain a struct value".to_string(),
1097            }),
1098        }
1099    }
1100
1101    pub fn update_field<F, V>(&self, field: &str, update: F) -> Result<()>
1102    where
1103        F: FnOnce(Value) -> Result<V>,
1104        V: IntoTypedValue,
1105    {
1106        match &self.value {
1107            Value::Struct { layout, fields, .. } => {
1108                let index = layout
1109                    .index_of_str(field)
1110                    .ok_or_else(|| LustError::RuntimeError {
1111                        message: format!(
1112                            "Struct '{}' has no field named '{}'",
1113                            self.type_name, field
1114                        ),
1115                    })?;
1116                let mut slots = fields.borrow_mut();
1117                let slot = slots
1118                    .get_mut(index)
1119                    .ok_or_else(|| LustError::RuntimeError {
1120                        message: format!(
1121                            "Struct '{}' field '{}' is unavailable",
1122                            self.type_name, field
1123                        ),
1124                    })?;
1125                let fallback = slot.clone();
1126                let current_canonical = std::mem::replace(slot, Value::Nil);
1127                let current_materialized = layout.materialize_field_value(index, current_canonical);
1128                let updated = match update(current_materialized) {
1129                    Ok(value) => value,
1130                    Err(err) => {
1131                        *slot = fallback;
1132                        return Err(err);
1133                    }
1134                };
1135                let typed_value = updated.into_typed_value();
1136                let matches_declared = typed_value.matches(layout.field_type(index));
1137                let matches_ref_inner = layout.is_weak(index)
1138                    && layout
1139                        .weak_target(index)
1140                        .map(|inner| typed_value.matches(inner))
1141                        .unwrap_or(false);
1142                if !(matches_declared || matches_ref_inner) {
1143                    *slot = fallback;
1144                    return Err(LustError::TypeError {
1145                        message: format!(
1146                            "Struct '{}' field '{}' expects Lust type '{}' but Rust provided '{}'",
1147                            self.type_name,
1148                            field,
1149                            layout.field_type(index),
1150                            typed_value.description()
1151                        ),
1152                    });
1153                }
1154
1155                let canonical_value = layout
1156                    .canonicalize_field_value(index, typed_value.into_value())
1157                    .map_err(|message| LustError::TypeError { message })?;
1158                *slot = canonical_value;
1159                Ok(())
1160            }
1161
1162            _ => Err(LustError::RuntimeError {
1163                message: "StructInstance does not contain a struct value".to_string(),
1164            }),
1165        }
1166    }
1167
1168    pub fn as_value(&self) -> &Value {
1169        &self.value
1170    }
1171}
1172
1173pub enum ValueRef<'a> {
1174    Borrowed(Ref<'a, Value>),
1175    Owned(Value),
1176}
1177
1178impl<'a> ValueRef<'a> {
1179    fn borrowed(inner: Ref<'a, Value>) -> Self {
1180        Self::Borrowed(inner)
1181    }
1182
1183    fn owned(value: Value) -> Self {
1184        Self::Owned(value)
1185    }
1186
1187    pub fn as_value(&self) -> &Value {
1188        match self {
1189            ValueRef::Borrowed(inner) => &*inner,
1190            ValueRef::Owned(value) => value,
1191        }
1192    }
1193
1194    pub fn to_owned(&self) -> Value {
1195        self.as_value().clone()
1196    }
1197
1198    pub fn into_owned(self) -> Value {
1199        match self {
1200            ValueRef::Borrowed(inner) => inner.clone(),
1201            ValueRef::Owned(value) => value,
1202        }
1203    }
1204
1205    pub fn as_bool(&self) -> Option<bool> {
1206        match self.as_value() {
1207            Value::Bool(value) => Some(*value),
1208            _ => None,
1209        }
1210    }
1211
1212    pub fn as_int(&self) -> Option<LustInt> {
1213        self.as_value().as_int()
1214    }
1215
1216    pub fn as_float(&self) -> Option<LustFloat> {
1217        self.as_value().as_float()
1218    }
1219
1220    pub fn as_string(&self) -> Option<&str> {
1221        self.as_value().as_string()
1222    }
1223
1224    pub fn as_rc_string(&self) -> Option<Rc<String>> {
1225        match self.as_value() {
1226            Value::String(value) => Some(value.clone()),
1227            _ => None,
1228        }
1229    }
1230
1231    pub fn as_array_handle(&self) -> Option<ArrayHandle> {
1232        match self.as_value() {
1233            Value::Array(items) => Some(ArrayHandle::from_rc(items.clone())),
1234            _ => None,
1235        }
1236    }
1237
1238    pub fn as_map_handle(&self) -> Option<MapHandle> {
1239        match self.as_value() {
1240            Value::Map(map) => Some(MapHandle::from_rc(map.clone())),
1241            _ => None,
1242        }
1243    }
1244}
1245
1246#[derive(Clone)]
1247pub struct ArrayHandle {
1248    inner: Rc<RefCell<Vec<Value>>>,
1249}
1250
1251impl ArrayHandle {
1252    fn from_rc(inner: Rc<RefCell<Vec<Value>>>) -> Self {
1253        Self { inner }
1254    }
1255
1256    pub fn len(&self) -> usize {
1257        self.inner.borrow().len()
1258    }
1259
1260    pub fn is_empty(&self) -> bool {
1261        self.len() == 0
1262    }
1263
1264    pub fn borrow(&self) -> Ref<'_, [Value]> {
1265        Ref::map(self.inner.borrow(), |values| values.as_slice())
1266    }
1267
1268    pub fn borrow_mut(&self) -> RefMut<'_, Vec<Value>> {
1269        self.inner.borrow_mut()
1270    }
1271
1272    pub fn push(&self, value: Value) {
1273        self.inner.borrow_mut().push(value);
1274    }
1275
1276    pub fn extend<I>(&self, iter: I)
1277    where
1278        I: IntoIterator<Item = Value>,
1279    {
1280        self.inner.borrow_mut().extend(iter);
1281    }
1282
1283    pub fn get(&self, index: usize) -> Option<ValueRef<'_>> {
1284        {
1285            let values = self.inner.borrow();
1286            if values.get(index).is_none() {
1287                return None;
1288            }
1289        }
1290
1291        let values = self.inner.borrow();
1292        Some(ValueRef::borrowed(Ref::map(values, move |items| {
1293            &items[index]
1294        })))
1295    }
1296
1297    pub fn with_ref<R>(&self, f: impl FnOnce(&[Value]) -> R) -> R {
1298        let values = self.inner.borrow();
1299        f(values.as_slice())
1300    }
1301
1302    pub fn with_mut<R>(&self, f: impl FnOnce(&mut Vec<Value>) -> R) -> R {
1303        let mut values = self.inner.borrow_mut();
1304        f(&mut values)
1305    }
1306}
1307
1308#[derive(Clone)]
1309pub struct MapHandle {
1310    inner: Rc<RefCell<HashMap<ValueKey, Value>>>,
1311}
1312
1313impl MapHandle {
1314    fn from_rc(inner: Rc<RefCell<HashMap<ValueKey, Value>>>) -> Self {
1315        Self { inner }
1316    }
1317
1318    pub fn len(&self) -> usize {
1319        self.inner.borrow().len()
1320    }
1321
1322    pub fn is_empty(&self) -> bool {
1323        self.len() == 0
1324    }
1325
1326    pub fn borrow(&self) -> Ref<'_, HashMap<ValueKey, Value>> {
1327        self.inner.borrow()
1328    }
1329
1330    pub fn borrow_mut(&self) -> RefMut<'_, HashMap<ValueKey, Value>> {
1331        self.inner.borrow_mut()
1332    }
1333
1334    pub fn contains_key<K>(&self, key: K) -> bool
1335    where
1336        K: Into<ValueKey>,
1337    {
1338        self.inner.borrow().contains_key(&key.into())
1339    }
1340
1341    pub fn get<K>(&self, key: K) -> Option<ValueRef<'_>>
1342    where
1343        K: Into<ValueKey>,
1344    {
1345        let key = key.into();
1346        {
1347            if !self.inner.borrow().contains_key(&key) {
1348                return None;
1349            }
1350        }
1351        let lookup = key.clone();
1352        let map = self.inner.borrow();
1353        Some(ValueRef::borrowed(Ref::map(map, move |values| {
1354            values
1355                .get(&lookup)
1356                .expect("lookup key should be present after contains_key")
1357        })))
1358    }
1359
1360    pub fn insert<K>(&self, key: K, value: Value) -> Option<Value>
1361    where
1362        K: Into<ValueKey>,
1363    {
1364        self.inner.borrow_mut().insert(key.into(), value)
1365    }
1366
1367    pub fn remove<K>(&self, key: K) -> Option<Value>
1368    where
1369        K: Into<ValueKey>,
1370    {
1371        self.inner.borrow_mut().remove(&key.into())
1372    }
1373
1374    pub fn with_ref<R>(&self, f: impl FnOnce(&HashMap<ValueKey, Value>) -> R) -> R {
1375        let map = self.inner.borrow();
1376        f(&map)
1377    }
1378
1379    pub fn with_mut<R>(&self, f: impl FnOnce(&mut HashMap<ValueKey, Value>) -> R) -> R {
1380        let mut map = self.inner.borrow_mut();
1381        f(&mut map)
1382    }
1383}
1384
1385#[derive(Clone)]
1386pub struct EnumInstance {
1387    type_name: String,
1388    variant: String,
1389    value: Value,
1390}
1391
1392impl EnumInstance {
1393    fn new(type_name: String, variant: String, value: Value) -> Self {
1394        debug_assert!(matches!(value, Value::Enum { .. }));
1395        Self {
1396            type_name,
1397            variant,
1398            value,
1399        }
1400    }
1401
1402    pub fn type_name(&self) -> &str {
1403        &self.type_name
1404    }
1405
1406    pub fn variant(&self) -> &str {
1407        &self.variant
1408    }
1409
1410    pub fn payload_len(&self) -> usize {
1411        match &self.value {
1412            Value::Enum { values, .. } => values.as_ref().map(|v| v.len()).unwrap_or(0),
1413            _ => 0,
1414        }
1415    }
1416
1417    pub fn payload<T: FromLustValue>(&self, index: usize) -> Result<T> {
1418        match &self.value {
1419            Value::Enum { values, .. } => {
1420                let values = values.as_ref().ok_or_else(|| LustError::RuntimeError {
1421                    message: format!(
1422                        "Enum variant '{}.{}' carries no payload",
1423                        self.type_name, self.variant
1424                    ),
1425                })?;
1426                let stored = values
1427                    .get(index)
1428                    .cloned()
1429                    .ok_or_else(|| LustError::RuntimeError {
1430                        message: format!(
1431                            "Enum variant '{}.{}' payload index {} is out of bounds",
1432                            self.type_name, self.variant, index
1433                        ),
1434                    })?;
1435                T::from_value(stored)
1436            }
1437
1438            _ => Err(LustError::RuntimeError {
1439                message: "EnumInstance does not contain an enum value".to_string(),
1440            }),
1441        }
1442    }
1443
1444    pub fn as_value(&self) -> &Value {
1445        &self.value
1446    }
1447}
1448
1449pub trait IntoTypedValue {
1450    fn into_typed_value(self) -> TypedValue;
1451}
1452
1453impl IntoTypedValue for Value {
1454    fn into_typed_value(self) -> TypedValue {
1455        TypedValue::new(self, |_value, _ty| true, "Value")
1456    }
1457}
1458
1459impl IntoTypedValue for StructInstance {
1460    fn into_typed_value(self) -> TypedValue {
1461        let StructInstance {
1462            type_name: _,
1463            value,
1464        } = self;
1465        TypedValue::new(value, |v, ty| matches_lust_struct(v, ty), "struct")
1466    }
1467}
1468
1469impl IntoTypedValue for EnumInstance {
1470    fn into_typed_value(self) -> TypedValue {
1471        let EnumInstance {
1472            type_name: _,
1473            variant: _,
1474            value,
1475        } = self;
1476        TypedValue::new(value, |v, ty| matches_lust_enum(v, ty), "enum")
1477    }
1478}
1479
1480macro_rules! impl_into_typed_for_primitive {
1481    ($ty:ty, $desc:expr, $matcher:expr) => {
1482        impl IntoTypedValue for $ty {
1483            fn into_typed_value(self) -> TypedValue {
1484                let value = self.into_value();
1485                TypedValue::new(value, $matcher, $desc)
1486            }
1487        }
1488    };
1489}
1490
1491impl_into_typed_for_primitive!(LustInt, "int", |_, ty: &Type| match &ty.kind {
1492    TypeKind::Int | TypeKind::Unknown => true,
1493    TypeKind::Union(types) => types
1494        .iter()
1495        .any(|alt| matches!(&alt.kind, TypeKind::Int | TypeKind::Unknown)),
1496    _ => false,
1497});
1498impl_into_typed_for_primitive!(LustFloat, "float", |_, ty: &Type| match &ty.kind {
1499    TypeKind::Float | TypeKind::Unknown => true,
1500    TypeKind::Union(types) => types
1501        .iter()
1502        .any(|alt| matches!(&alt.kind, TypeKind::Float | TypeKind::Unknown)),
1503    _ => false,
1504});
1505impl_into_typed_for_primitive!(bool, "bool", |_, ty: &Type| match &ty.kind {
1506    TypeKind::Bool | TypeKind::Unknown => true,
1507    TypeKind::Union(types) => types
1508        .iter()
1509        .any(|alt| matches!(&alt.kind, TypeKind::Bool | TypeKind::Unknown)),
1510    _ => false,
1511});
1512impl IntoTypedValue for String {
1513    fn into_typed_value(self) -> TypedValue {
1514        let value = self.into_value();
1515        TypedValue::new(value, string_matcher, "string")
1516    }
1517}
1518
1519impl<'a> IntoTypedValue for &'a str {
1520    fn into_typed_value(self) -> TypedValue {
1521        let value = self.into_value();
1522        TypedValue::new(value, string_matcher, "string")
1523    }
1524}
1525
1526impl<'a> IntoTypedValue for &'a String {
1527    fn into_typed_value(self) -> TypedValue {
1528        let value = self.into_value();
1529        TypedValue::new(value, string_matcher, "string")
1530    }
1531}
1532
1533impl IntoTypedValue for () {
1534    fn into_typed_value(self) -> TypedValue {
1535        TypedValue::new(
1536            Value::Nil,
1537            |_, ty| matches!(ty.kind, TypeKind::Unit | TypeKind::Unknown),
1538            "unit",
1539        )
1540    }
1541}
1542
1543impl<T> IntoTypedValue for Vec<T>
1544where
1545    T: IntoLustValue,
1546{
1547    fn into_typed_value(self) -> TypedValue {
1548        let values = self.into_iter().map(|item| item.into_value()).collect();
1549        TypedValue::new(
1550            Value::array(values),
1551            |_, ty| matches_array_type(ty, &T::matches_lust_type),
1552            "array",
1553        )
1554    }
1555}
1556
1557impl IntoTypedValue for ArrayHandle {
1558    fn into_typed_value(self) -> TypedValue {
1559        let value = self.into_value();
1560        TypedValue::new(value, |_, ty| matches_array_handle_type(ty), "array")
1561    }
1562}
1563
1564impl IntoTypedValue for MapHandle {
1565    fn into_typed_value(self) -> TypedValue {
1566        let value = self.into_value();
1567        TypedValue::new(value, |_, ty| matches_map_handle_type(ty), "map")
1568    }
1569}
1570
1571fn string_matcher(_: &Value, ty: &Type) -> bool {
1572    match &ty.kind {
1573        TypeKind::String | TypeKind::Unknown => true,
1574        TypeKind::Union(types) => types
1575            .iter()
1576            .any(|alt| matches!(&alt.kind, TypeKind::String | TypeKind::Unknown)),
1577        _ => false,
1578    }
1579}
1580
1581#[cfg(test)]
1582mod tests {
1583    use super::*;
1584    use std::future::Future;
1585    use std::pin::Pin;
1586    use std::sync::{Arc, Mutex};
1587    use std::task::{Context, Poll, Waker};
1588
1589    #[derive(Default)]
1590    struct ManualAsyncState {
1591        result: Mutex<Option<std::result::Result<LustInt, String>>>,
1592        waker: Mutex<Option<Waker>>,
1593    }
1594
1595    impl ManualAsyncState {
1596        fn new() -> Arc<Self> {
1597            Arc::new(Self::default())
1598        }
1599
1600        fn future(self: &Arc<Self>) -> ManualFuture {
1601            ManualFuture {
1602                state: Arc::clone(self),
1603            }
1604        }
1605
1606        fn complete_ok(&self, value: LustInt) {
1607            self.complete(Ok(value));
1608        }
1609
1610        fn complete_err(&self, message: impl Into<String>) {
1611            self.complete(Err(message.into()));
1612        }
1613
1614        fn complete(&self, value: std::result::Result<LustInt, String>) {
1615            {
1616                let mut slot = self.result.lock().unwrap();
1617                *slot = Some(value);
1618            }
1619
1620            if let Some(waker) = self.waker.lock().unwrap().take() {
1621                waker.wake();
1622            }
1623        }
1624    }
1625
1626    struct ManualFuture {
1627        state: Arc<ManualAsyncState>,
1628    }
1629
1630    impl Future for ManualFuture {
1631        type Output = std::result::Result<LustInt, String>;
1632
1633        fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
1634            {
1635                let mut slot = self.state.result.lock().unwrap();
1636                if let Some(result) = slot.take() {
1637                    return Poll::Ready(result);
1638                }
1639            }
1640
1641            let mut waker_slot = self.state.waker.lock().unwrap();
1642            *waker_slot = Some(cx.waker().clone());
1643            Poll::Pending
1644        }
1645    }
1646
1647    fn build_program(source: &str) -> EmbeddedProgram {
1648        EmbeddedProgram::builder()
1649            .module("main", source)
1650            .entry_module("main")
1651            .compile()
1652            .expect("compile embedded program")
1653    }
1654
1655    #[test]
1656    fn struct_instance_supports_mixed_field_types() {
1657        let source = r#"
1658            struct Mixed
1659                count: int
1660                label: string
1661                enabled: bool
1662            end
1663        "#;
1664
1665        let program = build_program(source);
1666        let mixed = program
1667            .struct_instance(
1668                "main.Mixed",
1669                [
1670                    struct_field("count", 7_i64),
1671                    struct_field("label", "hi"),
1672                    struct_field("enabled", true),
1673                ],
1674            )
1675            .expect("struct instance");
1676
1677        assert_eq!(mixed.field::<i64>("count").expect("count field"), 7);
1678        assert_eq!(mixed.field::<String>("label").expect("label field"), "hi");
1679        assert!(mixed.field::<bool>("enabled").expect("enabled field"));
1680    }
1681
1682    #[test]
1683    fn struct_instance_borrow_field_provides_reference_view() {
1684        let source = r#"
1685            struct Sample
1686                name: string
1687            end
1688        "#;
1689
1690        let program = build_program(source);
1691        let sample = program
1692            .struct_instance("main.Sample", [struct_field("name", "Borrowed")])
1693            .expect("struct instance");
1694
1695        let name_ref = sample.borrow_field("name").expect("borrow name field");
1696        assert_eq!(name_ref.as_string().unwrap(), "Borrowed");
1697        assert!(name_ref.as_array_handle().is_none());
1698    }
1699
1700    #[test]
1701    fn array_handle_allows_in_place_mutation() {
1702        let value = Value::array(vec![Value::Int(1)]);
1703        let handle = ArrayHandle::from_value(value).expect("array handle");
1704
1705        {
1706            let mut slots = handle.borrow_mut();
1707            slots.push(Value::Int(2));
1708            slots.push(Value::Int(3));
1709        }
1710
1711        let snapshot: Vec<_> = handle
1712            .borrow()
1713            .iter()
1714            .map(|value| value.as_int().expect("int value"))
1715            .collect();
1716        assert_eq!(snapshot, vec![1, 2, 3]);
1717    }
1718
1719    #[test]
1720    fn struct_instance_allows_setting_fields() {
1721        let source = r#"
1722            struct Mixed
1723                count: int
1724                label: string
1725                enabled: bool
1726            end
1727        "#;
1728
1729        let program = build_program(source);
1730        let mixed = program
1731            .struct_instance(
1732                "main.Mixed",
1733                [
1734                    struct_field("count", 1_i64),
1735                    struct_field("label", "start"),
1736                    struct_field("enabled", false),
1737                ],
1738            )
1739            .expect("struct instance");
1740
1741        mixed
1742            .set_field("count", 11_i64)
1743            .expect("update count field");
1744        assert_eq!(mixed.field::<i64>("count").expect("count field"), 11);
1745
1746        let err = mixed
1747            .set_field("count", "oops")
1748            .expect_err("type mismatch should fail");
1749        match err {
1750            LustError::TypeError { message } => {
1751                assert!(message.contains("count"));
1752                assert!(message.contains("int"));
1753            }
1754            other => panic!("unexpected error: {other:?}"),
1755        }
1756        assert_eq!(mixed.field::<i64>("count").expect("count field"), 11);
1757
1758        mixed
1759            .set_field("label", String::from("updated"))
1760            .expect("update label");
1761        assert_eq!(
1762            mixed.field::<String>("label").expect("label field"),
1763            "updated"
1764        );
1765
1766        mixed.set_field("enabled", true).expect("update enabled");
1767        assert!(mixed.field::<bool>("enabled").expect("enabled field"));
1768    }
1769
1770    #[test]
1771    fn struct_instance_accepts_nested_structs() {
1772        let source = r#"
1773            struct Child
1774                value: int
1775            end
1776
1777            struct Parent
1778                child: main.Child
1779            end
1780        "#;
1781
1782        let program = build_program(source);
1783        let child = program
1784            .struct_instance("main.Child", [struct_field("value", 42_i64)])
1785            .expect("child struct");
1786        let parent = program
1787            .struct_instance("main.Parent", [struct_field("child", child.clone())])
1788            .expect("parent struct");
1789
1790        let nested: StructInstance = parent.field("child").expect("child field");
1791        assert_eq!(nested.field::<i64>("value").expect("value field"), 42);
1792    }
1793
1794    #[test]
1795    fn globals_snapshot_exposes_lust_values() {
1796        let source = r#"
1797            struct Child
1798                value: int
1799            end
1800
1801            struct Parent
1802                child: unknown
1803            end
1804
1805            function make_parent(): Parent
1806                return Parent { child = Child { value = 3 } }
1807            end
1808        "#;
1809
1810        let mut program = build_program(source);
1811        program.run_entry_script().expect("run entry script");
1812        let parent: StructInstance = program
1813            .call_typed("main.make_parent", ())
1814            .expect("call make_parent");
1815        program.set_global_value("main.some_nested_structure", parent.clone());
1816
1817        let globals = program.globals();
1818        let (_, value) = globals
1819            .into_iter()
1820            .find(|(name, _)| name.ends_with("some_nested_structure"))
1821            .expect("global binding present");
1822        let stored = StructInstance::from_value(value).expect("convert to struct");
1823        let child_value = stored
1824            .field::<StructInstance>("child")
1825            .expect("nested child");
1826        assert_eq!(child_value.field::<i64>("value").expect("child value"), 3);
1827    }
1828
1829    #[test]
1830    fn update_field_modifies_value_in_place() {
1831        let source = r#"
1832            struct Counter
1833                value: int
1834            end
1835        "#;
1836
1837        let program = build_program(source);
1838        let counter = program
1839            .struct_instance("main.Counter", [struct_field("value", 10_i64)])
1840            .expect("counter struct");
1841
1842        counter
1843            .update_field("value", |current| match current {
1844                Value::Int(v) => Ok(v + 5),
1845                other => Err(LustError::RuntimeError {
1846                    message: format!("unexpected value {other:?}"),
1847                }),
1848            })
1849            .expect("update in place");
1850        assert_eq!(counter.field::<i64>("value").expect("value field"), 15);
1851
1852        let err = counter
1853            .update_field("value", |_| Ok(String::from("oops")))
1854            .expect_err("string should fail type check");
1855        match err {
1856            LustError::TypeError { message } => {
1857                assert!(message.contains("value"));
1858                assert!(message.contains("int"));
1859            }
1860            other => panic!("unexpected error: {other:?}"),
1861        }
1862        assert_eq!(counter.field::<i64>("value").expect("value field"), 15);
1863
1864        let err = counter
1865            .update_field("value", |_| -> Result<i64> {
1866                Err(LustError::RuntimeError {
1867                    message: "closure failure".to_string(),
1868                })
1869            })
1870            .expect_err("closure error should propagate");
1871        match err {
1872            LustError::RuntimeError { message } => assert_eq!(message, "closure failure"),
1873            other => panic!("unexpected error: {other:?}"),
1874        }
1875        assert_eq!(counter.field::<i64>("value").expect("value field"), 15);
1876    }
1877
1878    #[test]
1879    fn async_native_resumes_task_on_completion() {
1880        let source = r#"
1881            extern {
1882                function fetch_value(): int
1883            }
1884
1885            function compute(): int
1886                return fetch_value()
1887            end
1888        "#;
1889
1890        let mut program = build_program(source);
1891
1892        let state = ManualAsyncState::new();
1893        let register_state = Arc::clone(&state);
1894        program
1895            .register_async_typed_native::<(), LustInt, _, _>("fetch_value", move |_| {
1896                register_state.future()
1897            })
1898            .expect("register async native");
1899
1900        let handle = {
1901            let vm = program.vm_mut();
1902            let compute_fn = vm.function_value("main.compute").expect("compute function");
1903            vm.spawn_task_value(compute_fn, Vec::new())
1904                .expect("spawn task")
1905        };
1906
1907        assert!(program.has_pending_async_tasks());
1908        program.poll_async_tasks().expect("initial poll");
1909        assert!(program.has_pending_async_tasks());
1910
1911        state.complete_ok(123);
1912        program.poll_async_tasks().expect("resume after completion");
1913
1914        {
1915            let vm = program.vm_mut();
1916            let task = vm.get_task_instance(handle).expect("task exists");
1917            let result = task
1918                .last_result
1919                .as_ref()
1920                .and_then(|value| value.as_int())
1921                .expect("task produced result");
1922            assert_eq!(result, 123);
1923            assert!(task.error.is_none());
1924        }
1925
1926        assert!(!program.has_pending_async_tasks());
1927    }
1928
1929    #[test]
1930    fn async_native_failure_marks_task_failed() {
1931        let source = r#"
1932            extern {
1933                function fetch_value(): int
1934            }
1935
1936            function compute(): int
1937                return fetch_value()
1938            end
1939        "#;
1940
1941        let mut program = build_program(source);
1942
1943        let state = ManualAsyncState::new();
1944        let register_state = Arc::clone(&state);
1945        program
1946            .register_async_typed_native::<(), LustInt, _, _>("fetch_value", move |_| {
1947                register_state.future()
1948            })
1949            .expect("register async native");
1950
1951        let handle = {
1952            let vm = program.vm_mut();
1953            let compute_fn = vm.function_value("main.compute").expect("compute function");
1954            vm.spawn_task_value(compute_fn, Vec::new())
1955                .expect("spawn task")
1956        };
1957
1958        program.poll_async_tasks().expect("initial poll");
1959        state.complete_err("boom");
1960        let err = program
1961            .poll_async_tasks()
1962            .expect_err("poll should propagate failure");
1963        match err {
1964            LustError::RuntimeError { message } => assert_eq!(message, "boom"),
1965            other => panic!("unexpected error: {other:?}"),
1966        }
1967
1968        {
1969            let vm = program.vm_mut();
1970            let task = vm.get_task_instance(handle).expect("task exists");
1971            assert!(task.last_result.is_none());
1972            let error_message = task
1973                .error
1974                .as_ref()
1975                .map(|e| e.to_string())
1976                .expect("task should record error");
1977            assert!(error_message.contains("boom"));
1978        }
1979
1980        assert!(!program.has_pending_async_tasks());
1981    }
1982}
1983
1984fn matches_lust_struct(value: &Value, ty: &Type) -> bool {
1985    match (value, &ty.kind) {
1986        (Value::Struct { name, .. }, TypeKind::Named(expected)) => {
1987            lust_type_names_match(name, expected)
1988        }
1989        (Value::Struct { name, .. }, TypeKind::GenericInstance { name: expected, .. }) => {
1990            lust_type_names_match(name, expected)
1991        }
1992
1993        (value, TypeKind::Union(types)) => types.iter().any(|alt| matches_lust_struct(value, alt)),
1994        (_, TypeKind::Unknown) => true,
1995        _ => false,
1996    }
1997}
1998
1999fn matches_lust_enum(value: &Value, ty: &Type) -> bool {
2000    match (value, &ty.kind) {
2001        (Value::Enum { enum_name, .. }, TypeKind::Named(expected)) => {
2002            lust_type_names_match(enum_name, expected)
2003        }
2004        (Value::Enum { enum_name, .. }, TypeKind::GenericInstance { name: expected, .. }) => {
2005            lust_type_names_match(enum_name, expected)
2006        }
2007
2008        (value, TypeKind::Union(types)) => types.iter().any(|alt| matches_lust_enum(value, alt)),
2009        (_, TypeKind::Unknown) => true,
2010        _ => false,
2011    }
2012}
2013
2014fn lust_type_names_match(value: &str, expected: &str) -> bool {
2015    if value == expected {
2016        return true;
2017    }
2018
2019    let normalized_value = normalize_global_name(value);
2020    let normalized_expected = normalize_global_name(expected);
2021    if normalized_value == normalized_expected {
2022        return true;
2023    }
2024
2025    simple_type_name(&normalized_value) == simple_type_name(&normalized_expected)
2026}
2027
2028fn simple_type_name(name: &str) -> &str {
2029    name.rsplit(|c| c == '.' || c == ':').next().unwrap_or(name)
2030}
2031
2032fn matches_array_type<F>(ty: &Type, matcher: &F) -> bool
2033where
2034    F: Fn(&Type) -> bool,
2035{
2036    match &ty.kind {
2037        TypeKind::Array(inner) => matcher(inner),
2038        TypeKind::Unknown => true,
2039        TypeKind::Union(types) => types.iter().any(|alt| matches_array_type(alt, matcher)),
2040        _ => false,
2041    }
2042}
2043
2044fn matches_array_handle_type(ty: &Type) -> bool {
2045    match &ty.kind {
2046        TypeKind::Array(_) | TypeKind::Unknown => true,
2047        TypeKind::Union(types) => types.iter().any(|alt| matches_array_handle_type(alt)),
2048        _ => false,
2049    }
2050}
2051
2052fn matches_map_handle_type(ty: &Type) -> bool {
2053    match &ty.kind {
2054        TypeKind::Map(_, _) | TypeKind::Unknown => true,
2055        TypeKind::Union(types) => types.iter().any(|alt| matches_map_handle_type(alt)),
2056        _ => false,
2057    }
2058}
2059
2060pub trait FromLustArgs: Sized {
2061    fn from_values(values: &[Value]) -> std::result::Result<Self, String>;
2062    fn matches_signature(params: &[Type]) -> bool;
2063}
2064
2065macro_rules! impl_from_lust_args_tuple {
2066    ($( $name:ident ),+) => {
2067        impl<$($name),+> FromLustArgs for ($($name,)+)
2068        where
2069            $($name: FromLustValue,)+
2070        {
2071            fn from_values(values: &[Value]) -> std::result::Result<Self, String> {
2072                let expected = count_idents!($($name),+);
2073                if values.len() != expected {
2074                    return Err(format!(
2075                        "Native function expected {} argument(s) but received {}",
2076                        expected,
2077                        values.len()
2078                    ));
2079                }
2080
2081                let mut idx = 0;
2082                let result = (
2083                    $(
2084                        {
2085                            let value = $name::from_value(values[idx].clone()).map_err(|e| e.to_string())?;
2086                            idx += 1;
2087                            value
2088                        },
2089                    )+
2090                );
2091                let _ = idx;
2092                Ok(result)
2093            }
2094
2095            fn matches_signature(params: &[Type]) -> bool {
2096                let expected = count_idents!($($name),+);
2097                params.len() == expected && {
2098                    let mut idx = 0;
2099                    let mut ok = true;
2100                    $(
2101                        if ok && !$name::matches_lust_type(&params[idx]) {
2102                            ok = false;
2103                        }
2104
2105                        idx += 1;
2106                    )+
2107                    let _ = idx;
2108                    ok
2109                }
2110
2111            }
2112
2113        }
2114
2115    };
2116}
2117
2118macro_rules! count_idents {
2119    ($($name:ident),*) => {
2120        <[()]>::len(&[$(count_idents!(@sub $name)),*])
2121    };
2122    (@sub $name:ident) => { () };
2123}
2124
2125impl_from_lust_args_tuple!(A);
2126impl_from_lust_args_tuple!(A, B);
2127impl_from_lust_args_tuple!(A, B, C);
2128impl_from_lust_args_tuple!(A, B, C, D);
2129impl_from_lust_args_tuple!(A, B, C, D, E);
2130impl<T> FromLustArgs for T
2131where
2132    T: FromLustValue,
2133{
2134    fn from_values(values: &[Value]) -> std::result::Result<Self, String> {
2135        match values.len() {
2136            0 => T::from_value(Value::Nil).map_err(|e| e.to_string()),
2137            1 => T::from_value(values[0].clone()).map_err(|e| e.to_string()),
2138            count => Err(format!(
2139                "Native function expected 1 argument but received {}",
2140                count
2141            )),
2142        }
2143    }
2144
2145    fn matches_signature(params: &[Type]) -> bool {
2146        if params.is_empty() {
2147            let unit = Type::new(TypeKind::Unit, Span::new(0, 0, 0, 0));
2148            return T::matches_lust_type(&unit);
2149        }
2150
2151        params.len() == 1 && T::matches_lust_type(&params[0])
2152    }
2153}
2154
2155pub trait IntoLustValue: Sized {
2156    fn into_value(self) -> Value;
2157    fn matches_lust_type(ty: &Type) -> bool;
2158    fn type_description() -> &'static str;
2159}
2160
2161pub trait FromLustValue: Sized {
2162    fn from_value(value: Value) -> Result<Self>;
2163    fn matches_lust_type(ty: &Type) -> bool;
2164    fn type_description() -> &'static str;
2165}
2166
2167pub trait FunctionArgs {
2168    fn into_values(self) -> Vec<Value>;
2169    fn validate_signature(function_name: &str, params: &[Type]) -> Result<()>;
2170}
2171
2172impl IntoLustValue for Value {
2173    fn into_value(self) -> Value {
2174        self
2175    }
2176
2177    fn matches_lust_type(_: &Type) -> bool {
2178        true
2179    }
2180
2181    fn type_description() -> &'static str {
2182        "Value"
2183    }
2184}
2185
2186impl FromLustValue for Value {
2187    fn from_value(value: Value) -> Result<Self> {
2188        Ok(value)
2189    }
2190
2191    fn matches_lust_type(_: &Type) -> bool {
2192        true
2193    }
2194
2195    fn type_description() -> &'static str {
2196        "Value"
2197    }
2198}
2199
2200impl IntoLustValue for LustInt {
2201    fn into_value(self) -> Value {
2202        Value::Int(self)
2203    }
2204
2205    fn matches_lust_type(ty: &Type) -> bool {
2206        matches!(ty.kind, TypeKind::Int | TypeKind::Unknown)
2207    }
2208
2209    fn type_description() -> &'static str {
2210        "int"
2211    }
2212}
2213
2214impl FromLustValue for LustInt {
2215    fn from_value(value: Value) -> Result<Self> {
2216        match value {
2217            Value::Int(v) => Ok(v),
2218            other => Err(LustError::RuntimeError {
2219                message: format!("Expected Lust value 'int' but received '{:?}'", other),
2220            }),
2221        }
2222    }
2223
2224    fn matches_lust_type(ty: &Type) -> bool {
2225        matches!(ty.kind, TypeKind::Int | TypeKind::Unknown)
2226    }
2227
2228    fn type_description() -> &'static str {
2229        "int"
2230    }
2231}
2232
2233impl IntoLustValue for LustFloat {
2234    fn into_value(self) -> Value {
2235        Value::Float(self)
2236    }
2237
2238    fn matches_lust_type(ty: &Type) -> bool {
2239        matches!(ty.kind, TypeKind::Float | TypeKind::Unknown)
2240    }
2241
2242    fn type_description() -> &'static str {
2243        "float"
2244    }
2245}
2246
2247impl FromLustValue for LustFloat {
2248    fn from_value(value: Value) -> Result<Self> {
2249        match value {
2250            Value::Float(v) => Ok(v),
2251            other => Err(LustError::RuntimeError {
2252                message: format!("Expected Lust value 'float' but received '{:?}'", other),
2253            }),
2254        }
2255    }
2256
2257    fn matches_lust_type(ty: &Type) -> bool {
2258        matches!(ty.kind, TypeKind::Float | TypeKind::Unknown)
2259    }
2260
2261    fn type_description() -> &'static str {
2262        "float"
2263    }
2264}
2265
2266impl IntoLustValue for bool {
2267    fn into_value(self) -> Value {
2268        Value::Bool(self)
2269    }
2270
2271    fn matches_lust_type(ty: &Type) -> bool {
2272        matches!(ty.kind, TypeKind::Bool | TypeKind::Unknown)
2273    }
2274
2275    fn type_description() -> &'static str {
2276        "bool"
2277    }
2278}
2279
2280impl FromLustValue for bool {
2281    fn from_value(value: Value) -> Result<Self> {
2282        match value {
2283            Value::Bool(b) => Ok(b),
2284            other => Err(LustError::RuntimeError {
2285                message: format!("Expected Lust value 'bool' but received '{:?}'", other),
2286            }),
2287        }
2288    }
2289
2290    fn matches_lust_type(ty: &Type) -> bool {
2291        matches!(ty.kind, TypeKind::Bool | TypeKind::Unknown)
2292    }
2293
2294    fn type_description() -> &'static str {
2295        "bool"
2296    }
2297}
2298
2299impl IntoLustValue for String {
2300    fn into_value(self) -> Value {
2301        Value::String(Rc::new(self))
2302    }
2303
2304    fn matches_lust_type(ty: &Type) -> bool {
2305        matches!(ty.kind, TypeKind::String | TypeKind::Unknown)
2306    }
2307
2308    fn type_description() -> &'static str {
2309        "string"
2310    }
2311}
2312
2313impl IntoLustValue for Rc<String> {
2314    fn into_value(self) -> Value {
2315        Value::String(self)
2316    }
2317
2318    fn matches_lust_type(ty: &Type) -> bool {
2319        matches!(ty.kind, TypeKind::String | TypeKind::Unknown)
2320    }
2321
2322    fn type_description() -> &'static str {
2323        "string"
2324    }
2325}
2326
2327impl IntoLustValue for StructInstance {
2328    fn into_value(self) -> Value {
2329        self.value
2330    }
2331
2332    fn matches_lust_type(ty: &Type) -> bool {
2333        match &ty.kind {
2334            TypeKind::Unknown | TypeKind::Named(_) | TypeKind::GenericInstance { .. } => true,
2335            TypeKind::Union(types) => types
2336                .iter()
2337                .any(|alt| <Self as IntoLustValue>::matches_lust_type(alt)),
2338            _ => false,
2339        }
2340    }
2341
2342    fn type_description() -> &'static str {
2343        "struct"
2344    }
2345}
2346
2347impl FromLustValue for StructInstance {
2348    fn from_value(value: Value) -> Result<Self> {
2349        match &value {
2350            Value::Struct { name, .. } => Ok(StructInstance {
2351                type_name: name.clone(),
2352                value,
2353            }),
2354            other => Err(LustError::RuntimeError {
2355                message: format!("Expected Lust value 'struct' but received '{:?}'", other),
2356            }),
2357        }
2358    }
2359
2360    fn matches_lust_type(ty: &Type) -> bool {
2361        match &ty.kind {
2362            TypeKind::Unknown | TypeKind::Named(_) | TypeKind::GenericInstance { .. } => true,
2363            TypeKind::Union(types) => types
2364                .iter()
2365                .any(|alt| <Self as FromLustValue>::matches_lust_type(alt)),
2366            _ => false,
2367        }
2368    }
2369
2370    fn type_description() -> &'static str {
2371        "struct"
2372    }
2373}
2374
2375impl IntoLustValue for EnumInstance {
2376    fn into_value(self) -> Value {
2377        self.value
2378    }
2379
2380    fn matches_lust_type(ty: &Type) -> bool {
2381        match &ty.kind {
2382            TypeKind::Unknown | TypeKind::Named(_) | TypeKind::GenericInstance { .. } => true,
2383            TypeKind::Union(types) => types
2384                .iter()
2385                .any(|alt| <Self as IntoLustValue>::matches_lust_type(alt)),
2386            _ => false,
2387        }
2388    }
2389
2390    fn type_description() -> &'static str {
2391        "enum"
2392    }
2393}
2394
2395impl FromLustValue for EnumInstance {
2396    fn from_value(value: Value) -> Result<Self> {
2397        match &value {
2398            Value::Enum {
2399                enum_name, variant, ..
2400            } => Ok(EnumInstance {
2401                type_name: enum_name.clone(),
2402                variant: variant.clone(),
2403                value,
2404            }),
2405            other => Err(LustError::RuntimeError {
2406                message: format!("Expected Lust value 'enum' but received '{:?}'", other),
2407            }),
2408        }
2409    }
2410
2411    fn matches_lust_type(ty: &Type) -> bool {
2412        match &ty.kind {
2413            TypeKind::Unknown | TypeKind::Named(_) | TypeKind::GenericInstance { .. } => true,
2414            TypeKind::Union(types) => types
2415                .iter()
2416                .any(|alt| <Self as FromLustValue>::matches_lust_type(alt)),
2417            _ => false,
2418        }
2419    }
2420
2421    fn type_description() -> &'static str {
2422        "enum"
2423    }
2424}
2425
2426impl<T> IntoLustValue for Vec<T>
2427where
2428    T: IntoLustValue,
2429{
2430    fn into_value(self) -> Value {
2431        let values = self.into_iter().map(|item| item.into_value()).collect();
2432        Value::array(values)
2433    }
2434
2435    fn matches_lust_type(ty: &Type) -> bool {
2436        matches_array_type(ty, &T::matches_lust_type)
2437    }
2438
2439    fn type_description() -> &'static str {
2440        "array"
2441    }
2442}
2443
2444impl IntoLustValue for ArrayHandle {
2445    fn into_value(self) -> Value {
2446        Value::Array(self.inner)
2447    }
2448
2449    fn matches_lust_type(ty: &Type) -> bool {
2450        matches_array_handle_type(ty)
2451    }
2452
2453    fn type_description() -> &'static str {
2454        "array"
2455    }
2456}
2457
2458impl IntoLustValue for MapHandle {
2459    fn into_value(self) -> Value {
2460        Value::Map(self.inner)
2461    }
2462
2463    fn matches_lust_type(ty: &Type) -> bool {
2464        matches_map_handle_type(ty)
2465    }
2466
2467    fn type_description() -> &'static str {
2468        "map"
2469    }
2470}
2471
2472impl<T> FromLustValue for Vec<T>
2473where
2474    T: FromLustValue,
2475{
2476    fn from_value(value: Value) -> Result<Self> {
2477        match value {
2478            Value::Array(items) => {
2479                let borrowed = items.borrow();
2480                let mut result = Vec::with_capacity(borrowed.len());
2481                for item in borrowed.iter() {
2482                    result.push(T::from_value(item.clone())?);
2483                }
2484
2485                Ok(result)
2486            }
2487
2488            other => Err(LustError::RuntimeError {
2489                message: format!("Expected Lust value 'array' but received '{:?}'", other),
2490            }),
2491        }
2492    }
2493
2494    fn matches_lust_type(ty: &Type) -> bool {
2495        matches_array_type(ty, &T::matches_lust_type)
2496    }
2497
2498    fn type_description() -> &'static str {
2499        "array"
2500    }
2501}
2502
2503impl FromLustValue for ArrayHandle {
2504    fn from_value(value: Value) -> Result<Self> {
2505        match value {
2506            Value::Array(items) => Ok(ArrayHandle::from_rc(items)),
2507            other => Err(LustError::RuntimeError {
2508                message: format!("Expected Lust value 'array' but received '{:?}'", other),
2509            }),
2510        }
2511    }
2512
2513    fn matches_lust_type(ty: &Type) -> bool {
2514        matches_array_handle_type(ty)
2515    }
2516
2517    fn type_description() -> &'static str {
2518        "array"
2519    }
2520}
2521
2522impl FromLustValue for MapHandle {
2523    fn from_value(value: Value) -> Result<Self> {
2524        match value {
2525            Value::Map(map) => Ok(MapHandle::from_rc(map)),
2526            other => Err(LustError::RuntimeError {
2527                message: format!("Expected Lust value 'map' but received '{:?}'", other),
2528            }),
2529        }
2530    }
2531
2532    fn matches_lust_type(ty: &Type) -> bool {
2533        matches_map_handle_type(ty)
2534    }
2535
2536    fn type_description() -> &'static str {
2537        "map"
2538    }
2539}
2540
2541impl<'a> IntoLustValue for &'a str {
2542    fn into_value(self) -> Value {
2543        Value::String(Rc::new(self.to_owned()))
2544    }
2545
2546    fn matches_lust_type(ty: &Type) -> bool {
2547        matches!(ty.kind, TypeKind::String | TypeKind::Unknown)
2548    }
2549
2550    fn type_description() -> &'static str {
2551        "string"
2552    }
2553}
2554
2555impl<'a> IntoLustValue for &'a String {
2556    fn into_value(self) -> Value {
2557        Value::String(Rc::new(self.clone()))
2558    }
2559
2560    fn matches_lust_type(ty: &Type) -> bool {
2561        matches!(ty.kind, TypeKind::String | TypeKind::Unknown)
2562    }
2563
2564    fn type_description() -> &'static str {
2565        "string"
2566    }
2567}
2568
2569impl FromLustValue for String {
2570    fn from_value(value: Value) -> Result<Self> {
2571        match value {
2572            Value::String(s) => Ok((*s).clone()),
2573            other => Err(LustError::RuntimeError {
2574                message: format!("Expected Lust value 'string' but received '{:?}'", other),
2575            }),
2576        }
2577    }
2578
2579    fn matches_lust_type(ty: &Type) -> bool {
2580        matches!(ty.kind, TypeKind::String | TypeKind::Unknown)
2581    }
2582
2583    fn type_description() -> &'static str {
2584        "string"
2585    }
2586}
2587
2588impl FromLustValue for Rc<String> {
2589    fn from_value(value: Value) -> Result<Self> {
2590        match value {
2591            Value::String(s) => Ok(s),
2592            other => Err(LustError::RuntimeError {
2593                message: format!("Expected Lust value 'string' but received '{:?}'", other),
2594            }),
2595        }
2596    }
2597
2598    fn matches_lust_type(ty: &Type) -> bool {
2599        matches!(ty.kind, TypeKind::String | TypeKind::Unknown)
2600    }
2601
2602    fn type_description() -> &'static str {
2603        "string"
2604    }
2605}
2606
2607impl FromLustValue for () {
2608    fn from_value(value: Value) -> Result<Self> {
2609        match value {
2610            Value::Nil => Ok(()),
2611            other => Err(LustError::RuntimeError {
2612                message: format!("Expected Lust value 'unit' but received '{:?}'", other),
2613            }),
2614        }
2615    }
2616
2617    fn matches_lust_type(ty: &Type) -> bool {
2618        matches!(ty.kind, TypeKind::Unit | TypeKind::Unknown)
2619    }
2620
2621    fn type_description() -> &'static str {
2622        "unit"
2623    }
2624}
2625
2626impl FunctionArgs for () {
2627    fn into_values(self) -> Vec<Value> {
2628        Vec::new()
2629    }
2630
2631    fn validate_signature(function_name: &str, params: &[Type]) -> Result<()> {
2632        ensure_arity(function_name, params, 0)
2633    }
2634}
2635
2636impl<T> FunctionArgs for T
2637where
2638    T: IntoLustValue,
2639{
2640    fn into_values(self) -> Vec<Value> {
2641        vec![self.into_value()]
2642    }
2643
2644    fn validate_signature(function_name: &str, params: &[Type]) -> Result<()> {
2645        ensure_arity(function_name, params, 1)?;
2646        ensure_arg_type::<T>(function_name, params, 0)
2647    }
2648}
2649
2650impl<A, B> FunctionArgs for (A, B)
2651where
2652    A: IntoLustValue,
2653    B: IntoLustValue,
2654{
2655    fn into_values(self) -> Vec<Value> {
2656        vec![self.0.into_value(), self.1.into_value()]
2657    }
2658
2659    fn validate_signature(function_name: &str, params: &[Type]) -> Result<()> {
2660        ensure_arity(function_name, params, 2)?;
2661        ensure_arg_type::<A>(function_name, params, 0)?;
2662        ensure_arg_type::<B>(function_name, params, 1)?;
2663        Ok(())
2664    }
2665}
2666
2667impl<A, B, C> FunctionArgs for (A, B, C)
2668where
2669    A: IntoLustValue,
2670    B: IntoLustValue,
2671    C: IntoLustValue,
2672{
2673    fn into_values(self) -> Vec<Value> {
2674        vec![
2675            self.0.into_value(),
2676            self.1.into_value(),
2677            self.2.into_value(),
2678        ]
2679    }
2680
2681    fn validate_signature(function_name: &str, params: &[Type]) -> Result<()> {
2682        ensure_arity(function_name, params, 3)?;
2683        ensure_arg_type::<A>(function_name, params, 0)?;
2684        ensure_arg_type::<B>(function_name, params, 1)?;
2685        ensure_arg_type::<C>(function_name, params, 2)?;
2686        Ok(())
2687    }
2688}
2689
2690impl<A, B, C, D> FunctionArgs for (A, B, C, D)
2691where
2692    A: IntoLustValue,
2693    B: IntoLustValue,
2694    C: IntoLustValue,
2695    D: IntoLustValue,
2696{
2697    fn into_values(self) -> Vec<Value> {
2698        vec![
2699            self.0.into_value(),
2700            self.1.into_value(),
2701            self.2.into_value(),
2702            self.3.into_value(),
2703        ]
2704    }
2705
2706    fn validate_signature(function_name: &str, params: &[Type]) -> Result<()> {
2707        ensure_arity(function_name, params, 4)?;
2708        ensure_arg_type::<A>(function_name, params, 0)?;
2709        ensure_arg_type::<B>(function_name, params, 1)?;
2710        ensure_arg_type::<C>(function_name, params, 2)?;
2711        ensure_arg_type::<D>(function_name, params, 3)?;
2712        Ok(())
2713    }
2714}
2715
2716impl<A, B, C, D, E> FunctionArgs for (A, B, C, D, E)
2717where
2718    A: IntoLustValue,
2719    B: IntoLustValue,
2720    C: IntoLustValue,
2721    D: IntoLustValue,
2722    E: IntoLustValue,
2723{
2724    fn into_values(self) -> Vec<Value> {
2725        vec![
2726            self.0.into_value(),
2727            self.1.into_value(),
2728            self.2.into_value(),
2729            self.3.into_value(),
2730            self.4.into_value(),
2731        ]
2732    }
2733
2734    fn validate_signature(function_name: &str, params: &[Type]) -> Result<()> {
2735        ensure_arity(function_name, params, 5)?;
2736        ensure_arg_type::<A>(function_name, params, 0)?;
2737        ensure_arg_type::<B>(function_name, params, 1)?;
2738        ensure_arg_type::<C>(function_name, params, 2)?;
2739        ensure_arg_type::<D>(function_name, params, 3)?;
2740        ensure_arg_type::<E>(function_name, params, 4)?;
2741        Ok(())
2742    }
2743}
2744
2745fn ensure_arity(function_name: &str, params: &[Type], provided: usize) -> Result<()> {
2746    if params.len() == provided {
2747        Ok(())
2748    } else {
2749        Err(LustError::TypeError {
2750            message: format!(
2751                "Function '{}' expects {} argument(s) but {} were supplied",
2752                function_name,
2753                params.len(),
2754                provided
2755            ),
2756        })
2757    }
2758}
2759
2760fn ensure_arg_type<T: IntoLustValue>(
2761    function_name: &str,
2762    params: &[Type],
2763    index: usize,
2764) -> Result<()> {
2765    if <T as IntoLustValue>::matches_lust_type(&params[index]) {
2766        Ok(())
2767    } else {
2768        Err(argument_type_mismatch(
2769            function_name,
2770            index,
2771            <T as IntoLustValue>::type_description(),
2772            &params[index],
2773        ))
2774    }
2775}
2776
2777fn argument_type_mismatch(
2778    function_name: &str,
2779    index: usize,
2780    rust_type: &str,
2781    lust_type: &Type,
2782) -> LustError {
2783    LustError::TypeError {
2784        message: format!(
2785            "Function '{}' parameter {} expects Lust type '{}' but Rust provided '{}'",
2786            function_name,
2787            index + 1,
2788            lust_type,
2789            rust_type
2790        ),
2791    }
2792}