use std::collections::HashMap;
#[derive(Debug, Clone, PartialEq)]
pub enum Expr {
Nil,
Bool(bool),
Int(i64),
Float(f64),
Str(String),
Vararg,
Ident(String),
Index { table: Box<Expr>, key: Box<Expr> },
Field { table: Box<Expr>, name: String },
Call { callee: Box<Expr>, args: Vec<Expr> },
MethodCall { obj: Box<Expr>, method: String, args: Vec<Expr> },
Unary { op: UnOp, expr: Box<Expr> },
Binary { op: BinOp, lhs: Box<Expr>, rhs: Box<Expr> },
TableCtor(Vec<TableField>),
FuncExpr { params: Vec<String>, vararg: bool, body: Vec<Stmt> },
Ternary { cond: Box<Expr>, then_val: Box<Expr>, else_val: Box<Expr> },
}
#[derive(Debug, Clone, PartialEq)]
pub enum TableField {
ExprKey(Expr, Expr),
NameKey(String, Expr),
Value(Expr),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UnOp {
Neg, Not, Len, BitNot, }
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BinOp {
Add, Sub, Mul, Div, IDiv, Mod, Pow,
Concat, Eq, NotEq, Lt, LtEq, Gt, GtEq,
And, Or,
BitAnd, BitOr, BitXor, Shl, Shr,
}
impl BinOp {
pub fn precedence(self) -> u8 {
match self {
BinOp::Or => 1,
BinOp::And => 2,
BinOp::Eq | BinOp::NotEq
| BinOp::Lt | BinOp::LtEq
| BinOp::Gt | BinOp::GtEq => 3,
BinOp::Concat => 4,
BinOp::BitOr => 5,
BinOp::BitXor => 6,
BinOp::BitAnd => 7,
BinOp::Shl | BinOp::Shr => 8,
BinOp::Add | BinOp::Sub => 9,
BinOp::Mul | BinOp::Div
| BinOp::IDiv | BinOp::Mod => 10,
BinOp::Pow => 12,
}
}
pub fn is_right_assoc(self) -> bool {
matches!(self, BinOp::Pow | BinOp::Concat)
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum Stmt {
LocalDecl { name: String, init: Option<Expr> },
LocalMulti { names: Vec<String>, inits: Vec<Expr> },
Assign { target: Vec<Expr>, value: Vec<Expr> },
CompoundAssign { target: Expr, op: BinOp, value: Expr },
Call(Expr),
Do(Vec<Stmt>),
While { cond: Expr, body: Vec<Stmt> },
RepeatUntil { body: Vec<Stmt>, cond: Expr },
If { cond: Expr, then_body: Vec<Stmt>, elseif_branches: Vec<(Expr, Vec<Stmt>)>, else_body: Option<Vec<Stmt>> },
NumericFor { var: String, start: Expr, limit: Expr, step: Option<Expr>, body: Vec<Stmt> },
GenericFor { vars: Vec<String>, iter: Vec<Expr>, body: Vec<Stmt> },
FuncDecl { name: Vec<String>, params: Vec<String>, vararg: bool, body: Vec<Stmt> },
LocalFunc { name: String, params: Vec<String>, vararg: bool, body: Vec<Stmt> },
Return(Vec<Expr>),
Break,
Continue,
Match { expr: Expr, arms: Vec<MatchArm> },
Import { path: String, alias: Option<String> },
Export(String),
Expr(Expr),
}
#[derive(Debug, Clone, PartialEq)]
pub struct MatchArm {
pub pattern: MatchPattern,
pub body: Vec<Stmt>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum MatchPattern {
Literal(Expr),
Ident(String),
Wildcard,
Table(Vec<(String, MatchPattern)>),
}
#[derive(Debug, Clone)]
pub struct Script {
pub name: String,
pub stmts: Vec<Stmt>,
}