xbasic 0.3.2

A library that allows adding a scripting language onto your project with ease. This lets your users write their own arbitrary logic.
Documentation
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,
}