lust/
embed.rs

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