use std::{ops::{DerefMut, Deref}, fmt::Display, rc::Rc};
use crate::RantString;
#[repr(u8)]
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum PrintFlag {
None,
Hint,
Sink
}
impl PrintFlag {
#[inline]
pub fn prioritize(prev: PrintFlag, next: PrintFlag) -> PrintFlag {
match next {
PrintFlag::None => prev,
_ => next,
}
}
#[inline]
pub fn is_sink(&self) -> bool {
matches!(self, PrintFlag::Sink)
}
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct Identifier(RantString);
impl Identifier {
pub fn new(idstr: RantString) -> Self {
Self(idstr)
}
}
impl Deref for Identifier {
type Target = RantString;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl Display for Identifier {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Debug)]
pub enum VarAccessComponent {
Name(Identifier),
Index(i64),
Expression(Rc<Block>),
}
#[derive(Debug)]
pub struct VarAccessPath(Vec<VarAccessComponent>);
impl VarAccessPath {
pub fn new(parts: Vec<VarAccessComponent>) -> Self {
Self(parts)
}
pub fn dynamic_keys(&self) -> Vec<Rc<Block>> {
self.iter().filter_map(|c| {
match c {
VarAccessComponent::Expression(expr) => Some(Rc::clone(expr)),
_ => None
}
}).collect()
}
pub fn capture_var_name(&self) -> Option<Identifier> {
if self.len() > 0 {
match &self[0] {
VarAccessComponent::Name(id) => Some(id.clone()),
_ => None,
}
} else {
None
}
}
}
impl Deref for VarAccessPath {
type Target = Vec<VarAccessComponent>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for VarAccessPath {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[derive(Debug)]
pub struct Sequence(Vec<Rc<RST>>);
impl Sequence {
pub fn new(seq: Vec<Rc<RST>>) -> Self {
Self(seq)
}
pub fn one(rst: RST) -> Self {
Self(vec![Rc::new(rst)])
}
pub fn empty() -> Self {
Self::new(vec![])
}
}
impl Deref for Sequence {
type Target = Vec<Rc<RST>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Sequence {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[derive(Debug)]
pub struct Block {
pub flag: PrintFlag,
pub elements: Vec<Rc<Sequence>>
}
impl Block {
pub fn new(flag: PrintFlag, elements: Vec<Rc<Sequence>>) -> Self {
Block {
flag,
elements
}
}
#[inline]
pub fn len(&self) -> usize {
self.elements.len()
}
}
#[derive(Debug, Copy, Clone)]
pub enum Varity {
Required,
Optional,
VariadicStar,
VariadicPlus,
}
impl Varity {
pub fn is_valid_order(first: Varity, second: Varity) -> bool {
use Varity::*;
matches!((first, second),
(Required, Required) |
(Required, Optional) |
(Required, VariadicStar) |
(Required, VariadicPlus) |
(Optional, Optional) |
(Optional, VariadicStar)
)
}
pub fn is_variadic(&self) -> bool {
use Varity::*;
matches!(self, VariadicStar | VariadicPlus)
}
}
impl Display for Varity {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use Varity::*;
match self {
Required => write!(f, "required parameter"),
Optional => write!(f, "optional parameter"),
VariadicStar => write!(f, "optional variadic parameter"),
VariadicPlus => write!(f, "required variadic parameter"),
}
}
}
#[derive(Debug)]
pub struct Parameter {
pub name: Identifier,
pub varity: Varity,
}
impl Parameter {
#[inline]
pub fn is_required(&self) -> bool {
use Varity::*;
matches!(self.varity, Required | VariadicPlus)
}
}
#[derive(Debug)]
pub struct FunctionCall {
pub flag: PrintFlag,
pub id: Rc<VarAccessPath>,
pub arguments: Rc<Vec<Rc<Sequence>>>,
}
#[derive(Debug)]
pub struct FunctionDef {
pub id: Rc<VarAccessPath>,
pub params: Rc<Vec<Parameter>>,
pub capture_vars: Rc<Vec<Identifier>>,
pub body: Rc<Block>,
}
#[derive(Debug)]
pub struct ClosureExpr {
pub expr: Rc<Block>,
pub params: Rc<Vec<Parameter>>,
pub capture_vars: Rc<Vec<Identifier>>,
}
#[derive(Debug)]
pub struct AnonFunctionCall {
pub flag: PrintFlag,
pub expr: Rc<Sequence>,
pub args: Rc<Vec<Rc<Sequence>>>,
}
#[derive(Debug)]
pub enum MapKeyExpr {
Dynamic(Block),
Static(RantString),
}
#[derive(Debug)]
pub enum RST {
Nop,
Sequence(Rc<Sequence>),
Block(Block),
ListInit(Rc<Vec<Rc<Sequence>>>),
MapInit(Rc<Vec<(MapKeyExpr, Rc<Sequence>)>>),
Closure(ClosureExpr),
AnonFuncCall(AnonFunctionCall),
FuncCall(FunctionCall),
FuncDef(FunctionDef),
VarDef(Identifier, Option<Rc<Sequence>>),
VarGet(Rc<VarAccessPath>),
VarSet(Rc<VarAccessPath>, Rc<Sequence>),
Fragment(RantString),
Whitespace(RantString),
Integer(i64),
Float(f64),
Boolean(bool),
EmptyVal,
DebugInfoUpdateOuter(DebugInfo),
DebugInfoUpdateInner(DebugInfo),
}
impl RST {
pub fn display_name(&self) -> &'static str {
match self {
RST::Sequence(_) => "sequence",
RST::Block(..) => "block",
RST::ListInit(_) => "list",
RST::MapInit(_) => "map",
RST::Closure(_) => "closure",
RST::AnonFuncCall(_) => "anonymous function call",
RST::FuncCall(_) => "function call",
RST::FuncDef(_) => "function definition",
RST::Fragment(_) => "fragment",
RST::Whitespace(_) => "whitespace",
RST::Integer(_) => "integer",
RST::Float(_) => "float",
RST::Boolean(_) => "boolean",
RST::EmptyVal => "empty",
RST::Nop => "nothing",
RST::VarDef(..) => "variable definition",
RST::VarGet(_) => "variable",
RST::VarSet(..) => "variable assignment",
_ => "???"
}
}
pub fn is_printing(&self) -> bool {
matches!(self,
RST::Block(Block { flag: PrintFlag::Hint, .. }) |
RST::AnonFuncCall(AnonFunctionCall { flag: PrintFlag::Hint, .. }) |
RST::FuncCall(FunctionCall { flag: PrintFlag::Hint, .. }) |
RST::Integer(_) |
RST::Float(_) |
RST::Boolean(_) |
RST::Fragment(_) |
RST::Whitespace(_) |
RST::VarGet(_)
)
}
}
impl Display for RST {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.display_name())
}
}
#[derive(Debug)]
pub enum DebugInfo {
Location { line: usize, col: usize },
SourceName(RantString),
ScopeName(RantString),
}