use crate::data::tokens::*;
use crate::data::{ArgsType, Literal, Position};
use std::cmp::Ordering;
use std::collections::HashMap;
use std::fmt::{Debug, Display, Formatter};
use std::hash::{Hash, Hasher};
#[derive(Debug, Clone)]
pub struct Flow {
pub flow_instructions: HashMap<InstructionScope, Expr>,
pub flow_type: FlowType,
}
#[derive(PartialEq, Debug, Clone)]
pub enum FlowType {
Normal,
}
#[derive(Debug, Clone)]
pub struct ImportScope {
pub name: String,
pub original_name: Option<String>,
pub from_flow: Option<String>,
pub position: Position,
}
impl Hash for ImportScope {
fn hash<H: Hasher>(&self, state: &mut H) {
self.name.hash(state);
}
}
impl PartialEq for ImportScope {
fn eq(&self, other: &Self) -> bool {
self.name == other.name
}
}
impl Eq for ImportScope {}
#[derive(Debug, Clone)]
pub enum InstructionScope {
StepScope(String),
FunctionScope { name: String, args: Vec<String> },
ImportScope(ImportScope),
}
impl Hash for InstructionScope {
fn hash<H: Hasher>(&self, state: &mut H) {
match self {
InstructionScope::StepScope(name) => name.hash(state),
InstructionScope::FunctionScope { name, .. } => name.hash(state),
InstructionScope::ImportScope(import_scope) => import_scope.hash(state),
}
}
}
impl PartialEq for InstructionScope {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(InstructionScope::StepScope(name1), InstructionScope::StepScope(name2)) => {
name1 == name2
}
(
InstructionScope::FunctionScope { name: name1, .. },
InstructionScope::FunctionScope { name: name2, .. },
) => name1 == name2,
(
InstructionScope::ImportScope(import_scope1),
InstructionScope::ImportScope(import_scope2),
) => import_scope1 == import_scope2,
_ => false,
}
}
}
impl Eq for InstructionScope {}
impl Display for InstructionScope {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
match self {
InstructionScope::StepScope(ref idents) => write!(f, "{}", idents),
InstructionScope::FunctionScope { name, .. } => write!(f, "{}", name),
InstructionScope::ImportScope(ImportScope {
name,
original_name: _,
from_flow,
..
}) => write!(f, "import {} from {:?} ", name, from_flow),
}
}
}
#[derive(Debug, Clone)]
pub struct Instruction {
pub instruction_type: InstructionScope,
pub actions: Expr,
}
#[derive(PartialEq, Debug, Clone)]
pub enum GotoType {
Step(String),
Flow(String),
StepFlow { step: String, flow: String },
}
#[derive(Debug, Clone)]
pub enum DoType {
Update(Box<Expr>, Box<Expr>),
Exec(Box<Expr>),
}
#[derive(Debug, Clone)]
pub struct Function {
pub name: String,
pub interval: Interval,
pub args: Box<Expr>,
}
#[derive(Debug, Clone)]
pub enum ObjectType {
Goto(GotoType, Interval),
Hold(Interval),
Say(Box<Expr>),
Return(Box<Expr>),
Do(DoType),
Use(Box<Expr>),
Remember(Identifier, Box<Expr>),
Assign(Box<Expr>, Box<Expr>),
As(Identifier, Box<Expr>),
Import {
step_name: Identifier,
as_name: Option<Identifier>,
file_path: Option<Identifier>,
},
Normal(Function),
Break(Interval),
}
#[derive(PartialEq, Debug, Clone)]
pub struct InstructionInfo {
pub index: usize,
pub total: usize,
}
#[derive(Debug, Clone)]
pub struct Block {
pub commands: Vec<(Expr, InstructionInfo)>,
pub hooks: Vec<Hook>,
}
#[derive(PartialEq, Debug, Clone)]
pub struct Hook {
pub index: i64,
pub name: String,
pub step: String,
}
impl Default for Block {
fn default() -> Self {
Self {
commands: Vec::new(),
hooks: Vec::new(),
}
}
}
#[derive(PartialEq, Debug, Clone)]
pub enum BlockType {
LoopBlock,
Block,
IfLoop,
Step,
Function,
}
#[derive(Debug, Clone)]
pub enum IfStatement {
IfStmt {
cond: Box<Expr>,
consequence: Block,
then_branch: Option<(Box<IfStatement>, InstructionInfo)>,
},
ElseStmt(Block, RangeInterval),
}
#[derive(Debug, Clone)]
pub enum Expr {
Scope {
block_type: BlockType,
scope: Block,
range: RangeInterval,
},
ForEachExpr(
Identifier,
Option<Identifier>,
Box<Expr>,
Block,
RangeInterval,
),
ComplexLiteral(Vec<Expr>, RangeInterval),
MapExpr(HashMap<String, Expr>, RangeInterval),
VecExpr(Vec<Expr>, RangeInterval),
InfixExpr(Infix, Box<Expr>, Box<Expr>),
ObjectExpr(ObjectType),
IfExpr(IfStatement),
PathExpr {
literal: Box<Expr>,
path: Vec<(Interval, PathState)>,
},
IdentExpr(Identifier),
LitExpr(Literal),
}
impl Expr {
pub fn new_idents(ident: String, interval: Interval) -> Identifier {
Identifier { ident, interval }
}
}
#[derive(PartialEq, Debug, Clone)]
pub enum Infix {
Addition,
Subtraction,
Divide,
Multiply,
Remainder,
Not,
Match,
NotMatch,
Equal,
NotEqual,
GreaterThanEqual,
LessThanEqual,
GreaterThan,
LessThan,
And,
Or,
}
#[derive(PartialEq, Debug, Clone, Eq, Hash)]
pub struct RangeInterval {
pub start: Interval,
pub end: Interval,
}
impl RangeInterval {
pub fn new(start: Interval, end: Interval) -> Self {
Self { start, end }
}
}
#[derive(PartialEq, Debug, Clone, Eq, Hash, Copy)]
pub struct Interval {
pub line: u32,
pub column: u32,
}
impl Default for Interval {
fn default() -> Self {
Self { line: 0, column: 0 }
}
}
impl Interval {
pub fn new_as_u32(line: u32, column: u32) -> Self {
Self { line, column }
}
pub fn new_as_span(span: Span) -> Self {
Self {
line: span.location_line(),
column: span.get_column() as u32,
}
}
}
#[derive(Debug, Clone)]
pub enum PathState {
ExprIndex(Expr),
StringIndex(String),
Func(Function),
}
#[derive(Debug, Clone)]
pub enum PathLiteral {
VecIndex(usize),
MapIndex(String),
Func {
name: String,
interval: Interval,
args: ArgsType,
},
}
#[derive(Debug, Clone)]
pub struct Identifier {
pub ident: String,
pub interval: Interval,
}
impl Identifier {
pub fn new(ident: &str, interval: Interval) -> Self {
Self {
ident: ident.to_string(),
interval,
}
}
}
impl PartialEq for Identifier {
fn eq(&self, other: &Self) -> bool {
self.ident == other.ident
}
}
impl PartialOrd for Identifier {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.ident.partial_cmp(&other.ident)
}
}