use std::{
fmt::{ Debug, Formatter, Result as FMTResult, },
ops::{ Deref, },
};
use crate::{
common::{ Operator, Number, },
source::{ SourceRegion, },
ctx::{ GlobalKey, LocalItem, },
};
#[derive(Clone)]
#[allow(missing_docs)]
pub struct Block {
pub statements: Vec<Statement>,
pub trailing_expression: Option<Expression>,
pub origin: SourceRegion,
}
impl Debug for Block {
#[inline] fn fmt (&self, f: &mut Formatter) -> FMTResult {
f.debug_struct("Block")
.field("statements", &self.statements)
.field("trailing_expression", &self.trailing_expression)
.finish()
}
}
impl PartialEq for Block {
#[inline] fn eq (&self, other: &Self) -> bool { self.statements == other.statements && self.trailing_expression == other.trailing_expression }
}
impl Block {
pub fn new (statements: Vec<Statement>, trailing_expression: Option<Expression>, origin: SourceRegion) -> Self {
Self { statements, trailing_expression, origin }
}
pub fn no_src (statements: Vec<Statement>, trailing_expression: Option<Expression>) -> Self {
Self { statements, trailing_expression, origin: SourceRegion::ANONYMOUS }
}
pub fn is_expression (&self) -> bool {
self.trailing_expression.is_some()
}
}
#[derive(Clone)]
#[allow(missing_docs)]
pub struct ConditionalBranch {
pub condition: Expression,
pub body: Block,
pub origin: SourceRegion,
}
impl Debug for ConditionalBranch {
#[inline] fn fmt (&self, f: &mut Formatter) -> FMTResult {
f.debug_struct("ConditionalBranch")
.field("condition", &self.condition)
.field("body", &self.body)
.finish()
}
}
impl PartialEq for ConditionalBranch { #[inline] fn eq (&self, other: &Self) -> bool { self.condition == other.condition && self.body == other.body } }
impl ConditionalBranch {
pub fn new (condition: Expression, body: Block, origin: SourceRegion) -> Self {
Self { condition, body, origin }
}
pub fn no_src (condition: Expression, body: Block) -> Self {
Self { condition, body, origin: SourceRegion::ANONYMOUS }
}
pub fn is_expression (&self) -> bool {
self.body.is_expression()
}
}
#[derive(Clone)]
#[allow(missing_docs)]
pub struct Conditional {
pub if_branch: ConditionalBranch,
pub else_if_branches: Vec<ConditionalBranch>,
pub else_block: Option<Block>,
pub origin: SourceRegion,
}
impl Debug for Conditional {
#[inline]
fn fmt (&self, f: &mut Formatter) -> FMTResult {
f.debug_struct("Conditional")
.field("if_branch", &self.if_branch)
.field("else_if_branches", &self.else_if_branches)
.field("else_block", &self.else_block)
.finish()
}
}
impl PartialEq for Conditional {
#[inline] fn eq (&self, other: &Self) -> bool { self.if_branch == other.if_branch && self.else_if_branches == other.else_if_branches && self.else_block == other.else_block }
}
impl Conditional {
pub fn new (if_branch: ConditionalBranch, else_if_branches: Vec<ConditionalBranch>, else_block: Option<Block>, origin: SourceRegion) -> Self {
Self { if_branch, else_if_branches, else_block, origin }
}
pub fn no_src (if_branch: ConditionalBranch, else_if_branches: Vec<ConditionalBranch>, else_block: Option<Block>) -> Self {
Self { if_branch, else_if_branches, else_block, origin: SourceRegion::ANONYMOUS }
}
pub fn is_expression (&self) -> bool {
self.if_branch.is_expression()
}
}
#[allow(missing_docs)]
#[derive(Debug, Clone, PartialEq)]
pub enum StatementData {
Expression(Expression),
Declaration { ty: GlobalKey, initializer: Option<Expression> },
Assignment { target: Expression, value: Expression },
ModAssignment { target: Expression, value: Expression, operator: Operator },
Return(Option<Expression>),
Block(Box<Block>),
Conditional(Box<Conditional>),
}
impl StatementData {
pub fn is_expression (&self) -> bool {
matches!(self, StatementData::Expression(_))
}
}
#[derive(Clone)]
#[allow(missing_docs)]
pub struct Statement {
pub data: StatementData,
pub origin: SourceRegion,
}
impl Debug for Statement { #[inline] fn fmt (&self, f: &mut Formatter) -> FMTResult { self.data.fmt(f) } }
impl PartialEq for Statement { #[inline] fn eq (&self, other: &Self) -> bool { self.data == other.data } }
impl Deref for Statement {
type Target = StatementData;
#[inline] fn deref (&self) -> &Self::Target { &self.data }
}
impl Statement {
pub fn new (data: StatementData, origin: SourceRegion) -> Self {
Self { data, origin }
}
pub fn no_src (data: StatementData) -> Self {
Self { data, origin: SourceRegion::ANONYMOUS }
}
}
#[allow(missing_docs)]
#[derive(Debug, Clone, PartialEq)]
pub enum Reference {
Global(GlobalKey),
Local { is_parameter: bool, index: usize },
}
impl From<GlobalKey> for Reference { #[inline] fn from (key: GlobalKey) -> Self { Self::Global(key) } }
impl From<&LocalItem> for Reference { #[inline] fn from (local: &LocalItem) -> Self { Self::Local { is_parameter: local.is_parameter, index: local.index } } }
#[allow(missing_docs)]
#[derive(Debug, Clone, PartialEq)]
pub enum ExpressionData {
Coerce(Box<Expression>),
Reference(Reference),
Number(Number),
Unary {
operand: Box<Expression>,
operator: Operator,
},
Binary {
left: Box<Expression>,
right: Box<Expression>,
operator: Operator,
},
Call { callee: Box<Expression>, arguments: Vec<Expression> },
Block(Box<Block>),
Conditional(Box<Conditional>),
}
#[derive(Clone)]
#[allow(missing_docs)]
pub struct Expression {
pub data: ExpressionData,
pub ty: GlobalKey,
pub origin: SourceRegion,
}
impl Debug for Expression {
#[inline] fn fmt (&self, f: &mut Formatter) -> FMTResult {
f.debug_struct("")
.field("data", &self.data)
.field("ty", &self.ty)
.finish()
}
}
impl PartialEq for Expression { #[inline] fn eq (&self, other: &Self) -> bool { self.data == other.data } }
impl Deref for Expression {
type Target = ExpressionData;
#[inline] fn deref (&self) -> &Self::Target { &self.data }
}
impl Expression {
pub fn new (data: ExpressionData, ty: GlobalKey, origin: SourceRegion) -> Self {
Self { data, ty, origin }
}
pub fn no_src (data: ExpressionData, ty: GlobalKey) -> Self {
Self { data, ty, origin: SourceRegion::ANONYMOUS }
}
}