1use crate::core::error::WorkshopError;
4use crate::settings::Settings;
5use crate::source::{FileId, SourceDocument, SourceFile, Span};
6
7mod conversion;
8pub(crate) mod shared;
9mod source_map;
10pub use shared::{EventTarget, EventTeam, ModifyOp, PlayerEventKind};
11pub use source_map::{MAPPED_TEXT_V1, MappedText, SourceMap, SourceMapError, TEXT_V1};
12
13#[derive(Debug, Clone, Default)]
15pub struct Program {
16 pub settings: Option<Settings>,
17 pub global_variables: Vec<Variable>,
18 pub player_variables: Vec<Variable>,
19 pub subroutines: Vec<Subroutine>,
20 pub rules: Vec<Rule>,
21 files: Vec<SourceFile>,
22 provenance: Option<Box<ProgramProvenance>>,
23}
24
25#[derive(Debug, Clone, Default)]
26struct ProgramProvenance {
27 global_variables: Vec<DeclarationProvenance>,
28 player_variables: Vec<DeclarationProvenance>,
29 subroutines: Vec<DeclarationProvenance>,
30 rules: Vec<RuleProvenance>,
31}
32
33#[derive(Debug, Clone, Copy, Default)]
34struct DeclarationProvenance {
35 span: Option<Span>,
36 name_span: Option<Span>,
37}
38
39#[derive(Debug, Clone, Default)]
40struct RuleProvenance {
41 span: Option<crate::source::Span>,
42 name: Option<Span>,
44 event_name: Option<Span>,
46 conditions: Vec<ValueProvenance>,
47 actions: Vec<ActionProvenance>,
48}
49
50#[derive(Debug, Clone, Default)]
51struct ActionProvenance {
52 span: Option<Span>,
53 identifier: Option<Span>,
56 arguments: Vec<ValueProvenance>,
57}
58
59trait SpanSlot {
62 fn span_slot(&mut self) -> &mut Option<Span>;
63}
64
65impl SpanSlot for ValueProvenance {
66 fn span_slot(&mut self) -> &mut Option<Span> {
67 &mut self.span
68 }
69}
70
71impl SpanSlot for ActionProvenance {
72 fn span_slot(&mut self) -> &mut Option<Span> {
73 &mut self.span
74 }
75}
76
77#[derive(Debug, Clone, Default)]
80struct ValueProvenance {
81 span: Option<Span>,
82 identifier: Option<Span>,
85 children: Vec<ValueProvenance>,
86}
87
88#[derive(Debug, Clone, Copy, PartialEq, Eq)]
90#[non_exhaustive]
91pub enum SourceMappingError {
92 UnknownFile(FileId),
93 InvalidSpan(Span),
94 InvalidRule(usize),
95 InvalidCondition {
96 rule: usize,
97 condition: usize,
98 },
99 InvalidAction {
100 rule: usize,
101 action: usize,
102 },
103 InvalidActionArgument {
104 rule: usize,
105 action: usize,
106 argument: usize,
107 },
108 InvalidGlobalVariable(usize),
109 InvalidPlayerVariable(usize),
110 InvalidSubroutine(usize),
111}
112
113impl std::fmt::Display for SourceMappingError {
114 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
115 match self {
116 Self::UnknownFile(file) => {
117 write!(formatter, "source span references unknown file {file}")
118 }
119 Self::InvalidSpan(span) => write!(formatter, "invalid source span {span:?}"),
120 Self::InvalidRule(rule) => write!(formatter, "invalid rule index {rule}"),
121 Self::InvalidCondition { rule, condition } => {
122 write!(
123 formatter,
124 "invalid condition index {condition} in rule {rule}"
125 )
126 }
127 Self::InvalidAction { rule, action } => {
128 write!(formatter, "invalid action index {action} in rule {rule}")
129 }
130 Self::InvalidActionArgument {
131 rule,
132 action,
133 argument,
134 } => write!(
135 formatter,
136 "invalid argument index {argument} in action {action} of rule {rule}"
137 ),
138 Self::InvalidGlobalVariable(variable) => {
139 write!(formatter, "invalid global variable index {variable}")
140 }
141 Self::InvalidPlayerVariable(variable) => {
142 write!(formatter, "invalid player variable index {variable}")
143 }
144 Self::InvalidSubroutine(subroutine) => {
145 write!(formatter, "invalid subroutine index {subroutine}")
146 }
147 }
148 }
149}
150
151impl std::error::Error for SourceMappingError {}
152
153impl Program {
154 pub fn new() -> Self {
155 Self::default()
156 }
157
158 pub fn add_file(&mut self, mut file: SourceFile) -> FileId {
160 let id = FileId::from_index(self.files.len());
161 file.bind_file(id);
162 self.files.push(file);
163 id
164 }
165
166 pub fn global_variable(&mut self, variable: Variable) -> &mut Self {
167 self.global_variables.push(variable);
168 self
169 }
170
171 pub fn player_variable(&mut self, variable: Variable) -> &mut Self {
172 self.player_variables.push(variable);
173 self
174 }
175
176 pub fn subroutine(&mut self, subroutine: Subroutine) -> &mut Self {
177 self.subroutines.push(subroutine);
178 self
179 }
180
181 pub fn rule(&mut self, rule: Rule) -> &mut Self {
182 self.rules.push(rule);
183 self
184 }
185
186 pub fn source(&self, file: FileId) -> Option<&SourceDocument> {
188 self.files.get(file.index()).and_then(SourceFile::source)
189 }
190
191 pub fn set_rule_span(
193 &mut self,
194 rule: usize,
195 span: Option<Span>,
196 ) -> std::result::Result<(), SourceMappingError> {
197 self.validate_span(span)?;
198 self.rule_provenance_mut(rule)?.span = span;
199 Ok(())
200 }
201
202 pub fn set_condition_span(
204 &mut self,
205 rule: usize,
206 condition: usize,
207 span: Option<Span>,
208 ) -> std::result::Result<(), SourceMappingError> {
209 self.set_child_span(
210 rule,
211 condition,
212 span,
213 |rule| rule.conditions.len(),
214 |rule, index| SourceMappingError::InvalidCondition {
215 rule,
216 condition: index,
217 },
218 |rule_data| &mut rule_data.conditions,
219 )
220 }
221
222 pub fn set_action_span(
224 &mut self,
225 rule: usize,
226 action: usize,
227 span: Option<Span>,
228 ) -> std::result::Result<(), SourceMappingError> {
229 self.set_child_span(
230 rule,
231 action,
232 span,
233 |rule| rule.actions.len(),
234 |rule, index| SourceMappingError::InvalidAction {
235 rule,
236 action: index,
237 },
238 |rule_data| &mut rule_data.actions,
239 )
240 }
241
242 fn set_child_span<T: SpanSlot + Default>(
246 &mut self,
247 rule: usize,
248 index: usize,
249 span: Option<Span>,
250 count: impl Fn(&crate::Rule) -> usize,
251 invalid: impl Fn(usize, usize) -> SourceMappingError,
252 slots: impl Fn(&mut RuleProvenance) -> &mut Vec<T>,
253 ) -> std::result::Result<(), SourceMappingError> {
254 self.validate_span(span)?;
255 let child_count = self
256 .rules
257 .get(rule)
258 .ok_or(SourceMappingError::InvalidRule(rule))
259 .map(count)?;
260 if index >= child_count {
261 return Err(invalid(rule, index));
262 }
263 let rule_data = self.rule_provenance_mut(rule)?;
264 fit(slots(rule_data), child_count);
265 *slots(rule_data)[index].span_slot() = span;
266 Ok(())
267 }
268
269 pub fn set_action_argument_span(
271 &mut self,
272 rule: usize,
273 action: usize,
274 argument: usize,
275 span: Option<Span>,
276 ) -> std::result::Result<(), SourceMappingError> {
277 self.validate_span(span)?;
278 let action_value = self
279 .rules
280 .get(rule)
281 .ok_or(SourceMappingError::InvalidRule(rule))?
282 .actions
283 .get(action)
284 .ok_or(SourceMappingError::InvalidAction { rule, action })?;
285 let argument_count = action_argument_values(action_value).len();
286 if argument >= argument_count {
287 return Err(SourceMappingError::InvalidActionArgument {
288 rule,
289 action,
290 argument,
291 });
292 }
293 let action_data = self.action_provenance_mut(rule, action)?;
294 action_data
295 .arguments
296 .resize_with(argument + 1, ValueProvenance::default);
297 action_data.arguments[argument].span = span;
298 Ok(())
299 }
300
301 pub fn set_global_variable_spans(
303 &mut self,
304 variable: usize,
305 span: Option<Span>,
306 name_span: Option<Span>,
307 ) -> std::result::Result<(), SourceMappingError> {
308 self.set_declaration_spans(DeclarationTable::GlobalVariables, variable, span, name_span)
309 }
310
311 pub fn set_player_variable_spans(
313 &mut self,
314 variable: usize,
315 span: Option<Span>,
316 name_span: Option<Span>,
317 ) -> std::result::Result<(), SourceMappingError> {
318 self.set_declaration_spans(DeclarationTable::PlayerVariables, variable, span, name_span)
319 }
320
321 pub fn set_subroutine_spans(
323 &mut self,
324 subroutine: usize,
325 span: Option<Span>,
326 name_span: Option<Span>,
327 ) -> std::result::Result<(), SourceMappingError> {
328 self.set_declaration_spans(DeclarationTable::Subroutines, subroutine, span, name_span)
329 }
330
331 fn set_declaration_spans(
332 &mut self,
333 table: DeclarationTable,
334 index: usize,
335 span: Option<Span>,
336 name_span: Option<Span>,
337 ) -> std::result::Result<(), SourceMappingError> {
338 self.validate_span(span)?;
339 self.validate_span(name_span)?;
340 let count = table.count(self);
341 if index >= count {
342 return Err(table.invalid(index));
343 }
344 let slots = table.slots(self.provenance_mut());
345 fit(slots, count);
346 slots[index] = DeclarationProvenance { span, name_span };
347 Ok(())
348 }
349
350 pub fn rule_span(&self, rule: usize) -> Option<crate::source::Span> {
356 self.rule_provenance(rule)?.span
357 }
358
359 pub fn condition_span(&self, rule: usize, condition: usize) -> Option<crate::source::Span> {
361 self.condition_provenance(rule, condition)?.span
362 }
363
364 pub fn action_span(&self, rule: usize, action: usize) -> Option<crate::source::Span> {
366 self.action_provenance(rule, action)?.span
367 }
368
369 pub fn action_argument_span(
371 &self,
372 rule: usize,
373 action: usize,
374 argument: usize,
375 ) -> Option<crate::source::Span> {
376 self.action_provenance(rule, action)?
377 .arguments
378 .get(argument)?
379 .span
380 }
381
382 pub fn global_variable_name_span(&self, variable: usize) -> Option<Span> {
389 self.declaration_name_span(
390 |provenance| &provenance.global_variables,
391 self.global_variables.len(),
392 variable,
393 )
394 }
395
396 pub fn player_variable_name_span(&self, variable: usize) -> Option<Span> {
399 self.declaration_name_span(
400 |provenance| &provenance.player_variables,
401 self.player_variables.len(),
402 variable,
403 )
404 }
405
406 pub fn subroutine_name_span(&self, subroutine: usize) -> Option<Span> {
409 self.declaration_name_span(
410 |provenance| &provenance.subroutines,
411 self.subroutines.len(),
412 subroutine,
413 )
414 }
415
416 pub fn action_identifier_span(&self, rule: usize, action: usize) -> Option<Span> {
428 self.action_provenance(rule, action)?.identifier
429 }
430
431 pub fn rule_name_span(&self, rule: usize) -> Option<Span> {
434 self.rule_provenance(rule)?.name
435 }
436
437 pub fn rule_event_name_span(&self, rule: usize) -> Option<Span> {
441 self.rule_provenance(rule)?.event_name
442 }
443
444 pub fn condition_value_span(
459 &self,
460 rule: usize,
461 condition: usize,
462 path: &[usize],
463 ) -> Option<crate::source::Span> {
464 let mut value = self.condition_provenance(rule, condition)?;
465 for &index in path {
466 value = value.children.get(index)?;
467 }
468 value.identifier.or(value.span)
469 }
470
471 pub fn action_argument_value_span(
481 &self,
482 rule: usize,
483 action: usize,
484 argument: usize,
485 path: &[usize],
486 ) -> Option<crate::source::Span> {
487 let mut value = self
488 .action_provenance(rule, action)?
489 .arguments
490 .get(argument)?;
491 for &index in path {
492 value = value.children.get(index)?;
493 }
494 value.identifier.or(value.span)
495 }
496
497 pub fn edit_source(
500 &self,
501 span: crate::source::Span,
502 replacement: impl Into<String>,
503 ) -> std::result::Result<crate::source::SourceEdit, crate::source::SourceEditError> {
504 self.source(span.file)
505 .ok_or(crate::source::SourceEditError::InvalidRange)?
506 .edit_span(span, replacement)
507 }
508
509 pub fn validate(&self) -> std::result::Result<(), WorkshopError> {
514 let storage = self.to_wir()?;
515 storage
516 .validate()
517 .map_err(|error| WorkshopError::malformed(error.to_string(), error.span()))?;
518 if let Some(settings) = &self.settings {
519 if let Some(error) = crate::settings::check_emission(settings).into_iter().next() {
520 return Err(error);
521 }
522 }
523 Ok(())
524 }
525
526 pub fn settings_diagnostics(&self) -> Vec<crate::settings::SettingsDiagnostic> {
533 self.settings
534 .as_ref()
535 .map(crate::settings::check_emission_diagnostics)
536 .unwrap_or_default()
537 }
538
539 pub fn semantic_issues(
542 &self,
543 catalog: &crate::catalog::Catalog,
544 ) -> Vec<crate::rules::SemanticIssue> {
545 crate::analysis::semantic::inspect(self, catalog)
546 }
547
548 pub fn dump(&self) -> String {
550 self.to_wir().map_or_else(
551 |error| format!("invalid program: {error}"),
552 |program| program.dump(),
553 )
554 }
555
556 fn rule_provenance(&self, rule: usize) -> Option<&RuleProvenance> {
557 let recorded = &self.provenance.as_deref()?.rules;
558 if recorded.len() != self.rules.len() {
559 return None;
560 }
561 recorded.get(rule)
562 }
563
564 fn action_provenance(&self, rule: usize, action: usize) -> Option<&ActionProvenance> {
565 let recorded = self.rule_provenance(rule)?;
566 if recorded.actions.len() != self.rules[rule].actions.len() {
567 return None;
568 }
569 recorded.actions.get(action)
570 }
571
572 fn condition_provenance(&self, rule: usize, condition: usize) -> Option<&ValueProvenance> {
573 let recorded = self.rule_provenance(rule)?;
574 if recorded.conditions.len() != self.rules[rule].conditions.len() {
575 return None;
576 }
577 recorded.conditions.get(condition)
578 }
579
580 fn declaration_name_span(
581 &self,
582 recorded: impl Fn(&ProgramProvenance) -> &[DeclarationProvenance],
583 count: usize,
584 position: usize,
585 ) -> Option<Span> {
586 let declaration = self.declaration_provenance(recorded, count, position);
587 declaration.name_span.or(declaration.span)
588 }
589
590 fn declaration_provenance(
591 &self,
592 recorded: impl Fn(&ProgramProvenance) -> &[DeclarationProvenance],
593 count: usize,
594 position: usize,
595 ) -> DeclarationProvenance {
596 self.provenance
597 .as_deref()
598 .map(recorded)
599 .filter(|recorded| recorded.len() == count)
600 .and_then(|recorded| recorded.get(position))
601 .copied()
602 .unwrap_or_default()
603 }
604
605 fn validate_span(&self, span: Option<Span>) -> std::result::Result<(), SourceMappingError> {
606 let Some(span) = span else {
607 return Ok(());
608 };
609 if !span.is_valid() {
610 return Err(SourceMappingError::InvalidSpan(span));
611 }
612 if self.files.get(span.file.index()).is_none() {
613 return Err(SourceMappingError::UnknownFile(span.file));
614 }
615 Ok(())
616 }
617
618 fn provenance_mut(&mut self) -> &mut ProgramProvenance {
619 self.provenance
620 .get_or_insert_with(|| Box::new(ProgramProvenance::default()))
621 .as_mut()
622 }
623
624 fn rule_provenance_mut(
625 &mut self,
626 rule: usize,
627 ) -> std::result::Result<&mut RuleProvenance, SourceMappingError> {
628 if rule >= self.rules.len() {
629 return Err(SourceMappingError::InvalidRule(rule));
630 }
631 let rule_count = self.rules.len();
632 let provenance = self.provenance_mut();
633 fit(&mut provenance.rules, rule_count);
634 Ok(&mut provenance.rules[rule])
635 }
636
637 fn action_provenance_mut(
638 &mut self,
639 rule: usize,
640 action: usize,
641 ) -> std::result::Result<&mut ActionProvenance, SourceMappingError> {
642 let action_count = self
643 .rules
644 .get(rule)
645 .ok_or(SourceMappingError::InvalidRule(rule))?
646 .actions
647 .len();
648 if action >= action_count {
649 return Err(SourceMappingError::InvalidAction { rule, action });
650 }
651 let rule_data = self.rule_provenance_mut(rule)?;
652 fit(&mut rule_data.actions, action_count);
653 Ok(&mut rule_data.actions[action])
654 }
655}
656
657fn fit<T: Default>(items: &mut Vec<T>, len: usize) {
658 items.truncate(len);
659 items.resize_with(len, T::default);
660}
661
662#[derive(Copy, Clone)]
665enum DeclarationTable {
666 GlobalVariables,
667 PlayerVariables,
668 Subroutines,
669}
670
671impl DeclarationTable {
672 fn count(self, program: &Program) -> usize {
673 match self {
674 Self::GlobalVariables => program.global_variables.len(),
675 Self::PlayerVariables => program.player_variables.len(),
676 Self::Subroutines => program.subroutines.len(),
677 }
678 }
679
680 fn invalid(self, index: usize) -> SourceMappingError {
681 match self {
682 Self::GlobalVariables => SourceMappingError::InvalidGlobalVariable(index),
683 Self::PlayerVariables => SourceMappingError::InvalidPlayerVariable(index),
684 Self::Subroutines => SourceMappingError::InvalidSubroutine(index),
685 }
686 }
687
688 fn slots(self, provenance: &mut ProgramProvenance) -> &mut Vec<DeclarationProvenance> {
689 match self {
690 Self::GlobalVariables => &mut provenance.global_variables,
691 Self::PlayerVariables => &mut provenance.player_variables,
692 Self::Subroutines => &mut provenance.subroutines,
693 }
694 }
695}
696
697#[derive(Debug, Clone, PartialEq, Eq)]
699pub struct Variable {
700 pub name: String,
701 pub index: Option<u32>,
703}
704
705impl Variable {
706 pub fn new(name: impl Into<String>) -> Self {
707 Self {
708 name: name.into(),
709 index: None,
710 }
711 }
712
713 pub fn with_index(name: impl Into<String>, index: u32) -> Self {
714 Self {
715 name: name.into(),
716 index: Some(index),
717 }
718 }
719}
720
721#[derive(Debug, Clone, PartialEq, Eq)]
723pub struct Subroutine {
724 pub name: String,
725 pub index: Option<u32>,
727}
728
729impl Subroutine {
730 pub fn new(name: impl Into<String>) -> Self {
731 Self {
732 name: name.into(),
733 index: None,
734 }
735 }
736
737 pub fn with_index(name: impl Into<String>, index: u32) -> Self {
738 Self {
739 name: name.into(),
740 index: Some(index),
741 }
742 }
743}
744
745#[derive(Debug, Clone)]
747#[non_exhaustive]
748pub struct Rule {
749 pub name: String,
750 pub disabled: bool,
751 pub event: Event,
752 pub conditions: Vec<Condition>,
753 pub actions: Vec<Action>,
754}
755
756impl Rule {
757 pub fn new(name: impl Into<String>, event: Event) -> Self {
758 Self {
759 name: name.into(),
760 disabled: false,
761 event,
762 conditions: Vec::new(),
763 actions: Vec::new(),
764 }
765 }
766
767 pub fn condition(mut self, condition: impl Into<Condition>) -> Self {
768 self.conditions.push(condition.into());
769 self
770 }
771
772 pub fn action(mut self, action: Action) -> Self {
773 self.actions.push(action);
774 self
775 }
776}
777
778#[derive(Debug, Clone)]
780#[non_exhaustive]
781pub struct Condition {
782 pub value: Value,
783 pub disabled: bool,
784}
785
786impl Condition {
787 pub fn new(value: Value) -> Self {
788 Self {
789 value,
790 disabled: false,
791 }
792 }
793
794 pub fn disabled(value: Value) -> Self {
795 Self {
796 value,
797 disabled: true,
798 }
799 }
800}
801
802impl From<Value> for Condition {
803 fn from(value: Value) -> Self {
804 Self::new(value)
805 }
806}
807
808fn action_argument_values(action: &Action) -> Vec<&Value> {
811 match action {
812 Action::SetGlobalVariable { value, .. } | Action::ModifyGlobalVariable { value, .. } => {
813 vec![value]
814 }
815 Action::SetPlayerVariable { player, value, .. }
816 | Action::ModifyPlayerVariable { player, value, .. } => vec![player, value],
817 Action::AssignMember { target, value, .. } => vec![target, value],
818 Action::If { condition } | Action::ElseIf { condition } | Action::While { condition } => {
819 vec![condition]
820 }
821 Action::ForGlobalVariable {
822 start, stop, step, ..
823 } => vec![start, stop, step],
824 Action::ForPlayerVariable {
825 player,
826 start,
827 stop,
828 step,
829 ..
830 } => vec![player, start, stop, step],
831 Action::Call { args, .. } => args.iter().collect(),
832 Action::CallSubroutine { .. } | Action::Else | Action::End => Vec::new(),
833 Action::Disabled { action } => action_argument_values(action),
834 }
835}
836
837fn value_children(value: &Value) -> Vec<&Value> {
840 match value {
841 Value::Array(values) => values.iter().collect(),
842 Value::Vector { x, y, z } => vec![x.as_ref(), y.as_ref(), z.as_ref()],
843 Value::PlayerVariable { player, .. } => vec![player.as_ref()],
844 Value::Call { args, .. } => args.iter().collect(),
845 _ => Vec::new(),
846 }
847}
848
849#[derive(Debug, Clone, PartialEq, Eq)]
851pub enum Event {
852 Global,
853 EachPlayer,
854 EachPlayerWithFilters {
855 team: EventTeam,
856 target: EventTarget,
857 },
858 Player {
859 kind: PlayerEventKind,
860 team: EventTeam,
861 target: EventTarget,
862 },
863 Subroutine(String),
864}
865
866#[derive(Debug, Clone)]
869pub enum Action {
870 SetGlobalVariable {
871 variable: String,
872 value: Value,
873 },
874 ModifyGlobalVariable {
875 variable: String,
876 op: ModifyOp,
877 value: Value,
878 },
879 SetPlayerVariable {
880 player: Value,
881 variable: String,
882 value: Value,
883 },
884 ModifyPlayerVariable {
885 player: Value,
886 variable: String,
887 op: ModifyOp,
888 value: Value,
889 },
890 AssignMember {
891 target: Value,
892 op: Option<ModifyOp>,
893 value: Value,
894 },
895 CallSubroutine {
896 subroutine: String,
897 },
898 If {
899 condition: Value,
900 },
901 ElseIf {
902 condition: Value,
903 },
904 Else,
905 While {
906 condition: Value,
907 },
908 ForGlobalVariable {
909 variable: String,
910 start: Value,
911 stop: Value,
912 step: Value,
913 },
914 ForPlayerVariable {
915 player: Value,
916 variable: String,
917 start: Value,
918 stop: Value,
919 step: Value,
920 },
921 End,
922 Disabled {
923 action: Box<Action>,
924 },
925 Call {
926 name: String,
927 args: Vec<Value>,
928 },
929}
930
931impl Action {
932 pub fn disabled(action: Action) -> Self {
934 Self::Disabled {
935 action: Box::new(action),
936 }
937 }
938
939 pub fn call(name: impl Into<String>, args: impl IntoIterator<Item = Value>) -> Self {
941 Self::Call {
942 name: name.into(),
943 args: args.into_iter().collect(),
944 }
945 }
946}
947
948#[derive(Debug, Clone)]
950pub enum Value {
951 Number(f64),
952 String(String),
953 LocalizedString(String),
954 Bool(bool),
955 Null,
956 Array(Vec<Value>),
957 Vector {
958 x: Box<Value>,
959 y: Box<Value>,
960 z: Box<Value>,
961 },
962 Enum {
963 value_type: String,
964 value: String,
965 },
966 GlobalVariable(String),
967 PlayerVariable {
968 player: Box<Value>,
969 variable: String,
970 },
971 Subroutine(String),
972 EventPlayer,
973 Call {
974 name: String,
975 args: Vec<Value>,
976 },
977}
978
979impl Value {
980 pub fn number(value: f64) -> Self {
982 Self::Number(value)
983 }
984
985 pub fn string(value: impl Into<String>) -> Self {
987 Self::String(value.into())
988 }
989
990 pub fn global_variable(name: impl Into<String>) -> Self {
991 Self::GlobalVariable(name.into())
992 }
993
994 pub fn player_variable(player: Value, name: impl Into<String>) -> Self {
995 Self::PlayerVariable {
996 player: Box::new(player),
997 variable: name.into(),
998 }
999 }
1000
1001 pub fn call(name: impl Into<String>, args: impl IntoIterator<Item = Value>) -> Self {
1003 Self::Call {
1004 name: name.into(),
1005 args: args.into_iter().collect(),
1006 }
1007 }
1008}
1009
1010impl From<bool> for Value {
1011 fn from(value: bool) -> Self {
1012 Self::Bool(value)
1013 }
1014}
1015
1016impl From<f64> for Value {
1017 fn from(value: f64) -> Self {
1018 Self::Number(value)
1019 }
1020}
1021
1022impl From<f32> for Value {
1023 fn from(value: f32) -> Self {
1024 Self::Number(f64::from(value))
1025 }
1026}
1027
1028macro_rules! impl_integer_value {
1029 ($($type:ty),+ $(,)?) => {
1030 $(
1031 impl From<$type> for Value {
1032 fn from(value: $type) -> Self {
1033 Self::Number(value as f64)
1034 }
1035 }
1036 )+
1037 };
1038}
1039
1040impl_integer_value!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize);
1041
1042impl From<String> for Value {
1043 fn from(value: String) -> Self {
1044 Self::String(value)
1045 }
1046}
1047
1048impl From<&str> for Value {
1049 fn from(value: &str) -> Self {
1050 Self::String(value.to_string())
1051 }
1052}
1053
1054impl<T: Into<Value>> From<Vec<T>> for Value {
1055 fn from(values: Vec<T>) -> Self {
1056 Self::Array(values.into_iter().map(Into::into).collect())
1057 }
1058}
1059
1060impl<T: Into<Value>, const N: usize> From<[T; N]> for Value {
1061 fn from(values: [T; N]) -> Self {
1062 Self::Array(values.into_iter().map(Into::into).collect())
1063 }
1064}