rant/
lang.rs

1//! Contains Rant's syntax tree implementation and supporting data structures.
2
3use std::{collections::HashMap, fmt::Display, ops::{Deref, DerefMut}, rc::Rc};
4use crate::{RantProgramInfo, InternalString, RantValue, RantValueType};
5
6pub(crate) const PIPE_VALUE_NAME: &str = "~PIPE";
7
8/// Printflags indicate to the compiler whether a given program element is likely to print something or not.
9#[repr(u8)]
10#[derive(Debug, Copy, Clone, PartialEq)]
11pub enum PrintFlag {
12  /// Use default printing behavior.
13  None,
14  /// Treat the marked element as text.
15  Hint,
16  /// Suppress output from the next element..
17  Sink
18}
19
20/// Identifiers are special strings used to name variables and static (non-procedural) map keys.
21/// This is just a wrapper around a SmartString that enforces identifier formatting requirements.
22#[derive(Debug, Clone, Eq, PartialEq, Hash)]
23pub struct Identifier(InternalString);
24
25impl Identifier {
26  pub fn new(idstr: InternalString) -> Self {
27    Self(idstr)
28  }
29}
30
31impl From<&'static str> for Identifier {
32  fn from(s: &'static str) -> Self {
33    Self::new(InternalString::from(s))
34  }
35}
36
37impl std::borrow::Borrow<str> for Identifier {
38  fn borrow(&self) -> &str {
39    self.0.as_str()
40  }
41}
42
43impl Deref for Identifier {
44  type Target = InternalString;
45  fn deref(&self) -> &Self::Target {
46    &self.0
47  }
48}
49
50impl Display for Identifier {
51  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52    write!(f, "{}", self.0)
53  }
54}
55
56/// Checks if an identifier (variable name, arg name, static map key) is valid
57pub(crate) fn is_valid_ident(name: &str) -> bool {
58  if name.is_empty() { return false }
59  let mut has_non_digit = false;
60  let is_valid_chars = name.chars().all(|c| {
61    has_non_digit |= !c.is_ascii_digit();
62    c.is_alphanumeric() || matches!(c, '_' | '-')
63  });
64  has_non_digit && is_valid_chars
65}
66
67/// A single bound index for a slice expression.
68#[derive(Debug, Clone)]
69pub enum SliceIndex {
70  /// Static index.
71  Static(i64),
72  /// Dynamic index.
73  Dynamic(Rc<Sequence>)
74}
75
76impl Display for SliceIndex {
77  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
78    match self {
79      SliceIndex::Static(i) => write!(f, "{}", i),
80      SliceIndex::Dynamic(_expr) => write!(f, "{{...}}"),
81    }
82  }
83}
84
85/// An unevaluated list slice.
86#[derive(Debug, Clone)]
87pub enum SliceExpr {
88  /// Unbounded slice.
89  Full,
90  /// Start-bounded slice.
91  From(SliceIndex),
92  /// End-bounded slice.
93  To(SliceIndex),
94  /// Fully-bounded slice.
95  Between(SliceIndex, SliceIndex),
96}
97
98impl SliceExpr {
99  /// Creates a static slice from a dynamic slice, using a callback to retrieve a static index for each dynamic index.
100  ///
101  /// If any of the dynamic indices evaluate to a non-integer, function returns `Err` with the incompatible type.
102  pub(crate) fn as_static_slice<F: FnMut(&Rc<Sequence>) -> RantValue>(&self, mut index_converter: F) -> Result<Slice, RantValueType> {
103    macro_rules! convert_index {
104      ($index:expr) => {
105        match $index {
106          SliceIndex::Static(i) => *i,
107          SliceIndex::Dynamic(expr) => {
108            match index_converter(expr) {
109              RantValue::Int(i) => i,
110              other => return Err(other.get_type())
111            }
112          }
113        }
114      }
115    }
116
117    Ok(match self {
118      SliceExpr::Full => Slice::Full,
119      SliceExpr::From(from) => Slice::From(convert_index!(from)),
120      SliceExpr::To(to) => Slice::To(convert_index!(to)),
121      SliceExpr::Between(from, to) => Slice::Between(convert_index!(from), convert_index!(to)),
122    })
123  }
124}
125
126impl Display for SliceExpr {
127  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
128    match self {
129      SliceExpr::Full => write!(f, ":"),
130      SliceExpr::From(i) => write!(f, "{}:", i),
131      SliceExpr::To(i) => write!(f, ":{}", i),
132      SliceExpr::Between(l, r) => write!(f, "{}:{}", l, r),
133    }
134  }
135}
136
137/// An evaluated list slice.
138#[derive(Debug)]
139pub enum Slice {
140  /// Unbounded slice.
141  Full,
142  /// Start-bounded slice.
143  From(i64),
144  /// End-bounded slice.
145  To(i64),
146  /// Fully-bounded slice.
147  Between(i64, i64),
148}
149
150/// Component in an accessor path.
151#[derive(Debug, Clone)]
152pub enum AccessPathComponent {
153  /// Name of variable or map item
154  Name(Identifier),
155  /// List index
156  Index(i64),
157  /// Slice
158  Slice(SliceExpr),
159  /// An expression; either an anonymous source value or dynamic key, depending on the position in the path
160  Expression(Rc<Sequence>),
161  /// Pipeval
162  PipeValue,
163}
164
165impl Display for AccessPathComponent {
166  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
167    match self {
168      Self::Name(name) => write!(f, "{name}"),
169      Self::Index(i) => write!(f, "{i}"),
170      Self::Slice(slice_expr) => write!(f, "{slice_expr}"),
171      Self::Expression(expr) => write!(f, "({}...)", expr.name().map(|name| name.as_str()).unwrap_or("")),
172      Self::PipeValue => write!(f, "[]"),
173    }
174  }
175}
176
177/// Defines available variable resolution modes for variable access paths.
178#[derive(Debug, Copy, Clone, PartialEq)]
179pub enum VarAccessMode {
180  /// Path points to a variable in the current scope.
181  Local,
182  /// Path points explicitly to a global variable.
183  ExplicitGlobal,
184  /// Path points explicitly to a variable that is at most _n_ scopes above the current scope.
185  Descope(usize),
186}
187
188impl VarAccessMode {
189  /// Gets the number of explicit descopes required for this mode. If the path is explicitly global, returns 0.
190  pub fn descope_count(&self) -> usize {
191    match self {
192      VarAccessMode::Local | VarAccessMode::ExplicitGlobal => 0,
193      VarAccessMode::Descope(n) => *n
194    }
195  }
196
197  /// Returns `true` if the access type is `Local`.
198  #[inline]
199  pub fn is_local(&self) -> bool {
200    matches!(self, Self::Local)
201  }
202}
203
204/// Describes the location of a value.
205#[derive(Debug, Clone)]
206pub struct AccessPath {
207  path: Vec<AccessPathComponent>,
208  mode: VarAccessMode,
209}
210
211impl AccessPath {
212  #[inline]
213  pub fn new(path: Vec<AccessPathComponent>, kind: VarAccessMode) -> Self {
214    Self {
215      path,
216      mode: kind
217    }
218  }
219
220  /// Adds the specified amount of descopes to the path.
221  #[inline]
222  pub fn add_descope(self, n: usize) -> Self {
223    Self {
224      mode: match self.mode {
225        VarAccessMode::Local => VarAccessMode::Descope(n),
226        VarAccessMode::Descope(d) => VarAccessMode::Descope(d + n),
227        VarAccessMode::ExplicitGlobal => VarAccessMode::ExplicitGlobal,
228      },
229      .. self
230    }
231  }
232
233  /// Determines whether the access path is explicitly accessing a global value.
234  #[inline]
235  pub fn is_explicit_global(&self) -> bool {
236    matches!(self.mode, VarAccessMode::ExplicitGlobal)
237  }
238
239  /// Determines whether the root of the access path is an inline value.
240  #[inline]
241  pub fn is_anonymous(&self) -> bool {
242    matches!(self.first(), Some(AccessPathComponent::Expression(..) | AccessPathComponent::PipeValue))
243  }
244
245  /// Determines whether the access path targets *only* a variable (i.e. no child access).
246  #[inline]
247  pub fn is_variable_target(&self) -> bool {
248    self.len() == 1 && matches!(self.first(), Some(AccessPathComponent::Name(..) | AccessPathComponent::Expression(..) | AccessPathComponent::PipeValue))
249  }
250
251  /// Determines whether the access path targets *only* an anonymous (non-variable) value (i.e. no child access).
252  #[inline]
253  pub fn is_anonymous_target(&self) -> bool {
254    self.len() == 1 && matches!(self.first(), Some(AccessPathComponent::Expression(..) | AccessPathComponent::PipeValue))
255  }
256
257  /// Gets the kind access path this is.
258  #[inline]
259  pub fn mode(&self) -> VarAccessMode {
260    self.mode
261  }
262
263  /// Returns a list of dynamic keys used by the path in order.
264  #[inline]
265  pub fn dynamic_exprs(&self) -> Vec<Rc<Sequence>> {
266    use AccessPathComponent::*;
267    let mut exprs = vec![];
268    for component in self.iter() {
269      match component {
270        Expression(expr) => exprs.push(Rc::clone(expr)),
271        Slice(SliceExpr::From(SliceIndex::Dynamic(expr)))
272        | Slice(SliceExpr::To(SliceIndex::Dynamic(expr))) 
273        | Slice(SliceExpr::Between(SliceIndex::Static(_), SliceIndex::Dynamic(expr)))
274        | Slice(SliceExpr::Between(SliceIndex::Dynamic(expr), SliceIndex::Static(_))) => exprs.push(Rc::clone(expr)),
275        Slice(SliceExpr::Between(SliceIndex::Dynamic(expr_from), SliceIndex::Dynamic(expr_to))) => {
276          exprs.push(Rc::clone(expr_from));
277          exprs.push(Rc::clone(expr_to));
278        },
279        _ => {}
280      }
281    }
282    exprs
283  }
284
285  /// If the path statically accesses a variable, returns the name of the variable accessed; otherwise, returns `None`.
286  #[inline]
287  pub fn var_name(&self) -> Option<Identifier> {
288    if let Some(first) = self.first() {
289      return Some(match first {
290        AccessPathComponent::Name(id) => id.clone(),
291        AccessPathComponent::PipeValue => Identifier::from(PIPE_VALUE_NAME),
292        _ => return None
293      })
294    }
295    None
296  }
297}
298
299impl Deref for AccessPath {
300  type Target = Vec<AccessPathComponent>;
301  fn deref(&self) -> &Self::Target {
302    &self.path
303  }
304}
305
306impl DerefMut for AccessPath {
307  fn deref_mut(&mut self) -> &mut Self::Target {
308    &mut self.path
309  }
310}
311
312impl Display for AccessPath {
313  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
314    write!(f, "{}", self.iter().map(|part| part.to_string()).collect::<Vec<String>>().join("/"))
315  }
316}
317
318/// A series of Rant expressions to be executed in order.
319#[derive(Debug)]
320pub struct Sequence {
321  elements: Vec<Rc<Expression>>,
322  /// An optional name for the sequence.
323  pub name: Option<InternalString>,
324  /// Information about where the sequence came from, such as its source file.
325  pub origin: Rc<RantProgramInfo>,
326}
327
328impl Sequence {
329  /// Creates a new sequence.
330  #[inline]
331  pub fn new(seq: Vec<Rc<Expression>>, origin: &Rc<RantProgramInfo>) -> Self {
332    Self {
333      elements: seq,
334      name: None,
335      origin: Rc::clone(origin),
336    }
337  }
338  
339  /// Creates a new sequence with a single element.
340  #[inline]
341  pub fn one(rst: Expression, origin: &Rc<RantProgramInfo>) -> Self {
342    Self {
343      elements: vec![Rc::new(rst)],
344      name: None,
345      origin: Rc::clone(origin),
346    }
347  }
348  
349  /// Creates an empty sequence.
350  pub fn empty(origin: &Rc<RantProgramInfo>) -> Self {
351    Self::new(vec![], origin)
352  }
353
354  /// Creates an empty sequence with the specified name.
355  #[inline(always)]
356  pub fn with_name(mut self, name: InternalString) -> Self {
357    self.name = Some(name);
358    self
359  }
360
361  /// Creates an empty sequence with the specified name.
362  #[inline(always)]
363  pub fn with_name_str(mut self, name: &str) -> Self {
364    self.name = Some(InternalString::from(name));
365    self
366  }
367
368  /// Gets the name of the sequence.
369  pub fn name(&self) -> Option<&InternalString> {
370    self.name.as_ref()
371  }
372}
373
374impl Deref for Sequence {
375  type Target = Vec<Rc<Expression>>;
376  fn deref(&self) -> &Self::Target {
377    &self.elements
378  }
379}
380
381impl DerefMut for Sequence {
382  fn deref_mut(&mut self) -> &mut Self::Target {
383    &mut self.elements
384  }
385}
386
387/// A block is an ordered collection of one or more Rant expressions.
388#[derive(Debug)]
389pub struct Block {
390  /// Determines whether the block uses weights.
391  pub is_weighted: bool,
392  /// Determines the protection level of the block.
393  pub protection: Option<BlockProtection>,
394  /// The elements associated with the block.
395  pub elements: Rc<Vec<Rc<BlockElement>>>
396}
397
398impl Block {
399  /// Creates a new block.
400  pub fn new(is_weighted: bool, protection: Option<BlockProtection>, elements: Vec<Rc<BlockElement>>) -> Self {
401    Block {
402      is_weighted,
403      protection,
404      elements: Rc::new(elements),
405    }
406  }
407  
408  /// Gets the number of elements contained in the block.
409  #[inline]
410  pub fn len(&self) -> usize {
411    self.elements.len()
412  }
413}
414
415#[derive(Debug, Copy, Clone, PartialEq)]
416pub enum BlockProtection {
417  Outer,
418}
419
420/// A single element of a regular block.
421#[derive(Debug)]
422pub struct BlockElement {
423  /// The main body of the element.
424  pub main: Rc<Sequence>,
425  /// The weight of the element.
426  pub weight: Option<BlockWeight>,
427  /// Output modifier signature associated with the element sequence.
428  pub output_modifier: Option<OutputModifierSig>,
429}
430
431impl Clone for BlockElement {
432  #[inline]
433  fn clone(&self) -> Self {
434    Self {
435      main: Rc::clone(&self.main),
436      weight: self.weight.clone(),
437      output_modifier: self.output_modifier.clone(),
438    }
439  }
440}
441
442/// A block weight.
443#[derive(Debug)]
444pub enum BlockWeight {
445  /// A weight that is evaluated from an expression.
446  Dynamic(Rc<Sequence>),
447  /// A weight that is a constant value.
448  Constant(f64),
449}
450
451impl Clone for BlockWeight {
452  #[inline]
453  fn clone(&self) -> Self {
454    match self {
455      BlockWeight::Dynamic(s) => Self::Dynamic(Rc::clone(s)),
456      BlockWeight::Constant(c) => Self::Constant(*c),
457    }
458  }
459}
460
461/// Signature information for an output modifier.
462#[derive(Debug, Clone)]
463pub struct OutputModifierSig {
464  pub input_var: Option<Identifier>
465}
466
467/// Describes the arity requirements of a function parameter.
468#[derive(Debug, Copy, Clone)]
469pub enum Varity {
470  /// Single-value, always required
471  Required,
472  /// Single-value, may be omitted in favor of a default value
473  Optional,
474  /// Optional series of zero or more values; defaults to empty list
475  VariadicStar,
476  /// Required series of one or more values
477  VariadicPlus,
478}
479
480impl Varity {
481  /// Returns true if the supplied varity pair is in a valid order.
482  pub fn is_valid_order(first: Varity, second: Varity) -> bool {
483    use Varity::*;
484    matches!((first, second), 
485      (Required, Required) |
486      (Required, Optional) |
487      (Required, VariadicStar) |
488      (Required, VariadicPlus) |
489      (Optional, Optional) |
490      (Optional, VariadicStar)
491    )
492  }
493
494  /// Returns true if the varity is variadic.
495  pub fn is_variadic(&self) -> bool {
496    use Varity::*;
497    matches!(self, VariadicStar | VariadicPlus)
498  }
499}
500
501impl Display for Varity {
502  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
503    use Varity::*;
504    match self {
505      Required => write!(f, "required parameter"),
506      Optional => write!(f, "optional parameter"),
507      VariadicStar => write!(f, "optional variadic parameter"),
508      VariadicPlus => write!(f, "required variadic parameter"),
509    }
510  }
511}
512
513/// Defines spread modes for function arguments.
514#[derive(Debug, Copy, Clone)]
515pub enum ArgumentSpreadMode {
516  /// Pass as one argument.
517  NoSpread,
518  /// Iterate over the value and pass each element as a separate argument.
519  Parametric,
520  /// Iterate over the value and pass in each item as the argument in separate function calls.
521  /// 
522  /// If `is_complex` is set to `true`, each separate iteration of the argument will also be parametrically spread.
523  ///
524  /// If multiple arguments are temporal, the receiving function is called for each valid combination between them.
525  ///
526  /// Temporal arguments with matching labels will be iterated simultaneously.
527  Temporal { label: usize, is_complex: bool },
528}
529
530/// Describes a function argument expression.
531#[derive(Debug)]
532pub struct ArgumentExpr {
533  /// The expression that produces the argument value.
534  pub expr: Rc<Sequence>,
535  /// The spread mode for the argument.
536  pub spread_mode: ArgumentSpreadMode,
537}
538
539/// Describes what to call for a function call.
540#[derive(Debug)]
541pub enum FunctionCallTarget {
542  /// Indicates a path to a function variable.
543  /// Used for named function calls.
544  Path(Rc<AccessPath>),
545}
546
547/// A function call.
548#[derive(Debug)]
549pub struct FunctionCall {
550  /// The function to call.
551  pub target: FunctionCallTarget,
552  /// The arguments to pass.
553  pub arguments: Rc<Vec<ArgumentExpr>>,
554  /// Runtime flag to enable temporal calling.
555  pub is_temporal: bool,
556}
557
558/// A piped function call.
559#[derive(Debug)]
560pub struct PipedCall {
561  /// The function calls in the chain.
562  pub steps: Rc<Vec<FunctionCall>>,
563  /// Optional access path to assign the final piped value to.
564  pub assignment_pipe: Option<Rc<AssignmentPipeTarget>>,
565  /// Determines whether the call executes temporally.
566  pub is_temporal: bool,
567}
568
569/// Represents the target for an assignment pipe expression.
570#[derive(Debug)]
571pub enum AssignmentPipeTarget {
572  /// Set a value.
573  Set(Rc<AccessPath>),
574  /// Define a variable.
575  Def { ident: Identifier, is_const: bool, access_mode: VarAccessMode },
576}
577
578/// Keeps track of combination indices in a temporally-spread function call.
579#[derive(Debug)]
580pub struct TemporalSpreadState {
581  /// Counters associated with each temporal call in the chain.
582  counters: Vec<(usize, usize)>,
583  /// Maps argument indices to temporal counter indices.
584  arg_labels: HashMap<usize, usize>,
585}
586
587impl TemporalSpreadState {
588  /// Creates a new `TemporalSpreadState`.
589  #[inline]
590  pub fn new(arg_exprs: &[ArgumentExpr], args: &[RantValue]) -> Self {
591    let mut counters = Vec::with_capacity(args.len());
592    let mut arg_labels: HashMap<usize, usize> = Default::default();
593    for (i, expr) in arg_exprs.iter().enumerate() {
594      if let ArgumentSpreadMode::Temporal { label, .. } = expr.spread_mode {
595        arg_labels.insert(i, label);
596        // Since temporal indices are always incremental, we can assume the next label index will only be 1 ahead at most.
597        // This way, duplicate labels share the same counter.
598        let arg = &args[i];
599        if label >= counters.len() {
600          let counter_size = if arg.is_indexable() {
601            arg.len()
602          } else {
603            0
604          };
605          counters.push((0, counter_size));
606        } else {
607          // If it's an existing index, update the counter size to the minimum argument length.
608          // This way, we guarantee that temporal arguments with a shared label *always* provide the same number of values.
609          if arg.is_indexable() {
610            let (_, n) = &mut counters[label];
611            *n = arg.len().min(*n);
612          }
613        }
614      }
615    }
616    Self {
617      counters,
618      arg_labels,
619    }
620  }
621
622  /// Gets the number of counters in the state.
623  #[inline]
624  pub fn len(&self) -> usize {
625    self.counters.len()
626  }
627
628  /// Determines whether there are no counters in the state.
629  #[inline]
630  pub fn is_empty(&self) -> bool {
631    self.counters.is_empty() || self.counters.iter().all(|(.., n)| *n == 0)
632  }
633
634  /// Gets the current counter value of the specified argument index.
635  #[inline]
636  pub fn get(&self, arg_index: usize) -> Option<usize> {
637    self.arg_labels.get(&arg_index).map(|i| self.counters[*i].0)
638  }
639
640  /// Increments the temporal counters.
641  /// Returns `true` if another function call should be queued.
642  #[inline]
643  pub fn increment(&mut self) -> bool {
644    let mut success = false;
645    for (c, n) in self.counters.iter_mut() {
646      *c += 1;
647      // Check if counter has reached the end
648      if c >= n {
649        *c = 0;
650      } else {
651        success = true;
652        break
653      }
654    }
655    success
656  }
657}
658
659/// Describes a Rant function definition.
660#[derive(Debug, Clone)]
661pub struct FunctionDef {
662  /// The path to the function to define.
663  pub path: Rc<AccessPath>,
664  /// Indicates whether the function will be constant.
665  pub is_const: bool, // only used on variable definitions
666  /// The parameters associated with the function being defined.
667  pub params: Rc<Vec<Parameter>>,
668  /// The variables to capture into the function being defined.
669  pub capture_vars: Rc<Vec<Identifier>>,
670  /// The body of the function being defined.
671  pub body: Rc<Sequence>,
672}
673
674/// Describes a Rant lambda.
675#[derive(Debug, Clone)]
676pub struct LambdaExpr {
677  /// The body of the lambda. 
678  pub body: Rc<Sequence>,
679  /// The parameters associated with the lambda.
680  pub params: Rc<Vec<Parameter>>,
681  /// The variables to capture into the lambda.
682  pub capture_vars: Rc<Vec<Identifier>>,
683}
684
685/// Describes a function parameter.
686#[derive(Debug)]
687pub struct Parameter {
688  /// The name of the parameter
689  pub name: Identifier,
690  /// The varity of the parameter
691  pub varity: Varity,
692  /// The default value of the parameter.
693  pub default_value_expr: Option<Rc<Sequence>>,
694}
695
696impl Parameter {
697  /// Returns true if the parameter is required.
698  #[inline]
699  pub fn is_required(&self) -> bool {
700    use Varity::*;
701    matches!(self.varity, Required | VariadicPlus)
702  }
703
704  #[inline]
705  pub fn is_optional(&self) -> bool {
706    use Varity::*;
707    matches!(self.varity, Optional)
708  }
709}
710
711/// Key creation methods for map initializer entries.
712#[derive(Debug)]
713pub enum MapKeyExpr {
714  /// Map key is evaluated from an expression at runtime.
715  Dynamic(Rc<Sequence>),
716  /// Map key is evaluated at compile time from an identifier.
717  Static(InternalString),
718}
719
720/// Represents a getter accessor.
721#[derive(Debug)]
722pub struct Getter {
723  /// The path to the value.
724  pub path: Rc<AccessPath>,
725  /// The fallback expression to evaluate if the path cannot resolve.
726  pub fallback: Option<Rc<Sequence>>,
727}
728
729/// Represents a setter accessor.
730#[derive(Debug)]
731pub struct Setter {
732  /// The path to the target whose value will be set.
733  pub path: Rc<AccessPath>,
734  /// The value to set the target to.
735  pub value: Rc<Sequence>,
736}
737
738/// Defines operations that compound setters can perform.
739#[derive(Debug, Copy, Clone)]
740pub enum CompAssignOp {
741  /// Addition assignment
742  Add,
743  /// Subtraction assignment
744  Subtract,
745  /// Multiplication assignment
746  Multiply,
747  /// Division assignment
748  Divide,
749  /// Modulo assignment
750  Modulo,
751  /// Exponentiation assignment
752  Power,
753  /// Logical AND assignment
754  And,
755  /// Logical OR assignment
756  Or,
757  /// Logical XOR assignment
758  Xor,
759  /// Logical NAND assignment
760  Nand,
761  /// Logical NOR assignment
762  Nor,
763}
764
765/// Represents a variable definition accessor.
766#[derive(Debug)]
767pub struct Definition {
768  /// The name of the variable to define.
769  pub name: Identifier,
770  /// Will it be a constant?
771  pub is_const: bool,
772  /// The access mode for the variable to define.
773  pub access_mode: VarAccessMode,
774  /// The value to assign to the newly created variable.
775  pub value: Option<Rc<Sequence>>,
776}
777
778/// Defines Rant expression tree node types. These are directly executable by the VM.
779#[derive(Debug)]
780pub enum Expression {
781  /// No Operation
782  Nop,
783  /// Program sequence
784  Sequence(Rc<Sequence>),
785  /// Rant block containing zero or more sequences
786  Block(Rc<Block>),
787  /// List initializer
788  ListInit(Rc<Vec<Rc<Sequence>>>),
789  /// Tuple initializer
790  TupleInit(Rc<Vec<Rc<Sequence>>>),
791  /// Map initializer
792  MapInit(Rc<Vec<(MapKeyExpr, Rc<Sequence>)>>),
793  /// Lambda expression
794  Lambda(LambdaExpr),
795  /// Single function call
796  FuncCall(FunctionCall),
797  /// Piped function call
798  PipedCall(PipedCall),
799  /// Function definition
800  FuncDef(FunctionDef),
801  /// Variable definition
802  Define(Definition),
803  /// Getter
804  Get(Getter),
805  /// Setter
806  Set(Setter),
807  /// Pipe value
808  PipeValue,
809  /// Fragment
810  Fragment(InternalString),
811  /// Whitespace
812  Whitespace(InternalString),
813  /// Integer value
814  Integer(i64),
815  /// Floating-point value
816  Float(f64),
817  /// Boolean value
818  Boolean(bool),
819  /// Empty value
820  NothingVal,
821  /// Return
822  Return(Option<Rc<Sequence>>),
823  /// Continue
824  Continue(Option<Rc<Sequence>>),
825  /// Break
826  Break(Option<Rc<Sequence>>),
827  /// Logical NOT
828  LogicNot(Rc<Sequence>),
829  /// Negation
830  Negate(Rc<Sequence>),
831  /// Exponentiation
832  Power(Rc<Sequence>, Rc<Sequence>),
833  /// Multipliation
834  Multiply(Rc<Sequence>, Rc<Sequence>),
835  /// Division
836  Divide(Rc<Sequence>, Rc<Sequence>),
837  /// Modulo
838  Modulo(Rc<Sequence>, Rc<Sequence>),
839  /// Addition
840  Add(Rc<Sequence>, Rc<Sequence>),
841  /// Subtraction
842  Subtract(Rc<Sequence>, Rc<Sequence>),
843  /// Less than
844  Less(Rc<Sequence>, Rc<Sequence>),
845  /// Less than or equal
846  LessOrEqual(Rc<Sequence>, Rc<Sequence>),
847  /// Greater than
848  Greater(Rc<Sequence>, Rc<Sequence>),
849  /// Greater than or equal
850  GreaterOrEqual(Rc<Sequence>, Rc<Sequence>),
851  /// Equality
852  Equals(Rc<Sequence>, Rc<Sequence>),
853  /// Inequality
854  NotEquals(Rc<Sequence>, Rc<Sequence>),
855  /// Logical AND
856  LogicAnd(Rc<Sequence>, Rc<Sequence>),
857  /// Logical XOR
858  LogicXor(Rc<Sequence>, Rc<Sequence>),
859  /// Logical OR
860  LogicOr(Rc<Sequence>, Rc<Sequence>),
861  /// Conditional branch
862  Conditional { conditions: Rc<Vec<(Rc<Sequence>, Rc<Block>)>>, fallback: Option<Rc<Block>> },
863  /// Provides debug information about the next sequence element
864  DebugCursor(DebugInfo),
865  /// Require statement
866  Require { alias: Option<InternalString>, path: InternalString },
867}
868
869impl Expression {
870  /// Gets the diagnostic display name for the node.
871  pub fn display_name(&self) -> &'static str {
872    match self {
873      Self::Sequence(_) =>                     "sequence",
874      Self::Block(..) =>                       "block",
875      Self::ListInit(_) =>                     "list",
876      Self::TupleInit(_) =>                    "tuple",
877      Self::MapInit(_) =>                      "map",
878      Self::Lambda(_) =>                       "lambda",
879      Self::FuncCall(_) =>                     "call function",
880      Self::FuncDef(_) =>                      "define function",
881      Self::Fragment(_) =>                     "fragment",
882      Self::Whitespace(_) =>                   "whitespace",
883      Self::Integer(_) =>                      "integer",
884      Self::Float(_) =>                        "float",
885      Self::Boolean(_) =>                      "bool",
886      Self::NothingVal =>                      "nothing_val",
887      Self::Nop =>                             "no-op",
888      Self::Define(..) =>                      "definition",
889      Self::Get(..) =>                         "getter",
890      Self::Set(..) =>                         "setter",
891      Self::PipedCall(_) =>                    "piped call",
892      Self::PipeValue =>                       "pipeval",
893      Self::Return(_) =>                       "return",
894      Self::Continue(_) =>                     "continue",
895      Self::Break(_) =>                        "break",
896      Self::LogicNot(_) =>                     "not",
897      Self::Negate(_) =>                       "negate",
898      Self::Power(_, _) =>                     "power",
899      Self::Multiply(_, _) =>                  "multiply",
900      Self::Divide(_, _) =>                    "divide",
901      Self::Modulo(_, _) =>                    "modulo",
902      Self::Add(_, _) =>                       "add",
903      Self::Subtract(_, _) =>                  "subtract",
904      Self::Less(_, _) =>                      "less than",
905      Self::LessOrEqual(_, _) =>               "less than or equal",
906      Self::Greater(_, _) =>                   "greater than",
907      Self::GreaterOrEqual(_, _) =>            "greater than or equal",
908      Self::Equals(_, _) =>                    "equals",
909      Self::NotEquals(_, _) =>                 "not equals",
910      Self::LogicAnd(_, _) =>                  "and",
911      Self::LogicXor(_, _) =>                  "xor",
912      Self::LogicOr(_, _) =>                   "or",
913      Self::DebugCursor(_) =>                  "debug cursor",
914      Self::Conditional { .. } =>              "conditional",
915      Self::Require { .. } =>                  "require",
916    }
917  }
918}
919
920impl Display for Expression {
921  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
922    write!(f, "{}", self.display_name())
923  }
924}
925
926/// Provides debug information about a program element.
927#[derive(Debug)]
928pub enum DebugInfo {
929  /// Provides source code location information for the following sequence element.
930  Location { line: usize, col: usize },
931}