use std::rc::Rc;
use crate::{error::Location, function::Function, token::Operator, value::Value};
pub type Ident = (usize, usize);
#[derive(Clone)]
pub enum Expression {
Binary {
left: Box<Expression>,
operator: Operator,
right: Box<Expression>,
location: Location,
},
Unary {
operator: Operator,
right: Box<Expression>,
location: Location,
},
Literal { value: Value, location: Location },
GroupingExpression {
expression: Box<Expression>,
location: Location,
},
Variable { ident: Ident, location: Location },
Assign {
ident: Ident,
value: Box<Expression>,
location: Location,
},
Logical {
left: Box<Expression>,
operator: Operator,
right: Box<Expression>,
location: Location,
},
Call {
callee: Box<Expression>,
args: Vec<Expression>,
location: Location,
},
Function {
value: Rc<Function>,
location: Location,
},
InvalidExpression,
}
impl std::fmt::Display for Expression {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Expression::Binary {
left,
operator,
right,
location,
} => write!(f, "({} {} {})", operator, left, right),
Expression::Logical {
left,
operator,
right,
location,
} => write!(f, "({} {} {})", operator, left, right),
Expression::Unary {
operator,
right,
location,
} => write!(f, "({} {})", operator, right),
Expression::Literal { value, location } => write!(f, " {} ", value),
Expression::GroupingExpression {
expression,
location,
} => write!(f, "G({})", expression),
Expression::Variable { ident, location } => write!(f, "{}:{}", ident.0, ident.1),
Expression::Assign {
ident,
value,
location,
} => write!(f, "({}:{} := {})", ident.0, ident.1, value),
Expression::Call {
callee,
args: arguments,
..
} => {
let mut s = format!("({}(", callee);
for arg in arguments {
s.push_str(&format!("{},", arg));
}
s.push_str("))");
write!(f, "{}", s)
}
Expression::Function { value, .. } => write!(f, "function"),
Expression::InvalidExpression => write!(f, "!Invalid_Expression!"),
}
}
}