use crate::expr::Expr;
use crate::tokens::{Token, TokenType};
use crate::visitor::StmtVisitor;
#[derive(Clone)]
pub(crate) struct Stmt {
content: StmtContent,
pub(crate) line: usize,
}
#[derive(Clone)]
enum StmtContent {
Expression(ExpressionStmt),
Print(PrintStmt),
Input(InputStmt),
Assign(AssignStmt),
If(IfStmt),
While(WhileStmt),
For(ForStmt),
Return(ReturnStmt),
BinaryAssign(BinaryAssignStmt),
}
impl Stmt {
pub fn new_print(values: Vec<Expr>, line: usize) -> Self {
Self {
line,
content: StmtContent::Print(PrintStmt { values }),
}
}
pub fn new_input(variable: Token) -> Self {
Self {
line: variable.line,
content: StmtContent::Input(InputStmt { variable }),
}
}
pub fn new_expression(value: Expr, line: usize) -> Self {
Self {
line,
content: StmtContent::Expression(ExpressionStmt { value }),
}
}
pub fn new_assign(name: Token, value: Expr, line: usize) -> Self {
Self {
line,
content: StmtContent::Assign(AssignStmt { name, value }),
}
}
pub fn new_if(
condition: Expr,
then_stmts: Vec<Stmt>,
else_stmts: Vec<Stmt>,
line: usize,
) -> Self {
Self {
line,
content: StmtContent::If(IfStmt {
condition,
then_stmts,
else_stmts,
}),
}
}
pub fn new_for(
variable: Token,
min_value: Expr,
max_value: Expr,
body: Vec<Stmt>,
line: usize,
) -> Self {
Self {
line,
content: StmtContent::For(ForStmt {
variable,
min_value,
max_value,
body,
}),
}
}
pub fn new_while(condition: Expr, body: Vec<Stmt>, line: usize) -> Self {
Self {
line,
content: StmtContent::While(WhileStmt { condition, body }),
}
}
pub fn new_return(return_value: Expr, line: usize) -> Self {
Self {
line,
content: StmtContent::Return(ReturnStmt { return_value }),
}
}
pub fn new_binary_assign(name: Token, operator: TokenType, value: Expr, line: usize) -> Self {
Self {
line,
content: StmtContent::BinaryAssign(BinaryAssignStmt {
name,
operator,
value,
}),
}
}
pub(crate) fn accept<U, V>(&self, visitor: &mut V) -> U
where
V: StmtVisitor<U>,
{
let line = self.line;
match &self.content {
StmtContent::Assign(stmt) => visitor.visit_assign_stmt(stmt, line),
StmtContent::Expression(stmt) => visitor.visit_expression_stmt(stmt, line),
StmtContent::Print(stmt) => visitor.visit_print_stmt(stmt, line),
StmtContent::Input(stmt) => visitor.visit_input_stmt(stmt, line),
StmtContent::If(stmt) => visitor.visit_if_stmt(stmt, line),
StmtContent::While(stmt) => visitor.visit_while_stmt(stmt, line),
StmtContent::For(stmt) => visitor.visit_for_stmt(stmt, line),
StmtContent::Return(stmt) => visitor.visit_return_stmt(stmt, line),
StmtContent::BinaryAssign(stmt) => visitor.visit_binary_assign_stmt(stmt, line),
}
}
}
#[derive(Clone)]
pub(crate) struct PrintStmt {
pub values: Vec<Expr>,
}
#[derive(Clone)]
pub(crate) struct InputStmt {
pub variable: Token,
}
#[derive(Clone)]
pub(crate) struct ExpressionStmt {
pub value: Expr,
}
#[derive(Clone)]
pub(crate) struct AssignStmt {
pub name: Token,
pub value: Expr,
}
#[derive(Clone)]
pub(crate) struct IfStmt {
pub condition: Expr,
pub then_stmts: Vec<Stmt>,
pub else_stmts: Vec<Stmt>,
}
#[derive(Clone)]
pub(crate) struct WhileStmt {
pub condition: Expr,
pub body: Vec<Stmt>,
}
#[derive(Clone)]
pub(crate) struct ForStmt {
pub variable: Token,
pub min_value: Expr,
pub max_value: Expr,
pub body: Vec<Stmt>,
}
#[derive(Clone)]
pub(crate) struct ReturnStmt {
pub return_value: Expr,
}
#[derive(Clone)]
pub(crate) struct BinaryAssignStmt {
pub name: Token,
pub operator: TokenType,
pub value: Expr,
}