1use crate::{
32 Visibility,
33 context::Context,
34 function::{Function, FunctionBody, FunctionParameter, FunctionQuery, FunctionSignature},
35 meta::Meta,
36 registry::Registry,
37 types::{
38 TypeQuery,
39 enum_type::{EnumVariant, RuntimeEnumBuilder},
40 struct_type::{RuntimeStructBuilder, StructField},
41 },
42};
43use std::{
44 collections::HashMap,
45 error::Error,
46 path::{Path, PathBuf},
47 sync::Arc,
48};
49
50pub type ScriptHandle<'a, SE> = Arc<Script<'a, SE>>;
52pub type Script<'a, SE> = Vec<ScriptOperation<'a, SE>>;
54
55pub trait ScriptExpression: Send + Sync {
78 fn evaluate(&self, context: &mut Context, registry: &Registry);
80}
81
82impl ScriptExpression for () {
83 fn evaluate(&self, _: &mut Context, _: &Registry) {}
84}
85
86#[allow(clippy::type_complexity)]
91pub struct InlineExpression(Arc<dyn Fn(&mut Context, &Registry) + Send + Sync>);
92
93impl InlineExpression {
94 pub fn copied<T: Copy + Send + Sync + 'static>(value: T) -> Self {
96 Self(Arc::new(move |context, _| {
97 context.stack().push(value);
98 }))
99 }
100
101 pub fn cloned<T: Clone + Send + Sync + 'static>(value: T) -> Self {
103 Self(Arc::new(move |context, _| {
104 context.stack().push(value.clone());
105 }))
106 }
107
108 pub fn closure<F: Fn(&mut Context, &Registry) + Send + Sync + 'static>(f: F) -> Self {
110 Self(Arc::new(f))
111 }
112}
113
114impl ScriptExpression for InlineExpression {
115 fn evaluate(&self, context: &mut Context, registry: &Registry) {
116 (self.0)(context, registry);
117 }
118}
119
120#[derive(Debug)]
124pub enum ScriptOperation<'a, SE: ScriptExpression> {
125 None,
127 Expression { expression: SE },
129 DefineRegister { query: TypeQuery<'a> },
134 DropRegister { index: usize },
136 PushFromRegister { index: usize },
138 PopToRegister { index: usize },
140 MoveRegister { from: usize, to: usize },
142 CallFunction { query: FunctionQuery<'a> },
144 BranchScope {
148 scope_success: ScriptHandle<'a, SE>,
149 scope_failure: Option<ScriptHandle<'a, SE>>,
150 },
151 LoopScope { scope: ScriptHandle<'a, SE> },
156 PushScope { scope: ScriptHandle<'a, SE> },
158 PopScope,
160 ContinueScopeConditionally,
163 Suspend,
168}
169
170impl<SE: ScriptExpression> ScriptOperation<'_, SE> {
171 pub fn label(&self) -> &str {
173 match self {
174 Self::None => "None",
175 Self::Expression { .. } => "Expression",
176 Self::DefineRegister { .. } => "DefineRegister",
177 Self::DropRegister { .. } => "DropRegister",
178 Self::PushFromRegister { .. } => "PushFromRegister",
179 Self::PopToRegister { .. } => "PopToRegister",
180 Self::MoveRegister { .. } => "MoveRegister",
181 Self::CallFunction { .. } => "CallFunction",
182 Self::BranchScope { .. } => "BranchScope",
183 Self::LoopScope { .. } => "LoopScope",
184 Self::PushScope { .. } => "PushScope",
185 Self::PopScope => "PopScope",
186 Self::ContinueScopeConditionally => "ContinueScopeConditionally",
187 Self::Suspend => "Suspend",
188 }
189 }
190}
191
192pub struct ScriptBuilder<'a, SE: ScriptExpression>(Script<'a, SE>);
202
203impl<SE: ScriptExpression> Default for ScriptBuilder<'_, SE> {
204 fn default() -> Self {
205 Self(vec![])
206 }
207}
208
209impl<'a, SE: ScriptExpression> ScriptBuilder<'a, SE> {
210 pub fn build(self) -> ScriptHandle<'a, SE> {
212 ScriptHandle::new(self.0)
213 }
214
215 pub fn expression(mut self, expression: SE) -> Self {
217 self.0.push(ScriptOperation::Expression { expression });
218 self
219 }
220
221 pub fn define_register(mut self, query: TypeQuery<'a>) -> Self {
223 self.0.push(ScriptOperation::DefineRegister { query });
224 self
225 }
226
227 pub fn drop_register(mut self, index: usize) -> Self {
229 self.0.push(ScriptOperation::DropRegister { index });
230 self
231 }
232
233 pub fn push_from_register(mut self, index: usize) -> Self {
235 self.0.push(ScriptOperation::PushFromRegister { index });
236 self
237 }
238
239 pub fn pop_to_register(mut self, index: usize) -> Self {
241 self.0.push(ScriptOperation::PopToRegister { index });
242 self
243 }
244
245 pub fn move_register(mut self, from: usize, to: usize) -> Self {
247 self.0.push(ScriptOperation::MoveRegister { from, to });
248 self
249 }
250
251 pub fn call_function(mut self, query: FunctionQuery<'a>) -> Self {
253 self.0.push(ScriptOperation::CallFunction { query });
254 self
255 }
256
257 pub fn branch_scope(
259 mut self,
260 scope_success: ScriptHandle<'a, SE>,
261 scope_failure: Option<ScriptHandle<'a, SE>>,
262 ) -> Self {
263 self.0.push(ScriptOperation::BranchScope {
264 scope_success,
265 scope_failure,
266 });
267 self
268 }
269
270 pub fn loop_scope(mut self, scope: ScriptHandle<'a, SE>) -> Self {
272 self.0.push(ScriptOperation::LoopScope { scope });
273 self
274 }
275
276 pub fn push_scope(mut self, scope: ScriptHandle<'a, SE>) -> Self {
278 self.0.push(ScriptOperation::PushScope { scope });
279 self
280 }
281
282 pub fn pop_scope(mut self) -> Self {
284 self.0.push(ScriptOperation::PopScope);
285 self
286 }
287
288 pub fn continue_scope_conditionally(mut self) -> Self {
290 self.0.push(ScriptOperation::ContinueScopeConditionally);
291 self
292 }
293
294 pub fn suspend(mut self) -> Self {
296 self.0.push(ScriptOperation::Suspend);
297 self
298 }
299}
300
301#[derive(Debug)]
304pub struct ScriptFunctionParameter<'a> {
305 pub meta: Option<Meta>,
307 pub name: String,
309 pub type_query: TypeQuery<'a>,
311}
312
313impl ScriptFunctionParameter<'_> {
314 pub fn build(&self, registry: &Registry) -> FunctionParameter {
320 FunctionParameter {
321 meta: self.meta.to_owned(),
322 name: self.name.to_owned(),
323 type_handle: registry
324 .types()
325 .find(|type_| self.type_query.is_valid(type_))
326 .unwrap()
327 .clone(),
328 }
329 }
330}
331
332#[derive(Debug)]
335pub struct ScriptFunctionSignature<'a> {
336 pub meta: Option<Meta>,
338 pub name: String,
340 pub module_name: Option<String>,
342 pub type_query: Option<TypeQuery<'a>>,
344 pub visibility: Visibility,
346 pub inputs: Vec<ScriptFunctionParameter<'a>>,
348 pub outputs: Vec<ScriptFunctionParameter<'a>>,
350}
351
352impl ScriptFunctionSignature<'_> {
353 pub fn build(&self, registry: &Registry) -> FunctionSignature {
359 FunctionSignature {
360 meta: self.meta.to_owned(),
361 name: self.name.to_owned(),
362 module_name: self.module_name.to_owned(),
363 type_handle: self.type_query.as_ref().map(|type_query| {
364 registry
365 .types()
366 .find(|type_| type_query.is_valid(type_))
367 .unwrap()
368 .clone()
369 }),
370 visibility: self.visibility,
371 inputs: self
372 .inputs
373 .iter()
374 .map(|parameter| parameter.build(registry))
375 .collect(),
376 outputs: self
377 .outputs
378 .iter()
379 .map(|parameter| parameter.build(registry))
380 .collect(),
381 }
382 }
383}
384
385#[derive(Debug)]
388pub struct ScriptFunction<'a, SE: ScriptExpression> {
389 pub signature: ScriptFunctionSignature<'a>,
391 pub script: ScriptHandle<'a, SE>,
393}
394
395impl<SE: ScriptExpression> ScriptFunction<'static, SE> {
396 pub fn install<SFG: ScriptFunctionGenerator<SE>>(
401 &self,
402 registry: &mut Registry,
403 input: SFG::Input,
404 ) -> Option<SFG::Output> {
405 let (function, output) = SFG::generate_function(self, registry, input)?;
406 registry.add_function(function);
407 Some(output)
408 }
409}
410
411pub trait ScriptFunctionGenerator<SE: ScriptExpression> {
417 type Input;
419 type Output;
421
422 fn generate_function_body(
424 script: ScriptHandle<'static, SE>,
425 input: Self::Input,
426 ) -> Option<(FunctionBody, Self::Output)>;
427
428 fn generate_function(
430 function: &ScriptFunction<'static, SE>,
431 registry: &Registry,
432 input: Self::Input,
433 ) -> Option<(Function, Self::Output)> {
434 let (body, output) = Self::generate_function_body(function.script.clone(), input)?;
435 Some((
436 Function::new(function.signature.build(registry), body),
437 output,
438 ))
439 }
440}
441
442#[derive(Debug)]
445pub struct ScriptStructField<'a> {
446 pub meta: Option<Meta>,
448 pub name: String,
450 pub visibility: Visibility,
452 pub type_query: TypeQuery<'a>,
454}
455
456impl ScriptStructField<'_> {
457 pub fn build(&self, registry: &Registry) -> StructField {
463 let mut result = StructField::new(
464 &self.name,
465 registry
466 .types()
467 .find(|type_| self.type_query.is_valid(type_))
468 .unwrap()
469 .clone(),
470 )
471 .with_visibility(self.visibility);
472 result.meta.clone_from(&self.meta);
473 result
474 }
475}
476
477#[derive(Debug)]
482pub struct ScriptStruct<'a> {
483 pub meta: Option<Meta>,
485 pub name: String,
487 pub module_name: Option<String>,
489 pub visibility: Visibility,
491 pub fields: Vec<ScriptStructField<'a>>,
493}
494
495impl ScriptStruct<'_> {
496 pub fn declare(&self, registry: &mut Registry) {
498 let mut builder = RuntimeStructBuilder::new(&self.name);
499 builder = builder.visibility(self.visibility);
500 if let Some(module_name) = self.module_name.as_ref() {
501 builder = builder.module_name(module_name);
502 }
503 if let Some(meta) = self.meta.as_ref() {
504 builder = builder.meta(meta.to_owned());
505 }
506 registry.add_type(builder.build());
507 }
508
509 pub fn define(&self, registry: &mut Registry) {
513 let query = TypeQuery {
514 name: Some(self.name.as_str().into()),
515 module_name: self
516 .module_name
517 .as_ref()
518 .map(|module_name| module_name.into()),
519 ..Default::default()
520 };
521 if let Some(handle) = registry.find_type(query) {
522 let mut builder = RuntimeStructBuilder::new(&self.name);
523 builder = builder.visibility(self.visibility);
524 if let Some(module_name) = self.module_name.as_ref() {
525 builder = builder.module_name(module_name);
526 }
527 if let Some(meta) = self.meta.as_ref() {
528 builder = builder.meta(meta.to_owned());
529 }
530 for field in &self.fields {
531 builder = builder.field(field.build(registry));
532 }
533 unsafe {
534 let type_ = Arc::as_ptr(&handle).cast_mut();
535 *type_ = builder.build().into();
536 }
537 }
538 }
539
540 pub fn install(&self, registry: &mut Registry) {
545 let mut builder = RuntimeStructBuilder::new(&self.name);
546 builder = builder.visibility(self.visibility);
547 if let Some(module_name) = self.module_name.as_ref() {
548 builder = builder.module_name(module_name);
549 }
550 for field in &self.fields {
551 builder = builder.field(field.build(registry));
552 }
553 registry.add_type(builder.build());
554 }
555}
556
557#[derive(Debug)]
559pub struct ScriptEnumVariant<'a> {
560 pub meta: Option<Meta>,
562 pub name: String,
564 pub fields: Vec<ScriptStructField<'a>>,
566 pub discriminant: Option<u8>,
569}
570
571impl ScriptEnumVariant<'_> {
572 pub fn build(&self, registry: &Registry) -> EnumVariant {
578 let mut result = EnumVariant::new(&self.name);
579 result.fields = self
580 .fields
581 .iter()
582 .map(|field| field.build(registry))
583 .collect();
584 result.meta.clone_from(&self.meta);
585 result
586 }
587}
588
589#[derive(Debug)]
594pub struct ScriptEnum<'a> {
595 pub meta: Option<Meta>,
597 pub name: String,
599 pub module_name: Option<String>,
601 pub visibility: Visibility,
603 pub variants: Vec<ScriptEnumVariant<'a>>,
605 pub default_variant: Option<u8>,
607}
608
609impl ScriptEnum<'_> {
610 pub fn declare(&self, registry: &mut Registry) {
612 let mut builder = RuntimeEnumBuilder::new(&self.name);
613 if let Some(discriminant) = self.default_variant {
614 builder = builder.set_default_variant(discriminant);
615 }
616 builder = builder.visibility(self.visibility);
617 if let Some(module_name) = self.module_name.as_ref() {
618 builder = builder.module_name(module_name);
619 }
620 if let Some(meta) = self.meta.as_ref() {
621 builder = builder.meta(meta.to_owned());
622 }
623 registry.add_type(builder.build());
624 }
625
626 pub fn define(&self, registry: &mut Registry) {
630 let query = TypeQuery {
631 name: Some(self.name.as_str().into()),
632 module_name: self
633 .module_name
634 .as_ref()
635 .map(|module_name| module_name.into()),
636 ..Default::default()
637 };
638 if let Some(handle) = registry.find_type(query) {
639 let mut builder = RuntimeEnumBuilder::new(&self.name);
640 if let Some(discriminant) = self.default_variant {
641 builder = builder.set_default_variant(discriminant);
642 }
643 builder = builder.visibility(self.visibility);
644 if let Some(module_name) = self.module_name.as_ref() {
645 builder = builder.module_name(module_name);
646 }
647 if let Some(meta) = self.meta.as_ref() {
648 builder = builder.meta(meta.to_owned());
649 }
650 for variant in &self.variants {
651 if let Some(discriminant) = variant.discriminant {
652 builder =
653 builder.variant_with_discriminant(variant.build(registry), discriminant);
654 } else {
655 builder = builder.variant(variant.build(registry));
656 }
657 }
658 unsafe {
659 let type_ = Arc::as_ptr(&handle).cast_mut();
660 *type_ = builder.build().into();
661 }
662 }
663 }
664
665 pub fn install(&self, registry: &mut Registry) {
670 let mut builder = RuntimeEnumBuilder::new(&self.name);
671 if let Some(discriminant) = self.default_variant {
672 builder = builder.set_default_variant(discriminant);
673 }
674 builder = builder.visibility(self.visibility);
675 if let Some(module_name) = self.module_name.as_ref() {
676 builder = builder.module_name(module_name);
677 }
678 for variant in &self.variants {
679 if let Some(discriminant) = variant.discriminant {
680 builder = builder.variant_with_discriminant(variant.build(registry), discriminant);
681 } else {
682 builder = builder.variant(variant.build(registry));
683 }
684 }
685 registry.add_type(builder.build());
686 }
687}
688
689#[derive(Debug, Default)]
691pub struct ScriptModule<'a, SE: ScriptExpression> {
692 pub name: String,
694 pub structs: Vec<ScriptStruct<'a>>,
696 pub enums: Vec<ScriptEnum<'a>>,
698 pub functions: Vec<ScriptFunction<'a, SE>>,
700}
701
702impl<SE: ScriptExpression> ScriptModule<'_, SE> {
703 pub fn fix_module_names(&mut self) {
705 for type_ in &mut self.structs {
706 type_.module_name = Some(self.name.to_owned());
707 }
708 for type_ in &mut self.enums {
709 type_.module_name = Some(self.name.to_owned());
710 }
711 for function in &mut self.functions {
712 function.signature.module_name = Some(self.name.to_owned());
713 }
714 }
715
716 pub fn declare_types(&self, registry: &mut Registry) {
718 for type_ in &self.structs {
719 type_.declare(registry);
720 }
721 for type_ in &self.enums {
722 type_.declare(registry);
723 }
724 }
725
726 pub fn define_types(&self, registry: &mut Registry) {
728 for type_ in &self.structs {
729 type_.define(registry);
730 }
731 for type_ in &self.enums {
732 type_.define(registry);
733 }
734 }
735
736 pub fn install_types(&self, registry: &mut Registry) {
738 self.declare_types(registry);
739 self.define_types(registry);
740 }
741}
742
743impl<SE: ScriptExpression> ScriptModule<'static, SE> {
744 pub fn install_functions<SFG: ScriptFunctionGenerator<SE>>(
746 &self,
747 registry: &mut Registry,
748 input: SFG::Input,
749 ) where
750 SFG::Input: Clone,
751 {
752 for function in &self.functions {
753 function.install::<SFG>(registry, input.clone());
754 }
755 }
756}
757
758#[derive(Debug, Default)]
760pub struct ScriptPackage<'a, SE: ScriptExpression> {
761 pub modules: Vec<ScriptModule<'a, SE>>,
763}
764
765impl<SE: ScriptExpression> ScriptPackage<'static, SE> {
766 pub fn install<SFG: ScriptFunctionGenerator<SE>>(
771 &self,
772 registry: &mut Registry,
773 input: SFG::Input,
774 ) where
775 SFG::Input: Clone,
776 {
777 for module in &self.modules {
778 module.install_types(registry);
779 }
780 for module in &self.modules {
781 module.install_functions::<SFG>(registry, input.clone());
782 }
783 }
784}
785
786pub struct ScriptContent<T> {
792 pub path: String,
794 pub name: String,
796 pub data: Result<Option<T>, Box<dyn Error>>,
798}
799
800pub trait ScriptContentProvider<T> {
806 fn load(&mut self, path: &str) -> Result<Option<T>, Box<dyn Error>>;
809
810 fn unpack_load(&mut self, path: &str) -> Result<Vec<ScriptContent<T>>, Box<dyn Error>> {
814 Ok(vec![ScriptContent {
815 path: path.to_owned(),
816 name: path.to_owned(),
817 data: self.load(path),
818 }])
819 }
820
821 fn sanitize_path(&self, path: &str) -> Result<String, Box<dyn Error>> {
826 Ok(path.to_owned())
827 }
828
829 fn join_paths(&self, parent: &str, relative: &str) -> Result<String, Box<dyn Error>>;
831}
832
833pub struct ExtensionContentProvider<S> {
838 default_extension: Option<String>,
839 extension_providers: HashMap<String, Box<dyn ScriptContentProvider<S>>>,
840}
841
842impl<S> Default for ExtensionContentProvider<S> {
843 fn default() -> Self {
844 Self {
845 default_extension: None,
846 extension_providers: Default::default(),
847 }
848 }
849}
850
851impl<S> ExtensionContentProvider<S> {
852 pub fn default_extension(mut self, extension: impl ToString) -> Self {
854 self.default_extension = Some(extension.to_string());
855 self
856 }
857
858 pub fn extension(
860 mut self,
861 extension: &str,
862 content_provider: impl ScriptContentProvider<S> + 'static,
863 ) -> Self {
864 self.extension_providers
865 .insert(extension.to_owned(), Box::new(content_provider));
866 self
867 }
868}
869
870impl<S> ScriptContentProvider<S> for ExtensionContentProvider<S> {
871 fn load(&mut self, _: &str) -> Result<Option<S>, Box<dyn Error>> {
872 Ok(None)
873 }
874
875 fn unpack_load(&mut self, path: &str) -> Result<Vec<ScriptContent<S>>, Box<dyn Error>> {
876 let extension = match Path::new(path).extension() {
877 Some(extension) => extension.to_string_lossy().to_string(),
878 None => match &self.default_extension {
879 Some(extension) => extension.to_owned(),
880 None => return Err(Box::new(ExtensionContentProviderError::NoDefaultExtension)),
881 },
882 };
883 if let Some(content_provider) = self.extension_providers.get_mut(&extension) {
884 content_provider.unpack_load(path)
885 } else {
886 Err(Box::new(
887 ExtensionContentProviderError::ContentProviderForExtensionNotFound(extension),
888 ))
889 }
890 }
891
892 fn sanitize_path(&self, path: &str) -> Result<String, Box<dyn Error>> {
893 let extension = match Path::new(path).extension() {
894 Some(extension) => extension.to_string_lossy().to_string(),
895 None => match &self.default_extension {
896 Some(extension) => extension.to_owned(),
897 None => return Err(Box::new(ExtensionContentProviderError::NoDefaultExtension)),
898 },
899 };
900 if let Some(content_provider) = self.extension_providers.get(&extension) {
901 content_provider.sanitize_path(path)
902 } else {
903 Err(Box::new(
904 ExtensionContentProviderError::ContentProviderForExtensionNotFound(extension),
905 ))
906 }
907 }
908
909 fn join_paths(&self, parent: &str, relative: &str) -> Result<String, Box<dyn Error>> {
910 let extension = match Path::new(relative).extension() {
911 Some(extension) => extension.to_string_lossy().to_string(),
912 None => match &self.default_extension {
913 Some(extension) => extension.to_owned(),
914 None => return Err(Box::new(ExtensionContentProviderError::NoDefaultExtension)),
915 },
916 };
917 if let Some(content_provider) = self.extension_providers.get(&extension) {
918 content_provider.join_paths(parent, relative)
919 } else {
920 Err(Box::new(
921 ExtensionContentProviderError::ContentProviderForExtensionNotFound(extension),
922 ))
923 }
924 }
925}
926
927#[derive(Debug)]
929pub enum ExtensionContentProviderError {
930 NoDefaultExtension,
932 ContentProviderForExtensionNotFound(String),
934}
935
936impl std::fmt::Display for ExtensionContentProviderError {
937 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
938 match self {
939 ExtensionContentProviderError::NoDefaultExtension => {
940 write!(f, "No default extension set")
941 }
942 ExtensionContentProviderError::ContentProviderForExtensionNotFound(extension) => {
943 write!(
944 f,
945 "Could not find content provider for extension: `{extension}`"
946 )
947 }
948 }
949 }
950}
951
952impl Error for ExtensionContentProviderError {}
953
954pub struct IgnoreContentProvider;
958
959impl<S> ScriptContentProvider<S> for IgnoreContentProvider {
960 fn load(&mut self, _: &str) -> Result<Option<S>, Box<dyn Error>> {
961 Ok(None)
962 }
963
964 fn join_paths(&self, parent: &str, relative: &str) -> Result<String, Box<dyn Error>> {
965 Ok(format!("{parent}/{relative}"))
966 }
967}
968
969pub trait BytesContentParser<T> {
971 fn parse(&self, bytes: Vec<u8>) -> Result<T, Box<dyn Error>>;
973}
974
975pub struct FileContentProvider<T> {
980 extension: String,
981 parser: Box<dyn BytesContentParser<T>>,
982}
983
984impl<T> FileContentProvider<T> {
985 pub fn new(extension: impl ToString, parser: impl BytesContentParser<T> + 'static) -> Self {
987 Self {
988 extension: extension.to_string(),
989 parser: Box::new(parser),
990 }
991 }
992}
993
994impl<T> ScriptContentProvider<T> for FileContentProvider<T> {
995 fn load(&mut self, path: &str) -> Result<Option<T>, Box<dyn Error>> {
996 Ok(Some(self.parser.parse(std::fs::read(path)?)?))
997 }
998
999 fn sanitize_path(&self, path: &str) -> Result<String, Box<dyn Error>> {
1000 let mut result = PathBuf::from(path);
1001 if result.extension().is_none() {
1002 result.set_extension(&self.extension);
1003 }
1004 Ok(result.canonicalize()?.to_string_lossy().into_owned())
1005 }
1006
1007 fn join_paths(&self, parent: &str, relative: &str) -> Result<String, Box<dyn Error>> {
1008 let mut path = PathBuf::from(parent);
1009 path.pop();
1010 Ok(path.join(relative).to_string_lossy().into_owned())
1011 }
1012}