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