use crate::value::Value;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Program {
pub statements: Vec<Statement>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Statement {
VarDeclaration {
name: String,
value: Expression,
is_const: bool,
},
Assignment {
target: AssignmentTarget,
operator: AssignmentOperator,
value: Expression,
},
Expression(Expression),
If {
condition: Expression,
then_branch: Vec<Statement>,
else_branch: Option<Vec<Statement>>,
},
While {
condition: Expression,
body: Vec<Statement>,
},
For {
variable: String,
iterable: Expression,
body: Vec<Statement>,
},
Function {
name: String,
parameters: Vec<Parameter>,
body: Vec<Statement>,
return_type: Option<Type>,
},
Return(Option<Expression>),
Break,
Continue,
Block(Vec<Statement>),
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum AssignmentTarget {
Variable(String),
Property {
object: Expression,
property: String
},
Index {
object: Expression,
index: Expression
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum AssignmentOperator {
Assign,
PlusAssign,
MinusAssign,
MultiplyAssign,
DivideAssign,
ModuloAssign,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Expression {
Literal(Value),
Variable(String),
Binary {
left: Box<Expression>,
operator: BinaryOperator,
right: Box<Expression>,
},
Unary {
operator: UnaryOperator,
operand: Box<Expression>,
},
Call {
callee: Box<Expression>,
arguments: Vec<Expression>,
},
Property {
object: Box<Expression>,
property: String,
},
Index {
object: Box<Expression>,
index: Box<Expression>,
},
Array(Vec<Expression>),
Object(HashMap<String, Expression>),
StringInterpolation(Vec<StringPart>),
Lambda {
parameters: Vec<Parameter>,
body: Box<Expression>,
},
Conditional {
condition: Box<Expression>,
true_expr: Box<Expression>,
false_expr: Box<Expression>,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum StringPart {
Literal(String),
Expression(Expression),
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum BinaryOperator {
Add,
Subtract,
Multiply,
Divide,
Modulo,
Power,
Equal,
NotEqual,
Less,
LessEqual,
Greater,
GreaterEqual,
And,
Or,
Concat,
BitwiseAnd,
BitwiseOr,
BitwiseXor,
LeftShift,
RightShift,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum UnaryOperator {
Minus,
Not,
BitwiseNot,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Parameter {
pub name: String,
pub param_type: Option<Type>,
pub default_value: Option<Expression>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Type {
String,
Number,
Boolean,
Array(Box<Type>),
Object(HashMap<String, Type>),
Function {
parameters: Vec<Type>,
return_type: Box<Type>,
},
Any,
Null,
}
impl Statement {
pub fn is_control_flow(&self) -> bool {
matches!(
self,
Statement::If { .. }
| Statement::While { .. }
| Statement::For { .. }
| Statement::Return(_)
| Statement::Break
| Statement::Continue
)
}
pub fn is_declaration(&self) -> bool {
matches!(
self,
Statement::VarDeclaration { .. } | Statement::Function { .. }
)
}
}
impl Expression {
pub fn is_literal(&self) -> bool {
matches!(self, Expression::Literal(_))
}
pub fn is_constant(&self) -> bool {
match self {
Expression::Literal(_) => true,
Expression::Array(elements) => elements.iter().all(|e| e.is_constant()),
Expression::Object(fields) => fields.values().all(|e| e.is_constant()),
Expression::Binary { left, right, .. } => {
left.is_constant() && right.is_constant()
}
Expression::Unary { operand, .. } => operand.is_constant(),
_ => false,
}
}
pub fn precedence(&self) -> u8 {
match self {
Expression::Binary { operator, .. } => operator.precedence(),
Expression::Unary { .. } => 7,
Expression::Call { .. } | Expression::Property { .. } | Expression::Index { .. } => 8,
_ => 0,
}
}
}
impl BinaryOperator {
pub fn precedence(&self) -> u8 {
match self {
BinaryOperator::Or => 1,
BinaryOperator::And => 2,
BinaryOperator::Equal | BinaryOperator::NotEqual => 3,
BinaryOperator::Less
| BinaryOperator::LessEqual
| BinaryOperator::Greater
| BinaryOperator::GreaterEqual => 4,
BinaryOperator::BitwiseOr => 5,
BinaryOperator::BitwiseXor => 6,
BinaryOperator::BitwiseAnd => 7,
BinaryOperator::LeftShift | BinaryOperator::RightShift => 8,
BinaryOperator::Add | BinaryOperator::Subtract | BinaryOperator::Concat => 9,
BinaryOperator::Multiply | BinaryOperator::Divide | BinaryOperator::Modulo => 10,
BinaryOperator::Power => 11,
}
}
}