use serde::{Deserialize, Serialize};
pub mod visitor;
pub use visitor::{walk_block, walk_expr, walk_program, walk_stmt, Visitor};
fn is_false(b: &bool) -> bool {
!b
}
fn skip_none<T>(opt: &Option<T>) -> bool {
opt.is_none()
}
fn is_zero_u32(n: &u32) -> bool {
*n == 0
}
#[derive(Debug, Clone, Copy, Default)]
pub struct Loc {
pub line: u32,
pub column: u32,
}
impl Loc {
pub fn new(line: u32, column: u32) -> Self {
Self { line, column }
}
pub fn position(&self) -> Option<(u32, u32)> {
(self.line != 0).then_some((self.line, self.column))
}
pub fn line(&self) -> Option<u32> {
(self.line != 0).then_some(self.line)
}
}
impl PartialEq for Loc {
fn eq(&self, _other: &Self) -> bool {
true
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum TypeQualifier {
Const,
Input,
Simple,
Series,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
pub enum VarKind {
#[default]
Plain,
Var,
Varip,
}
impl VarKind {
pub fn is_persistent(self) -> bool {
!matches!(self, VarKind::Plain)
}
fn is_plain(&self) -> bool {
matches!(self, VarKind::Plain)
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Argument {
Positional(Expr),
Named { name: String, value: Expr },
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Expr {
Literal(Literal),
Variable(String),
Binary {
left: Box<Expr>,
op: BinOp,
right: Box<Expr>,
#[serde(skip)]
loc: Loc,
},
Unary {
op: UnOp,
expr: Box<Expr>,
},
Call {
callee: Box<Expr>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
type_args: Vec<String>, args: Vec<Argument>,
#[serde(default, skip_serializing_if = "is_zero_u32")]
id: u32,
#[serde(skip)]
loc: Loc,
},
Index {
expr: Box<Expr>,
index: Box<Expr>,
},
MemberAccess {
object: Box<Expr>,
member: String,
},
Ternary {
condition: Box<Expr>,
then_expr: Box<Expr>,
else_expr: Box<Expr>,
},
Function {
params: Vec<FunctionParam>,
body: Vec<Stmt>,
},
Array(Vec<Expr>),
Switch {
value: Box<Expr>,
cases: Vec<(Expr, Expr)>, },
IfExpr {
condition: Box<Expr>,
then_expr: Box<Expr>,
else_if_branches: Vec<(Expr, Expr)>, else_expr: Option<Box<Expr>>, },
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Literal {
Int(i64),
Number(f64),
String(String),
Bool(bool),
Na, HexColor(String), }
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum BinOp {
Add,
Sub,
Mul,
Div,
Mod,
Eq,
NotEq,
Less,
Greater,
LessEq,
GreaterEq,
And,
Or,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum UnOp {
Neg,
Not,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Stmt {
VarDecl {
name: String,
#[serde(skip_serializing_if = "skip_none")]
type_qualifier: Option<TypeQualifier>,
type_annotation: Option<String>,
initializer: Option<Expr>,
#[serde(default, skip_serializing_if = "VarKind::is_plain")]
var_kind: VarKind,
},
Assignment {
target: Expr, value: Expr,
},
TupleAssignment {
names: Vec<String>,
value: Expr,
},
Expression(Expr),
If {
condition: Expr,
then_branch: Vec<Stmt>,
else_if_branches: Vec<(Expr, Vec<Stmt>)>, else_branch: Option<Vec<Stmt>>,
},
For {
var_name: String,
from: Expr,
to: Expr,
body: Vec<Stmt>,
},
ForIn {
index_var: Option<String>, item_var: String,
collection: Expr,
body: Vec<Stmt>,
},
While {
condition: Expr,
body: Vec<Stmt>,
},
Break,
Continue,
TypeDecl {
name: String,
fields: Vec<TypeField>,
#[serde(default, skip_serializing_if = "is_false")]
export: bool,
},
MethodDecl {
name: String,
params: Vec<MethodParam>,
body: Vec<Stmt>,
#[serde(default, skip_serializing_if = "is_false")]
export: bool,
},
EnumDecl {
name: String,
fields: Vec<EnumField>,
#[serde(default, skip_serializing_if = "is_false")]
export: bool,
},
FunctionDecl {
name: String,
params: Vec<FunctionParam>,
body: Vec<Stmt>,
#[serde(default, skip_serializing_if = "is_false")]
export: bool,
},
Export {
item: ExportItem,
},
Import {
path: String, alias: String, },
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum ExportItem {
Type(String), Function(String), }
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct EnumField {
pub name: String,
pub title: Option<String>, }
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct MethodParam {
#[serde(skip_serializing_if = "skip_none")]
pub type_qualifier: Option<TypeQualifier>,
pub type_annotation: Option<String>, pub name: String,
pub default_value: Option<Expr>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct FunctionParam {
#[serde(skip_serializing_if = "skip_none")]
pub type_qualifier: Option<TypeQualifier>,
#[serde(skip_serializing_if = "skip_none")]
pub type_annotation: Option<String>,
pub name: String,
#[serde(skip_serializing_if = "skip_none")]
pub default_value: Option<Expr>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct TypeField {
pub name: String,
#[serde(skip_serializing_if = "skip_none")]
pub type_qualifier: Option<TypeQualifier>,
pub type_annotation: String,
pub default_value: Option<Expr>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Program {
pub statements: Vec<Stmt>,
}
impl Program {
pub fn new(statements: Vec<Stmt>) -> Self {
Self { statements }
}
}