use valua_diagnostics::Span;
#[cfg(feature = "serde")]
use serde::Serialize;
#[cfg_attr(feature = "serde", derive(Serialize))]
#[derive(Debug, Clone)]
pub struct Block {
pub stmts: Vec<Statement>,
pub span: Span,
}
#[cfg_attr(feature = "serde", derive(Serialize))]
#[derive(Debug, Clone)]
pub enum Statement {
LocalDecl(LocalDecl),
Assign(Assign),
Do(Do),
While(While),
Repeat(Repeat),
If(If),
NumericFor(NumericFor),
GenericFor(GenericFor),
FunctionDecl(FunctionDecl),
LocalFunctionDecl(LocalFunctionDecl),
Return(Return),
Break(Span),
Goto(Goto),
Label(Label),
ExprStmt(Expression),
}
#[cfg_attr(feature = "serde", derive(Serialize))]
#[derive(Debug, Clone)]
pub struct LocalDecl {
pub names: Vec<LocalName>,
pub values: Vec<Expression>,
pub span: Span,
}
#[cfg_attr(feature = "serde", derive(Serialize))]
#[derive(Debug, Clone)]
pub struct LocalName {
pub name: String,
pub attribute: Option<Attribute>,
pub span: Span,
}
#[cfg_attr(feature = "serde", derive(Serialize))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Attribute {
Const,
Close,
}
#[cfg_attr(feature = "serde", derive(Serialize))]
#[derive(Debug, Clone)]
pub struct Assign {
pub targets: Vec<Expression>,
pub values: Vec<Expression>,
pub span: Span,
}
#[cfg_attr(feature = "serde", derive(Serialize))]
#[derive(Debug, Clone)]
pub struct Do {
pub body: Block,
pub span: Span,
}
#[cfg_attr(feature = "serde", derive(Serialize))]
#[derive(Debug, Clone)]
pub struct While {
pub condition: Box<Expression>,
pub body: Block,
pub span: Span,
}
#[cfg_attr(feature = "serde", derive(Serialize))]
#[derive(Debug, Clone)]
pub struct Repeat {
pub body: Block,
pub condition: Box<Expression>,
pub span: Span,
}
#[cfg_attr(feature = "serde", derive(Serialize))]
#[derive(Debug, Clone)]
pub struct If {
pub condition: Box<Expression>,
pub then_block: Block,
pub elseif_clauses: Vec<ElseIf>,
pub else_block: Option<Block>,
pub span: Span,
}
#[cfg_attr(feature = "serde", derive(Serialize))]
#[derive(Debug, Clone)]
pub struct ElseIf {
pub condition: Box<Expression>,
pub body: Block,
pub span: Span,
}
#[cfg_attr(feature = "serde", derive(Serialize))]
#[derive(Debug, Clone)]
pub struct NumericFor {
pub var: String,
pub start: Box<Expression>,
pub limit: Box<Expression>,
pub step: Option<Box<Expression>>,
pub body: Block,
pub span: Span,
}
#[cfg_attr(feature = "serde", derive(Serialize))]
#[derive(Debug, Clone)]
pub struct GenericFor {
pub vars: Vec<String>,
pub iterators: Vec<Expression>,
pub body: Block,
pub span: Span,
}
#[cfg_attr(feature = "serde", derive(Serialize))]
#[derive(Debug, Clone)]
pub struct FunctionDecl {
pub name: FunctionName,
pub func: FunctionBody,
pub span: Span,
}
#[cfg_attr(feature = "serde", derive(Serialize))]
#[derive(Debug, Clone)]
pub struct LocalFunctionDecl {
pub name: String,
pub func: FunctionBody,
pub span: Span,
}
#[cfg_attr(feature = "serde", derive(Serialize))]
#[derive(Debug, Clone)]
pub struct FunctionName {
pub parts: Vec<String>,
pub method: Option<String>,
pub span: Span,
}
#[cfg_attr(feature = "serde", derive(Serialize))]
#[derive(Debug, Clone)]
pub struct Return {
pub values: Vec<Expression>,
pub span: Span,
}
#[cfg_attr(feature = "serde", derive(Serialize))]
#[derive(Debug, Clone)]
pub struct Goto {
pub label: String,
pub span: Span,
}
#[cfg_attr(feature = "serde", derive(Serialize))]
#[derive(Debug, Clone)]
pub struct Label {
pub name: String,
pub span: Span,
}
#[cfg_attr(feature = "serde", derive(Serialize))]
#[derive(Debug, Clone)]
pub struct FunctionBody {
pub params: Vec<Param>,
pub is_vararg: bool,
pub body: Block,
pub span: Span,
}
#[cfg_attr(feature = "serde", derive(Serialize))]
#[derive(Debug, Clone)]
pub struct Param {
pub name: String,
pub span: Span,
}
#[cfg_attr(feature = "serde", derive(Serialize))]
#[derive(Debug, Clone)]
pub enum Expression {
Nil(Span),
True(Span),
False(Span),
Integer(i64, Span),
Float(f64, Span),
String(String, Span),
Vararg(Span),
Name(String, Span),
Index(Box<Expression>, String, Span),
IndexExpr(Box<Expression>, Box<Expression>, Span),
BinOp(Box<Expression>, BinaryOp, Box<Expression>, Span),
UnOp(UnaryOp, Box<Expression>, Span),
Call(Call),
Function(FunctionBody),
Table(TableConstructor),
}
impl Expression {
#[must_use]
#[allow(clippy::match_same_arms)]
pub fn span(&self) -> Span {
match self {
Expression::Nil(s)
| Expression::True(s)
| Expression::False(s)
| Expression::Vararg(s) => *s,
Expression::Integer(_, s) => *s,
Expression::Float(_, s) => *s,
Expression::String(_, s) => *s,
Expression::Name(_, s) => *s,
Expression::Index(_, _, s) => *s,
Expression::IndexExpr(_, _, s) => *s,
Expression::BinOp(_, _, _, s) => *s,
Expression::UnOp(_, _, s) => *s,
Expression::Call(c) => c.span(),
Expression::Function(f) => f.span,
Expression::Table(t) => t.span,
}
}
}
#[cfg_attr(feature = "serde", derive(Serialize))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BinaryOp {
Add,
Sub,
Mul,
Div,
Mod,
Pow,
IDiv,
Lt,
Le,
Gt,
Ge,
Eq,
Ne,
And,
Or,
BitwiseAnd,
BitwiseOr,
BitwiseXor,
Shl,
Shr,
Concat,
}
#[cfg_attr(feature = "serde", derive(Serialize))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UnaryOp {
Neg,
Not,
Len,
BitwiseNot,
}
#[cfg_attr(feature = "serde", derive(Serialize))]
#[derive(Debug, Clone)]
pub enum Call {
Call {
func: Box<Expression>,
args: Vec<Expression>,
span: Span,
},
MethodCall {
obj: Box<Expression>,
method: String,
args: Vec<Expression>,
span: Span,
},
}
impl Call {
#[must_use]
pub fn span(&self) -> Span {
match self {
Call::Call { span, .. } | Call::MethodCall { span, .. } => *span,
}
}
}
#[cfg_attr(feature = "serde", derive(Serialize))]
#[derive(Debug, Clone)]
pub struct TableConstructor {
pub fields: Vec<TableField>,
pub span: Span,
}
#[cfg_attr(feature = "serde", derive(Serialize))]
#[derive(Debug, Clone)]
pub enum TableField {
ExprKey {
key: Box<Expression>,
value: Box<Expression>,
span: Span,
},
NameKey {
key: String,
value: Box<Expression>,
span: Span,
},
Positional(Expression),
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[ignore = "TODO: verify Block can be constructed and iterated"]
fn test_block_construction() {
todo!()
}
#[test]
#[ignore = "TODO: verify Attribute variants are distinct"]
fn test_attribute_variants() {
todo!()
}
#[test]
#[ignore = "TODO: Expression::span() returns the correct span for each variant"]
fn test_expression_span() {
todo!()
}
#[test]
#[ignore = "TODO: BinaryOp includes all bitwise variants"]
fn test_binary_op_bitwise_variants() {
todo!()
}
}
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum LuaTarget {
#[default]
Lua51,
LuaJIT,
}