lust/
embed.rs

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