xlang_syntax/
ast.rs

1/// The location of an expression.
2pub type Loc = std::ops::Range<usize>;
3
4/// A trait which can locate an expression in its source file.
5pub trait Locate {
6    /// Returns the location of this expression.
7    fn loc(&self) -> Loc;
8}
9
10/// A **`none`** value.
11#[derive(Clone, Debug, PartialEq)]
12pub struct None {
13    pub loc: Loc,
14}
15
16impl None {
17    /// Creates a new **`none`** value.
18    pub fn new(loc: Loc) -> Self {
19        Self { loc }
20    }
21}
22
23impl Locate for None {
24    fn loc(&self) -> Loc {
25        self.loc.clone()
26    }
27}
28
29/// A boolean constant.
30#[derive(Clone, Debug, PartialEq)]
31pub struct Bool<'input> {
32    pub loc: Loc,
33    pub value: &'input str,
34}
35
36impl<'input> Bool<'input> {
37    /// Creates a new boolean constant.
38    pub fn new(loc: Loc, value: &'input str) -> Self {
39        Self { loc, value }
40    }
41}
42
43impl<'input> Locate for Bool<'input> {
44    fn loc(&self) -> Loc {
45        self.loc.clone()
46    }
47}
48
49/// The kind of a number.
50#[derive(Clone, Copy, Debug, PartialEq)]
51pub enum NumKind {
52    /// A plain decimal integer.
53    /// 
54    /// ```xlang
55    /// 042
56    /// 1_000_000
57    /// ```
58    Dec,
59
60    /// A hexadecimal integer.
61    /// 
62    /// ```xlang
63    /// 0x123456
64    /// 0xabcdef
65    /// 0xa_b_c_d_e_f
66    /// ```
67    Hex,
68
69    /// A binary integer.
70    /// 
71    /// ```xlang
72    /// 0b0100_0001
73    /// ```
74    Bin,
75
76    /// An octal integer.
77    /// 
78    /// ```xlang
79    /// 0o01234567
80    /// ```
81    Oct,
82
83    /// A floating point number.
84    /// 
85    /// ```xlang
86    /// 0.
87    /// 0.42
88    /// 4.2e1
89    /// ```
90    Float,
91}
92
93/// A number constant.
94#[derive(Clone, Debug, PartialEq)]
95pub struct Num<'input> {
96    pub loc: Loc,
97    pub kind: NumKind,
98    pub value: &'input str,
99}
100
101impl<'input> Num<'input> {
102    /// Creates a new decimal integer number.
103    pub fn dec(loc: Loc, value: &'input str) -> Self {
104        Self { loc, kind: NumKind::Dec, value }
105    }
106
107    /// Creates a new hexadecimal integer number.
108    pub fn hex(loc: Loc, value: &'input str) -> Self {
109        Self { loc, kind: NumKind::Hex, value }
110    }
111
112    /// Creates a new binary integer number.
113    pub fn bin(loc: Loc, value: &'input str) -> Self {
114        Self { loc, kind: NumKind::Bin, value }
115    }
116
117    /// Creates a new octal integer number.
118    pub fn oct(loc: Loc, value: &'input str) -> Self {
119        Self { loc, kind: NumKind::Oct, value }
120    }
121
122    /// Creates a new floating point number.
123    pub fn float(loc: Loc, value: &'input str) -> Self {
124        Self { loc, kind: NumKind::Float, value }
125    }
126}
127
128impl<'input> Locate for Num<'input> {
129    fn loc(&self) -> Loc {
130        self.loc.clone()
131    }
132}
133
134/// An identifier literal.
135#[derive(Clone, Debug, PartialEq)]
136pub struct Ident<'input> {
137    pub loc: Loc,
138    pub value: &'input str,
139}
140
141impl<'input> Ident<'input> {
142    /// Creates a new identifier literal.
143    pub fn new(loc: Loc, value: &'input str) -> Self {
144        Self { loc, value }
145    }
146}
147
148impl<'input> Locate for Ident<'input> {
149    fn loc(&self) -> Loc {
150        self.loc.clone()
151    }
152}
153
154/// An atom constant.
155#[derive(Clone, Debug, PartialEq)]
156pub struct Atom<'input> {
157    pub loc: Loc,
158    pub value: &'input str,
159}
160
161impl<'input> Atom<'input> {
162    /// Creates a new atom constant.
163    pub fn new(loc: Loc, value: &'input str) -> Self {
164        Self { loc, value }
165    }
166}
167
168impl<'input> Locate for Atom<'input> {
169    fn loc(&self) -> Loc {
170        self.loc.clone()
171    }
172}
173
174/// A string literal.
175#[derive(Clone, Debug, PartialEq)]
176pub struct Str<'input> {
177    pub loc: Loc,
178    pub value: &'input str,
179}
180
181impl<'input> Str<'input> {
182    /// Creates a new string literal.
183    pub fn new(loc: Loc, value: &'input str) -> Self {
184        Self { loc, value }
185    }
186}
187
188impl<'input> Locate for Str<'input> {
189    fn loc(&self) -> Loc {
190        self.loc.clone()
191    }
192}
193
194/// A operator which takes two operands.
195#[derive(Clone, Copy, Debug, PartialEq)]
196pub enum BinaryOp {
197    /// **`.`**
198    /// 
199    /// ```xlang
200    /// my_value.my_value2
201    /// ```
202    ObjIdx,
203    
204    /// **`::`**
205    /// 
206    /// ```xlang
207    /// my_value::my_value2
208    /// ```
209    StaticIdx,
210
211    /// **`[..]`**
212    /// 
213    /// ```xlang
214    /// my_value["my_value2"]
215    /// ```
216    ExprIdx,
217
218    /// **`*`**
219    /// 
220    /// ```xlang
221    /// 42 * 2 // => 84
222    /// ```
223    Mul,
224
225    /// **`/`**
226    /// 
227    /// ```xlang
228    /// 42 / 2 // => 21
229    /// ```
230    Div,
231
232    /// **`%`**
233    /// 
234    /// ```xlang
235    /// 100 % 1 == 0
236    /// ```
237    Mod,
238
239    /// **`+`**
240    /// 
241    /// ```xlang
242    /// 1 + 1 == 2
243    /// ```
244    Add,
245
246    /// **`-`**
247    /// 
248    /// ```xlang
249    /// 1 - 1 == 0
250    /// ```
251    Sub,
252
253    /// **`<<`**
254    /// 
255    /// ```xlang
256    /// 0b01 << 1 == 0b10
257    /// ```
258    Shl,
259
260    /// **`>>`**
261    /// 
262    /// ```xlang
263    /// 0b10 >> 1 == 0b01
264    /// ```
265    Shr,
266
267    /// **`&`**
268    /// 
269    /// ```xlang
270    /// 0b101 & 0b011 == 0b001 // => true
271    /// ```
272    BitAnd,
273
274    /// **`^`**
275    /// 
276    /// ```xlang
277    /// 0b101 & 0b011 == 0b110 // => true
278    /// ```
279    BitXor,
280
281    /// **`|`**
282    /// 
283    /// ```xlang
284    /// 0b101 | 0b011 == 0b111 // => true
285    /// ```
286    BitOr,
287
288    /// **`==`**
289    /// 
290    /// ```xlang
291    /// 1 == 1 // => true
292    /// ```
293    Eq,
294
295    /// **`!=`**
296    /// 
297    /// ```xlang
298    /// 1 != 1 // => false
299    /// ```
300    Neq,
301
302    /// **`<`**
303    /// 
304    /// ```xlang
305    /// 0 < 1 // => true
306    /// ```
307    Lt,
308
309    /// **`>`**
310    /// 
311    /// ```xlang
312    /// 0 > 1 // => false
313    /// ```
314    Gt,
315
316    /// **`<=`**
317    /// 
318    /// ```xlang
319    /// 0 <= 1 // => true
320    /// 0 <= 0 // => true
321    /// 0 <= -1 // => false
322    /// ```
323    LtEq,
324
325    /// **`>=`**
326    /// 
327    /// ```xlang
328    /// 0 >= 1 // => false
329    /// 0 >= 0 // => false
330    /// 0 >= -1 // => true
331    /// ```
332    GtEq,
333
334    /// **`&&`**
335    /// 
336    /// ```xlang
337    /// 1 > 0 && 0 < 1 // => true
338    /// ```
339    And,
340
341    /// **`||`**
342    /// 
343    /// ```xlang
344    /// false || true // => true
345    /// ```
346    Or,
347}
348
349/// A binary operation.
350#[derive(Clone, Debug, PartialEq)]
351pub struct Binary<'input> {
352    pub loc: Loc,
353    pub op: BinaryOp,
354    pub left: Box<Expr<'input>>,
355    pub right: Box<Expr<'input>>,
356}
357
358impl<'input> Binary<'input> {
359    /// Creates a new binary operation.
360    pub fn new(loc: Loc, op: BinaryOp, left: Box<Expr<'input>>, right: Box<Expr<'input>>) -> Self {
361        Self { loc, op, left, right }
362    }
363}
364
365impl<'input> Locate for Binary<'input> {
366    fn loc(&self) -> Loc {
367        self.loc.clone()
368    }
369}
370
371/// A function call.
372#[derive(Clone, Debug, PartialEq)]
373pub struct Call<'input> {
374    pub loc: Loc,
375    pub fun: Box<Expr<'input>>,
376    pub args: Vec<Expr<'input>>,
377}
378
379impl<'input> Call<'input> {
380    /// Creates a new function call operation.
381    pub fn new(loc: Loc, fun: Box<Expr<'input>>, args: Vec<Expr<'input>>) -> Self {
382        Self { loc, fun, args }
383    }
384}
385
386impl<'input> Locate for Call<'input> {
387    fn loc(&self) -> Loc {
388        self.loc.clone()
389    }
390}
391
392/// An operator which takes only one operand.
393#[derive(Clone, Copy, Debug, PartialEq)]
394pub enum UnaryOp {
395    /// **`.deref`**
396    Deref,
397
398    /// **`.cloned`**
399    Cloned,
400
401    /// **`.new`**
402    New,
403
404    /// **`+`**
405    Pos,
406
407    /// **`-`**
408    Neg,
409
410    /// **`!`**
411    Not,
412
413    /// **`~`**
414    BitNot,
415}
416
417/// A unary operation.
418#[derive(Clone, Debug, PartialEq)]
419pub struct Unary<'input> {
420    pub loc: Loc,
421    pub op: UnaryOp,
422    pub subject: Box<Expr<'input>>,
423}
424
425impl<'input> Unary<'input> {
426    /// Creates a new unary operation.
427    pub fn new(loc: Loc, op: UnaryOp, subject: Box<Expr<'input>>) -> Self {
428        Self { loc, op, subject }
429    }
430}
431
432impl<'input> Locate for Unary<'input> {
433    fn loc(&self) -> Loc {
434        self.loc.clone()
435    }
436}
437
438/// An assignment operator.
439#[derive(Clone, Copy, Debug, PartialEq)]
440pub enum AssignOp {
441    Assign,
442    AssignAdd,
443    AssignSub,
444    AssignMul,
445    AssignDiv,
446    AssignMod,
447    AssignBitOr,
448    AssignBitXor,
449    AssignShl,
450    AssignShr,
451}
452
453/// An assignment operation.
454#[derive(Clone, Debug, PartialEq)]
455pub struct Assign<'input> {
456    pub loc: Loc,
457    pub op: AssignOp,
458    pub left: Box<Expr<'input>>,
459    pub right: Box<Expr<'input>>,
460}
461
462impl<'input> Assign<'input> {
463    /// Creates a new assignment operation.
464    pub fn new(loc: Loc, op: AssignOp, left: Box<Expr<'input>>, right: Box<Expr<'input>>) -> Self {
465        Self { loc, op, left, right }
466    }
467}
468
469impl<'input> Locate for Assign<'input> {
470    fn loc(&self) -> Loc {
471        self.loc.clone()
472    }
473}
474
475/// A code block.
476#[derive(Clone, Debug, PartialEq)]
477pub struct Block<'input> {
478    pub loc: Loc,
479    pub action: Vec<Expr<'input>>,
480}
481
482impl<'input> Block<'input> {
483    /// Creates a new code block.
484    pub fn new(loc: Loc, action: Vec<Expr<'input>>) -> Self {
485        Self { loc, action }
486    }
487}
488
489impl<'input> Locate for Block<'input> {
490    fn loc(&self) -> Loc {
491        self.loc.clone()
492    }
493}
494
495/// An **`else if`** branch.
496#[derive(Clone, Debug, PartialEq)]
497pub struct ElseIf<'input> {
498    pub loc: Loc,
499    pub cond: Box<Expr<'input>>,
500    pub block: Block<'input>,
501}
502
503impl<'input> ElseIf<'input> {
504    /// Creates a new **`else if`** branch.
505    pub fn new(loc: Loc, cond: Box<Expr<'input>>, block: Block<'input>) -> Self {
506        Self { loc, cond, block }
507    }
508}
509
510impl<'input> Locate for ElseIf<'input> {
511    fn loc(&self) -> Loc {
512        self.loc.clone()
513    }
514}
515
516/// An **`else`** branch.
517#[derive(Clone, Debug, PartialEq)]
518pub struct Else<'input> {
519    pub loc: Loc,
520    pub block: Block<'input>,
521}
522
523impl<'input> Else<'input> {
524    /// Creates a new **`else`** branch.
525    pub fn new(loc: Loc, block: Block<'input>) -> Self {
526        Self { loc, block }
527    }
528}
529
530impl<'input> Locate for Else<'input> {
531    fn loc(&self) -> Loc {
532        self.loc.clone()
533    }
534}
535
536/// A branch from an **`if`** statement.
537#[derive(Clone, Debug, PartialEq)]
538pub enum IfBranch<'input> {
539    ElseIf(ElseIf<'input>),
540    Else(Else<'input>),
541}
542
543impl<'input> Locate for IfBranch<'input> {
544    fn loc(&self) -> Loc {
545        match self {
546            Self::ElseIf(branch) => branch.loc(),
547            Self::Else(branch) => branch.loc(),
548        }
549    }
550}
551
552/// An **`if`** statement.
553#[derive(Clone, Debug, PartialEq)]
554pub struct If<'input> {
555    pub loc: Loc,
556    pub cond: Box<Expr<'input>>,
557    pub block: Block<'input>,
558    pub branches: Vec<IfBranch<'input>>,
559}
560
561impl<'input> If<'input> {
562    /// Creates a new **`if`** statement.
563    pub fn new(loc: Loc, cond: Box<Expr<'input>>, block: Block<'input>, branches: Vec<IfBranch<'input>>) -> Self {
564        Self { loc, cond, block, branches }
565    }
566}
567
568impl<'input> Locate for If<'input> {
569    fn loc(&self) -> Loc {
570        self.loc.clone()
571    }
572}
573
574/// An inline function.
575#[derive(Clone, Debug, PartialEq)]
576pub struct InlineFun<'input> {
577    pub loc: Loc,
578    pub args: Vec<Ident<'input>>,
579    pub block: Block<'input>,
580}
581
582impl<'input> InlineFun<'input> {
583    /// Creates a new function value.
584    pub fn new(loc: Loc, args: Vec<Ident<'input>>, block: Block<'input>) -> Self {
585        Self { loc, args, block }
586    }
587}
588
589impl<'input> Locate for InlineFun<'input> {
590    fn loc(&self) -> Loc {
591        self.loc.clone()
592    }
593}
594
595/// A function declaration.
596#[derive(Clone, Debug, PartialEq)]
597pub struct Fun<'input> {
598    pub loc: Loc,
599    pub publ: bool,
600    pub name: Ident<'input>,
601    pub args: Vec<Ident<'input>>,
602    pub block: Block<'input>,
603}
604
605impl<'input> Fun<'input> {
606    /// Creates a new function value.
607    pub fn new(loc: Loc, publ: bool, name: Ident<'input>, args: Vec<Ident<'input>>, block: Block<'input>) -> Self {
608        Self { loc, publ, name, args, block }
609    }
610}
611
612impl<'input> Locate for Fun<'input> {
613    fn loc(&self) -> Loc {
614        self.loc.clone()
615    }
616}
617
618/// A list literal.
619#[derive(Clone, Debug, PartialEq)]
620pub struct ListLit<'input> {
621    pub loc: Loc,
622    pub items: Vec<Expr<'input>>,
623}
624
625impl<'input> ListLit<'input> {
626    /// Creates a new list expression.
627    pub fn new(loc: Loc, items: Vec<Expr<'input>>) -> Self {
628        Self { loc, items }
629    }
630}
631
632impl<'input> Locate for ListLit<'input> {
633    fn loc(&self) -> Loc {
634        self.loc.clone()
635    }
636}
637
638/// A key and value in a map literal.
639#[derive(Clone, Debug, PartialEq)]
640pub enum MapPair<'input> {
641    /// A local variable will be used as the value.
642    Local {
643        loc: Loc,
644        name: Ident<'input>,
645    },
646    
647    /// A value has been explicitly used as the name.
648    Literal {
649        loc: Loc,
650        name: Ident<'input>,
651        value: Box<Expr<'input>>
652    },
653    
654    /// An expression is used as the key and will be evaluated at runtime.
655    Evaluated {
656        loc: Loc,
657        name: Box<Expr<'input>>,
658        value: Box<Expr<'input>>
659    },
660}
661
662impl<'input> MapPair<'input> {
663    /// Creates a local map pair.
664    pub fn local(loc: Loc, name: Ident<'input>) -> Self {
665        Self::Local { loc, name }
666    }
667
668    /// Creates a literal map pair.
669    pub fn literal(loc: Loc, name: Ident<'input>, value: Box<Expr<'input>>) -> Self {
670        Self::Literal { loc, name, value }
671    }
672
673    /// Creates a expre map pair.
674    pub fn evaluated(loc: Loc, name: Box<Expr<'input>>, value: Box<Expr<'input>>) -> Self {
675        Self::Evaluated { loc, name, value }
676    }
677}
678
679impl<'input> Locate for MapPair<'input> {
680    fn loc(&self) -> Loc {
681        match self {
682            Self::Local { loc, .. } => loc.clone(),
683            Self::Literal { loc, .. } => loc.clone(),
684            Self::Evaluated { loc, .. } => loc.clone(),
685        }
686    }
687}
688
689/// A map literal.
690#[derive(Clone, Debug, PartialEq)]
691pub struct MapLit<'input> {
692    pub loc: Loc,
693    pub items: Vec<MapPair<'input>>,
694}
695
696impl<'input> MapLit<'input> {
697    /// Creates a new map literal.
698    pub fn new(loc: Loc, items: Vec<MapPair<'input>>) -> Self {
699        Self { loc, items }
700    }
701}
702
703impl<'input> Locate for MapLit<'input> {
704    fn loc(&self) -> Loc {
705        self.loc.clone()
706    }
707}
708
709/// A property of a struct.
710#[derive(Clone, Debug, PartialEq)]
711pub struct StructProp<'input> {
712    pub loc: Loc,
713    pub publ: bool,
714    pub name: Ident<'input>,
715}
716
717impl<'input> StructProp<'input> {
718    /// Creates a new struct property.
719    pub fn new(loc: Loc, publ: bool, name: Ident<'input>) -> Self {
720        Self { loc, publ, name }
721    }
722}
723
724impl<'input> Locate for StructProp<'input> {
725    fn loc(&self) -> Loc {
726        self.loc.clone()
727    }
728}
729
730/// A member of a struct.
731#[derive(Clone, Debug, PartialEq)]
732pub enum StructMember<'input> {
733    Prop(StructProp<'input>),
734    Fun(Fun<'input>),
735}
736
737impl<'input> Locate for StructMember<'input> {
738    fn loc(&self) -> Loc {
739        match self {
740            Self::Prop(member) => member.loc.clone(),
741            Self::Fun(member) => member.loc.clone(),
742        }
743    }
744}
745
746/// A struct declaration.
747#[derive(Clone, Debug, PartialEq)]
748pub struct Struct<'input> {
749    pub loc: Loc,
750    pub publ: bool,
751    pub name: Ident<'input>,
752    pub members: Vec<StructMember<'input>>,
753}
754
755impl<'input> Struct<'input> {
756    /// Creates a new struct declaration.
757    pub fn new(loc: Loc, publ: bool, name: Ident<'input>, members: Vec<StructMember<'input>>) -> Self {
758        Self { loc, publ, name, members }
759    }
760}
761
762impl<'input> Locate for Struct<'input> {
763    fn loc(&self) -> Loc {
764        self.loc.clone()
765    }
766}
767
768/// The decorator used to initialize a variable.
769#[derive(Clone, Debug, PartialEq)]
770pub enum VarDeco {
771    Mut {
772        loc: Loc,
773    },
774    Const {
775        loc: Loc,
776    }
777}
778
779impl VarDeco {
780    /// Creates a mutable variable decorator.
781    pub fn mut_(loc: Loc) -> Self {
782        Self::Mut { loc }
783    }
784
785    /// Creates a constant variable decorator.
786    pub fn const_(loc: Loc) -> Self {
787        Self::Const { loc }
788    }
789}
790
791impl Locate for VarDeco {
792    fn loc(&self) -> Loc {
793        match self {
794            Self::Mut { loc } => loc.clone(),
795            Self::Const { loc } => loc.clone(),
796        }
797    }
798}
799
800/// A pattern expression to match.
801#[derive(Clone, Debug, PartialEq)]
802pub enum PatternExpr<'input> {
803    Named(Ident<'input>, Expr<'input>),
804    Literal(Expr<'input>),
805    Evaluated(Expr<'input>),
806}
807
808/// A pattern to match in a variable.
809#[derive(Clone, Debug, PartialEq)]
810pub struct VarPatternList<'input> {
811    pub loc: Loc,
812    pub pattern: Vec<PatternExpr<'input>>,
813}
814
815impl<'input> VarPatternList<'input> {
816    /// Creates a new variable pattern.
817    pub fn new(loc: Loc, pattern: Vec<PatternExpr<'input>>) -> Self {
818        Self { loc, pattern }
819    }
820}
821
822impl<'input> Locate for VarPatternList<'input> {
823    fn loc(&self) -> Loc {
824        self.loc.clone()
825    }
826}
827
828/// A pattern to match in a variable.
829#[derive(Clone, Debug, PartialEq)]
830pub struct VarPatternMap<'input> {
831    pub loc: Loc,
832    pub pattern: Vec<PatternExpr<'input>>,
833}
834
835impl<'input> VarPatternMap<'input> {
836    /// Creates a new variable pattern.
837    pub fn new(loc: Loc, pattern: Vec<PatternExpr<'input>>) -> Self {
838        Self { loc, pattern }
839    }
840}
841
842impl<'input> Locate for VarPatternMap<'input> {
843    fn loc(&self) -> Loc {
844        self.loc.clone()
845    }
846}
847
848/// The kind of a variable.
849#[derive(Clone, Debug, PartialEq)]
850pub enum VarKind<'input> {
851    Named(Ident<'input>, Box<Option<Expr<'input>>>),
852    PatternList(VarPatternList<'input>, Box<Expr<'input>>),
853    PatternMap(VarPatternMap<'input>, Box<Expr<'input>>),
854}
855
856impl<'input> Locate for VarKind<'input> {
857    fn loc(&self) -> Loc {
858        match self {
859            VarKind::Named(kind, _) => kind.loc(),
860            VarKind::PatternList(kind, _) => kind.loc(),
861            VarKind::PatternMap(kind, _) => kind.loc(),
862        }
863    }
864}
865
866/// A variable declaration.
867#[derive(Clone, Debug, PartialEq)]
868pub struct Var<'input> {
869    pub loc: Loc,
870    pub deco: VarDeco,
871    pub kind: VarKind<'input>,
872}
873
874impl<'input> Var<'input> {
875    /// Creates a new variable declaration.
876    pub fn named(loc: Loc, deco: VarDeco, name: Ident<'input>, value: Box<Option<Expr<'input>>>) -> Self {
877        Self { loc, deco, kind: VarKind::Named(name, value) }
878    }
879
880    /// Creates a new pattern matching variable declaration.
881    pub fn pattern_list(loc: Loc, deco: VarDeco, pattern: VarPatternList<'input>, value: Box<Expr<'input>>) -> Self {
882        Self { loc, deco, kind: VarKind::PatternList(pattern, value) }
883    }
884
885    /// Creates a new pattern matching variable declaration.
886    pub fn pattern_map(loc: Loc, deco: VarDeco, pattern: VarPatternMap<'input>, value: Box<Expr<'input>>) -> Self {
887        Self { loc, deco, kind: VarKind::PatternMap(pattern, value) }
888    }
889}
890
891impl<'input> Locate for Var<'input> {
892    fn loc(&self) -> Loc {
893        self.loc.clone()
894    }
895}
896
897/// A **`while`** statement.
898#[derive(Clone, Debug, PartialEq)]
899pub struct While<'input> {
900    pub loc: Loc,
901    pub label: Option<Ident<'input>>,
902    pub cond: Box<Expr<'input>>,
903    pub block: Block<'input>,
904}
905
906impl<'input> While<'input> {
907    /// Creates a new **`while`** statement.
908    pub fn new(loc: Loc, label: Option<Ident<'input>>, cond: Box<Expr<'input>>, block: Block<'input>) -> Self {
909        Self { loc, label, cond, block }
910    }
911}
912
913impl<'input> Locate for While<'input> {
914    fn loc(&self) -> Loc {
915        self.loc.clone()
916    }
917}
918
919/// A **`break`** statement.
920#[derive(Clone, Debug, PartialEq)]
921pub struct Break<'input> {
922    pub loc: Loc,
923    pub label: Option<Ident<'input>>,
924}
925
926impl<'input> Break<'input> {
927    /// Creates a new **`break`** statement.
928    pub fn new(loc: Loc, label: Option<Ident<'input>>) -> Self {
929        Self { loc, label }
930    }
931}
932
933impl<'input> Locate for Break<'input> {
934    fn loc(&self) -> Loc {
935        self.loc.clone()
936    }
937}
938
939/// A **`continue`** statement.
940#[derive(Clone, Debug, PartialEq)]
941pub struct Continue<'input> {
942    pub loc: Loc,
943    pub label: Option<Ident<'input>>,
944}
945
946impl<'input> Continue<'input> {
947    /// Creates a new **`continue`** statement.
948    pub fn new(loc: Loc, label: Option<Ident<'input>>) -> Self {
949        Self { loc, label }
950    }
951}
952
953impl<'input> Locate for Continue<'input> {
954    fn loc(&self) -> Loc {
955        self.loc.clone()
956    }
957}
958
959/// A **`return`** statement.
960#[derive(Clone, Debug, PartialEq)]
961pub struct Return<'input> {
962    pub loc: Loc,
963    pub value: Box<Option<Expr<'input>>>,
964}
965
966impl<'input> Return<'input> {
967    /// Creates a new **`return`** statement.
968    pub fn new(loc: Loc, value: Box<Option<Expr<'input>>>) -> Self {
969        Self { loc, value }
970    }
971}
972
973impl<'input> Locate for Return<'input> {
974    fn loc(&self) -> Loc {
975        self.loc.clone()
976    }
977}
978
979/// An operator used to create a range.
980#[derive(Clone, Debug, PartialEq)]
981pub enum RangeOp<'input> {
982    /// **`..`**
983    Exclusive(Box<Option<Expr<'input>>>, Box<Option<Expr<'input>>>),
984
985    /// **`..=`**
986    Inclusive(Box<Option<Expr<'input>>>, Box<Expr<'input>>),
987}
988
989/// A range operation.
990#[derive(Clone, Debug, PartialEq)]
991pub struct Range<'input> {
992    pub loc: Loc,
993    pub op: RangeOp<'input>,
994}
995
996impl<'input> Range<'input> {
997    /// Creates a new range expression.
998    pub fn new(loc: Loc, op: RangeOp<'input>) -> Self {
999        Self { loc, op }
1000    }
1001}
1002
1003impl<'input> Locate for Range<'input> {
1004    fn loc(&self) -> Loc {
1005        self.loc.clone()
1006    }
1007}
1008
1009/// An *xlang* expression.
1010#[derive(Clone, Debug, PartialEq)]
1011pub enum Expr<'input> {
1012    None(None),
1013    Bool(Bool<'input>),
1014    Num(Num<'input>),
1015    Ident(Ident<'input>),
1016    Atom(Atom<'input>),
1017    Str(Str<'input>),
1018    Binary(Binary<'input>),
1019    Call(Call<'input>),
1020    Unary(Unary<'input>),
1021    Assign(Assign<'input>),
1022    If(If<'input>),
1023    InlineFun(InlineFun<'input>),
1024    Fun(Fun<'input>),
1025    Block(Block<'input>),
1026    ListLit(ListLit<'input>),
1027    MapLit(MapLit<'input>),
1028    Struct(Struct<'input>),
1029    Var(Var<'input>),
1030    While(While<'input>),
1031    Break(Break<'input>),
1032    Continue(Continue<'input>),
1033    Return(Return<'input>),
1034    Range(Range<'input>),
1035}
1036
1037impl<'input> Expr<'input> {
1038    /// Creates a new **`none`** expression.
1039    #[inline]
1040    pub fn none(loc: Loc) -> Self {
1041        Self::None(None::new(loc))
1042    }
1043
1044    /// Creates a new boolean expression.
1045    #[inline]
1046    pub fn bool(loc: Loc, value: &'input str) -> Self {
1047        Self::Bool(Bool::new(loc, value))
1048    }
1049
1050    /// Creates a new decimal integer expression.
1051    #[inline]
1052    pub fn dec(loc: Loc, value: &'input str) -> Self {
1053        Self::Num(Num::dec(loc, value))
1054    }
1055
1056    /// Creates a new hexadecimal integer expression.
1057    #[inline]
1058    pub fn hex(loc: Loc, value: &'input str) -> Self {
1059        Self::Num(Num::hex(loc, value))
1060    }
1061
1062    /// Creates a new binary integer expression.
1063    #[inline]
1064    pub fn bin(loc: Loc, value: &'input str) -> Self {
1065        Self::Num(Num::bin(loc, value))
1066    }
1067
1068    /// Creates a new octal integer expression.
1069    #[inline]
1070    pub fn oct(loc: Loc, value: &'input str) -> Self {
1071        Self::Num(Num::oct(loc, value))
1072    }
1073
1074    /// Creates a new floating point number expression.
1075    #[inline]
1076    pub fn float(loc: Loc, value: &'input str) -> Self {
1077        Self::Num(Num::float(loc, value))
1078    }
1079
1080    /// Creates a new identifier expression.
1081    #[inline]
1082    pub fn ident(loc: Loc, value: &'input str) -> Self {
1083        Self::Ident(Ident::new(loc, value))
1084    }
1085
1086    /// Creates a new atom expression.
1087    #[inline]
1088    pub fn atom(loc: Loc, value: &'input str) -> Self {
1089        Self::Ident(Ident::new(loc, value))
1090    }
1091
1092    /// Creates a new string expression.
1093    #[inline]
1094    pub fn str(loc: Loc, value: &'input str) -> Self {
1095        Self::Str(Str::new(loc, value))
1096    }
1097
1098    /// Creates a new binary operation.
1099    #[inline]
1100    pub fn binary(loc: Loc, left: Self, op: BinaryOp, right: Self) -> Self {
1101        Self::Binary(Binary::new(loc, op, Box::new(left), Box::new(right)))
1102    }
1103
1104    /// Creates a new function call operation.
1105    #[inline]
1106    pub fn call(loc: Loc, fun: Self, args: Vec<Self>) -> Self {
1107        Self::Call(Call::new(loc, Box::new(fun), args))
1108    }
1109
1110    /// Creates a new function call operation.
1111    #[inline]
1112    pub fn unary(loc: Loc, op: UnaryOp, subject: Self) -> Self {
1113        Self::Unary(Unary::new(loc, op, Box::new(subject)))
1114    }
1115
1116    /// Creates a new assignment operation.
1117    #[inline]
1118    pub fn assign(loc: Loc, left: Self, op: AssignOp, right: Self) -> Self {
1119        Self::Assign(Assign::new(loc, op, Box::new(left), Box::new(right)))
1120    }
1121
1122    /// Creates an exclusive range.
1123    #[inline]
1124    pub fn range_exclusive(loc: Loc, left: Option<Self>, right: Option<Self>) -> Self {
1125        Self::Range(Range::new(loc, RangeOp::Exclusive(Box::new(left), Box::new(right))))
1126    }
1127
1128    /// Creates an inclusive range.
1129    #[inline]
1130    pub fn range_inclusive(loc: Loc, left: Option<Self>, right: Self) -> Self {
1131        Self::Range(Range::new(loc, RangeOp::Inclusive(Box::new(left), Box::new(right))))
1132    }
1133}
1134
1135impl<'input> Locate for Expr<'input> {
1136    fn loc(&self) -> Loc {
1137        match self {
1138            Expr::None(expr) => expr.loc(),
1139            Expr::Bool(expr) => expr.loc(),
1140            Expr::Num(expr) => expr.loc(),
1141            Expr::Ident(expr) => expr.loc(),
1142            Expr::Atom(expr) => expr.loc(),
1143            Expr::Str(expr) => expr.loc(),
1144            Expr::Binary(expr) => expr.loc(),
1145            Expr::Call(expr) => expr.loc(),
1146            Expr::Unary(expr) => expr.loc(),
1147            Expr::Assign(expr) => expr.loc(),
1148            Expr::If(expr) => expr.loc(),
1149            Expr::InlineFun(expr) => expr.loc(),
1150            Expr::Fun(expr) => expr.loc(),
1151            Expr::Block(expr) => expr.loc(),
1152            Expr::ListLit(expr) => expr.loc(),
1153            Expr::MapLit(expr) => expr.loc(),
1154            Expr::Struct(expr) => expr.loc(),
1155            Expr::Var(expr) => expr.loc(),
1156            Expr::While(expr) => expr.loc(),
1157            Expr::Break(expr) => expr.loc(),
1158            Expr::Continue(expr) => expr.loc(),
1159            Expr::Return(expr) => expr.loc(),
1160            Expr::Range(expr) => expr.loc(),
1161        }
1162    }
1163}