Skip to main content

unlab_gpu/
tree.rs

1//
2// Copyright (c) 2025-2026 Ɓukasz Szpakowski
3//
4// This Source Code Form is subject to the terms of the Mozilla Public
5// License, v. 2.0. If a copy of the MPL was not distributed with this
6// file, You can obtain one at https://mozilla.org/MPL/2.0/.
7//
8//! A module of syntax tree.
9use std::fmt;
10use std::sync::Arc;
11use crate::error::*;
12
13/// A structure of syntax tree.
14///
15/// The syntax tree creates from tokens by a parser. An interpreter can take the syntax tree to
16/// interpretation.
17#[derive(Clone, Debug)]
18pub struct Tree(pub Vec<Node>);
19
20/// A node enumeration.
21#[derive(Clone, Debug)]
22pub enum Node
23{
24    /// A definition.
25    Def(Box<Def>),
26    /// A statement.
27    Stat(Box<Stat>),
28}
29
30/// A definition enumeration.
31#[derive(Clone, Debug)]
32pub enum Def
33{
34    /// A module.
35    Mod(String, Box<Mod>, Pos),
36    /// A function.
37    Fun(String, Arc<Fun>, Pos),
38}
39
40impl Def
41{
42    /// Returns the file position.
43    pub fn pos(&self) -> &Pos
44    {
45        match self {
46            Def::Mod(_, _, pos) => pos,
47            Def::Fun(_, _, pos) => pos,
48        }
49    }
50
51    /// Sets the file position.
52    pub fn set_pos(&mut self, pos: Pos)
53    {
54        match self {
55            Def::Mod(_, _, pos2) => *pos2 = pos,
56            Def::Fun(_, _, pos2) => *pos2 = pos,
57        }
58    }
59}
60
61/// A module structure.
62#[derive(Clone, Debug)]
63pub struct Mod(pub Vec<Node>);
64
65/// A function structure.
66#[derive(Clone, Debug)]
67pub struct Fun(pub Vec<Arg>, pub Vec<Box<Stat>>);
68
69/// An argument structure.
70#[derive(Clone, Debug)]
71pub struct Arg(pub String, pub Pos);
72
73impl Arg
74{
75    /// Returns the file position.
76    pub fn pos(&self) -> &Pos
77    { &self.1 }
78    
79    /// Sets the file position.
80    pub fn set_pos(&mut self, pos: Pos)
81    { self.1 = pos; }
82}
83
84/// A statement enumeration.
85#[derive(Clone, Debug)]
86pub enum Stat
87{
88    /// An expression statement.
89    Expr(Box<Expr>, Pos),
90    /// An assignment statement.
91    Assign(Box<Expr>, Box<Expr>, Pos),
92    /// An `if` statement.
93    If(Box<Expr>, Vec<Box<Stat>>, Vec<(Box<Expr>, Vec<Box<Stat>>)>, Option<Vec<Box<Stat>>>, Pos),
94    /// A `for` statement.
95    For(String, Box<Expr>, Vec<Box<Stat>>, Pos),
96    /// A `while` statement.
97    While(Box<Expr>, Vec<Box<Stat>>, Pos),
98    /// A `break` statement.
99    Break(Pos),
100    /// A `continue` statement.
101    Continue(Pos),
102    /// A `return` statement.
103    Return(Option<Box<Expr>>, Pos),
104    /// A `quit` statement.
105    Quit(Pos),
106}
107
108impl Stat
109{
110    /// Returns the file position.
111    pub fn pos(&self) -> &Pos
112    {
113        match self {
114            Stat::Expr(_, pos) => pos,
115            Stat::Assign(_, _, pos) => pos,
116            Stat::If(_, _, _, _, pos) => pos,
117            Stat::For(_, _, _, pos) => pos,
118            Stat::While(_, _, pos) => pos,
119            Stat::Break(pos) => pos,
120            Stat::Continue(pos) => pos,
121            Stat::Return(_, pos) => pos,
122            Stat::Quit(pos) => pos,
123        }
124    }
125
126    /// Sets the file position.
127    pub fn set_pos(&mut self, pos: Pos)
128    {
129        match self {
130            Stat::Expr(_, pos2) => *pos2 = pos,
131            Stat::Assign(_, _, pos2) => *pos2 = pos,
132            Stat::If(_, _, _, _, pos2) => *pos2 = pos,
133            Stat::For(_, _, _, pos2) => *pos2 = pos,
134            Stat::While(_, _, pos2) => *pos2 = pos,
135            Stat::Break(pos2) => *pos2 = pos,
136            Stat::Continue(pos2) => *pos2 = pos,
137            Stat::Return(_, pos2) => *pos2 = pos,
138            Stat::Quit(pos2) => *pos2 = pos,
139        }
140    }
141}
142
143/// An expression.
144#[derive(Clone, Debug)]
145pub enum Expr
146{
147    /// A literal.
148    Lit(Lit, Pos),
149    /// A variable.
150    Var(Name, Pos),
151    /// A function application.
152    App(Box<Expr>, Vec<Box<Expr>>, Pos),
153    /// An expression of unary operator.
154    UnaryOp(UnaryOp, Box<Expr>, Pos),
155    /// An expression of binary operator.
156    BinOp(BinOp, Box<Expr>, Box<Expr>, Pos),
157    /// A logical AND expression.
158    And(Box<Expr>, Box<Expr>, Pos),
159    /// A logical OR expression.
160    Or(Box<Expr>, Box<Expr>, Pos),
161    /// A field access.
162    Field(Box<Expr>, String, Pos),
163    /// A range.
164    Range(Box<Expr>, Box<Expr>, Option<Box<Expr>>, Pos),
165    /// An error propagation.
166    PropagateError(Box<Expr>, Pos),
167}
168
169impl Expr
170{
171    /// Returns the file position.
172    pub fn pos(&self) -> &Pos
173    {
174        match self {
175            Expr::Lit(_, pos) => pos,
176            Expr::Var(_, pos) => pos,
177            Expr::App(_, _, pos) => pos,
178            Expr::UnaryOp(_, _, pos) => pos,
179            Expr::BinOp(_, _, _, pos) => pos,
180            Expr::And(_, _, pos) => pos,
181            Expr::Or(_, _, pos) => pos,
182            Expr::Field(_, _, pos) => pos,
183            Expr::Range(_, _, _, pos) => pos,
184            Expr::PropagateError(_, pos) => pos,
185        }
186    }
187
188    /// Sets the file position.
189    pub fn set_pos(&mut self, pos: Pos)
190    {
191        match self {
192            Expr::Lit(_, pos2) => *pos2 = pos,
193            Expr::Var(_, pos2) => *pos2 = pos,
194            Expr::App(_, _, pos2) => *pos2 = pos,
195            Expr::UnaryOp(_, _, pos2) => *pos2 = pos,
196            Expr::BinOp(_, _, _, pos2) => *pos2 = pos,
197            Expr::And(_, _, pos2) => *pos2 = pos,
198            Expr::Or(_, _, pos2) => *pos2 = pos,
199            Expr::Field(_, _, pos2) => *pos2 = pos,
200            Expr::Range(_, _, _, pos2) => *pos2 = pos,
201            Expr::PropagateError(_, pos2) => *pos2 = pos,
202        }
203    }
204}
205
206/// A literal.
207#[derive(Clone, Debug)]
208pub enum Lit
209{
210    /// A none literal.
211    None,
212    /// A boolean literal
213    Bool(bool),
214    /// An integer number literal.
215    Int(i64),
216    /// A floating-point number literal.
217    Float(f32),
218    /// A stribg literal.
219    String(String),
220    /// A matrix literal.
221    Matrix(Vec<MatrixRow>),
222    /// A filled matrix literal.
223    FilledMatrix(MatrixRow, Box<Expr>),
224    /// An array literal.
225    Array(Vec<Box<Expr>>),
226    /// A filled array literal with one value.
227    FilledArray(Box<Expr>, Box<Expr>),
228    /// A structure literal.
229    Struct(Vec<FieldPair>),
230}
231
232/// An enumeration of matrix row.
233#[derive(Clone, Debug)]
234pub enum MatrixRow
235{
236    /// An matrix row.
237    Row(Vec<Box<Expr>>),
238    /// A filled matrix row with one value.
239    FilledRow(Box<Expr>, Box<Expr>),
240}
241
242/// A structure of field pair. 
243#[derive(Clone, Debug)]
244pub struct FieldPair(pub String, pub Box<Expr>, pub Pos);
245
246impl FieldPair
247{
248    /// Returns the file position.
249    pub fn pos(&self) -> &Pos
250    { &self.2 }
251    
252    /// Sets the file position.
253    pub fn set_pos(&mut self, pos: Pos)
254    { self.2 = pos; }
255}
256
257/// An enumeration of unary operator.
258#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
259pub enum UnaryOp
260{
261    /// A negation.
262    Neg,
263    /// A dot negation.
264    DotNeg,
265    /// A logical NOT.
266    Not,
267    /// A transpose.
268    Transpose,
269}
270
271/// An enumeration of binary operator.
272#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
273pub enum BinOp
274{
275    /// An index operator.
276    Index,
277    /// A multiplication.
278    Mul,
279    /// A dot multiplication.
280    DotMul,
281    /// A division.
282    Div,
283    /// A dot division.
284    DotDiv,
285    /// An addition.
286    Add,
287    /// A dot addition.
288    DotAdd,
289    /// A subtraction.
290    Sub,
291    /// A dot subtraction.
292    DotSub,
293    /// Less than.
294    Lt,
295    /// Greater than or equal to.
296    Ge,
297    /// Greater than.
298    Gt,
299    /// Less than or equal to.
300    Le,
301    /// Equal.
302    Eq,
303    /// Not equal.
304    Ne,
305}
306
307/// An enumeration of variable name.
308#[derive(Clone, Eq, PartialEq, Debug)]
309pub enum Name
310{
311    /// An absolute name with identifiers of modules and a variable identifier.
312    Abs(Vec<String>, String),
313    /// A relative name with identifiers of modules and a variable identifier.
314    Rel(Vec<String>, String),
315    /// A name with one identifier.
316    Var(String),
317}
318
319impl fmt::Display for Name
320{
321    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
322    {
323        match self {
324            Name::Abs(idents, ident) => {
325                write!(f, "root")?;
326                for ident2 in idents {
327                    write!(f, "::{}", ident2)?;
328                }
329                write!(f, "::{}", ident)
330            },
331            Name::Rel(idents, ident) => {
332                let mut is_first = true;
333                for ident2 in idents {
334                    if !is_first {
335                        write!(f, "::{}", ident2)?;
336                    } else {
337                        write!(f, "{}", ident2)?;
338                    }
339                    is_first = false;
340                }
341                write!(f, "::{}", ident)
342            },
343            Name::Var(ident) => write!(f, "{}", ident),
344        }
345    }
346}