use crate::lexer::Span;
#[derive(Debug, Clone)]
pub struct Program {
pub uses: Vec<UseStmt>,
pub decl: TopLevelDecl,
pub span: Span,
pub path: String,
}
#[derive(Debug, Clone)]
pub struct UseStmt {
pub path: String,
pub alias: Option<String>,
pub imports: Vec<String>,
pub deferred: bool,
pub span: Span,
}
#[derive(Debug, Clone)]
pub enum TopLevelDecl {
Plugin(PluginDecl),
Writer(WriterDecl),
Interface(InterfaceDecl),
Module(ModuleDecl),
}
#[derive(Debug, Clone)]
pub struct ModuleDecl {
pub items: Vec<PluginItem>,
pub span: Span,
pub path: String,
}
#[derive(Debug, Clone)]
pub struct PluginDecl {
pub name: String,
pub body: Vec<PluginItem>,
pub span: Span,
pub path: String,
}
#[derive(Debug, Clone)]
pub struct WriterDecl {
pub name: String,
pub body: Vec<PluginItem>,
pub span: Span,
pub path: String,
}
#[derive(Debug, Clone)]
pub enum PluginItem {
Struct(StructDecl),
Enum(EnumDecl),
Function(FnDecl),
Impl(ImplBlock),
PreHook(FnDecl), ExitHook(FnDecl), Static(StaticDecl), PubUse(UseStmt), }
#[derive(Debug, Clone)]
pub struct StaticDecl {
pub name: String,
pub ty: Type,
pub init: Expr,
pub is_mut: bool,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct StructDecl {
pub is_pub: bool,
pub name: String,
pub fields: Vec<StructField>,
pub derives: Vec<String>, pub lifetimes: Vec<String>, pub span: Span,
pub path: String,
}
#[derive(Debug, Clone)]
pub struct StructField {
pub is_pub: bool,
pub name: String,
pub ty: Type,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct EnumDecl {
pub is_pub: bool,
pub name: String,
pub variants: Vec<EnumVariant>,
pub derives: Vec<String>, pub span: Span,
pub path: String,
}
#[derive(Debug, Clone)]
pub enum EnumVariantFields {
Tuple(Vec<Type>),
Struct(Vec<(String, Type)>),
Unit,
}
#[derive(Debug, Clone)]
pub struct EnumVariant {
pub name: String,
pub fields: EnumVariantFields,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct FnDecl {
pub is_pub: bool,
pub name: String,
pub type_params: Vec<GenericParam>, pub params: Vec<Param>,
pub return_type: Option<Type>,
pub where_clause: Vec<WherePredicate>, pub body: Block,
pub span: Span,
pub path: String,
}
#[derive(Debug, Clone)]
pub struct GenericParam {
pub name: String,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct WherePredicate {
pub target: String, pub bound: Type, pub span: Span,
}
#[derive(Debug, Clone)]
pub struct Param {
pub name: String,
pub ty: Type,
pub span: Span,
pub path: String,
}
#[derive(Debug, Clone)]
pub struct ImplBlock {
pub target: String,
pub items: Vec<FnDecl>,
pub span: Span,
pub path: String,
}
#[derive(Debug, Clone)]
pub enum Type {
Primitive(String),
Reference {
mutable: bool,
inner: Box<Type>,
},
Container {
name: String,
type_args: Vec<Type>,
},
Named(String),
Array { element: Box<Type> },
Tuple(Vec<Type>),
Optional(Box<Type>),
Unit,
FnTrait {
params: Vec<Type>,
return_type: Box<Type>,
},
RawPointer {
mutable: bool,
inner: Box<Type>,
},
AstNode(String),
}
impl Type {
pub fn to_ts_type(&self) -> TsType {
match self {
Type::Primitive(name) => match name.as_str() {
"Str" | "String" | "str" => TsType::String,
"i32" | "i64" | "u32" | "u64" | "usize" | "isize" | "f32" | "f64" => TsType::Number,
"bool" => TsType::Boolean,
"()" => TsType::Void,
_ => TsType::TypeReference {
name: name.clone(),
type_args: vec![],
},
},
Type::Reference { inner, .. } => inner.to_ts_type(),
Type::Container { name, type_args } => TsType::TypeReference {
name: name.clone(),
type_args: type_args.iter().map(|t| t.to_ts_type()).collect(),
},
Type::Named(name) => {
if name == "_" {
TsType::Any
} else {
TsType::TypeReference {
name: name.clone(),
type_args: vec![],
}
}
}
Type::Array { element } => TsType::Array(Box::new(element.to_ts_type())),
Type::Tuple(elements) => TsType::Tuple(elements.iter().map(|t| t.to_ts_type()).collect()),
Type::Optional(inner) => {
TsType::Union(vec![
inner.to_ts_type(),
TsType::Null,
TsType::Undefined,
])
}
Type::Unit => TsType::Void,
Type::FnTrait { params, return_type } => TsType::FunctionType {
params: params.iter().map(|t| t.to_ts_type()).collect(),
return_type: Box::new(return_type.to_ts_type()),
},
Type::RawPointer { inner, .. } => {
inner.to_ts_type()
}
Type::AstNode(name) => {
TsType::TypeReference {
name: name.clone(),
type_args: vec![],
}
}
}
}
}
#[derive(Debug, Clone)]
pub enum TsType {
String,
Number,
Boolean,
Any,
Void,
Null,
Undefined,
Never,
Unknown,
Array(Box<TsType>),
Tuple(Vec<TsType>),
Union(Vec<TsType>),
Intersection(Vec<TsType>),
TypeReference {
name: String,
type_args: Vec<TsType>,
},
FunctionType {
params: Vec<TsType>,
return_type: Box<TsType>,
},
LiteralString(String),
LiteralNumber(f64),
LiteralBoolean(bool),
}
impl TsType {
pub fn to_reluxscript_type(&self) -> Type {
match self {
TsType::String => Type::Primitive("Str".to_string()),
TsType::Number => Type::Primitive("f64".to_string()),
TsType::Boolean => Type::Primitive("bool".to_string()),
TsType::Array(inner) => Type::Container {
name: "Vec".to_string(),
type_args: vec![inner.to_reluxscript_type()],
},
TsType::TypeReference { name, type_args } => {
if type_args.is_empty() {
Type::Named(name.clone())
} else {
Type::Container {
name: name.clone(),
type_args: type_args.iter().map(|t| t.to_reluxscript_type()).collect(),
}
}
}
TsType::Void => Type::Unit,
TsType::Null | TsType::Undefined => Type::Named("None".to_string()),
_ => Type::Named("dynamic".to_string()),
}
}
}
#[derive(Debug, Clone)]
pub struct InterfaceDecl {
pub name: String,
pub members: Vec<InterfaceMember>,
pub extends: Vec<String>,
pub type_params: Vec<TypeParam>,
pub span: Span,
}
#[derive(Debug, Clone)]
pub enum InterfaceMember {
Property(PropertySignature),
Method(MethodSignature),
Index(IndexSignature),
}
#[derive(Debug, Clone)]
pub struct PropertySignature {
pub key: String,
pub type_annotation: Option<TsType>,
pub optional: bool,
pub readonly: bool,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct MethodSignature {
pub name: String,
pub params: Vec<TsType>,
pub return_type: Option<TsType>,
pub optional: bool,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct IndexSignature {
pub key_name: String,
pub key_type: TsType,
pub value_type: TsType,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct TypeParam {
pub name: String,
pub constraint: Option<TsType>,
pub default: Option<TsType>,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct TemplateElement {
pub raw: String,
pub cooked: Option<String>,
pub tail: bool,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct Block {
pub stmts: Vec<Stmt>,
pub span: Span,
pub path: String,
}
#[derive(Debug, Clone)]
pub enum Stmt {
Let(LetStmt),
Const(ConstStmt),
Expr(ExprStmt),
If(IfStmt),
Match(MatchStmt),
For(ForStmt),
While(WhileStmt),
Loop(LoopStmt),
Return(ReturnStmt),
Break(BreakStmt),
Continue(ContinueStmt),
Traverse(TraverseStmt),
Function(FnDecl), Verbatim(VerbatimStmt), CustomPropAssignment(CustomPropAssignment), Unsafe(UnsafeBlock), }
#[derive(Debug, Clone)]
pub struct UnsafeBlock {
pub body: Block,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct LetStmt {
pub mutable: bool,
pub pattern: Pattern, pub ty: Option<Type>,
pub init: Option<Expr>, pub span: Span,
pub path: String,
}
#[derive(Debug, Clone)]
pub struct ConstStmt {
pub name: String,
pub ty: Option<Type>,
pub init: Expr,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct ExprStmt {
pub expr: Expr,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct IfStmt {
pub condition: Expr,
pub pattern: Option<Pattern>,
pub then_branch: Block,
pub else_if_branches: Vec<(Expr, Block)>,
pub else_branch: Option<Block>,
pub span: Span,
pub path: String,
}
#[derive(Debug, Clone)]
pub struct MatchStmt {
pub scrutinee: Expr,
pub arms: Vec<MatchArm>,
pub span: Span,
pub path: String,
}
#[derive(Debug, Clone)]
pub struct MatchArm {
pub pattern: Pattern,
pub body: Expr,
pub span: Span,
pub path: String,
}
#[derive(Debug, Clone)]
pub enum Pattern {
Literal(Literal),
Ident(String),
Wildcard,
Tuple(Vec<Pattern>),
Struct {
name: String,
fields: Vec<(String, Pattern)>,
},
Variant {
name: String,
inner: Option<Box<Pattern>>,
},
Array(Vec<Pattern>),
Object(Vec<ObjectPatternProp>),
Rest(Box<Pattern>),
Or(Vec<Pattern>),
Ref {
is_mut: bool,
pattern: Box<Pattern>,
},
}
#[derive(Debug, Clone)]
pub enum ObjectPatternProp {
Shorthand(String),
KeyValue { key: String, value: Pattern },
Rest(String),
Or(Vec<Pattern>),
}
#[derive(Debug, Clone)]
pub struct ForStmt {
pub pattern: Pattern, pub iter: Expr,
pub body: Block,
pub span: Span,
pub path: String,
}
#[derive(Debug, Clone)]
pub struct WhileStmt {
pub condition: Expr,
pub body: Block,
pub span: Span,
pub path: String,
}
#[derive(Debug, Clone)]
pub struct LoopStmt {
pub body: Block,
pub span: Span,
pub path: String,
}
#[derive(Debug, Clone)]
pub struct ReturnStmt {
pub value: Option<Expr>,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct BreakStmt {
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct ContinueStmt {
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct VerbatimStmt {
pub target: VerbatimTarget,
pub code: String,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum VerbatimTarget {
JavaScript,
Rust,
}
#[derive(Debug, Clone)]
pub struct CustomPropAssignment {
pub node: Box<Expr>,
pub property: String,
pub value: Box<Expr>,
pub ty: Option<Type>,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct TraverseStmt {
pub target: Expr,
pub captures: Vec<Capture>,
pub kind: TraverseKind,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct Capture {
pub name: String,
pub mutable: bool,
pub span: Span,
}
#[derive(Debug, Clone)]
pub enum TraverseKind {
Inline(InlineVisitor),
Delegated(String),
}
#[derive(Debug, Clone)]
pub struct InlineVisitor {
pub state: Vec<LetStmt>,
pub methods: Vec<FnDecl>,
pub span: Span,
}
impl TraverseStmt {
pub fn span(&self) -> Span {
self.span
}
}
#[derive(Debug, Clone)]
pub enum Expr {
Literal(Literal),
Ident(IdentExpr),
Binary(BinaryExpr),
Unary(UnaryExpr),
Call(CallExpr),
Member(MemberExpr),
Index(IndexExpr),
StructInit(StructInitExpr),
VecInit(VecInitExpr),
If(Box<IfExpr>),
Match(Box<MatchExpr>),
Closure(ClosureExpr),
Ref(RefExpr),
Deref(DerefExpr),
Assign(AssignExpr),
CompoundAssign(CompoundAssignExpr),
Range(RangeExpr),
Paren(Box<Expr>),
Block(Block),
Try(Box<Expr>),
Tuple(Vec<Expr>),
Matches(MatchesExpr),
RegexCall(RegexCall),
CustomPropAccess(CustomPropAccess),
Return(Option<Box<Expr>>),
Break,
Continue,
Path(PathExpr),
}
#[derive(Debug, Clone)]
pub struct PathExpr {
pub segments: Vec<String>,
pub span: Span,
pub path: String,
}
#[derive(Debug, Clone)]
pub enum Literal {
String(String),
Int(i64),
Float(f64),
Bool(bool),
Null,
Unit,
}
#[derive(Debug, Clone)]
pub struct IdentExpr {
pub name: String,
pub span: Span,
pub path: String,
}
#[derive(Debug, Clone)]
pub struct BinaryExpr {
pub op: BinaryOp,
pub left: Box<Expr>,
pub right: Box<Expr>,
pub span: Span,
pub path: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BinaryOp {
Add,
Sub,
Mul,
Div,
Mod,
Eq,
NotEq,
Lt,
Gt,
LtEq,
GtEq,
And,
Or,
NullCoalesce,
}
#[derive(Debug, Clone)]
pub struct UnaryExpr {
pub op: UnaryOp,
pub operand: Box<Expr>,
pub span: Span,
pub path: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UnaryOp {
Neg,
Not,
Deref,
Ref,
RefMut,
}
#[derive(Debug, Clone)]
pub struct CallExpr {
pub callee: Box<Expr>,
pub args: Vec<Expr>,
pub type_args: Vec<TsType>,
pub optional: bool,
pub is_macro: bool,
pub span: Span,
pub path: String,
}
#[derive(Debug, Clone)]
pub struct MemberExpr {
pub object: Box<Expr>,
pub property: String,
pub optional: bool,
pub computed: bool,
pub is_path: bool,
pub span: Span,
pub path: String,
}
#[derive(Debug, Clone)]
pub struct IndexExpr {
pub object: Box<Expr>,
pub index: Box<Expr>,
pub span: Span,
pub path: String,
}
#[derive(Debug, Clone)]
pub struct StructInitExpr {
pub name: String,
pub fields: Vec<(String, Expr)>,
pub span: Span,
pub path: String,
}
#[derive(Debug, Clone)]
pub struct VecInitExpr {
pub elements: Vec<Expr>,
pub span: Span,
pub path: String,
}
#[derive(Debug, Clone)]
pub struct IfExpr {
pub condition: Expr,
pub pattern: Option<Pattern>,
pub then_branch: Block,
pub else_branch: Option<Block>,
pub span: Span,
pub path: String,
}
#[derive(Debug, Clone)]
pub struct MatchExpr {
pub scrutinee: Expr,
pub arms: Vec<MatchArm>,
pub span: Span,
pub path: String,
}
#[derive(Debug, Clone)]
pub struct MatchesExpr {
pub scrutinee: Box<Expr>,
pub pattern: Pattern,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct RegexCall {
pub method: RegexMethod,
pub text_arg: Box<Expr>,
pub pattern_arg: String, pub replacement_arg: Option<Box<Expr>>, pub span: Span,
}
#[derive(Debug, Clone)]
pub struct CustomPropAccess {
pub node: Box<Expr>,
pub property: String,
pub span: Span,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RegexMethod {
Matches,
Find,
FindAll,
Captures,
Replace,
ReplaceAll,
}
#[derive(Debug, Clone)]
pub struct ClosureExpr {
pub params: Vec<ClosureParam>,
pub body: Box<Expr>,
pub span: Span,
pub path: String,
}
#[derive(Debug, Clone)]
pub enum ClosureParam {
Ident(String),
Tuple(Vec<String>),
Typed { name: String, ty: Type },
}
#[derive(Debug, Clone)]
pub struct RefExpr {
pub mutable: bool,
pub expr: Box<Expr>,
pub span: Span,
pub path: String,
}
#[derive(Debug, Clone)]
pub struct DerefExpr {
pub expr: Box<Expr>,
pub span: Span,
pub path: String,
}
#[derive(Debug, Clone)]
pub struct AssignExpr {
pub target: Box<Expr>,
pub value: Box<Expr>,
pub span: Span,
pub path: String,
}
#[derive(Debug, Clone)]
pub struct CompoundAssignExpr {
pub op: CompoundAssignOp,
pub target: Box<Expr>,
pub value: Box<Expr>,
pub span: Span,
pub path: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CompoundAssignOp {
AddAssign,
SubAssign,
MulAssign,
DivAssign,
}
#[derive(Debug, Clone)]
pub struct RangeExpr {
pub start: Option<Box<Expr>>,
pub end: Option<Box<Expr>>,
pub inclusive: bool,
pub span: Span,
pub path: String,
}