use react_compiler_diagnostics::SourceLocation;
use crate::{
AliasingEffect, BlockId, EvaluationOrder, InstructionValue, LogicalOperator, ParamPattern,
Place, ScopeId,
};
#[derive(Debug, Clone)]
pub struct ReactiveFunction {
pub loc: Option<SourceLocation>,
pub id: Option<String>,
pub name_hint: Option<String>,
pub params: Vec<ParamPattern>,
pub generator: bool,
pub is_async: bool,
pub body: ReactiveBlock,
pub directives: Vec<String>,
}
pub type ReactiveBlock = Vec<ReactiveStatement>;
#[derive(Debug, Clone)]
pub enum ReactiveStatement {
Instruction(ReactiveInstruction),
Terminal(ReactiveTerminalStatement),
Scope(ReactiveScopeBlock),
PrunedScope(PrunedReactiveScopeBlock),
}
#[derive(Debug, Clone)]
pub struct ReactiveInstruction {
pub id: EvaluationOrder,
pub lvalue: Option<Place>,
pub value: ReactiveValue,
pub effects: Option<Vec<AliasingEffect>>,
pub loc: Option<SourceLocation>,
}
#[derive(Debug, Clone)]
pub enum ReactiveValue {
Instruction(InstructionValue),
LogicalExpression {
operator: LogicalOperator,
left: Box<ReactiveValue>,
right: Box<ReactiveValue>,
loc: Option<SourceLocation>,
},
ConditionalExpression {
test: Box<ReactiveValue>,
consequent: Box<ReactiveValue>,
alternate: Box<ReactiveValue>,
loc: Option<SourceLocation>,
},
SequenceExpression {
instructions: Vec<ReactiveInstruction>,
id: EvaluationOrder,
value: Box<ReactiveValue>,
loc: Option<SourceLocation>,
},
OptionalExpression {
id: EvaluationOrder,
value: Box<ReactiveValue>,
optional: bool,
loc: Option<SourceLocation>,
},
}
#[derive(Debug, Clone)]
pub struct ReactiveTerminalStatement {
pub terminal: ReactiveTerminal,
pub label: Option<ReactiveLabel>,
}
#[derive(Debug, Clone)]
pub struct ReactiveLabel {
pub id: BlockId,
pub implicit: bool,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ReactiveTerminalTargetKind {
Implicit,
Labeled,
Unlabeled,
}
impl std::fmt::Display for ReactiveTerminalTargetKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ReactiveTerminalTargetKind::Implicit => write!(f, "implicit"),
ReactiveTerminalTargetKind::Labeled => write!(f, "labeled"),
ReactiveTerminalTargetKind::Unlabeled => write!(f, "unlabeled"),
}
}
}
#[derive(Debug, Clone)]
pub enum ReactiveTerminal {
Break {
target: BlockId,
id: EvaluationOrder,
target_kind: ReactiveTerminalTargetKind,
loc: Option<SourceLocation>,
},
Continue {
target: BlockId,
id: EvaluationOrder,
target_kind: ReactiveTerminalTargetKind,
loc: Option<SourceLocation>,
},
Return {
value: Place,
id: EvaluationOrder,
loc: Option<SourceLocation>,
},
Throw {
value: Place,
id: EvaluationOrder,
loc: Option<SourceLocation>,
},
Switch {
test: Place,
cases: Vec<ReactiveSwitchCase>,
id: EvaluationOrder,
loc: Option<SourceLocation>,
},
DoWhile {
loop_block: ReactiveBlock,
test: ReactiveValue,
id: EvaluationOrder,
loc: Option<SourceLocation>,
},
While {
test: ReactiveValue,
loop_block: ReactiveBlock,
id: EvaluationOrder,
loc: Option<SourceLocation>,
},
For {
init: ReactiveValue,
test: ReactiveValue,
update: Option<ReactiveValue>,
loop_block: ReactiveBlock,
id: EvaluationOrder,
loc: Option<SourceLocation>,
},
ForOf {
init: ReactiveValue,
test: ReactiveValue,
loop_block: ReactiveBlock,
id: EvaluationOrder,
loc: Option<SourceLocation>,
},
ForIn {
init: ReactiveValue,
loop_block: ReactiveBlock,
id: EvaluationOrder,
loc: Option<SourceLocation>,
},
If {
test: Place,
consequent: ReactiveBlock,
alternate: Option<ReactiveBlock>,
id: EvaluationOrder,
loc: Option<SourceLocation>,
},
Label {
block: ReactiveBlock,
id: EvaluationOrder,
loc: Option<SourceLocation>,
},
Try {
block: ReactiveBlock,
handler_binding: Option<Place>,
handler: ReactiveBlock,
id: EvaluationOrder,
loc: Option<SourceLocation>,
},
}
#[derive(Debug, Clone)]
pub struct ReactiveSwitchCase {
pub test: Option<Place>,
pub block: Option<ReactiveBlock>,
}
#[derive(Debug, Clone)]
pub struct ReactiveScopeBlock {
pub scope: ScopeId,
pub instructions: ReactiveBlock,
}
#[derive(Debug, Clone)]
pub struct PrunedReactiveScopeBlock {
pub scope: ScopeId,
pub instructions: ReactiveBlock,
}