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