robinpath 0.2.0

RobinPath - A lightweight, fast scripting language interpreter for automation and data processing
Documentation
use super::expr::Expr;
use super::span::Span;
use crate::value::AttributePathSegment;
use serde::{Deserialize, Serialize};

/// An argument in a command call. Can be an expression or a named argument.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Arg {
    Expr(Expr),
    Named { name: String, value: Expr },
}

/// Into target for command results
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct IntoTarget {
    pub name: String,
    pub path: Vec<AttributePathSegment>,
    pub span: Span,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Stmt {
    /// Command call: funcName arg1 arg2 [into $var]
    Command {
        name: String,
        args: Vec<Arg>,
        into: Option<IntoTarget>,
        span: Span,
    },

    /// Variable assignment: $var = expr
    Assignment {
        target_name: String,
        target_path: Vec<AttributePathSegment>,
        value: Expr,
        is_set: bool,
        is_var: bool,
        is_const: bool,
        fallback: Option<Expr>,
        span: Span,
    },

    /// If block: if cond ... elseif ... else ... endif
    IfBlock {
        condition: Expr,
        then_branch: Vec<Stmt>,
        elseif_branches: Vec<ElseIfBranch>,
        else_branch: Option<Vec<Stmt>>,
        span: Span,
    },

    /// Inline if: if cond then command [else command]
    InlineIf {
        condition: Expr,
        command: Box<Stmt>,
        else_command: Option<Box<Stmt>>,
        span: Span,
    },

    /// iftrue command
    IfTrue {
        command: Box<Stmt>,
        span: Span,
    },

    /// iffalse command
    IfFalse {
        command: Box<Stmt>,
        span: Span,
    },

    /// For loop: for $v in expr / for $v from N to M [by S]
    ForLoop {
        var_name: String,
        iterable: Option<Expr>,
        from: Option<Expr>,
        to: Option<Expr>,
        step: Option<Expr>,
        key_var_name: Option<String>,
        body: Vec<Stmt>,
        span: Span,
    },

    /// Function definition: def name $param1 $param2 ... enddef
    Define {
        name: String,
        param_names: Vec<String>,
        body: Vec<Stmt>,
        span: Span,
    },

    /// Scope block: do [$param1 $param2] ... enddo [into $var]
    ScopeBlock {
        param_names: Vec<String>,
        body: Vec<Stmt>,
        into: Option<IntoTarget>,
        span: Span,
    },

    /// Repeat block: repeat N with ... endwith [into $var]
    RepeatBlock {
        count: Expr,
        body: Vec<Stmt>,
        into: Option<IntoTarget>,
        span: Span,
    },

    /// Together block: together ... endtogether
    TogetherBlock {
        blocks: Vec<Stmt>, // Each must be ScopeBlock
        span: Span,
    },

    /// Event handler: on eventName ... endon
    OnBlock {
        event_name: String,
        body: Vec<Stmt>,
        span: Span,
    },

    /// Return statement
    Return {
        value: Option<Expr>,
        span: Span,
    },

    /// Break statement
    Break {
        span: Span,
    },

    /// Continue statement
    Continue {
        span: Span,
    },

    /// Comment
    Comment {
        text: String,
        span: Span,
    },

    /// Chunk marker: --- chunk:name ---
    ChunkMarker {
        id: String,
        span: Span,
    },

    /// Cell block: ---cell type id:xxx--- ... ---end---
    CellBlock {
        cell_type: String,
        content: Vec<Stmt>,
        raw_text: Option<String>,
        span: Span,
    },

    /// Prompt block: --- ... ---
    PromptBlock {
        text: String,
        span: Span,
    },

    /// Use module: use math
    UseModule {
        module_name: String,
        span: Span,
    },

    /// Decorator: @name
    Decorator {
        name: String,
        args: Vec<Arg>,
        span: Span,
    },
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ElseIfBranch {
    pub condition: Expr,
    pub body: Vec<Stmt>,
    pub span: Span,
}

impl Stmt {
    pub fn span(&self) -> &Span {
        match self {
            Stmt::Command { span, .. }
            | Stmt::Assignment { span, .. }
            | Stmt::IfBlock { span, .. }
            | Stmt::InlineIf { span, .. }
            | Stmt::IfTrue { span, .. }
            | Stmt::IfFalse { span, .. }
            | Stmt::ForLoop { span, .. }
            | Stmt::Define { span, .. }
            | Stmt::ScopeBlock { span, .. }
            | Stmt::RepeatBlock { span, .. }
            | Stmt::TogetherBlock { span, .. }
            | Stmt::OnBlock { span, .. }
            | Stmt::Return { span, .. }
            | Stmt::Break { span }
            | Stmt::Continue { span }
            | Stmt::Comment { span, .. }
            | Stmt::ChunkMarker { span, .. }
            | Stmt::CellBlock { span, .. }
            | Stmt::PromptBlock { span, .. }
            | Stmt::UseModule { span, .. }
            | Stmt::Decorator { span, .. } => span,
        }
    }
}