1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
//! Main abstract syntax tree specification for the piske programming language. This
//! hererogeneous node tree is annotated with an arbitrary annotation node type `A`.
//!
//! This abstract syntax tree is constructed by the rust-peg parser, and annotated by the AST
//! visitors.

use sindra::{Identifier, Node};
use ast::Annotation;

/// Root-level program. Only contains a statement block.
#[derive(Debug, Clone, PartialEq)]
pub struct Program(pub Node<Block>);
annotate!(Program, Annotation);

/// Statement block is simply a list of statements.
#[derive(Debug, Clone, PartialEq)]
pub struct Block(pub Vec<Node<Statement>>);
annotate!(Block, Annotation);

/// The various allowed statements in the piske programming language.
#[derive(Debug, Clone, PartialEq)]
pub enum Statement {
    /// Statement only containing an expression.
    Expression(Node<Expression>),
    /// Variable declaration statement.
    Declare(Node<Identifier>, Node<Expression>),
    /// Variable assignment statement.
    Assign(Node<Identifier>, Node<Expression>),
    /// Function definition statement.
    FnDefine(FunctionDef),
    /// Return statement.
    Return(Node<Expression>),
    /// Break statement.
    Break(Node<Expression>),
    /// Print statement.
    Print(Vec<Node<Expression>>),
}
annotate!(Statement, Annotation);

/// Definition of a function.
#[derive(Debug, Clone, PartialEq)]
pub struct FunctionDef {
    /// Function name.
    pub name: Node<Identifier>,
    /// Return type.
    pub ret_type: Node<Identifier>,
    /// List of function parameters.
    pub params: Vec<Node<Parameter>>,
    /// Body of the function.
    pub body: Node<Block>,
}

/// Function parameter (used in function definitions).
#[derive(Debug, Clone, PartialEq)]
pub struct Parameter {
    /// Paramter variable name.
    pub name: Node<Identifier>,
    /// Parameter variable type.
    pub ty: Node<Identifier>,
}
annotate!(Parameter, Annotation);

/// Valid expressions in the piske programming language.
#[derive(Debug, Clone, PartialEq)]
pub enum Expression {
    /// A sole literal
    Literal(Node<Literal>),
    /// An identifier
    Identifier(Node<Identifier>),
    /// An infix operation, of form <expr> <op> <expr>
    Infix {
        /// The specific type of infix operation (e.g. add, subtract)
        op: InfixOp,
        /// The left operand
        left: Box<Node<Expression>>,
        /// The right operand
        right: Box<Node<Expression>>,
    },
    /// A prefix operation, of form <op> <expr>
    Prefix {
        /// The specific type of prefix operation (e.g. negation)
        op: PrefixOp,
        /// The operand
        right: Box<Node<Expression>>,
    },
    /// A postfix operation, of form <expr> <op>
    Postfix {
        /// The specific type of postfix operation
        op: PostfixOp,
        /// The operand
        left: Box<Node<Expression>>,
    },
    /// A block of statements is treated as an expression (and can have a return value)
    Block(Node<Block>),
    /// A function call
    FnCall {
        /// Function name.
        name: Node<Identifier>,
        /// List of arguments passed into the function.
        args: Vec<Node<Expression>>
    },
    /// If / else expression
    IfElse {
        /// conditional
        cond: Box<Node<Expression>>,
        /// if-block (executed if cond is true)
        if_block: Node<Block>,
        /// else-block (executed if cond is false); optional
        else_block: Option<Node<Block>>
    },
    /// Loop expression
    Loop {
        /// name of loop-varying symbol
        variant: Option<Node<Identifier>>,
        /// set of elements to loop over
        set: Node<Set>,
        /// loop body
        body: Node<Block>,
    }
}
annotate!(Expression, Annotation);

/// Set (collection) structure
#[derive(Debug, Clone, PartialEq)]
pub enum Set {
    /// Interval-defined set
    Interval {
        /// Start of interval (inclusive)
        start: Box<Node<Expression>>,
        /// End of interval
        end: Box<Node<Expression>>,
        /// Whether or not interval end is inclusive
        end_inclusive: bool,
        /// Interval step
        step: Box<Node<Expression>>
    },
}
annotate!(Set, Annotation);

/// Supported literals
#[derive(Debug, Clone, PartialEq)]
pub enum Literal {
    /// Simple string literal
    String(String),
    /// Floating point literal
    Float(f64),
    /// Integer literal
    Int(i64),
    /// Boolean literal
    Boolean(bool),
}
annotate!(Literal);

/// Valid prefix operations
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum PrefixOp {
    /// Unary minus (negation)
    UnaryMinus,
    /// Unary plus (posation - basically a no-op)
    UnaryPlus,
}

/// Valid infix operations
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum InfixOp {
    /// Addition
    Add,
    /// Subtraction
    Subtract,
    /// Multiplication
    Multiply,
    /// Division
    Divide,
    /// Exponentiation
    Power,
    /// Comparison
    Comparison(CompareOp),
}

/// Valid postfix operations
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum PostfixOp {
    /// Conjugation
    Conjugate,
    /// Imaginary number
    Imaginary,
}

/// Comparison operations
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum CompareOp {
    /// Lhs strictly less than rhs
    LessThan,
    /// Lhs less than or equal to rhs
    LessThanEqual,
    /// Lhs strictly greater than rhs
    GreaterThan,
    /// Lhs greater than or euqal to rhs
    GreaterThanEqual,
    /// Lhs strictly equal to rhs
    Equal,
    /// Lhs not equal rhs
    NotEqual
}