lust/
embed.rs

1use crate::ast::{EnumDef, FieldOwnership, Item, ItemKind, Span, StructDef, Type, TypeKind};
2use crate::bytecode::{Compiler, NativeCallResult, TaskHandle, Value};
3use crate::modules::{ModuleImports, ModuleLoader};
4use crate::number::{LustFloat, LustInt};
5use crate::typechecker::{FunctionSignature, TypeChecker};
6use crate::vm::VM;
7use crate::{LustConfig, LustError, Result};
8use std::cell::RefCell;
9use hashbrown::HashMap;
10use std::future::Future;
11use std::pin::Pin;
12use std::path::{Path, PathBuf};
13use std::rc::Rc;
14use std::sync::Arc;
15use std::sync::atomic::{AtomicBool, Ordering};
16use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
17
18type AsyncValueFuture = Pin<Box<dyn Future<Output = std::result::Result<Value, String>>>>;
19
20struct AsyncRegistry {
21    pending: HashMap<u64, AsyncTaskEntry>,
22}
23
24impl AsyncRegistry {
25    fn new() -> Self {
26        Self {
27            pending: HashMap::new(),
28        }
29    }
30
31    fn register(
32        &mut self,
33        handle: TaskHandle,
34        future: AsyncValueFuture,
35    ) -> std::result::Result<(), String> {
36        let key = handle.id();
37        if self.pending.contains_key(&key) {
38            return Err(format!(
39                "Task {} already has a pending async native call",
40                key
41            ));
42        }
43
44        self.pending
45            .insert(key, AsyncTaskEntry::new(handle, future));
46        Ok(())
47    }
48
49    fn is_empty(&self) -> bool {
50        self.pending.is_empty()
51    }
52}
53
54struct AsyncTaskEntry {
55    handle: TaskHandle,
56    future: AsyncValueFuture,
57    wake_flag: Arc<WakeFlag>,
58    immediate_poll: bool,
59}
60
61impl AsyncTaskEntry {
62    fn new(handle: TaskHandle, future: AsyncValueFuture) -> Self {
63        Self {
64            handle,
65            future,
66            wake_flag: Arc::new(WakeFlag::new()),
67            immediate_poll: true,
68        }
69    }
70
71    fn take_should_poll(&mut self) -> bool {
72        if self.immediate_poll {
73            self.immediate_poll = false;
74            true
75        } else {
76            self.wake_flag.take()
77        }
78    }
79
80    fn make_waker(&self) -> Waker {
81        make_async_waker(&self.wake_flag)
82    }
83}
84
85struct WakeFlag {
86    pending: AtomicBool,
87}
88
89impl WakeFlag {
90    fn new() -> Self {
91        Self {
92            pending: AtomicBool::new(true),
93        }
94    }
95
96    fn take(&self) -> bool {
97        self.pending.swap(false, Ordering::SeqCst)
98    }
99
100    fn wake(&self) {
101        self.pending.store(true, Ordering::SeqCst);
102    }
103}
104
105fn make_async_waker(flag: &Arc<WakeFlag>) -> Waker {
106    unsafe {
107        Waker::from_raw(RawWaker::new(
108            Arc::into_raw(flag.clone()) as *const (),
109            &ASYNC_WAKER_VTABLE,
110        ))
111    }
112}
113
114unsafe fn async_waker_clone(ptr: *const ()) -> RawWaker {
115    let arc = Arc::<WakeFlag>::from_raw(ptr as *const WakeFlag);
116    let cloned = arc.clone();
117    std::mem::forget(arc);
118    RawWaker::new(Arc::into_raw(cloned) as *const (), &ASYNC_WAKER_VTABLE)
119}
120
121unsafe fn async_waker_wake(ptr: *const ()) {
122    let arc = Arc::<WakeFlag>::from_raw(ptr as *const WakeFlag);
123    arc.wake();
124}
125
126unsafe fn async_waker_wake_by_ref(ptr: *const ()) {
127    let arc = Arc::<WakeFlag>::from_raw(ptr as *const WakeFlag);
128    arc.wake();
129    std::mem::forget(arc);
130}
131
132unsafe fn async_waker_drop(ptr: *const ()) {
133    let _ = Arc::<WakeFlag>::from_raw(ptr as *const WakeFlag);
134}
135
136static ASYNC_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(
137    async_waker_clone,
138    async_waker_wake,
139    async_waker_wake_by_ref,
140    async_waker_drop,
141);
142pub struct EmbeddedBuilder {
143    base_dir: PathBuf,
144    modules: HashMap<String, String>,
145    entry_module: Option<String>,
146    config: LustConfig,
147}
148
149impl Default for EmbeddedBuilder {
150    fn default() -> Self {
151        Self {
152            base_dir: PathBuf::from("__embedded__"),
153            modules: HashMap::new(),
154            entry_module: None,
155            config: LustConfig::default(),
156        }
157    }
158}
159
160impl EmbeddedBuilder {
161    pub fn new() -> Self {
162        Self::default()
163    }
164
165    pub fn with_base_dir(self, base_dir: impl Into<PathBuf>) -> Self {
166        self.set_base_dir(base_dir)
167    }
168
169    pub fn set_base_dir(mut self, base_dir: impl Into<PathBuf>) -> Self {
170        self.base_dir = base_dir.into();
171        self
172    }
173
174    pub fn module(mut self, module_path: impl Into<String>, source: impl Into<String>) -> Self {
175        self.modules.insert(module_path.into(), source.into());
176        self
177    }
178
179    pub fn enable_stdlib_module<S: AsRef<str>>(mut self, module: S) -> Self {
180        self.config.enable_module(module);
181        self
182    }
183
184    pub fn add_stdlib_module<S: AsRef<str>>(mut self, module: S) -> Self {
185        self.config.enable_module(module);
186        self
187    }
188
189    pub fn with_config(mut self, config: LustConfig) -> Self {
190        self.config = config;
191        self
192    }
193
194    pub fn set_config(mut self, config: LustConfig) -> Self {
195        self.config = config;
196        self
197    }
198
199    pub fn add_module(
200        &mut self,
201        module_path: impl Into<String>,
202        source: impl Into<String>,
203    ) -> &mut Self {
204        self.modules.insert(module_path.into(), source.into());
205        self
206    }
207
208    pub fn entry_module(mut self, module_path: impl Into<String>) -> Self {
209        self.set_entry_module(module_path);
210        self
211    }
212
213    pub fn set_entry_module(&mut self, module_path: impl Into<String>) -> &mut Self {
214        self.entry_module = Some(module_path.into());
215        self
216    }
217
218    pub fn compile(self) -> Result<EmbeddedProgram> {
219        let entry_module = self
220            .entry_module
221            .ok_or_else(|| LustError::Unknown("No entry module configured for embedding".into()))?;
222        let has_entry = self.modules.contains_key(&entry_module);
223        if !has_entry {
224            return Err(LustError::Unknown(format!(
225                "Entry module '{}' was not provided via EmbeddedBuilder::module",
226                entry_module
227            )));
228        }
229
230        let overrides: HashMap<PathBuf, String> = self
231            .modules
232            .into_iter()
233            .map(|(module, source)| (module_path_to_file(&self.base_dir, &module), source))
234            .collect();
235        compile_in_memory(self.base_dir, entry_module, overrides, self.config)
236    }
237}
238
239pub struct EmbeddedProgram {
240    vm: VM,
241    signatures: HashMap<String, FunctionSignature>,
242    struct_defs: HashMap<String, StructDef>,
243    enum_defs: HashMap<String, EnumDef>,
244    entry_script: Option<String>,
245    entry_module: String,
246    async_registry: Rc<RefCell<AsyncRegistry>>,
247}
248
249impl EmbeddedProgram {
250    pub fn builder() -> EmbeddedBuilder {
251        EmbeddedBuilder::default()
252    }
253
254    pub fn vm_mut(&mut self) -> &mut VM {
255        &mut self.vm
256    }
257
258    pub fn signature(&self, function_name: &str) -> Option<&FunctionSignature> {
259        self.find_signature(function_name).map(|(_, sig)| sig)
260    }
261
262    pub fn typed_functions(&self) -> impl Iterator<Item = (&String, &FunctionSignature)> {
263        self.signatures.iter()
264    }
265
266    pub fn struct_definition(&self, type_name: &str) -> Option<&StructDef> {
267        self.struct_defs.get(type_name)
268    }
269
270    pub fn enum_definition(&self, type_name: &str) -> Option<&EnumDef> {
271        self.enum_defs.get(type_name)
272    }
273
274    fn find_signature(&self, name: &str) -> Option<(String, &FunctionSignature)> {
275        if let Some(sig) = self.signatures.get(name) {
276            return Some((name.to_string(), sig));
277        }
278
279        for candidate in self.signature_lookup_candidates(name) {
280            if let Some(sig) = self.signatures.get(&candidate) {
281                return Some((candidate, sig));
282            }
283        }
284
285        let matches = self
286            .signatures
287            .iter()
288            .filter_map(|(key, sig)| {
289                if Self::simple_name(key) == name {
290                    Some((key, sig))
291                } else {
292                    None
293                }
294            })
295            .collect::<Vec<_>>();
296        if matches.len() == 1 {
297            let (key, sig) = matches[0];
298            return Some((key.clone(), sig));
299        }
300
301        None
302    }
303
304    fn resolve_signature(&self, name: &str) -> Result<(String, &FunctionSignature)> {
305        if let Some(found) = self.find_signature(name) {
306            return Ok(found);
307        }
308
309        let matches = self
310            .signatures
311            .keys()
312            .filter(|key| Self::simple_name(key) == name)
313            .count();
314        if matches > 1 {
315            return Err(LustError::TypeError {
316                message: format!(
317                    "Cannot register native '{}': multiple matching functions found; specify a fully qualified name",
318                    name
319                ),
320            });
321        }
322
323        Err(LustError::TypeError {
324            message: format!(
325                "Cannot register native '{}': function not declared in Lust source",
326                name
327            ),
328        })
329    }
330
331    fn signature_lookup_candidates(&self, name: &str) -> Vec<String> {
332        let mut candidates: Vec<String> = Vec::new();
333        if name.contains("::") {
334            candidates.push(name.replace("::", "."));
335        }
336
337        if name.contains('.') {
338            candidates.push(name.replace('.', "::"));
339        }
340
341        if !name.contains('.') && !name.contains("::") {
342            let module = &self.entry_module;
343            candidates.push(format!("{}.{}", module, name));
344            candidates.push(format!("{}::{}", module, name));
345        }
346
347        candidates
348    }
349
350    fn simple_name(name: &str) -> &str {
351        name.rsplit(|c| c == '.' || c == ':').next().unwrap_or(name)
352    }
353
354    fn register_native_with_aliases<F>(
355        &mut self,
356        requested_name: &str,
357        canonical: String,
358        func: F,
359    ) where
360        F: Fn(&[Value]) -> std::result::Result<NativeCallResult, String> + 'static,
361    {
362        let native_fn: Rc<dyn Fn(&[Value]) -> std::result::Result<NativeCallResult, String>> =
363            Rc::new(func);
364        let value = Value::NativeFunction(native_fn);
365        let mut aliases: Vec<String> = Vec::new();
366        aliases.push(canonical.clone());
367        let canonical_normalized = normalize_global_name(&canonical);
368        if canonical_normalized != canonical {
369            aliases.push(canonical_normalized);
370        }
371
372        if requested_name != canonical {
373            aliases.push(requested_name.to_string());
374            let normalized = normalize_global_name(requested_name);
375            if normalized != requested_name {
376                aliases.push(normalized);
377            }
378        }
379
380        aliases.sort();
381        aliases.dedup();
382        for key in aliases {
383            self.vm.register_native(key, value.clone());
384        }
385    }
386
387    pub fn get_global_value(&self, name: &str) -> Option<Value> {
388        let normalized = normalize_global_name(name);
389        self.vm.get_global(&normalized)
390    }
391
392    pub fn get_typed_global<T: FromLustValue>(&self, name: &str) -> Result<Option<T>> {
393        let normalized = normalize_global_name(name);
394        match self.vm.get_global(&normalized) {
395            Some(value) => T::from_value(value).map(Some),
396            None => Ok(None),
397        }
398    }
399
400    pub fn set_global_value<V: IntoTypedValue>(&mut self, name: impl Into<String>, value: V) {
401        let name_string = name.into();
402        let normalized = normalize_global_name(&name_string);
403        let value = value.into_typed_value().into_value();
404        self.vm.set_global(normalized, value);
405    }
406
407    pub fn struct_instance<I, K, V>(
408        &self,
409        type_name: impl Into<String>,
410        fields: I,
411    ) -> Result<StructInstance>
412    where
413        I: IntoIterator<Item = (K, V)>,
414        K: Into<String>,
415        V: IntoTypedValue,
416    {
417        let type_name = type_name.into();
418        let def = self
419            .struct_defs
420            .get(&type_name)
421            .ok_or_else(|| LustError::TypeError {
422                message: format!("Unknown struct '{}'", type_name),
423            })?;
424        let mut provided: HashMap<String, TypedValue> = fields
425            .into_iter()
426            .map(|(name, value)| (name.into(), value.into_typed_value()))
427            .collect();
428        let mut ordered_fields: Vec<(Rc<String>, Value)> = Vec::with_capacity(def.fields.len());
429        for field in &def.fields {
430            let typed_value = provided
431                .remove(&field.name)
432                .ok_or_else(|| LustError::TypeError {
433                    message: format!(
434                        "Struct '{}' is missing required field '{}'",
435                        type_name, field.name
436                    ),
437                })?;
438            let matches_declared = typed_value.matches(&field.ty);
439            let matches_ref_inner = matches!(field.ownership, FieldOwnership::Weak)
440                && field
441                    .weak_target
442                    .as_ref()
443                    .map(|inner| typed_value.matches(inner))
444                    .unwrap_or(false);
445            if !(matches_declared || matches_ref_inner) {
446                return Err(LustError::TypeError {
447                    message: format!(
448                        "Struct '{}' field '{}' expects Lust type '{}' but Rust provided '{}'",
449                        type_name,
450                        field.name,
451                        field.ty,
452                        typed_value.description()
453                    ),
454                });
455            }
456
457            ordered_fields.push((Rc::new(field.name.clone()), typed_value.into_value()));
458        }
459
460        if !provided.is_empty() {
461            let extra = provided.keys().cloned().collect::<Vec<_>>().join(", ");
462            return Err(LustError::TypeError {
463                message: format!(
464                    "Struct '{}' received unknown field(s): {}",
465                    type_name, extra
466                ),
467            });
468        }
469
470        let value = self.vm.instantiate_struct(&type_name, ordered_fields)?;
471        Ok(StructInstance::new(type_name.clone(), value))
472    }
473
474    pub fn enum_variant(
475        &self,
476        type_name: impl Into<String>,
477        variant: impl Into<String>,
478    ) -> Result<EnumInstance> {
479        self.enum_variant_with(type_name, variant, std::iter::empty::<Value>())
480    }
481
482    pub fn enum_variant_with<I, V>(
483        &self,
484        type_name: impl Into<String>,
485        variant: impl Into<String>,
486        payload: I,
487    ) -> Result<EnumInstance>
488    where
489        I: IntoIterator<Item = V>,
490        V: IntoTypedValue,
491    {
492        let type_name = type_name.into();
493        let variant_name = variant.into();
494        let def = self
495            .enum_defs
496            .get(&type_name)
497            .ok_or_else(|| LustError::TypeError {
498                message: format!("Unknown enum '{}'", type_name),
499            })?;
500        let enum_variant = def
501            .variants
502            .iter()
503            .find(|v| v.name == variant_name)
504            .ok_or_else(|| LustError::TypeError {
505                message: format!(
506                    "Enum '{}' has no variant named '{}'",
507                    type_name, variant_name
508                ),
509            })?;
510        let mut values: Vec<TypedValue> =
511            payload.into_iter().map(|v| v.into_typed_value()).collect();
512        let coerced_values: Option<Rc<Vec<Value>>> = match &enum_variant.fields {
513            None => {
514                if !values.is_empty() {
515                    return Err(LustError::TypeError {
516                        message: format!(
517                            "Enum variant '{}.{}' does not accept payload values",
518                            type_name, variant_name
519                        ),
520                    });
521                }
522
523                None
524            }
525
526            Some(field_types) => {
527                if values.len() != field_types.len() {
528                    return Err(LustError::TypeError {
529                        message: format!(
530                            "Enum variant '{}.{}' expects {} value(s) but {} were supplied",
531                            type_name,
532                            variant_name,
533                            field_types.len(),
534                            values.len()
535                        ),
536                    });
537                }
538
539                let mut collected = Vec::with_capacity(field_types.len());
540                for (idx, (typed_value, field_ty)) in
541                    values.drain(..).zip(field_types.iter()).enumerate()
542                {
543                    if !typed_value.matches(field_ty) {
544                        return Err(LustError::TypeError {
545                            message: format!(
546                                "Enum variant '{}.{}' field {} expects Lust type '{}' but Rust provided '{}'",
547                                type_name,
548                                variant_name,
549                                idx + 1,
550                                field_ty,
551                                typed_value.description()
552                            ),
553                        });
554                    }
555
556                    collected.push(typed_value.into_value());
557                }
558
559                Some(Rc::new(collected))
560            }
561        };
562        Ok(EnumInstance::new(
563            type_name.clone(),
564            variant_name.clone(),
565            Value::Enum {
566                enum_name: type_name,
567                variant: variant_name,
568                values: coerced_values,
569            },
570        ))
571    }
572
573    pub fn register_native_fn<F>(&mut self, name: impl Into<String>, func: F)
574    where
575        F: Fn(&[Value]) -> std::result::Result<NativeCallResult, String> + 'static,
576    {
577        let native = Value::NativeFunction(Rc::new(func));
578        self.vm.register_native(name, native);
579    }
580
581    pub fn register_async_native<F, Fut>(
582        &mut self,
583        name: impl Into<String>,
584        func: F,
585    ) -> Result<()>
586    where
587        F: Fn(Vec<Value>) -> Fut + 'static,
588        Fut: Future<Output = std::result::Result<Value, String>> + 'static,
589    {
590        let registry = self.async_registry.clone();
591        let name_string = name.into();
592        let handler = move |values: &[Value]| -> std::result::Result<NativeCallResult, String> {
593            let args: Vec<Value> = values.iter().cloned().collect();
594            let future: AsyncValueFuture = Box::pin(func(args));
595            VM::with_current(|vm| {
596                let handle = vm
597                    .current_task_handle()
598                    .ok_or_else(|| "Async native functions require a running task".to_string())?;
599                registry.borrow_mut().register(handle, future)?;
600                Ok(NativeCallResult::Yield(Value::Nil))
601            })
602        };
603        self.register_native_fn(name_string, handler);
604        Ok(())
605    }
606
607    pub fn register_typed_native<Args, R, F>(&mut self, name: &str, func: F) -> Result<()>
608    where
609        Args: FromLustArgs,
610        R: IntoLustValue + FromLustValue,
611        F: Fn(Args) -> std::result::Result<R, String> + 'static,
612    {
613        let (canonical, signature) = self.resolve_signature(name)?;
614        if !Args::matches_signature(&signature.params) {
615            return Err(LustError::TypeError {
616                message: format!(
617                    "Native '{}' argument types do not match Lust signature",
618                    name
619                ),
620            });
621        }
622
623        ensure_return_type::<R>(name, &signature.return_type)?;
624        let handler = move |values: &[Value]| -> std::result::Result<NativeCallResult, String> {
625            let args = Args::from_values(values)?;
626            let result = func(args)?;
627            Ok(NativeCallResult::Return(result.into_value()))
628        };
629        self.register_native_with_aliases(name, canonical, handler);
630        Ok(())
631    }
632
633    pub fn register_async_typed_native<Args, R, F, Fut>(
634        &mut self,
635        name: &str,
636        func: F,
637    ) -> Result<()>
638    where
639        Args: FromLustArgs,
640        R: IntoLustValue + FromLustValue,
641        F: Fn(Args) -> Fut + 'static,
642        Fut: Future<Output = std::result::Result<R, String>> + 'static,
643    {
644        let (canonical, signature) = self.resolve_signature(name)?;
645        let signature = signature.clone();
646        if !Args::matches_signature(&signature.params) {
647            return Err(LustError::TypeError {
648                message: format!(
649                    "Native '{}' argument types do not match Lust signature",
650                    name
651                ),
652            });
653        }
654
655        ensure_return_type::<R>(name, &signature.return_type)?;
656        let registry = self.async_registry.clone();
657        let handler = move |values: &[Value]| -> std::result::Result<NativeCallResult, String> {
658            let args = Args::from_values(values)?;
659            let future = func(args);
660            let mapped = async move {
661                match future.await {
662                    Ok(result) => Ok(result.into_value()),
663                    Err(err) => Err(err),
664                }
665            };
666            let future: AsyncValueFuture = Box::pin(mapped);
667            VM::with_current(|vm| {
668                let handle = vm
669                    .current_task_handle()
670                    .ok_or_else(|| "Async native functions require a running task".to_string())?;
671                registry.borrow_mut().register(handle, future)?;
672                Ok(NativeCallResult::Yield(Value::Nil))
673            })
674        };
675        self.register_native_with_aliases(name, canonical, handler);
676        Ok(())
677    }
678
679    pub fn call_typed<Args, R>(&mut self, function_name: &str, args: Args) -> Result<R>
680    where
681        Args: FunctionArgs,
682        R: FromLustValue,
683    {
684        let signature = self
685            .signatures
686            .get(function_name)
687            .ok_or_else(|| LustError::TypeError {
688                message: format!(
689                    "No type information available for function '{}'; \
690                     use call_raw if the function is dynamically typed",
691                    function_name
692                ),
693            })?;
694        Args::validate_signature(function_name, &signature.params)?;
695        ensure_return_type::<R>(function_name, &signature.return_type)?;
696        let values = args.into_values();
697        let value = self.vm.call(function_name, values)?;
698        R::from_value(value)
699    }
700
701    pub fn call_raw(&mut self, function_name: &str, args: Vec<Value>) -> Result<Value> {
702        self.vm.call(function_name, args)
703    }
704
705    pub fn run_entry_script(&mut self) -> Result<()> {
706        let Some(entry) = &self.entry_script else {
707            return Err(LustError::RuntimeError {
708                message: "Embedded program has no entry script".into(),
709            });
710        };
711        let result = self.vm.call(entry, Vec::new())?;
712        match result {
713            Value::Nil => Ok(()),
714            other => Err(LustError::RuntimeError {
715                message: format!(
716                    "Entry script '{}' returned non-unit value: {:?}",
717                    entry, other
718                ),
719            }),
720        }
721    }
722
723    pub fn poll_async_tasks(&mut self) -> Result<()> {
724        let pending_ids: Vec<u64> = {
725            let registry = self.async_registry.borrow();
726            registry.pending.keys().copied().collect()
727        };
728
729        let mut completions: Vec<(TaskHandle, std::result::Result<Value, String>)> = Vec::new();
730        for id in pending_ids {
731            let handle = TaskHandle(id);
732            if self.vm.get_task_instance(handle).is_err() {
733                self.async_registry.borrow_mut().pending.remove(&id);
734                continue;
735            }
736
737            let maybe_outcome = {
738                let mut registry = self.async_registry.borrow_mut();
739                let entry = match registry.pending.get_mut(&id) {
740                    Some(entry) => entry,
741                    None => continue,
742                };
743
744                if !entry.take_should_poll() {
745                    continue;
746                }
747
748                let waker = entry.make_waker();
749                let mut cx = Context::from_waker(&waker);
750                match entry.future.as_mut().poll(&mut cx) {
751                    Poll::Ready(result) => {
752                        let handle = entry.handle;
753                        registry.pending.remove(&id);
754                        Some((handle, result))
755                    }
756
757                    Poll::Pending => None,
758                }
759            };
760
761            if let Some(outcome) = maybe_outcome {
762                completions.push(outcome);
763            }
764        }
765
766        for (handle, outcome) in completions {
767            match outcome {
768                Ok(value) => {
769                    self.vm.resume_task_handle(handle, Some(value))?;
770                }
771
772                Err(message) => {
773                    self.vm.fail_task_handle(
774                        handle,
775                        LustError::RuntimeError { message },
776                    )?;
777                }
778            }
779        }
780
781        Ok(())
782    }
783
784    pub fn has_pending_async_tasks(&self) -> bool {
785        !self.async_registry.borrow().is_empty()
786    }
787}
788
789fn compile_in_memory(
790    base_dir: PathBuf,
791    entry_module: String,
792    overrides: HashMap<PathBuf, String>,
793    config: LustConfig,
794) -> Result<EmbeddedProgram> {
795    let mut loader = ModuleLoader::new(base_dir.clone());
796    loader.set_source_overrides(overrides);
797    let entry_path = module_path_to_file(&base_dir, &entry_module);
798    let entry_path_str = entry_path
799        .to_str()
800        .ok_or_else(|| LustError::Unknown("Entry path contained invalid UTF-8".into()))?
801        .to_string();
802    let program = loader.load_program_from_entry(&entry_path_str)?;
803    let mut imports_map: HashMap<String, ModuleImports> = HashMap::new();
804    for module in &program.modules {
805        imports_map.insert(module.path.clone(), module.imports.clone());
806    }
807
808    let mut wrapped_items: Vec<Item> = Vec::new();
809    for module in &program.modules {
810        wrapped_items.push(Item::new(
811            ItemKind::Module {
812                name: module.path.clone(),
813                items: module.items.clone(),
814            },
815            Span::new(0, 0, 0, 0),
816        ));
817    }
818
819    let mut typechecker = TypeChecker::with_config(&config);
820    typechecker.set_imports_by_module(imports_map.clone());
821    typechecker.check_program(&program.modules)?;
822    let struct_defs = typechecker.struct_definitions();
823    let enum_defs = typechecker.enum_definitions();
824    let mut signatures = typechecker.function_signatures();
825    let mut compiler = Compiler::new();
826    compiler.configure_stdlib(&config);
827    compiler.set_imports_by_module(imports_map);
828    compiler.set_entry_module(program.entry_module.clone());
829    let functions = compiler.compile_module(&wrapped_items)?;
830    let trait_impls = compiler.get_trait_impls().to_vec();
831    let mut init_funcs = Vec::new();
832    for module in &program.modules {
833        if module.path != program.entry_module {
834            if let Some(init) = &module.init_function {
835                init_funcs.push(init.clone());
836            }
837        }
838    }
839
840    let function_names: Vec<String> = functions.iter().map(|f| f.name.clone()).collect();
841    let entry_script = function_names
842        .iter()
843        .find(|name| name.as_str() == "__script")
844        .cloned();
845    if let Some(script_name) = &entry_script {
846        signatures
847            .entry(script_name.clone())
848            .or_insert_with(|| FunctionSignature {
849                params: Vec::new(),
850                return_type: Type::new(TypeKind::Unit, Span::new(0, 0, 0, 0)),
851                is_method: false,
852            });
853    }
854
855    let mut vm = VM::with_config(&config);
856    vm.load_functions(functions);
857    vm.register_structs(&struct_defs);
858    for (type_name, trait_name) in trait_impls {
859        vm.register_trait_impl(type_name, trait_name);
860    }
861
862    for init in init_funcs {
863        vm.call(&init, Vec::new())?;
864    }
865
866    Ok(EmbeddedProgram {
867        vm,
868        signatures,
869        struct_defs,
870        enum_defs,
871        entry_script,
872        entry_module: program.entry_module,
873        async_registry: Rc::new(RefCell::new(AsyncRegistry::new())),
874    })
875}
876
877fn module_path_to_file(base_dir: &Path, module_path: &str) -> PathBuf {
878    let mut path = base_dir.to_path_buf();
879    for segment in module_path.split('.') {
880        path.push(segment);
881    }
882
883    path.set_extension("lust");
884    path
885}
886
887fn normalize_global_name(name: &str) -> String {
888    if name.contains("::") {
889        name.to_string()
890    } else if let Some((module, identifier)) = name.rsplit_once('.') {
891        format!("{}::{}", module, identifier)
892    } else {
893        name.to_string()
894    }
895}
896
897fn ensure_return_type<R: FromLustValue>(function_name: &str, ty: &Type) -> Result<()> {
898    if matches!(ty.kind, TypeKind::Unknown) || R::matches_lust_type(ty) {
899        return Ok(());
900    }
901
902    Err(LustError::TypeError {
903        message: format!(
904            "Function '{}' reports return type '{}' which is incompatible with Rust receiver '{}'",
905            function_name,
906            ty,
907            R::type_description()
908        ),
909    })
910}
911
912pub struct TypedValue {
913    value: Value,
914    matcher: Box<dyn Fn(&Value, &Type) -> bool>,
915    description: &'static str,
916}
917
918impl TypedValue {
919    fn new<F>(value: Value, matcher: F, description: &'static str) -> Self
920    where
921        F: Fn(&Value, &Type) -> bool + 'static,
922    {
923        Self {
924            value,
925            matcher: Box::new(matcher),
926            description,
927        }
928    }
929
930    fn matches(&self, ty: &Type) -> bool {
931        match &ty.kind {
932            TypeKind::Union(types) => types.iter().any(|alt| (self.matcher)(&self.value, alt)),
933            _ => (self.matcher)(&self.value, ty),
934        }
935    }
936
937    fn description(&self) -> &'static str {
938        self.description
939    }
940
941    fn into_value(self) -> Value {
942        self.value
943    }
944}
945
946#[derive(Clone)]
947pub struct StructInstance {
948    type_name: String,
949    value: Value,
950}
951
952impl StructInstance {
953    fn new(type_name: String, value: Value) -> Self {
954        debug_assert!(matches!(value, Value::Struct { .. }));
955        Self { type_name, value }
956    }
957
958    pub fn type_name(&self) -> &str {
959        &self.type_name
960    }
961
962    pub fn field<T: FromLustValue>(&self, field: &str) -> Result<T> {
963        match &self.value {
964            Value::Struct { layout, fields, .. } => {
965                let index = layout
966                    .index_of_str(field)
967                    .ok_or_else(|| LustError::RuntimeError {
968                        message: format!(
969                            "Struct '{}' has no field named '{}'",
970                            self.type_name, field
971                        ),
972                    })?;
973                let stored =
974                    fields
975                        .borrow()
976                        .get(index)
977                        .cloned()
978                        .ok_or_else(|| LustError::RuntimeError {
979                            message: format!(
980                                "Struct '{}' field '{}' is unavailable",
981                                self.type_name, field
982                            ),
983                        })?;
984                let materialized = layout.materialize_field_value(index, stored);
985                T::from_value(materialized)
986            }
987
988            _ => Err(LustError::RuntimeError {
989                message: "StructInstance does not contain a struct value".to_string(),
990            }),
991        }
992    }
993
994    pub fn as_value(&self) -> &Value {
995        &self.value
996    }
997}
998
999#[derive(Clone)]
1000pub struct EnumInstance {
1001    type_name: String,
1002    variant: String,
1003    value: Value,
1004}
1005
1006impl EnumInstance {
1007    fn new(type_name: String, variant: String, value: Value) -> Self {
1008        debug_assert!(matches!(value, Value::Enum { .. }));
1009        Self {
1010            type_name,
1011            variant,
1012            value,
1013        }
1014    }
1015
1016    pub fn type_name(&self) -> &str {
1017        &self.type_name
1018    }
1019
1020    pub fn variant(&self) -> &str {
1021        &self.variant
1022    }
1023
1024    pub fn payload_len(&self) -> usize {
1025        match &self.value {
1026            Value::Enum { values, .. } => values.as_ref().map(|v| v.len()).unwrap_or(0),
1027            _ => 0,
1028        }
1029    }
1030
1031    pub fn payload<T: FromLustValue>(&self, index: usize) -> Result<T> {
1032        match &self.value {
1033            Value::Enum { values, .. } => {
1034                let values = values.as_ref().ok_or_else(|| LustError::RuntimeError {
1035                    message: format!(
1036                        "Enum variant '{}.{}' carries no payload",
1037                        self.type_name, self.variant
1038                    ),
1039                })?;
1040                let stored = values
1041                    .get(index)
1042                    .cloned()
1043                    .ok_or_else(|| LustError::RuntimeError {
1044                        message: format!(
1045                            "Enum variant '{}.{}' payload index {} is out of bounds",
1046                            self.type_name, self.variant, index
1047                        ),
1048                    })?;
1049                T::from_value(stored)
1050            }
1051
1052            _ => Err(LustError::RuntimeError {
1053                message: "EnumInstance does not contain an enum value".to_string(),
1054            }),
1055        }
1056    }
1057
1058    pub fn as_value(&self) -> &Value {
1059        &self.value
1060    }
1061}
1062
1063pub trait IntoTypedValue {
1064    fn into_typed_value(self) -> TypedValue;
1065}
1066
1067impl IntoTypedValue for Value {
1068    fn into_typed_value(self) -> TypedValue {
1069        TypedValue::new(self, |_value, _ty| true, "Value")
1070    }
1071}
1072
1073impl IntoTypedValue for StructInstance {
1074    fn into_typed_value(self) -> TypedValue {
1075        let StructInstance {
1076            type_name: _,
1077            value,
1078        } = self;
1079        TypedValue::new(value, |v, ty| matches_lust_struct(v, ty), "struct")
1080    }
1081}
1082
1083impl IntoTypedValue for EnumInstance {
1084    fn into_typed_value(self) -> TypedValue {
1085        let EnumInstance {
1086            type_name: _,
1087            variant: _,
1088            value,
1089        } = self;
1090        TypedValue::new(value, |v, ty| matches_lust_enum(v, ty), "enum")
1091    }
1092}
1093
1094macro_rules! impl_into_typed_for_primitive {
1095    ($ty:ty, $desc:expr, $matcher:expr) => {
1096        impl IntoTypedValue for $ty {
1097            fn into_typed_value(self) -> TypedValue {
1098                let value = self.into_value();
1099                TypedValue::new(value, $matcher, $desc)
1100            }
1101        }
1102    };
1103}
1104
1105impl_into_typed_for_primitive!(LustInt, "int", |_, ty: &Type| match &ty.kind {
1106    TypeKind::Int | TypeKind::Unknown => true,
1107    TypeKind::Union(types) => types
1108        .iter()
1109        .any(|alt| matches!(&alt.kind, TypeKind::Int | TypeKind::Unknown)),
1110    _ => false,
1111});
1112impl_into_typed_for_primitive!(LustFloat, "float", |_, ty: &Type| match &ty.kind {
1113    TypeKind::Float | TypeKind::Unknown => true,
1114    TypeKind::Union(types) => types
1115        .iter()
1116        .any(|alt| matches!(&alt.kind, TypeKind::Float | TypeKind::Unknown)),
1117    _ => false,
1118});
1119impl_into_typed_for_primitive!(bool, "bool", |_, ty: &Type| match &ty.kind {
1120    TypeKind::Bool | TypeKind::Unknown => true,
1121    TypeKind::Union(types) => types
1122        .iter()
1123        .any(|alt| matches!(&alt.kind, TypeKind::Bool | TypeKind::Unknown)),
1124    _ => false,
1125});
1126impl IntoTypedValue for String {
1127    fn into_typed_value(self) -> TypedValue {
1128        let value = self.into_value();
1129        TypedValue::new(value, string_matcher, "string")
1130    }
1131}
1132
1133impl<'a> IntoTypedValue for &'a str {
1134    fn into_typed_value(self) -> TypedValue {
1135        let value = self.into_value();
1136        TypedValue::new(value, string_matcher, "string")
1137    }
1138}
1139
1140impl<'a> IntoTypedValue for &'a String {
1141    fn into_typed_value(self) -> TypedValue {
1142        let value = self.into_value();
1143        TypedValue::new(value, string_matcher, "string")
1144    }
1145}
1146
1147impl IntoTypedValue for () {
1148    fn into_typed_value(self) -> TypedValue {
1149        TypedValue::new(
1150            Value::Nil,
1151            |_, ty| matches!(ty.kind, TypeKind::Unit | TypeKind::Unknown),
1152            "unit",
1153        )
1154    }
1155}
1156
1157impl<T> IntoTypedValue for Vec<T>
1158where
1159    T: IntoLustValue,
1160{
1161    fn into_typed_value(self) -> TypedValue {
1162        let values = self.into_iter().map(|item| item.into_value()).collect();
1163        TypedValue::new(
1164            Value::array(values),
1165            |_, ty| matches_array_type(ty, &T::matches_lust_type),
1166            "array",
1167        )
1168    }
1169}
1170
1171fn string_matcher(_: &Value, ty: &Type) -> bool {
1172    match &ty.kind {
1173        TypeKind::String | TypeKind::Unknown => true,
1174        TypeKind::Union(types) => types
1175            .iter()
1176            .any(|alt| matches!(&alt.kind, TypeKind::String | TypeKind::Unknown)),
1177        _ => false,
1178    }
1179}
1180
1181#[cfg(test)]
1182mod tests {
1183    use super::*;
1184    use std::future::Future;
1185    use std::pin::Pin;
1186    use std::sync::{Arc, Mutex};
1187    use std::task::{Context, Poll, Waker};
1188
1189    #[derive(Default)]
1190    struct ManualAsyncState {
1191        result: Mutex<Option<std::result::Result<LustInt, String>>>,
1192        waker: Mutex<Option<Waker>>,
1193    }
1194
1195    impl ManualAsyncState {
1196        fn new() -> Arc<Self> {
1197            Arc::new(Self::default())
1198        }
1199
1200        fn future(self: &Arc<Self>) -> ManualFuture {
1201            ManualFuture {
1202                state: Arc::clone(self),
1203            }
1204        }
1205
1206        fn complete_ok(&self, value: LustInt) {
1207            self.complete(Ok(value));
1208        }
1209
1210        fn complete_err(&self, message: impl Into<String>) {
1211            self.complete(Err(message.into()));
1212        }
1213
1214        fn complete(&self, value: std::result::Result<LustInt, String>) {
1215            {
1216                let mut slot = self.result.lock().unwrap();
1217                *slot = Some(value);
1218            }
1219
1220            if let Some(waker) = self.waker.lock().unwrap().take() {
1221                waker.wake();
1222            }
1223        }
1224    }
1225
1226    struct ManualFuture {
1227        state: Arc<ManualAsyncState>,
1228    }
1229
1230    impl Future for ManualFuture {
1231        type Output = std::result::Result<LustInt, String>;
1232
1233        fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
1234            {
1235                let mut slot = self.state.result.lock().unwrap();
1236                if let Some(result) = slot.take() {
1237                    return Poll::Ready(result);
1238                }
1239            }
1240
1241            let mut waker_slot = self.state.waker.lock().unwrap();
1242            *waker_slot = Some(cx.waker().clone());
1243            Poll::Pending
1244        }
1245    }
1246
1247    fn build_program(source: &str) -> EmbeddedProgram {
1248        EmbeddedProgram::builder()
1249            .module("main", source)
1250            .entry_module("main")
1251            .compile()
1252            .expect("compile embedded program")
1253    }
1254
1255    #[test]
1256    fn async_native_resumes_task_on_completion() {
1257        let source = r#"
1258            extern {
1259                function fetch_value(): int
1260            }
1261
1262            function compute(): int
1263                return fetch_value()
1264            end
1265        "#;
1266
1267        let mut program = build_program(source);
1268
1269        let state = ManualAsyncState::new();
1270        let register_state = Arc::clone(&state);
1271        program
1272            .register_async_typed_native::<(), LustInt, _, _>("fetch_value", move |_| {
1273                register_state.future()
1274            })
1275            .expect("register async native");
1276
1277        let handle = {
1278            let vm = program.vm_mut();
1279            let compute_fn = vm
1280                .function_value("main.compute")
1281                .expect("compute function");
1282            vm.spawn_task_value(compute_fn, Vec::new())
1283                .expect("spawn task")
1284        };
1285
1286        assert!(program.has_pending_async_tasks());
1287        program.poll_async_tasks().expect("initial poll");
1288        assert!(program.has_pending_async_tasks());
1289
1290        state.complete_ok(123);
1291        program
1292            .poll_async_tasks()
1293            .expect("resume after completion");
1294
1295        {
1296            let vm = program.vm_mut();
1297            let task = vm.get_task_instance(handle).expect("task exists");
1298            let result = task
1299                .last_result
1300                .as_ref()
1301                .and_then(|value| value.as_int())
1302                .expect("task produced result");
1303            assert_eq!(result, 123);
1304            assert!(task.error.is_none());
1305        }
1306
1307        assert!(!program.has_pending_async_tasks());
1308    }
1309
1310    #[test]
1311    fn async_native_failure_marks_task_failed() {
1312        let source = r#"
1313            extern {
1314                function fetch_value(): int
1315            }
1316
1317            function compute(): int
1318                return fetch_value()
1319            end
1320        "#;
1321
1322        let mut program = build_program(source);
1323
1324        let state = ManualAsyncState::new();
1325        let register_state = Arc::clone(&state);
1326        program
1327            .register_async_typed_native::<(), LustInt, _, _>("fetch_value", move |_| {
1328                register_state.future()
1329            })
1330            .expect("register async native");
1331
1332        let handle = {
1333            let vm = program.vm_mut();
1334            let compute_fn = vm
1335                .function_value("main.compute")
1336                .expect("compute function");
1337            vm.spawn_task_value(compute_fn, Vec::new())
1338                .expect("spawn task")
1339        };
1340
1341        program.poll_async_tasks().expect("initial poll");
1342        state.complete_err("boom");
1343        let err = program
1344            .poll_async_tasks()
1345            .expect_err("poll should propagate failure");
1346        match err {
1347            LustError::RuntimeError { message } => assert_eq!(message, "boom"),
1348            other => panic!("unexpected error: {other:?}"),
1349        }
1350
1351        {
1352            let vm = program.vm_mut();
1353            let task = vm.get_task_instance(handle).expect("task exists");
1354            assert!(task.last_result.is_none());
1355            let error_message = task
1356                .error
1357                .as_ref()
1358                .map(|e| e.to_string())
1359                .expect("task should record error");
1360            assert!(error_message.contains("boom"));
1361        }
1362
1363        assert!(!program.has_pending_async_tasks());
1364    }
1365}
1366
1367fn matches_lust_struct(value: &Value, ty: &Type) -> bool {
1368    match (value, &ty.kind) {
1369        (Value::Struct { name, .. }, TypeKind::Named(expected)) => name == expected,
1370        (Value::Struct { name, .. }, TypeKind::GenericInstance { name: expected, .. }) => {
1371            name == expected
1372        }
1373
1374        (value, TypeKind::Union(types)) => types.iter().any(|alt| matches_lust_struct(value, alt)),
1375        (_, TypeKind::Unknown) => true,
1376        _ => false,
1377    }
1378}
1379
1380fn matches_lust_enum(value: &Value, ty: &Type) -> bool {
1381    match (value, &ty.kind) {
1382        (Value::Enum { enum_name, .. }, TypeKind::Named(expected)) => enum_name == expected,
1383        (Value::Enum { enum_name, .. }, TypeKind::GenericInstance { name: expected, .. }) => {
1384            enum_name == expected
1385        }
1386
1387        (value, TypeKind::Union(types)) => types.iter().any(|alt| matches_lust_enum(value, alt)),
1388        (_, TypeKind::Unknown) => true,
1389        _ => false,
1390    }
1391}
1392
1393fn matches_array_type<F>(ty: &Type, matcher: &F) -> bool
1394where
1395    F: Fn(&Type) -> bool,
1396{
1397    match &ty.kind {
1398        TypeKind::Array(inner) => matcher(inner),
1399        TypeKind::Unknown => true,
1400        TypeKind::Union(types) => types.iter().any(|alt| matches_array_type(alt, matcher)),
1401        _ => false,
1402    }
1403}
1404
1405pub trait FromLustArgs: Sized {
1406    fn from_values(values: &[Value]) -> std::result::Result<Self, String>;
1407    fn matches_signature(params: &[Type]) -> bool;
1408}
1409
1410macro_rules! impl_from_lust_args_tuple {
1411    ($( $name:ident ),+) => {
1412        impl<$($name),+> FromLustArgs for ($($name,)+)
1413        where
1414            $($name: FromLustValue,)+
1415        {
1416            fn from_values(values: &[Value]) -> std::result::Result<Self, String> {
1417                let expected = count_idents!($($name),+);
1418                if values.len() != expected {
1419                    return Err(format!(
1420                        "Native function expected {} argument(s) but received {}",
1421                        expected,
1422                        values.len()
1423                    ));
1424                }
1425
1426                let mut idx = 0;
1427                let result = (
1428                    $(
1429                        {
1430                            let value = $name::from_value(values[idx].clone()).map_err(|e| e.to_string())?;
1431                            idx += 1;
1432                            value
1433                        },
1434                    )+
1435                );
1436                let _ = idx;
1437                Ok(result)
1438            }
1439
1440            fn matches_signature(params: &[Type]) -> bool {
1441                let expected = count_idents!($($name),+);
1442                params.len() == expected && {
1443                    let mut idx = 0;
1444                    let mut ok = true;
1445                    $(
1446                        if ok && !$name::matches_lust_type(&params[idx]) {
1447                            ok = false;
1448                        }
1449
1450                        idx += 1;
1451                    )+
1452                    let _ = idx;
1453                    ok
1454                }
1455
1456            }
1457
1458        }
1459
1460    };
1461}
1462
1463macro_rules! count_idents {
1464    ($($name:ident),*) => {
1465        <[()]>::len(&[$(count_idents!(@sub $name)),*])
1466    };
1467    (@sub $name:ident) => { () };
1468}
1469
1470impl_from_lust_args_tuple!(A);
1471impl_from_lust_args_tuple!(A, B);
1472impl_from_lust_args_tuple!(A, B, C);
1473impl_from_lust_args_tuple!(A, B, C, D);
1474impl_from_lust_args_tuple!(A, B, C, D, E);
1475impl<T> FromLustArgs for T
1476where
1477    T: FromLustValue,
1478{
1479    fn from_values(values: &[Value]) -> std::result::Result<Self, String> {
1480        match values.len() {
1481            0 => T::from_value(Value::Nil).map_err(|e| e.to_string()),
1482            1 => T::from_value(values[0].clone()).map_err(|e| e.to_string()),
1483            count => Err(format!(
1484                "Native function expected 1 argument but received {}",
1485                count
1486            )),
1487        }
1488    }
1489
1490    fn matches_signature(params: &[Type]) -> bool {
1491        if params.is_empty() {
1492            let unit = Type::new(TypeKind::Unit, Span::new(0, 0, 0, 0));
1493            return T::matches_lust_type(&unit);
1494        }
1495
1496        params.len() == 1 && T::matches_lust_type(&params[0])
1497    }
1498}
1499
1500pub trait IntoLustValue: Sized {
1501    fn into_value(self) -> Value;
1502    fn matches_lust_type(ty: &Type) -> bool;
1503    fn type_description() -> &'static str;
1504}
1505
1506pub trait FromLustValue: Sized {
1507    fn from_value(value: Value) -> Result<Self>;
1508    fn matches_lust_type(ty: &Type) -> bool;
1509    fn type_description() -> &'static str;
1510}
1511
1512pub trait FunctionArgs {
1513    fn into_values(self) -> Vec<Value>;
1514    fn validate_signature(function_name: &str, params: &[Type]) -> Result<()>;
1515}
1516
1517impl IntoLustValue for Value {
1518    fn into_value(self) -> Value {
1519        self
1520    }
1521
1522    fn matches_lust_type(_: &Type) -> bool {
1523        true
1524    }
1525
1526    fn type_description() -> &'static str {
1527        "Value"
1528    }
1529}
1530
1531impl FromLustValue for Value {
1532    fn from_value(value: Value) -> Result<Self> {
1533        Ok(value)
1534    }
1535
1536    fn matches_lust_type(_: &Type) -> bool {
1537        true
1538    }
1539
1540    fn type_description() -> &'static str {
1541        "Value"
1542    }
1543}
1544
1545impl IntoLustValue for LustInt {
1546    fn into_value(self) -> Value {
1547        Value::Int(self)
1548    }
1549
1550    fn matches_lust_type(ty: &Type) -> bool {
1551        matches!(ty.kind, TypeKind::Int | TypeKind::Unknown)
1552    }
1553
1554    fn type_description() -> &'static str {
1555        "int"
1556    }
1557}
1558
1559impl FromLustValue for LustInt {
1560    fn from_value(value: Value) -> Result<Self> {
1561        match value {
1562            Value::Int(v) => Ok(v),
1563            other => Err(LustError::RuntimeError {
1564                message: format!("Expected Lust value 'int' but received '{:?}'", other),
1565            }),
1566        }
1567    }
1568
1569    fn matches_lust_type(ty: &Type) -> bool {
1570        matches!(ty.kind, TypeKind::Int | TypeKind::Unknown)
1571    }
1572
1573    fn type_description() -> &'static str {
1574        "int"
1575    }
1576}
1577
1578impl IntoLustValue for LustFloat {
1579    fn into_value(self) -> Value {
1580        Value::Float(self)
1581    }
1582
1583    fn matches_lust_type(ty: &Type) -> bool {
1584        matches!(ty.kind, TypeKind::Float | TypeKind::Unknown)
1585    }
1586
1587    fn type_description() -> &'static str {
1588        "float"
1589    }
1590}
1591
1592impl FromLustValue for LustFloat {
1593    fn from_value(value: Value) -> Result<Self> {
1594        match value {
1595            Value::Float(v) => Ok(v),
1596            other => Err(LustError::RuntimeError {
1597                message: format!("Expected Lust value 'float' but received '{:?}'", other),
1598            }),
1599        }
1600    }
1601
1602    fn matches_lust_type(ty: &Type) -> bool {
1603        matches!(ty.kind, TypeKind::Float | TypeKind::Unknown)
1604    }
1605
1606    fn type_description() -> &'static str {
1607        "float"
1608    }
1609}
1610
1611impl IntoLustValue for bool {
1612    fn into_value(self) -> Value {
1613        Value::Bool(self)
1614    }
1615
1616    fn matches_lust_type(ty: &Type) -> bool {
1617        matches!(ty.kind, TypeKind::Bool | TypeKind::Unknown)
1618    }
1619
1620    fn type_description() -> &'static str {
1621        "bool"
1622    }
1623}
1624
1625impl FromLustValue for bool {
1626    fn from_value(value: Value) -> Result<Self> {
1627        match value {
1628            Value::Bool(b) => Ok(b),
1629            other => Err(LustError::RuntimeError {
1630                message: format!("Expected Lust value 'bool' but received '{:?}'", other),
1631            }),
1632        }
1633    }
1634
1635    fn matches_lust_type(ty: &Type) -> bool {
1636        matches!(ty.kind, TypeKind::Bool | TypeKind::Unknown)
1637    }
1638
1639    fn type_description() -> &'static str {
1640        "bool"
1641    }
1642}
1643
1644impl IntoLustValue for String {
1645    fn into_value(self) -> Value {
1646        Value::String(Rc::new(self))
1647    }
1648
1649    fn matches_lust_type(ty: &Type) -> bool {
1650        matches!(ty.kind, TypeKind::String | TypeKind::Unknown)
1651    }
1652
1653    fn type_description() -> &'static str {
1654        "string"
1655    }
1656}
1657
1658impl IntoLustValue for StructInstance {
1659    fn into_value(self) -> Value {
1660        self.value
1661    }
1662
1663    fn matches_lust_type(ty: &Type) -> bool {
1664        match &ty.kind {
1665            TypeKind::Unknown | TypeKind::Named(_) | TypeKind::GenericInstance { .. } => true,
1666            TypeKind::Union(types) => types
1667                .iter()
1668                .any(|alt| <Self as IntoLustValue>::matches_lust_type(alt)),
1669            _ => false,
1670        }
1671    }
1672
1673    fn type_description() -> &'static str {
1674        "struct"
1675    }
1676}
1677
1678impl FromLustValue for StructInstance {
1679    fn from_value(value: Value) -> Result<Self> {
1680        match &value {
1681            Value::Struct { name, .. } => Ok(StructInstance {
1682                type_name: name.clone(),
1683                value,
1684            }),
1685            other => Err(LustError::RuntimeError {
1686                message: format!("Expected Lust value 'struct' but received '{:?}'", other),
1687            }),
1688        }
1689    }
1690
1691    fn matches_lust_type(ty: &Type) -> bool {
1692        match &ty.kind {
1693            TypeKind::Unknown | TypeKind::Named(_) | TypeKind::GenericInstance { .. } => true,
1694            TypeKind::Union(types) => types
1695                .iter()
1696                .any(|alt| <Self as FromLustValue>::matches_lust_type(alt)),
1697            _ => false,
1698        }
1699    }
1700
1701    fn type_description() -> &'static str {
1702        "struct"
1703    }
1704}
1705
1706impl IntoLustValue for EnumInstance {
1707    fn into_value(self) -> Value {
1708        self.value
1709    }
1710
1711    fn matches_lust_type(ty: &Type) -> bool {
1712        match &ty.kind {
1713            TypeKind::Unknown | TypeKind::Named(_) | TypeKind::GenericInstance { .. } => true,
1714            TypeKind::Union(types) => types
1715                .iter()
1716                .any(|alt| <Self as IntoLustValue>::matches_lust_type(alt)),
1717            _ => false,
1718        }
1719    }
1720
1721    fn type_description() -> &'static str {
1722        "enum"
1723    }
1724}
1725
1726impl FromLustValue for EnumInstance {
1727    fn from_value(value: Value) -> Result<Self> {
1728        match &value {
1729            Value::Enum {
1730                enum_name, variant, ..
1731            } => Ok(EnumInstance {
1732                type_name: enum_name.clone(),
1733                variant: variant.clone(),
1734                value,
1735            }),
1736            other => Err(LustError::RuntimeError {
1737                message: format!("Expected Lust value 'enum' but received '{:?}'", other),
1738            }),
1739        }
1740    }
1741
1742    fn matches_lust_type(ty: &Type) -> bool {
1743        match &ty.kind {
1744            TypeKind::Unknown | TypeKind::Named(_) | TypeKind::GenericInstance { .. } => true,
1745            TypeKind::Union(types) => types
1746                .iter()
1747                .any(|alt| <Self as FromLustValue>::matches_lust_type(alt)),
1748            _ => false,
1749        }
1750    }
1751
1752    fn type_description() -> &'static str {
1753        "enum"
1754    }
1755}
1756
1757impl<T> IntoLustValue for Vec<T>
1758where
1759    T: IntoLustValue,
1760{
1761    fn into_value(self) -> Value {
1762        let values = self.into_iter().map(|item| item.into_value()).collect();
1763        Value::array(values)
1764    }
1765
1766    fn matches_lust_type(ty: &Type) -> bool {
1767        matches_array_type(ty, &T::matches_lust_type)
1768    }
1769
1770    fn type_description() -> &'static str {
1771        "array"
1772    }
1773}
1774
1775impl<T> FromLustValue for Vec<T>
1776where
1777    T: FromLustValue,
1778{
1779    fn from_value(value: Value) -> Result<Self> {
1780        match value {
1781            Value::Array(items) => {
1782                let borrowed = items.borrow();
1783                let mut result = Vec::with_capacity(borrowed.len());
1784                for item in borrowed.iter() {
1785                    result.push(T::from_value(item.clone())?);
1786                }
1787
1788                Ok(result)
1789            }
1790
1791            other => Err(LustError::RuntimeError {
1792                message: format!("Expected Lust value 'array' but received '{:?}'", other),
1793            }),
1794        }
1795    }
1796
1797    fn matches_lust_type(ty: &Type) -> bool {
1798        matches_array_type(ty, &T::matches_lust_type)
1799    }
1800
1801    fn type_description() -> &'static str {
1802        "array"
1803    }
1804}
1805
1806impl<'a> IntoLustValue for &'a str {
1807    fn into_value(self) -> Value {
1808        Value::String(Rc::new(self.to_owned()))
1809    }
1810
1811    fn matches_lust_type(ty: &Type) -> bool {
1812        matches!(ty.kind, TypeKind::String | TypeKind::Unknown)
1813    }
1814
1815    fn type_description() -> &'static str {
1816        "string"
1817    }
1818}
1819
1820impl<'a> IntoLustValue for &'a String {
1821    fn into_value(self) -> Value {
1822        Value::String(Rc::new(self.clone()))
1823    }
1824
1825    fn matches_lust_type(ty: &Type) -> bool {
1826        matches!(ty.kind, TypeKind::String | TypeKind::Unknown)
1827    }
1828
1829    fn type_description() -> &'static str {
1830        "string"
1831    }
1832}
1833
1834impl FromLustValue for String {
1835    fn from_value(value: Value) -> Result<Self> {
1836        match value {
1837            Value::String(s) => Ok((*s).clone()),
1838            other => Err(LustError::RuntimeError {
1839                message: format!("Expected Lust value 'string' but received '{:?}'", other),
1840            }),
1841        }
1842    }
1843
1844    fn matches_lust_type(ty: &Type) -> bool {
1845        matches!(ty.kind, TypeKind::String | TypeKind::Unknown)
1846    }
1847
1848    fn type_description() -> &'static str {
1849        "string"
1850    }
1851}
1852
1853impl FromLustValue for () {
1854    fn from_value(value: Value) -> Result<Self> {
1855        match value {
1856            Value::Nil => Ok(()),
1857            other => Err(LustError::RuntimeError {
1858                message: format!("Expected Lust value 'unit' but received '{:?}'", other),
1859            }),
1860        }
1861    }
1862
1863    fn matches_lust_type(ty: &Type) -> bool {
1864        matches!(ty.kind, TypeKind::Unit | TypeKind::Unknown)
1865    }
1866
1867    fn type_description() -> &'static str {
1868        "unit"
1869    }
1870}
1871
1872impl FunctionArgs for () {
1873    fn into_values(self) -> Vec<Value> {
1874        Vec::new()
1875    }
1876
1877    fn validate_signature(function_name: &str, params: &[Type]) -> Result<()> {
1878        ensure_arity(function_name, params, 0)
1879    }
1880}
1881
1882impl<T> FunctionArgs for T
1883where
1884    T: IntoLustValue,
1885{
1886    fn into_values(self) -> Vec<Value> {
1887        vec![self.into_value()]
1888    }
1889
1890    fn validate_signature(function_name: &str, params: &[Type]) -> Result<()> {
1891        ensure_arity(function_name, params, 1)?;
1892        ensure_arg_type::<T>(function_name, params, 0)
1893    }
1894}
1895
1896impl<A, B> FunctionArgs for (A, B)
1897where
1898    A: IntoLustValue,
1899    B: IntoLustValue,
1900{
1901    fn into_values(self) -> Vec<Value> {
1902        vec![self.0.into_value(), self.1.into_value()]
1903    }
1904
1905    fn validate_signature(function_name: &str, params: &[Type]) -> Result<()> {
1906        ensure_arity(function_name, params, 2)?;
1907        ensure_arg_type::<A>(function_name, params, 0)?;
1908        ensure_arg_type::<B>(function_name, params, 1)?;
1909        Ok(())
1910    }
1911}
1912
1913impl<A, B, C> FunctionArgs for (A, B, C)
1914where
1915    A: IntoLustValue,
1916    B: IntoLustValue,
1917    C: IntoLustValue,
1918{
1919    fn into_values(self) -> Vec<Value> {
1920        vec![
1921            self.0.into_value(),
1922            self.1.into_value(),
1923            self.2.into_value(),
1924        ]
1925    }
1926
1927    fn validate_signature(function_name: &str, params: &[Type]) -> Result<()> {
1928        ensure_arity(function_name, params, 3)?;
1929        ensure_arg_type::<A>(function_name, params, 0)?;
1930        ensure_arg_type::<B>(function_name, params, 1)?;
1931        ensure_arg_type::<C>(function_name, params, 2)?;
1932        Ok(())
1933    }
1934}
1935
1936impl<A, B, C, D> FunctionArgs for (A, B, C, D)
1937where
1938    A: IntoLustValue,
1939    B: IntoLustValue,
1940    C: IntoLustValue,
1941    D: IntoLustValue,
1942{
1943    fn into_values(self) -> Vec<Value> {
1944        vec![
1945            self.0.into_value(),
1946            self.1.into_value(),
1947            self.2.into_value(),
1948            self.3.into_value(),
1949        ]
1950    }
1951
1952    fn validate_signature(function_name: &str, params: &[Type]) -> Result<()> {
1953        ensure_arity(function_name, params, 4)?;
1954        ensure_arg_type::<A>(function_name, params, 0)?;
1955        ensure_arg_type::<B>(function_name, params, 1)?;
1956        ensure_arg_type::<C>(function_name, params, 2)?;
1957        ensure_arg_type::<D>(function_name, params, 3)?;
1958        Ok(())
1959    }
1960}
1961
1962impl<A, B, C, D, E> FunctionArgs for (A, B, C, D, E)
1963where
1964    A: IntoLustValue,
1965    B: IntoLustValue,
1966    C: IntoLustValue,
1967    D: IntoLustValue,
1968    E: IntoLustValue,
1969{
1970    fn into_values(self) -> Vec<Value> {
1971        vec![
1972            self.0.into_value(),
1973            self.1.into_value(),
1974            self.2.into_value(),
1975            self.3.into_value(),
1976            self.4.into_value(),
1977        ]
1978    }
1979
1980    fn validate_signature(function_name: &str, params: &[Type]) -> Result<()> {
1981        ensure_arity(function_name, params, 5)?;
1982        ensure_arg_type::<A>(function_name, params, 0)?;
1983        ensure_arg_type::<B>(function_name, params, 1)?;
1984        ensure_arg_type::<C>(function_name, params, 2)?;
1985        ensure_arg_type::<D>(function_name, params, 3)?;
1986        ensure_arg_type::<E>(function_name, params, 4)?;
1987        Ok(())
1988    }
1989}
1990
1991fn ensure_arity(function_name: &str, params: &[Type], provided: usize) -> Result<()> {
1992    if params.len() == provided {
1993        Ok(())
1994    } else {
1995        Err(LustError::TypeError {
1996            message: format!(
1997                "Function '{}' expects {} argument(s) but {} were supplied",
1998                function_name,
1999                params.len(),
2000                provided
2001            ),
2002        })
2003    }
2004}
2005
2006fn ensure_arg_type<T: IntoLustValue>(
2007    function_name: &str,
2008    params: &[Type],
2009    index: usize,
2010) -> Result<()> {
2011    if <T as IntoLustValue>::matches_lust_type(&params[index]) {
2012        Ok(())
2013    } else {
2014        Err(argument_type_mismatch(
2015            function_name,
2016            index,
2017            <T as IntoLustValue>::type_description(),
2018            &params[index],
2019        ))
2020    }
2021}
2022
2023fn argument_type_mismatch(
2024    function_name: &str,
2025    index: usize,
2026    rust_type: &str,
2027    lust_type: &Type,
2028) -> LustError {
2029    LustError::TypeError {
2030        message: format!(
2031            "Function '{}' parameter {} expects Lust type '{}' but Rust provided '{}'",
2032            function_name,
2033            index + 1,
2034            lust_type,
2035            rust_type
2036        ),
2037    }
2038}