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 struct_defs = typechecker.struct_definitions();
823    let enum_defs = typechecker.enum_definitions();
824    let mut signatures = typechecker.function_signatures();
825    let mut compiler = Compiler::new();
826    compiler.configure_stdlib(&config);
827    compiler.set_imports_by_module(imports_map);
828    compiler.set_entry_module(program.entry_module.clone());
829    let functions = compiler.compile_module(&wrapped_items)?;
830    let trait_impls = compiler.get_trait_impls().to_vec();
831    let mut init_funcs = Vec::new();
832    for module in &program.modules {
833        if module.path != program.entry_module {
834            if let Some(init) = &module.init_function {
835                init_funcs.push(init.clone());
836            }
837        }
838    }
839
840    let function_names: Vec<String> = functions.iter().map(|f| f.name.clone()).collect();
841    let entry_script = function_names
842        .iter()
843        .find(|name| name.as_str() == "__script")
844        .cloned();
845    if let Some(script_name) = &entry_script {
846        signatures
847            .entry(script_name.clone())
848            .or_insert_with(|| FunctionSignature {
849                params: Vec::new(),
850                return_type: Type::new(TypeKind::Unit, Span::new(0, 0, 0, 0)),
851                is_method: false,
852            });
853    }
854
855    let mut vm = VM::with_config(&config);
856    vm.load_functions(functions);
857    vm.register_structs(&struct_defs);
858    for (type_name, trait_name) in trait_impls {
859        vm.register_trait_impl(type_name, trait_name);
860    }
861
862    for init in init_funcs {
863        vm.call(&init, Vec::new())?;
864    }
865
866    Ok(EmbeddedProgram {
867        vm,
868        signatures,
869        struct_defs,
870        enum_defs,
871        entry_script,
872        entry_module: program.entry_module,
873        async_registry: Rc::new(RefCell::new(AsyncRegistry::new())),
874    })
875}
876
877fn module_path_to_file(base_dir: &Path, module_path: &str) -> PathBuf {
878    let mut path = base_dir.to_path_buf();
879    for segment in module_path.split('.') {
880        path.push(segment);
881    }
882
883    path.set_extension("lust");
884    path
885}
886
887fn normalize_global_name(name: &str) -> String {
888    if name.contains("::") {
889        name.to_string()
890    } else if let Some((module, identifier)) = name.rsplit_once('.') {
891        format!("{}::{}", module, identifier)
892    } else {
893        name.to_string()
894    }
895}
896
897fn ensure_return_type<R: FromLustValue>(function_name: &str, ty: &Type) -> Result<()> {
898    if matches!(ty.kind, TypeKind::Unknown) || R::matches_lust_type(ty) {
899        return Ok(());
900    }
901
902    Err(LustError::TypeError {
903        message: format!(
904            "Function '{}' reports return type '{}' which is incompatible with Rust receiver '{}'",
905            function_name,
906            ty,
907            R::type_description()
908        ),
909    })
910}
911
912pub struct TypedValue {
913    value: Value,
914    matcher: Box<dyn Fn(&Value, &Type) -> bool>,
915    description: &'static str,
916}
917
918impl TypedValue {
919    fn new<F>(value: Value, matcher: F, description: &'static str) -> Self
920    where
921        F: Fn(&Value, &Type) -> bool + 'static,
922    {
923        Self {
924            value,
925            matcher: Box::new(matcher),
926            description,
927        }
928    }
929
930    fn matches(&self, ty: &Type) -> bool {
931        match &ty.kind {
932            TypeKind::Union(types) => types.iter().any(|alt| (self.matcher)(&self.value, alt)),
933            _ => (self.matcher)(&self.value, ty),
934        }
935    }
936
937    fn description(&self) -> &'static str {
938        self.description
939    }
940
941    fn into_value(self) -> Value {
942        self.value
943    }
944}
945
946pub struct StructField {
947    name: String,
948    value: TypedValue,
949}
950
951impl StructField {
952    pub fn new(name: impl Into<String>, value: impl IntoTypedValue) -> Self {
953        Self {
954            name: name.into(),
955            value: value.into_typed_value(),
956        }
957    }
958
959    pub fn name(&self) -> &str {
960        &self.name
961    }
962
963    fn into_parts(self) -> (String, TypedValue) {
964        (self.name, self.value)
965    }
966}
967
968pub fn struct_field(name: impl Into<String>, value: impl IntoTypedValue) -> StructField {
969    StructField::new(name, value)
970}
971
972impl<K, V> From<(K, V)> for StructField
973where
974    K: Into<String>,
975    V: IntoTypedValue,
976{
977    fn from((name, value): (K, V)) -> Self {
978        StructField::new(name, value)
979    }
980}
981
982#[derive(Clone)]
983pub struct StructInstance {
984    type_name: String,
985    value: Value,
986}
987
988impl StructInstance {
989    fn new(type_name: String, value: Value) -> Self {
990        debug_assert!(matches!(value, Value::Struct { .. }));
991        Self { type_name, value }
992    }
993
994    pub fn type_name(&self) -> &str {
995        &self.type_name
996    }
997
998    pub fn field<T: FromLustValue>(&self, field: &str) -> Result<T> {
999        let value_ref = self.borrow_field(field)?;
1000        T::from_value(value_ref.into_owned())
1001    }
1002
1003    pub fn borrow_field(&self, field: &str) -> Result<ValueRef<'_>> {
1004        match &self.value {
1005            Value::Struct { layout, fields, .. } => {
1006                let index = layout
1007                    .index_of_str(field)
1008                    .ok_or_else(|| LustError::RuntimeError {
1009                        message: format!(
1010                            "Struct '{}' has no field named '{}'",
1011                            self.type_name, field
1012                        ),
1013                    })?;
1014                match layout.field_storage(index) {
1015                    FieldStorage::Strong => {
1016                        let slots = fields.borrow();
1017                        if slots.get(index).is_none() {
1018                            return Err(LustError::RuntimeError {
1019                                message: format!(
1020                                    "Struct '{}' field '{}' is unavailable",
1021                                    self.type_name, field
1022                                ),
1023                            });
1024                        }
1025
1026                        Ok(ValueRef::borrowed(Ref::map(slots, move |values| {
1027                            &values[index]
1028                        })))
1029                    }
1030
1031                    FieldStorage::Weak => {
1032                        let stored = {
1033                            let slots = fields.borrow();
1034                            slots
1035                                .get(index)
1036                                .cloned()
1037                                .ok_or_else(|| LustError::RuntimeError {
1038                                    message: format!(
1039                                        "Struct '{}' field '{}' is unavailable",
1040                                        self.type_name, field
1041                                    ),
1042                                })?
1043                        };
1044                        let materialized = layout.materialize_field_value(index, stored);
1045                        Ok(ValueRef::owned(materialized))
1046                    }
1047                }
1048            }
1049
1050            _ => Err(LustError::RuntimeError {
1051                message: "StructInstance does not contain a struct value".to_string(),
1052            }),
1053        }
1054    }
1055
1056    pub fn set_field<V: IntoTypedValue>(&self, field: &str, value: V) -> Result<()> {
1057        match &self.value {
1058            Value::Struct { layout, fields, .. } => {
1059                let index = layout
1060                    .index_of_str(field)
1061                    .ok_or_else(|| LustError::RuntimeError {
1062                        message: format!(
1063                            "Struct '{}' has no field named '{}'",
1064                            self.type_name, field
1065                        ),
1066                    })?;
1067                let typed_value = value.into_typed_value();
1068                let matches_declared = typed_value.matches(layout.field_type(index));
1069                let matches_ref_inner = layout.is_weak(index)
1070                    && layout
1071                        .weak_target(index)
1072                        .map(|inner| typed_value.matches(inner))
1073                        .unwrap_or(false);
1074                if !(matches_declared || matches_ref_inner) {
1075                    return Err(LustError::TypeError {
1076                        message: format!(
1077                            "Struct '{}' field '{}' expects Lust type '{}' but Rust provided '{}'",
1078                            self.type_name,
1079                            field,
1080                            layout.field_type(index),
1081                            typed_value.description()
1082                        ),
1083                    });
1084                }
1085
1086                let canonical_value = layout
1087                    .canonicalize_field_value(index, typed_value.into_value())
1088                    .map_err(|message| LustError::TypeError { message })?;
1089                fields.borrow_mut()[index] = canonical_value;
1090                Ok(())
1091            }
1092
1093            _ => Err(LustError::RuntimeError {
1094                message: "StructInstance does not contain a struct value".to_string(),
1095            }),
1096        }
1097    }
1098
1099    pub fn update_field<F, V>(&self, field: &str, update: F) -> Result<()>
1100    where
1101        F: FnOnce(Value) -> Result<V>,
1102        V: IntoTypedValue,
1103    {
1104        match &self.value {
1105            Value::Struct { layout, fields, .. } => {
1106                let index = layout
1107                    .index_of_str(field)
1108                    .ok_or_else(|| LustError::RuntimeError {
1109                        message: format!(
1110                            "Struct '{}' has no field named '{}'",
1111                            self.type_name, field
1112                        ),
1113                    })?;
1114                let mut slots = fields.borrow_mut();
1115                let slot = slots
1116                    .get_mut(index)
1117                    .ok_or_else(|| LustError::RuntimeError {
1118                        message: format!(
1119                            "Struct '{}' field '{}' is unavailable",
1120                            self.type_name, field
1121                        ),
1122                    })?;
1123                let fallback = slot.clone();
1124                let current_canonical = std::mem::replace(slot, Value::Nil);
1125                let current_materialized = layout.materialize_field_value(index, current_canonical);
1126                let updated = match update(current_materialized) {
1127                    Ok(value) => value,
1128                    Err(err) => {
1129                        *slot = fallback;
1130                        return Err(err);
1131                    }
1132                };
1133                let typed_value = updated.into_typed_value();
1134                let matches_declared = typed_value.matches(layout.field_type(index));
1135                let matches_ref_inner = layout.is_weak(index)
1136                    && layout
1137                        .weak_target(index)
1138                        .map(|inner| typed_value.matches(inner))
1139                        .unwrap_or(false);
1140                if !(matches_declared || matches_ref_inner) {
1141                    *slot = fallback;
1142                    return Err(LustError::TypeError {
1143                        message: format!(
1144                            "Struct '{}' field '{}' expects Lust type '{}' but Rust provided '{}'",
1145                            self.type_name,
1146                            field,
1147                            layout.field_type(index),
1148                            typed_value.description()
1149                        ),
1150                    });
1151                }
1152
1153                let canonical_value = layout
1154                    .canonicalize_field_value(index, typed_value.into_value())
1155                    .map_err(|message| LustError::TypeError { message })?;
1156                *slot = canonical_value;
1157                Ok(())
1158            }
1159
1160            _ => Err(LustError::RuntimeError {
1161                message: "StructInstance does not contain a struct value".to_string(),
1162            }),
1163        }
1164    }
1165
1166    pub fn as_value(&self) -> &Value {
1167        &self.value
1168    }
1169}
1170
1171pub enum ValueRef<'a> {
1172    Borrowed(Ref<'a, Value>),
1173    Owned(Value),
1174}
1175
1176impl<'a> ValueRef<'a> {
1177    fn borrowed(inner: Ref<'a, Value>) -> Self {
1178        Self::Borrowed(inner)
1179    }
1180
1181    fn owned(value: Value) -> Self {
1182        Self::Owned(value)
1183    }
1184
1185    pub fn as_value(&self) -> &Value {
1186        match self {
1187            ValueRef::Borrowed(inner) => &*inner,
1188            ValueRef::Owned(value) => value,
1189        }
1190    }
1191
1192    pub fn to_owned(&self) -> Value {
1193        self.as_value().clone()
1194    }
1195
1196    pub fn into_owned(self) -> Value {
1197        match self {
1198            ValueRef::Borrowed(inner) => inner.clone(),
1199            ValueRef::Owned(value) => value,
1200        }
1201    }
1202
1203    pub fn as_bool(&self) -> Option<bool> {
1204        match self.as_value() {
1205            Value::Bool(value) => Some(*value),
1206            _ => None,
1207        }
1208    }
1209
1210    pub fn as_int(&self) -> Option<LustInt> {
1211        self.as_value().as_int()
1212    }
1213
1214    pub fn as_float(&self) -> Option<LustFloat> {
1215        self.as_value().as_float()
1216    }
1217
1218    pub fn as_string(&self) -> Option<&str> {
1219        self.as_value().as_string()
1220    }
1221
1222    pub fn as_rc_string(&self) -> Option<Rc<String>> {
1223        match self.as_value() {
1224            Value::String(value) => Some(value.clone()),
1225            _ => None,
1226        }
1227    }
1228
1229    pub fn as_array_handle(&self) -> Option<ArrayHandle> {
1230        match self.as_value() {
1231            Value::Array(items) => Some(ArrayHandle::from_rc(items.clone())),
1232            _ => None,
1233        }
1234    }
1235
1236    pub fn as_map_handle(&self) -> Option<MapHandle> {
1237        match self.as_value() {
1238            Value::Map(map) => Some(MapHandle::from_rc(map.clone())),
1239            _ => None,
1240        }
1241    }
1242
1243    pub fn as_table_handle(&self) -> Option<TableHandle> {
1244        match self.as_value() {
1245            Value::Table(table) => Some(TableHandle::from_rc(table.clone())),
1246            _ => None,
1247        }
1248    }
1249}
1250
1251#[derive(Clone)]
1252pub struct ArrayHandle {
1253    inner: Rc<RefCell<Vec<Value>>>,
1254}
1255
1256impl ArrayHandle {
1257    fn from_rc(inner: Rc<RefCell<Vec<Value>>>) -> Self {
1258        Self { inner }
1259    }
1260
1261    pub fn len(&self) -> usize {
1262        self.inner.borrow().len()
1263    }
1264
1265    pub fn is_empty(&self) -> bool {
1266        self.len() == 0
1267    }
1268
1269    pub fn borrow(&self) -> Ref<'_, [Value]> {
1270        Ref::map(self.inner.borrow(), |values| values.as_slice())
1271    }
1272
1273    pub fn borrow_mut(&self) -> RefMut<'_, Vec<Value>> {
1274        self.inner.borrow_mut()
1275    }
1276
1277    pub fn push(&self, value: Value) {
1278        self.inner.borrow_mut().push(value);
1279    }
1280
1281    pub fn extend<I>(&self, iter: I)
1282    where
1283        I: IntoIterator<Item = Value>,
1284    {
1285        self.inner.borrow_mut().extend(iter);
1286    }
1287
1288    pub fn get(&self, index: usize) -> Option<ValueRef<'_>> {
1289        {
1290            let values = self.inner.borrow();
1291            if values.get(index).is_none() {
1292                return None;
1293            }
1294        }
1295
1296        let values = self.inner.borrow();
1297        Some(ValueRef::borrowed(Ref::map(values, move |items| {
1298            &items[index]
1299        })))
1300    }
1301
1302    pub fn with_ref<R>(&self, f: impl FnOnce(&[Value]) -> R) -> R {
1303        let values = self.inner.borrow();
1304        f(values.as_slice())
1305    }
1306
1307    pub fn with_mut<R>(&self, f: impl FnOnce(&mut Vec<Value>) -> R) -> R {
1308        let mut values = self.inner.borrow_mut();
1309        f(&mut values)
1310    }
1311}
1312
1313#[derive(Clone)]
1314pub struct MapHandle {
1315    inner: Rc<RefCell<HashMap<ValueKey, Value>>>,
1316}
1317
1318impl MapHandle {
1319    fn from_rc(inner: Rc<RefCell<HashMap<ValueKey, Value>>>) -> Self {
1320        Self { inner }
1321    }
1322
1323    pub fn len(&self) -> usize {
1324        self.inner.borrow().len()
1325    }
1326
1327    pub fn is_empty(&self) -> bool {
1328        self.len() == 0
1329    }
1330
1331    pub fn borrow(&self) -> Ref<'_, HashMap<ValueKey, Value>> {
1332        self.inner.borrow()
1333    }
1334
1335    pub fn borrow_mut(&self) -> RefMut<'_, HashMap<ValueKey, Value>> {
1336        self.inner.borrow_mut()
1337    }
1338
1339    pub fn contains_key<K>(&self, key: K) -> bool
1340    where
1341        K: Into<ValueKey>,
1342    {
1343        self.inner.borrow().contains_key(&key.into())
1344    }
1345
1346    pub fn get<K>(&self, key: K) -> Option<ValueRef<'_>>
1347    where
1348        K: Into<ValueKey>,
1349    {
1350        let key = key.into();
1351        {
1352            if !self.inner.borrow().contains_key(&key) {
1353                return None;
1354            }
1355        }
1356        let lookup = key.clone();
1357        let map = self.inner.borrow();
1358        Some(ValueRef::borrowed(Ref::map(map, move |values| {
1359            values
1360                .get(&lookup)
1361                .expect("lookup key should be present after contains_key")
1362        })))
1363    }
1364
1365    pub fn insert<K>(&self, key: K, value: Value) -> Option<Value>
1366    where
1367        K: Into<ValueKey>,
1368    {
1369        self.inner.borrow_mut().insert(key.into(), value)
1370    }
1371
1372    pub fn remove<K>(&self, key: K) -> Option<Value>
1373    where
1374        K: Into<ValueKey>,
1375    {
1376        self.inner.borrow_mut().remove(&key.into())
1377    }
1378
1379    pub fn with_ref<R>(&self, f: impl FnOnce(&HashMap<ValueKey, Value>) -> R) -> R {
1380        let map = self.inner.borrow();
1381        f(&map)
1382    }
1383
1384    pub fn with_mut<R>(&self, f: impl FnOnce(&mut HashMap<ValueKey, Value>) -> R) -> R {
1385        let mut map = self.inner.borrow_mut();
1386        f(&mut map)
1387    }
1388}
1389
1390#[derive(Clone)]
1391pub struct TableHandle {
1392    inner: Rc<RefCell<HashMap<ValueKey, Value>>>,
1393}
1394
1395impl TableHandle {
1396    fn from_rc(inner: Rc<RefCell<HashMap<ValueKey, Value>>>) -> Self {
1397        Self { inner }
1398    }
1399
1400    pub fn len(&self) -> usize {
1401        self.inner.borrow().len()
1402    }
1403
1404    pub fn is_empty(&self) -> bool {
1405        self.len() == 0
1406    }
1407
1408    pub fn borrow(&self) -> Ref<'_, HashMap<ValueKey, Value>> {
1409        self.inner.borrow()
1410    }
1411
1412    pub fn borrow_mut(&self) -> RefMut<'_, HashMap<ValueKey, Value>> {
1413        self.inner.borrow_mut()
1414    }
1415
1416    pub fn contains_key<K>(&self, key: K) -> bool
1417    where
1418        K: Into<ValueKey>,
1419    {
1420        self.inner.borrow().contains_key(&key.into())
1421    }
1422
1423    pub fn get<K>(&self, key: K) -> Option<ValueRef<'_>>
1424    where
1425        K: Into<ValueKey>,
1426    {
1427        let key = key.into();
1428        {
1429            if !self.inner.borrow().contains_key(&key) {
1430                return None;
1431            }
1432        }
1433        let lookup = key.clone();
1434        let table = self.inner.borrow();
1435        Some(ValueRef::borrowed(Ref::map(table, move |values| {
1436            values
1437                .get(&lookup)
1438                .expect("lookup key should be present after contains_key")
1439        })))
1440    }
1441
1442    pub fn insert<K>(&self, key: K, value: Value) -> Option<Value>
1443    where
1444        K: Into<ValueKey>,
1445    {
1446        self.inner.borrow_mut().insert(key.into(), value)
1447    }
1448
1449    pub fn remove<K>(&self, key: K) -> Option<Value>
1450    where
1451        K: Into<ValueKey>,
1452    {
1453        self.inner.borrow_mut().remove(&key.into())
1454    }
1455
1456    pub fn with_ref<R>(&self, f: impl FnOnce(&HashMap<ValueKey, Value>) -> R) -> R {
1457        let table = self.inner.borrow();
1458        f(&table)
1459    }
1460
1461    pub fn with_mut<R>(&self, f: impl FnOnce(&mut HashMap<ValueKey, Value>) -> R) -> R {
1462        let mut table = self.inner.borrow_mut();
1463        f(&mut table)
1464    }
1465}
1466
1467#[derive(Clone)]
1468pub struct EnumInstance {
1469    type_name: String,
1470    variant: String,
1471    value: Value,
1472}
1473
1474impl EnumInstance {
1475    fn new(type_name: String, variant: String, value: Value) -> Self {
1476        debug_assert!(matches!(value, Value::Enum { .. }));
1477        Self {
1478            type_name,
1479            variant,
1480            value,
1481        }
1482    }
1483
1484    pub fn type_name(&self) -> &str {
1485        &self.type_name
1486    }
1487
1488    pub fn variant(&self) -> &str {
1489        &self.variant
1490    }
1491
1492    pub fn payload_len(&self) -> usize {
1493        match &self.value {
1494            Value::Enum { values, .. } => values.as_ref().map(|v| v.len()).unwrap_or(0),
1495            _ => 0,
1496        }
1497    }
1498
1499    pub fn payload<T: FromLustValue>(&self, index: usize) -> Result<T> {
1500        match &self.value {
1501            Value::Enum { values, .. } => {
1502                let values = values.as_ref().ok_or_else(|| LustError::RuntimeError {
1503                    message: format!(
1504                        "Enum variant '{}.{}' carries no payload",
1505                        self.type_name, self.variant
1506                    ),
1507                })?;
1508                let stored = values
1509                    .get(index)
1510                    .cloned()
1511                    .ok_or_else(|| LustError::RuntimeError {
1512                        message: format!(
1513                            "Enum variant '{}.{}' payload index {} is out of bounds",
1514                            self.type_name, self.variant, index
1515                        ),
1516                    })?;
1517                T::from_value(stored)
1518            }
1519
1520            _ => Err(LustError::RuntimeError {
1521                message: "EnumInstance does not contain an enum value".to_string(),
1522            }),
1523        }
1524    }
1525
1526    pub fn as_value(&self) -> &Value {
1527        &self.value
1528    }
1529}
1530
1531pub trait IntoTypedValue {
1532    fn into_typed_value(self) -> TypedValue;
1533}
1534
1535impl IntoTypedValue for Value {
1536    fn into_typed_value(self) -> TypedValue {
1537        TypedValue::new(self, |_value, _ty| true, "Value")
1538    }
1539}
1540
1541impl IntoTypedValue for StructInstance {
1542    fn into_typed_value(self) -> TypedValue {
1543        let StructInstance {
1544            type_name: _,
1545            value,
1546        } = self;
1547        TypedValue::new(value, |v, ty| matches_lust_struct(v, ty), "struct")
1548    }
1549}
1550
1551impl IntoTypedValue for EnumInstance {
1552    fn into_typed_value(self) -> TypedValue {
1553        let EnumInstance {
1554            type_name: _,
1555            variant: _,
1556            value,
1557        } = self;
1558        TypedValue::new(value, |v, ty| matches_lust_enum(v, ty), "enum")
1559    }
1560}
1561
1562macro_rules! impl_into_typed_for_primitive {
1563    ($ty:ty, $desc:expr, $matcher:expr) => {
1564        impl IntoTypedValue for $ty {
1565            fn into_typed_value(self) -> TypedValue {
1566                let value = self.into_value();
1567                TypedValue::new(value, $matcher, $desc)
1568            }
1569        }
1570    };
1571}
1572
1573impl_into_typed_for_primitive!(LustInt, "int", |_, ty: &Type| match &ty.kind {
1574    TypeKind::Int | TypeKind::Unknown => true,
1575    TypeKind::Union(types) => types
1576        .iter()
1577        .any(|alt| matches!(&alt.kind, TypeKind::Int | TypeKind::Unknown)),
1578    _ => false,
1579});
1580impl_into_typed_for_primitive!(LustFloat, "float", |_, ty: &Type| match &ty.kind {
1581    TypeKind::Float | TypeKind::Unknown => true,
1582    TypeKind::Union(types) => types
1583        .iter()
1584        .any(|alt| matches!(&alt.kind, TypeKind::Float | TypeKind::Unknown)),
1585    _ => false,
1586});
1587impl_into_typed_for_primitive!(bool, "bool", |_, ty: &Type| match &ty.kind {
1588    TypeKind::Bool | TypeKind::Unknown => true,
1589    TypeKind::Union(types) => types
1590        .iter()
1591        .any(|alt| matches!(&alt.kind, TypeKind::Bool | TypeKind::Unknown)),
1592    _ => false,
1593});
1594impl IntoTypedValue for String {
1595    fn into_typed_value(self) -> TypedValue {
1596        let value = self.into_value();
1597        TypedValue::new(value, string_matcher, "string")
1598    }
1599}
1600
1601impl<'a> IntoTypedValue for &'a str {
1602    fn into_typed_value(self) -> TypedValue {
1603        let value = self.into_value();
1604        TypedValue::new(value, string_matcher, "string")
1605    }
1606}
1607
1608impl<'a> IntoTypedValue for &'a String {
1609    fn into_typed_value(self) -> TypedValue {
1610        let value = self.into_value();
1611        TypedValue::new(value, string_matcher, "string")
1612    }
1613}
1614
1615impl IntoTypedValue for () {
1616    fn into_typed_value(self) -> TypedValue {
1617        TypedValue::new(
1618            Value::Nil,
1619            |_, ty| matches!(ty.kind, TypeKind::Unit | TypeKind::Unknown),
1620            "unit",
1621        )
1622    }
1623}
1624
1625impl<T> IntoTypedValue for Vec<T>
1626where
1627    T: IntoLustValue,
1628{
1629    fn into_typed_value(self) -> TypedValue {
1630        let values = self.into_iter().map(|item| item.into_value()).collect();
1631        TypedValue::new(
1632            Value::array(values),
1633            |_, ty| matches_array_type(ty, &T::matches_lust_type),
1634            "array",
1635        )
1636    }
1637}
1638
1639impl IntoTypedValue for ArrayHandle {
1640    fn into_typed_value(self) -> TypedValue {
1641        let value = self.into_value();
1642        TypedValue::new(value, |_, ty| matches_array_handle_type(ty), "array")
1643    }
1644}
1645
1646impl IntoTypedValue for MapHandle {
1647    fn into_typed_value(self) -> TypedValue {
1648        let value = self.into_value();
1649        TypedValue::new(value, |_, ty| matches_map_handle_type(ty), "map")
1650    }
1651}
1652
1653impl IntoTypedValue for TableHandle {
1654    fn into_typed_value(self) -> TypedValue {
1655        let value = self.into_value();
1656        TypedValue::new(value, |_, ty| matches_table_handle_type(ty), "table")
1657    }
1658}
1659
1660fn string_matcher(_: &Value, ty: &Type) -> bool {
1661    match &ty.kind {
1662        TypeKind::String | TypeKind::Unknown => true,
1663        TypeKind::Union(types) => types
1664            .iter()
1665            .any(|alt| matches!(&alt.kind, TypeKind::String | TypeKind::Unknown)),
1666        _ => false,
1667    }
1668}
1669
1670#[cfg(test)]
1671mod tests {
1672    use super::*;
1673    use std::future::Future;
1674    use std::pin::Pin;
1675    use std::sync::{Arc, Mutex};
1676    use std::task::{Context, Poll, Waker};
1677
1678    #[derive(Default)]
1679    struct ManualAsyncState {
1680        result: Mutex<Option<std::result::Result<LustInt, String>>>,
1681        waker: Mutex<Option<Waker>>,
1682    }
1683
1684    impl ManualAsyncState {
1685        fn new() -> Arc<Self> {
1686            Arc::new(Self::default())
1687        }
1688
1689        fn future(self: &Arc<Self>) -> ManualFuture {
1690            ManualFuture {
1691                state: Arc::clone(self),
1692            }
1693        }
1694
1695        fn complete_ok(&self, value: LustInt) {
1696            self.complete(Ok(value));
1697        }
1698
1699        fn complete_err(&self, message: impl Into<String>) {
1700            self.complete(Err(message.into()));
1701        }
1702
1703        fn complete(&self, value: std::result::Result<LustInt, String>) {
1704            {
1705                let mut slot = self.result.lock().unwrap();
1706                *slot = Some(value);
1707            }
1708
1709            if let Some(waker) = self.waker.lock().unwrap().take() {
1710                waker.wake();
1711            }
1712        }
1713    }
1714
1715    struct ManualFuture {
1716        state: Arc<ManualAsyncState>,
1717    }
1718
1719    impl Future for ManualFuture {
1720        type Output = std::result::Result<LustInt, String>;
1721
1722        fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
1723            {
1724                let mut slot = self.state.result.lock().unwrap();
1725                if let Some(result) = slot.take() {
1726                    return Poll::Ready(result);
1727                }
1728            }
1729
1730            let mut waker_slot = self.state.waker.lock().unwrap();
1731            *waker_slot = Some(cx.waker().clone());
1732            Poll::Pending
1733        }
1734    }
1735
1736    fn build_program(source: &str) -> EmbeddedProgram {
1737        EmbeddedProgram::builder()
1738            .module("main", source)
1739            .entry_module("main")
1740            .compile()
1741            .expect("compile embedded program")
1742    }
1743
1744    #[test]
1745    fn struct_instance_supports_mixed_field_types() {
1746        let source = r#"
1747            struct Mixed
1748                count: int
1749                label: string
1750                enabled: bool
1751            end
1752        "#;
1753
1754        let program = build_program(source);
1755        let mixed = program
1756            .struct_instance(
1757                "main.Mixed",
1758                [
1759                    struct_field("count", 7_i64),
1760                    struct_field("label", "hi"),
1761                    struct_field("enabled", true),
1762                ],
1763            )
1764            .expect("struct instance");
1765
1766        assert_eq!(mixed.field::<i64>("count").expect("count field"), 7);
1767        assert_eq!(mixed.field::<String>("label").expect("label field"), "hi");
1768        assert!(mixed.field::<bool>("enabled").expect("enabled field"));
1769    }
1770
1771    #[test]
1772    fn struct_instance_borrow_field_provides_reference_view() {
1773        let source = r#"
1774            struct Sample
1775                name: string
1776            end
1777        "#;
1778
1779        let program = build_program(source);
1780        let sample = program
1781            .struct_instance("main.Sample", [struct_field("name", "Borrowed")])
1782            .expect("struct instance");
1783
1784        let name_ref = sample.borrow_field("name").expect("borrow name field");
1785        assert_eq!(name_ref.as_string().unwrap(), "Borrowed");
1786        assert!(name_ref.as_array_handle().is_none());
1787    }
1788
1789    #[test]
1790    fn array_handle_allows_in_place_mutation() {
1791        let value = Value::array(vec![Value::Int(1)]);
1792        let handle = ArrayHandle::from_value(value).expect("array handle");
1793
1794        {
1795            let mut slots = handle.borrow_mut();
1796            slots.push(Value::Int(2));
1797            slots.push(Value::Int(3));
1798        }
1799
1800        let snapshot: Vec<_> = handle
1801            .borrow()
1802            .iter()
1803            .map(|value| value.as_int().expect("int value"))
1804            .collect();
1805        assert_eq!(snapshot, vec![1, 2, 3]);
1806    }
1807
1808    #[test]
1809    fn struct_instance_allows_setting_fields() {
1810        let source = r#"
1811            struct Mixed
1812                count: int
1813                label: string
1814                enabled: bool
1815            end
1816        "#;
1817
1818        let program = build_program(source);
1819        let mixed = program
1820            .struct_instance(
1821                "main.Mixed",
1822                [
1823                    struct_field("count", 1_i64),
1824                    struct_field("label", "start"),
1825                    struct_field("enabled", false),
1826                ],
1827            )
1828            .expect("struct instance");
1829
1830        mixed
1831            .set_field("count", 11_i64)
1832            .expect("update count field");
1833        assert_eq!(mixed.field::<i64>("count").expect("count field"), 11);
1834
1835        let err = mixed
1836            .set_field("count", "oops")
1837            .expect_err("type mismatch should fail");
1838        match err {
1839            LustError::TypeError { message } => {
1840                assert!(message.contains("count"));
1841                assert!(message.contains("int"));
1842            }
1843            other => panic!("unexpected error: {other:?}"),
1844        }
1845        assert_eq!(mixed.field::<i64>("count").expect("count field"), 11);
1846
1847        mixed
1848            .set_field("label", String::from("updated"))
1849            .expect("update label");
1850        assert_eq!(
1851            mixed.field::<String>("label").expect("label field"),
1852            "updated"
1853        );
1854
1855        mixed.set_field("enabled", true).expect("update enabled");
1856        assert!(mixed.field::<bool>("enabled").expect("enabled field"));
1857    }
1858
1859    #[test]
1860    fn struct_instance_accepts_nested_structs() {
1861        let source = r#"
1862            struct Child
1863                value: int
1864            end
1865
1866            struct Parent
1867                child: main.Child
1868            end
1869        "#;
1870
1871        let program = build_program(source);
1872        let child = program
1873            .struct_instance("main.Child", [struct_field("value", 42_i64)])
1874            .expect("child struct");
1875        let parent = program
1876            .struct_instance("main.Parent", [struct_field("child", child.clone())])
1877            .expect("parent struct");
1878
1879        let nested: StructInstance = parent.field("child").expect("child field");
1880        assert_eq!(nested.field::<i64>("value").expect("value field"), 42);
1881    }
1882
1883    #[test]
1884    fn globals_snapshot_exposes_lust_values() {
1885        let source = r#"
1886            struct Child
1887                value: int
1888            end
1889
1890            struct Parent
1891                child: unknown
1892            end
1893
1894            function make_parent(): Parent
1895                return Parent { child = Child { value = 3 } }
1896            end
1897        "#;
1898
1899        let mut program = build_program(source);
1900        program.run_entry_script().expect("run entry script");
1901        let parent: StructInstance = program
1902            .call_typed("main.make_parent", ())
1903            .expect("call make_parent");
1904        program.set_global_value("main.some_nested_structure", parent.clone());
1905
1906        let globals = program.globals();
1907        let (_, value) = globals
1908            .into_iter()
1909            .find(|(name, _)| name.ends_with("some_nested_structure"))
1910            .expect("global binding present");
1911        let stored = StructInstance::from_value(value).expect("convert to struct");
1912        let child_value = stored
1913            .field::<StructInstance>("child")
1914            .expect("nested child");
1915        assert_eq!(child_value.field::<i64>("value").expect("child value"), 3);
1916    }
1917
1918    #[test]
1919    fn update_field_modifies_value_in_place() {
1920        let source = r#"
1921            struct Counter
1922                value: int
1923            end
1924        "#;
1925
1926        let program = build_program(source);
1927        let counter = program
1928            .struct_instance("main.Counter", [struct_field("value", 10_i64)])
1929            .expect("counter struct");
1930
1931        counter
1932            .update_field("value", |current| match current {
1933                Value::Int(v) => Ok(v + 5),
1934                other => Err(LustError::RuntimeError {
1935                    message: format!("unexpected value {other:?}"),
1936                }),
1937            })
1938            .expect("update in place");
1939        assert_eq!(counter.field::<i64>("value").expect("value field"), 15);
1940
1941        let err = counter
1942            .update_field("value", |_| Ok(String::from("oops")))
1943            .expect_err("string should fail type check");
1944        match err {
1945            LustError::TypeError { message } => {
1946                assert!(message.contains("value"));
1947                assert!(message.contains("int"));
1948            }
1949            other => panic!("unexpected error: {other:?}"),
1950        }
1951        assert_eq!(counter.field::<i64>("value").expect("value field"), 15);
1952
1953        let err = counter
1954            .update_field("value", |_| -> Result<i64> {
1955                Err(LustError::RuntimeError {
1956                    message: "closure failure".to_string(),
1957                })
1958            })
1959            .expect_err("closure error should propagate");
1960        match err {
1961            LustError::RuntimeError { message } => assert_eq!(message, "closure failure"),
1962            other => panic!("unexpected error: {other:?}"),
1963        }
1964        assert_eq!(counter.field::<i64>("value").expect("value field"), 15);
1965    }
1966
1967    #[test]
1968    fn async_native_resumes_task_on_completion() {
1969        let source = r#"
1970            extern {
1971                function fetch_value(): int
1972            }
1973
1974            function compute(): int
1975                return fetch_value()
1976            end
1977        "#;
1978
1979        let mut program = build_program(source);
1980
1981        let state = ManualAsyncState::new();
1982        let register_state = Arc::clone(&state);
1983        program
1984            .register_async_typed_native::<(), LustInt, _, _>("fetch_value", move |_| {
1985                register_state.future()
1986            })
1987            .expect("register async native");
1988
1989        let handle = {
1990            let vm = program.vm_mut();
1991            let compute_fn = vm.function_value("main.compute").expect("compute function");
1992            vm.spawn_task_value(compute_fn, Vec::new())
1993                .expect("spawn task")
1994        };
1995
1996        assert!(program.has_pending_async_tasks());
1997        program.poll_async_tasks().expect("initial poll");
1998        assert!(program.has_pending_async_tasks());
1999
2000        state.complete_ok(123);
2001        program.poll_async_tasks().expect("resume after completion");
2002
2003        {
2004            let vm = program.vm_mut();
2005            let task = vm.get_task_instance(handle).expect("task exists");
2006            let result = task
2007                .last_result
2008                .as_ref()
2009                .and_then(|value| value.as_int())
2010                .expect("task produced result");
2011            assert_eq!(result, 123);
2012            assert!(task.error.is_none());
2013        }
2014
2015        assert!(!program.has_pending_async_tasks());
2016    }
2017
2018    #[test]
2019    fn async_native_failure_marks_task_failed() {
2020        let source = r#"
2021            extern {
2022                function fetch_value(): int
2023            }
2024
2025            function compute(): int
2026                return fetch_value()
2027            end
2028        "#;
2029
2030        let mut program = build_program(source);
2031
2032        let state = ManualAsyncState::new();
2033        let register_state = Arc::clone(&state);
2034        program
2035            .register_async_typed_native::<(), LustInt, _, _>("fetch_value", move |_| {
2036                register_state.future()
2037            })
2038            .expect("register async native");
2039
2040        let handle = {
2041            let vm = program.vm_mut();
2042            let compute_fn = vm.function_value("main.compute").expect("compute function");
2043            vm.spawn_task_value(compute_fn, Vec::new())
2044                .expect("spawn task")
2045        };
2046
2047        program.poll_async_tasks().expect("initial poll");
2048        state.complete_err("boom");
2049        let err = program
2050            .poll_async_tasks()
2051            .expect_err("poll should propagate failure");
2052        match err {
2053            LustError::RuntimeError { message } => assert_eq!(message, "boom"),
2054            other => panic!("unexpected error: {other:?}"),
2055        }
2056
2057        {
2058            let vm = program.vm_mut();
2059            let task = vm.get_task_instance(handle).expect("task exists");
2060            assert!(task.last_result.is_none());
2061            let error_message = task
2062                .error
2063                .as_ref()
2064                .map(|e| e.to_string())
2065                .expect("task should record error");
2066            assert!(error_message.contains("boom"));
2067        }
2068
2069        assert!(!program.has_pending_async_tasks());
2070    }
2071}
2072
2073fn matches_lust_struct(value: &Value, ty: &Type) -> bool {
2074    match (value, &ty.kind) {
2075        (Value::Struct { name, .. }, TypeKind::Named(expected)) => {
2076            lust_type_names_match(name, expected)
2077        }
2078        (Value::Struct { name, .. }, TypeKind::GenericInstance { name: expected, .. }) => {
2079            lust_type_names_match(name, expected)
2080        }
2081
2082        (value, TypeKind::Union(types)) => types.iter().any(|alt| matches_lust_struct(value, alt)),
2083        (_, TypeKind::Unknown) => true,
2084        _ => false,
2085    }
2086}
2087
2088fn matches_lust_enum(value: &Value, ty: &Type) -> bool {
2089    match (value, &ty.kind) {
2090        (Value::Enum { enum_name, .. }, TypeKind::Named(expected)) => {
2091            lust_type_names_match(enum_name, expected)
2092        }
2093        (Value::Enum { enum_name, .. }, TypeKind::GenericInstance { name: expected, .. }) => {
2094            lust_type_names_match(enum_name, expected)
2095        }
2096
2097        (value, TypeKind::Union(types)) => types.iter().any(|alt| matches_lust_enum(value, alt)),
2098        (_, TypeKind::Unknown) => true,
2099        _ => false,
2100    }
2101}
2102
2103fn lust_type_names_match(value: &str, expected: &str) -> bool {
2104    if value == expected {
2105        return true;
2106    }
2107
2108    let normalized_value = normalize_global_name(value);
2109    let normalized_expected = normalize_global_name(expected);
2110    if normalized_value == normalized_expected {
2111        return true;
2112    }
2113
2114    simple_type_name(&normalized_value) == simple_type_name(&normalized_expected)
2115}
2116
2117fn simple_type_name(name: &str) -> &str {
2118    name.rsplit(|c| c == '.' || c == ':').next().unwrap_or(name)
2119}
2120
2121fn matches_array_type<F>(ty: &Type, matcher: &F) -> bool
2122where
2123    F: Fn(&Type) -> bool,
2124{
2125    match &ty.kind {
2126        TypeKind::Array(inner) => matcher(inner),
2127        TypeKind::Unknown => true,
2128        TypeKind::Union(types) => types.iter().any(|alt| matches_array_type(alt, matcher)),
2129        _ => false,
2130    }
2131}
2132
2133fn matches_array_handle_type(ty: &Type) -> bool {
2134    match &ty.kind {
2135        TypeKind::Array(_) | TypeKind::Unknown => true,
2136        TypeKind::Union(types) => types.iter().any(|alt| matches_array_handle_type(alt)),
2137        _ => false,
2138    }
2139}
2140
2141fn matches_map_handle_type(ty: &Type) -> bool {
2142    match &ty.kind {
2143        TypeKind::Map(_, _) | TypeKind::Unknown => true,
2144        TypeKind::Union(types) => types.iter().any(|alt| matches_map_handle_type(alt)),
2145        _ => false,
2146    }
2147}
2148
2149fn matches_table_handle_type(ty: &Type) -> bool {
2150    match &ty.kind {
2151        TypeKind::Table | TypeKind::Unknown => true,
2152        TypeKind::Union(types) => types.iter().any(|alt| matches_table_handle_type(alt)),
2153        _ => false,
2154    }
2155}
2156
2157pub trait FromLustArgs: Sized {
2158    fn from_values(values: &[Value]) -> std::result::Result<Self, String>;
2159    fn matches_signature(params: &[Type]) -> bool;
2160}
2161
2162macro_rules! impl_from_lust_args_tuple {
2163    ($( $name:ident ),+) => {
2164        impl<$($name),+> FromLustArgs for ($($name,)+)
2165        where
2166            $($name: FromLustValue,)+
2167        {
2168            fn from_values(values: &[Value]) -> std::result::Result<Self, String> {
2169                let expected = count_idents!($($name),+);
2170                if values.len() != expected {
2171                    return Err(format!(
2172                        "Native function expected {} argument(s) but received {}",
2173                        expected,
2174                        values.len()
2175                    ));
2176                }
2177
2178                let mut idx = 0;
2179                let result = (
2180                    $(
2181                        {
2182                            let value = $name::from_value(values[idx].clone()).map_err(|e| e.to_string())?;
2183                            idx += 1;
2184                            value
2185                        },
2186                    )+
2187                );
2188                let _ = idx;
2189                Ok(result)
2190            }
2191
2192            fn matches_signature(params: &[Type]) -> bool {
2193                let expected = count_idents!($($name),+);
2194                params.len() == expected && {
2195                    let mut idx = 0;
2196                    let mut ok = true;
2197                    $(
2198                        if ok && !$name::matches_lust_type(&params[idx]) {
2199                            ok = false;
2200                        }
2201
2202                        idx += 1;
2203                    )+
2204                    let _ = idx;
2205                    ok
2206                }
2207
2208            }
2209
2210        }
2211
2212    };
2213}
2214
2215macro_rules! count_idents {
2216    ($($name:ident),*) => {
2217        <[()]>::len(&[$(count_idents!(@sub $name)),*])
2218    };
2219    (@sub $name:ident) => { () };
2220}
2221
2222impl_from_lust_args_tuple!(A);
2223impl_from_lust_args_tuple!(A, B);
2224impl_from_lust_args_tuple!(A, B, C);
2225impl_from_lust_args_tuple!(A, B, C, D);
2226impl_from_lust_args_tuple!(A, B, C, D, E);
2227impl<T> FromLustArgs for T
2228where
2229    T: FromLustValue,
2230{
2231    fn from_values(values: &[Value]) -> std::result::Result<Self, String> {
2232        match values.len() {
2233            0 => T::from_value(Value::Nil).map_err(|e| e.to_string()),
2234            1 => T::from_value(values[0].clone()).map_err(|e| e.to_string()),
2235            count => Err(format!(
2236                "Native function expected 1 argument but received {}",
2237                count
2238            )),
2239        }
2240    }
2241
2242    fn matches_signature(params: &[Type]) -> bool {
2243        if params.is_empty() {
2244            let unit = Type::new(TypeKind::Unit, Span::new(0, 0, 0, 0));
2245            return T::matches_lust_type(&unit);
2246        }
2247
2248        params.len() == 1 && T::matches_lust_type(&params[0])
2249    }
2250}
2251
2252pub trait IntoLustValue: Sized {
2253    fn into_value(self) -> Value;
2254    fn matches_lust_type(ty: &Type) -> bool;
2255    fn type_description() -> &'static str;
2256}
2257
2258pub trait FromLustValue: Sized {
2259    fn from_value(value: Value) -> Result<Self>;
2260    fn matches_lust_type(ty: &Type) -> bool;
2261    fn type_description() -> &'static str;
2262}
2263
2264pub trait FunctionArgs {
2265    fn into_values(self) -> Vec<Value>;
2266    fn validate_signature(function_name: &str, params: &[Type]) -> Result<()>;
2267}
2268
2269impl IntoLustValue for Value {
2270    fn into_value(self) -> Value {
2271        self
2272    }
2273
2274    fn matches_lust_type(_: &Type) -> bool {
2275        true
2276    }
2277
2278    fn type_description() -> &'static str {
2279        "Value"
2280    }
2281}
2282
2283impl FromLustValue for Value {
2284    fn from_value(value: Value) -> Result<Self> {
2285        Ok(value)
2286    }
2287
2288    fn matches_lust_type(_: &Type) -> bool {
2289        true
2290    }
2291
2292    fn type_description() -> &'static str {
2293        "Value"
2294    }
2295}
2296
2297impl IntoLustValue for LustInt {
2298    fn into_value(self) -> Value {
2299        Value::Int(self)
2300    }
2301
2302    fn matches_lust_type(ty: &Type) -> bool {
2303        matches!(ty.kind, TypeKind::Int | TypeKind::Unknown)
2304    }
2305
2306    fn type_description() -> &'static str {
2307        "int"
2308    }
2309}
2310
2311impl FromLustValue for LustInt {
2312    fn from_value(value: Value) -> Result<Self> {
2313        match value {
2314            Value::Int(v) => Ok(v),
2315            other => Err(LustError::RuntimeError {
2316                message: format!("Expected Lust value 'int' but received '{:?}'", other),
2317            }),
2318        }
2319    }
2320
2321    fn matches_lust_type(ty: &Type) -> bool {
2322        matches!(ty.kind, TypeKind::Int | TypeKind::Unknown)
2323    }
2324
2325    fn type_description() -> &'static str {
2326        "int"
2327    }
2328}
2329
2330impl IntoLustValue for LustFloat {
2331    fn into_value(self) -> Value {
2332        Value::Float(self)
2333    }
2334
2335    fn matches_lust_type(ty: &Type) -> bool {
2336        matches!(ty.kind, TypeKind::Float | TypeKind::Unknown)
2337    }
2338
2339    fn type_description() -> &'static str {
2340        "float"
2341    }
2342}
2343
2344impl FromLustValue for LustFloat {
2345    fn from_value(value: Value) -> Result<Self> {
2346        match value {
2347            Value::Float(v) => Ok(v),
2348            other => Err(LustError::RuntimeError {
2349                message: format!("Expected Lust value 'float' but received '{:?}'", other),
2350            }),
2351        }
2352    }
2353
2354    fn matches_lust_type(ty: &Type) -> bool {
2355        matches!(ty.kind, TypeKind::Float | TypeKind::Unknown)
2356    }
2357
2358    fn type_description() -> &'static str {
2359        "float"
2360    }
2361}
2362
2363impl IntoLustValue for bool {
2364    fn into_value(self) -> Value {
2365        Value::Bool(self)
2366    }
2367
2368    fn matches_lust_type(ty: &Type) -> bool {
2369        matches!(ty.kind, TypeKind::Bool | TypeKind::Unknown)
2370    }
2371
2372    fn type_description() -> &'static str {
2373        "bool"
2374    }
2375}
2376
2377impl FromLustValue for bool {
2378    fn from_value(value: Value) -> Result<Self> {
2379        match value {
2380            Value::Bool(b) => Ok(b),
2381            other => Err(LustError::RuntimeError {
2382                message: format!("Expected Lust value 'bool' but received '{:?}'", other),
2383            }),
2384        }
2385    }
2386
2387    fn matches_lust_type(ty: &Type) -> bool {
2388        matches!(ty.kind, TypeKind::Bool | TypeKind::Unknown)
2389    }
2390
2391    fn type_description() -> &'static str {
2392        "bool"
2393    }
2394}
2395
2396impl IntoLustValue for String {
2397    fn into_value(self) -> Value {
2398        Value::String(Rc::new(self))
2399    }
2400
2401    fn matches_lust_type(ty: &Type) -> bool {
2402        matches!(ty.kind, TypeKind::String | TypeKind::Unknown)
2403    }
2404
2405    fn type_description() -> &'static str {
2406        "string"
2407    }
2408}
2409
2410impl IntoLustValue for Rc<String> {
2411    fn into_value(self) -> Value {
2412        Value::String(self)
2413    }
2414
2415    fn matches_lust_type(ty: &Type) -> bool {
2416        matches!(ty.kind, TypeKind::String | TypeKind::Unknown)
2417    }
2418
2419    fn type_description() -> &'static str {
2420        "string"
2421    }
2422}
2423
2424impl IntoLustValue for StructInstance {
2425    fn into_value(self) -> Value {
2426        self.value
2427    }
2428
2429    fn matches_lust_type(ty: &Type) -> bool {
2430        match &ty.kind {
2431            TypeKind::Unknown | TypeKind::Named(_) | TypeKind::GenericInstance { .. } => true,
2432            TypeKind::Union(types) => types
2433                .iter()
2434                .any(|alt| <Self as IntoLustValue>::matches_lust_type(alt)),
2435            _ => false,
2436        }
2437    }
2438
2439    fn type_description() -> &'static str {
2440        "struct"
2441    }
2442}
2443
2444impl FromLustValue for StructInstance {
2445    fn from_value(value: Value) -> Result<Self> {
2446        match &value {
2447            Value::Struct { name, .. } => Ok(StructInstance {
2448                type_name: name.clone(),
2449                value,
2450            }),
2451            other => Err(LustError::RuntimeError {
2452                message: format!("Expected Lust value 'struct' but received '{:?}'", other),
2453            }),
2454        }
2455    }
2456
2457    fn matches_lust_type(ty: &Type) -> bool {
2458        match &ty.kind {
2459            TypeKind::Unknown | TypeKind::Named(_) | TypeKind::GenericInstance { .. } => true,
2460            TypeKind::Union(types) => types
2461                .iter()
2462                .any(|alt| <Self as FromLustValue>::matches_lust_type(alt)),
2463            _ => false,
2464        }
2465    }
2466
2467    fn type_description() -> &'static str {
2468        "struct"
2469    }
2470}
2471
2472impl IntoLustValue for EnumInstance {
2473    fn into_value(self) -> Value {
2474        self.value
2475    }
2476
2477    fn matches_lust_type(ty: &Type) -> bool {
2478        match &ty.kind {
2479            TypeKind::Unknown | TypeKind::Named(_) | TypeKind::GenericInstance { .. } => true,
2480            TypeKind::Union(types) => types
2481                .iter()
2482                .any(|alt| <Self as IntoLustValue>::matches_lust_type(alt)),
2483            _ => false,
2484        }
2485    }
2486
2487    fn type_description() -> &'static str {
2488        "enum"
2489    }
2490}
2491
2492impl FromLustValue for EnumInstance {
2493    fn from_value(value: Value) -> Result<Self> {
2494        match &value {
2495            Value::Enum {
2496                enum_name, variant, ..
2497            } => Ok(EnumInstance {
2498                type_name: enum_name.clone(),
2499                variant: variant.clone(),
2500                value,
2501            }),
2502            other => Err(LustError::RuntimeError {
2503                message: format!("Expected Lust value 'enum' but received '{:?}'", other),
2504            }),
2505        }
2506    }
2507
2508    fn matches_lust_type(ty: &Type) -> bool {
2509        match &ty.kind {
2510            TypeKind::Unknown | TypeKind::Named(_) | TypeKind::GenericInstance { .. } => true,
2511            TypeKind::Union(types) => types
2512                .iter()
2513                .any(|alt| <Self as FromLustValue>::matches_lust_type(alt)),
2514            _ => false,
2515        }
2516    }
2517
2518    fn type_description() -> &'static str {
2519        "enum"
2520    }
2521}
2522
2523impl<T> IntoLustValue for Vec<T>
2524where
2525    T: IntoLustValue,
2526{
2527    fn into_value(self) -> Value {
2528        let values = self.into_iter().map(|item| item.into_value()).collect();
2529        Value::array(values)
2530    }
2531
2532    fn matches_lust_type(ty: &Type) -> bool {
2533        matches_array_type(ty, &T::matches_lust_type)
2534    }
2535
2536    fn type_description() -> &'static str {
2537        "array"
2538    }
2539}
2540
2541impl IntoLustValue for ArrayHandle {
2542    fn into_value(self) -> Value {
2543        Value::Array(self.inner)
2544    }
2545
2546    fn matches_lust_type(ty: &Type) -> bool {
2547        matches_array_handle_type(ty)
2548    }
2549
2550    fn type_description() -> &'static str {
2551        "array"
2552    }
2553}
2554
2555impl IntoLustValue for MapHandle {
2556    fn into_value(self) -> Value {
2557        Value::Map(self.inner)
2558    }
2559
2560    fn matches_lust_type(ty: &Type) -> bool {
2561        matches_map_handle_type(ty)
2562    }
2563
2564    fn type_description() -> &'static str {
2565        "map"
2566    }
2567}
2568
2569impl IntoLustValue for TableHandle {
2570    fn into_value(self) -> Value {
2571        Value::Table(self.inner)
2572    }
2573
2574    fn matches_lust_type(ty: &Type) -> bool {
2575        matches_table_handle_type(ty)
2576    }
2577
2578    fn type_description() -> &'static str {
2579        "table"
2580    }
2581}
2582
2583impl<T> FromLustValue for Vec<T>
2584where
2585    T: FromLustValue,
2586{
2587    fn from_value(value: Value) -> Result<Self> {
2588        match value {
2589            Value::Array(items) => {
2590                let borrowed = items.borrow();
2591                let mut result = Vec::with_capacity(borrowed.len());
2592                for item in borrowed.iter() {
2593                    result.push(T::from_value(item.clone())?);
2594                }
2595
2596                Ok(result)
2597            }
2598
2599            other => Err(LustError::RuntimeError {
2600                message: format!("Expected Lust value 'array' but received '{:?}'", other),
2601            }),
2602        }
2603    }
2604
2605    fn matches_lust_type(ty: &Type) -> bool {
2606        matches_array_type(ty, &T::matches_lust_type)
2607    }
2608
2609    fn type_description() -> &'static str {
2610        "array"
2611    }
2612}
2613
2614impl FromLustValue for ArrayHandle {
2615    fn from_value(value: Value) -> Result<Self> {
2616        match value {
2617            Value::Array(items) => Ok(ArrayHandle::from_rc(items)),
2618            other => Err(LustError::RuntimeError {
2619                message: format!("Expected Lust value 'array' but received '{:?}'", other),
2620            }),
2621        }
2622    }
2623
2624    fn matches_lust_type(ty: &Type) -> bool {
2625        matches_array_handle_type(ty)
2626    }
2627
2628    fn type_description() -> &'static str {
2629        "array"
2630    }
2631}
2632
2633impl FromLustValue for MapHandle {
2634    fn from_value(value: Value) -> Result<Self> {
2635        match value {
2636            Value::Map(map) => Ok(MapHandle::from_rc(map)),
2637            other => Err(LustError::RuntimeError {
2638                message: format!("Expected Lust value 'map' but received '{:?}'", other),
2639            }),
2640        }
2641    }
2642
2643    fn matches_lust_type(ty: &Type) -> bool {
2644        matches_map_handle_type(ty)
2645    }
2646
2647    fn type_description() -> &'static str {
2648        "map"
2649    }
2650}
2651
2652impl FromLustValue for TableHandle {
2653    fn from_value(value: Value) -> Result<Self> {
2654        match value {
2655            Value::Table(table) => Ok(TableHandle::from_rc(table)),
2656            other => Err(LustError::RuntimeError {
2657                message: format!("Expected Lust value 'table' but received '{:?}'", other),
2658            }),
2659        }
2660    }
2661
2662    fn matches_lust_type(ty: &Type) -> bool {
2663        matches_table_handle_type(ty)
2664    }
2665
2666    fn type_description() -> &'static str {
2667        "table"
2668    }
2669}
2670
2671impl<'a> IntoLustValue for &'a str {
2672    fn into_value(self) -> Value {
2673        Value::String(Rc::new(self.to_owned()))
2674    }
2675
2676    fn matches_lust_type(ty: &Type) -> bool {
2677        matches!(ty.kind, TypeKind::String | TypeKind::Unknown)
2678    }
2679
2680    fn type_description() -> &'static str {
2681        "string"
2682    }
2683}
2684
2685impl<'a> IntoLustValue for &'a String {
2686    fn into_value(self) -> Value {
2687        Value::String(Rc::new(self.clone()))
2688    }
2689
2690    fn matches_lust_type(ty: &Type) -> bool {
2691        matches!(ty.kind, TypeKind::String | TypeKind::Unknown)
2692    }
2693
2694    fn type_description() -> &'static str {
2695        "string"
2696    }
2697}
2698
2699impl FromLustValue for String {
2700    fn from_value(value: Value) -> Result<Self> {
2701        match value {
2702            Value::String(s) => Ok((*s).clone()),
2703            other => Err(LustError::RuntimeError {
2704                message: format!("Expected Lust value 'string' but received '{:?}'", other),
2705            }),
2706        }
2707    }
2708
2709    fn matches_lust_type(ty: &Type) -> bool {
2710        matches!(ty.kind, TypeKind::String | TypeKind::Unknown)
2711    }
2712
2713    fn type_description() -> &'static str {
2714        "string"
2715    }
2716}
2717
2718impl FromLustValue for Rc<String> {
2719    fn from_value(value: Value) -> Result<Self> {
2720        match value {
2721            Value::String(s) => Ok(s),
2722            other => Err(LustError::RuntimeError {
2723                message: format!("Expected Lust value 'string' but received '{:?}'", other),
2724            }),
2725        }
2726    }
2727
2728    fn matches_lust_type(ty: &Type) -> bool {
2729        matches!(ty.kind, TypeKind::String | TypeKind::Unknown)
2730    }
2731
2732    fn type_description() -> &'static str {
2733        "string"
2734    }
2735}
2736
2737impl FromLustValue for () {
2738    fn from_value(value: Value) -> Result<Self> {
2739        match value {
2740            Value::Nil => Ok(()),
2741            other => Err(LustError::RuntimeError {
2742                message: format!("Expected Lust value 'unit' but received '{:?}'", other),
2743            }),
2744        }
2745    }
2746
2747    fn matches_lust_type(ty: &Type) -> bool {
2748        matches!(ty.kind, TypeKind::Unit | TypeKind::Unknown)
2749    }
2750
2751    fn type_description() -> &'static str {
2752        "unit"
2753    }
2754}
2755
2756impl FunctionArgs for () {
2757    fn into_values(self) -> Vec<Value> {
2758        Vec::new()
2759    }
2760
2761    fn validate_signature(function_name: &str, params: &[Type]) -> Result<()> {
2762        ensure_arity(function_name, params, 0)
2763    }
2764}
2765
2766impl<T> FunctionArgs for T
2767where
2768    T: IntoLustValue,
2769{
2770    fn into_values(self) -> Vec<Value> {
2771        vec![self.into_value()]
2772    }
2773
2774    fn validate_signature(function_name: &str, params: &[Type]) -> Result<()> {
2775        ensure_arity(function_name, params, 1)?;
2776        ensure_arg_type::<T>(function_name, params, 0)
2777    }
2778}
2779
2780impl<A, B> FunctionArgs for (A, B)
2781where
2782    A: IntoLustValue,
2783    B: IntoLustValue,
2784{
2785    fn into_values(self) -> Vec<Value> {
2786        vec![self.0.into_value(), self.1.into_value()]
2787    }
2788
2789    fn validate_signature(function_name: &str, params: &[Type]) -> Result<()> {
2790        ensure_arity(function_name, params, 2)?;
2791        ensure_arg_type::<A>(function_name, params, 0)?;
2792        ensure_arg_type::<B>(function_name, params, 1)?;
2793        Ok(())
2794    }
2795}
2796
2797impl<A, B, C> FunctionArgs for (A, B, C)
2798where
2799    A: IntoLustValue,
2800    B: IntoLustValue,
2801    C: IntoLustValue,
2802{
2803    fn into_values(self) -> Vec<Value> {
2804        vec![
2805            self.0.into_value(),
2806            self.1.into_value(),
2807            self.2.into_value(),
2808        ]
2809    }
2810
2811    fn validate_signature(function_name: &str, params: &[Type]) -> Result<()> {
2812        ensure_arity(function_name, params, 3)?;
2813        ensure_arg_type::<A>(function_name, params, 0)?;
2814        ensure_arg_type::<B>(function_name, params, 1)?;
2815        ensure_arg_type::<C>(function_name, params, 2)?;
2816        Ok(())
2817    }
2818}
2819
2820impl<A, B, C, D> FunctionArgs for (A, B, C, D)
2821where
2822    A: IntoLustValue,
2823    B: IntoLustValue,
2824    C: IntoLustValue,
2825    D: IntoLustValue,
2826{
2827    fn into_values(self) -> Vec<Value> {
2828        vec![
2829            self.0.into_value(),
2830            self.1.into_value(),
2831            self.2.into_value(),
2832            self.3.into_value(),
2833        ]
2834    }
2835
2836    fn validate_signature(function_name: &str, params: &[Type]) -> Result<()> {
2837        ensure_arity(function_name, params, 4)?;
2838        ensure_arg_type::<A>(function_name, params, 0)?;
2839        ensure_arg_type::<B>(function_name, params, 1)?;
2840        ensure_arg_type::<C>(function_name, params, 2)?;
2841        ensure_arg_type::<D>(function_name, params, 3)?;
2842        Ok(())
2843    }
2844}
2845
2846impl<A, B, C, D, E> FunctionArgs for (A, B, C, D, E)
2847where
2848    A: IntoLustValue,
2849    B: IntoLustValue,
2850    C: IntoLustValue,
2851    D: IntoLustValue,
2852    E: IntoLustValue,
2853{
2854    fn into_values(self) -> Vec<Value> {
2855        vec![
2856            self.0.into_value(),
2857            self.1.into_value(),
2858            self.2.into_value(),
2859            self.3.into_value(),
2860            self.4.into_value(),
2861        ]
2862    }
2863
2864    fn validate_signature(function_name: &str, params: &[Type]) -> Result<()> {
2865        ensure_arity(function_name, params, 5)?;
2866        ensure_arg_type::<A>(function_name, params, 0)?;
2867        ensure_arg_type::<B>(function_name, params, 1)?;
2868        ensure_arg_type::<C>(function_name, params, 2)?;
2869        ensure_arg_type::<D>(function_name, params, 3)?;
2870        ensure_arg_type::<E>(function_name, params, 4)?;
2871        Ok(())
2872    }
2873}
2874
2875fn ensure_arity(function_name: &str, params: &[Type], provided: usize) -> Result<()> {
2876    if params.len() == provided {
2877        Ok(())
2878    } else {
2879        Err(LustError::TypeError {
2880            message: format!(
2881                "Function '{}' expects {} argument(s) but {} were supplied",
2882                function_name,
2883                params.len(),
2884                provided
2885            ),
2886        })
2887    }
2888}
2889
2890fn ensure_arg_type<T: IntoLustValue>(
2891    function_name: &str,
2892    params: &[Type],
2893    index: usize,
2894) -> Result<()> {
2895    if <T as IntoLustValue>::matches_lust_type(&params[index]) {
2896        Ok(())
2897    } else {
2898        Err(argument_type_mismatch(
2899            function_name,
2900            index,
2901            <T as IntoLustValue>::type_description(),
2902            &params[index],
2903        ))
2904    }
2905}
2906
2907fn argument_type_mismatch(
2908    function_name: &str,
2909    index: usize,
2910    rust_type: &str,
2911    lust_type: &Type,
2912) -> LustError {
2913    LustError::TypeError {
2914        message: format!(
2915            "Function '{}' parameter {} expects Lust type '{}' but Rust provided '{}'",
2916            function_name,
2917            index + 1,
2918            lust_type,
2919            rust_type
2920        ),
2921    }
2922}