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 AccessPathComponent {
Name(Identifier),
Index(i64),
Expression(Rc<Sequence>),
}
impl Display for AccessPathComponent {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
AccessPathComponent::Name(name) => write!(f, "{}", name),
AccessPathComponent::Index(i) => write!(f, "{}", i),
AccessPathComponent::Expression(expr) => write!(f, "{{{}...}}", expr.name().map(|name| name.as_str()).unwrap_or("")),
}
}
}
#[derive(Debug, Copy, Clone)]
pub enum AccessPathKind {
Local,
ExplicitGlobal,
Descope(usize),
}
impl AccessPathKind {
pub fn descope_count(&self) -> usize {
match self {
AccessPathKind::Local | AccessPathKind::ExplicitGlobal => 0,
AccessPathKind::Descope(n) => *n
}
}
}
#[derive(Debug)]
pub struct AccessPath {
path: Vec<AccessPathComponent>,
kind: AccessPathKind,
}
impl AccessPath {
#[inline]
pub fn new(path: Vec<AccessPathComponent>, kind: AccessPathKind) -> Self {
Self {
path,
kind
}
}
#[inline]
pub fn is_explicit_global(&self) -> bool {
matches!(self.kind, AccessPathKind::ExplicitGlobal)
}
#[inline]
pub fn kind(&self) -> AccessPathKind {
self.kind
}
#[inline]
pub fn dynamic_keys(&self) -> Vec<Rc<Sequence>> {
self.iter().filter_map(|c| {
match c {
AccessPathComponent::Expression(expr) => Some(Rc::clone(expr)),
_ => None
}
}).collect()
}
#[inline]
pub fn capture_var_name(&self) -> Option<Identifier> {
if let Some(AccessPathComponent::Name(id)) = self.first() {
Some(id.clone())
} else {
None
}
}
}
impl Deref for AccessPath {
type Target = Vec<AccessPathComponent>;
fn deref(&self) -> &Self::Target {
&self.path
}
}
impl DerefMut for AccessPath {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.path
}
}
impl Display for AccessPath {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.iter().map(|part| part.to_string()).collect::<Vec<String>>().join("/"))
}
}
#[derive(Debug)]
pub struct Sequence {
elements: Vec<Rc<RST>>,
name: Option<RantString>,
}
impl Sequence {
pub fn new(seq: Vec<Rc<RST>>) -> Self {
Self {
elements: seq,
name: None,
}
}
pub fn one(rst: RST) -> Self {
Self {
elements: vec![Rc::new(rst)],
name: None,
}
}
pub fn empty() -> Self {
Self::new(vec![])
}
#[inline(always)]
pub fn with_name(mut self, name: RantString) -> Self {
self.name = Some(name);
self
}
#[inline(always)]
pub fn with_name_str(mut self, name: &str) -> Self {
self.name = Some(RantString::from(name));
self
}
pub fn name(&self) -> Option<&RantString> {
self.name.as_ref()
}
}
impl Deref for Sequence {
type Target = Vec<Rc<RST>>;
fn deref(&self) -> &Self::Target {
&self.elements
}
}
impl DerefMut for Sequence {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.elements
}
}
#[derive(Debug)]
pub struct Block {
pub flag: PrintFlag,
pub elements: Rc<Vec<Rc<Sequence>>>
}
impl Block {
pub fn new(flag: PrintFlag, elements: Vec<Rc<Sequence>>) -> Self {
Block {
flag,
elements: Rc::new(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<AccessPath>,
pub arguments: Rc<Vec<Rc<Sequence>>>,
}
#[derive(Debug)]
pub struct FunctionDef {
pub id: Rc<AccessPath>,
pub params: Rc<Vec<Parameter>>,
pub capture_vars: Rc<Vec<Identifier>>,
pub body: Rc<Sequence>,
}
#[derive(Debug)]
pub struct ClosureExpr {
pub expr: Rc<Sequence>,
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(Rc<Sequence>),
Static(RantString),
}
#[derive(Debug)]
pub enum RST {
Nop,
Sequence(Rc<Sequence>),
Block(Block),
BlockValue(Rc<Block>),
ListInit(Rc<Vec<Rc<Sequence>>>),
MapInit(Rc<Vec<(MapKeyExpr, Rc<Sequence>)>>),
Closure(ClosureExpr),
AnonFuncCall(AnonFunctionCall),
FuncCall(FunctionCall),
FuncDef(FunctionDef),
VarDef(Identifier, AccessPathKind, Option<Rc<Sequence>>),
VarGet(Rc<AccessPath>),
VarSet(Rc<AccessPath>, 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),
}