procc_ll/
lib.rs

1use std::cell::RefCell;
2use std::fmt::{Debug, Formatter};
3use std::rc::Rc;
4use log::{debug};
5use regex::Regex;
6use crate::context::Context;
7use crate::Errors::{FunctionNotFound, MemoryDefNotFound, TokenNotMatched};
8use crate::token::Token;
9
10pub mod context;
11pub mod token;
12#[cfg(test)]
13mod tests;
14
15///measures the execution time and prints it on the screen,
16/// example:
17///```
18/// use procc_ll::measure_time;
19/// measure_time! ({println! ("hello ") });
20/// ```
21/// return the result of the code inside, only print the execution time if the RUST_LOG = debug
22#[macro_export]
23macro_rules! measure_time_debug {
24    ($expression:expr) => {{
25        use std::time::Instant;
26
27        let start = Instant::now();
28        let result = $expression;  // Ejecuta la expresión
29        let duration = start.elapsed();
30
31        debug!("Run Time: {:?}", duration);
32
33        result  // Retorna el resultado de la expresión
34    }};
35}
36#[macro_export]
37macro_rules! measure_time {
38    ($expression:expr) => {{
39        use std::time::Instant;
40
41        let start = Instant::now();
42        let result = $expression;  // Ejecuta la expresión
43        let duration = start.elapsed();
44
45        println!("Run Time: {:?}", duration);
46
47        result  // Retorna el resultado de la expresión
48    }};
49}
50
51
52lazy_static::lazy_static! {
53    static ref FUNC_REGEX: Regex = Regex::new(r"(.+)\((.+)\)").unwrap();
54}
55/// is a part of the program, contains the context, i is capable of executing
56/// Use example:
57/// ```
58/// use procc_ll::Program;
59/// let mut main = Program::new();
60///
61/// // now use the main ProgramBlock
62/// ```
63
64#[derive(Clone)]
65pub struct Program {
66    pub context: crate::context::Context,
67}
68impl Program {
69    pub fn new() -> Rc<RefCell<Self>> {
70        Rc::new(RefCell::new(Program { context: crate::context::Context::new() }))
71    }
72    pub fn new_from_context(context: crate::context::Context) -> Self {
73        Program { context }
74    }
75    /// Executes a new token
76    /// Use example:
77    /// ```
78    /// use procc_ll::Program;
79    ///
80    /// let mut main = Program::new();
81    ///
82    /// main.borrow_mut().push_internal_key("echo", |tok, prog| {
83    ///     print!("{}" ,tok);
84    ///     procc_ll::Values::Null
85    /// });
86    /// main.borrow_mut().exec("echo hello world!!");
87    pub fn exec(&mut self, token: &str) -> Result<Values, Errors> {
88
89        let token = token.trim();
90        let token = token.replace("\n", "");
91
92        // check keys
93        debug!("[E] split token");
94        let split: Vec<String> = measure_time_debug!({token.to_owned().split_whitespace() // Divide la cadena en espacios
95            .map(|s| s.to_string()) // Convierte cada &str a String
96            .collect()}); // Recolecta en un Vec<String>
97
98        if self.context.keys.borrow().contains_key(&split[0]) {
99            debug!("[V] token is has key");
100            let content = token.replace(&split[0], "").trim().to_string();
101            debug!("[E] getting key function");
102            let func = measure_time_debug!({self.context.get_key(&split[0])});
103            return Ok(func(content, self));
104        }
105
106        // checking import
107        debug!("[E] checking references");
108        if token.starts_with("$") {
109            debug!("[E] token is reference");
110            let name = token.replace("$", "").trim().to_string();
111            debug!("[E] getting memory value: {}", &name);
112            if !self.context.has_memory(&name) { return Err(MemoryDefNotFound(format!("\"{}\" not found", name))); }
113            return Ok(self.context.get_memory(&name));
114        }
115
116        // check functions
117        debug!("[E] checking function");
118        debug!("[REGEX] Matching regex");
119        if measure_time_debug!({FUNC_REGEX.is_match(&token)}) {
120            debug!("[V] token is function");
121            debug!("[E] getting function infos");
122            let (name, args): (String, String) = if let Some(cap) = FUNC_REGEX.captures(&token) {
123                debug!("[V] getting name");
124                let name = measure_time_debug!({cap.get(1).map_or("", |m| m.as_str()).to_string()});
125                debug!("[E] getting args");
126                let args = measure_time_debug!({cap.get(2).map_or("", |m| m.as_str()).to_string()});
127                (name, args)
128            } else { ("".to_owned(), "".to_owned()) };
129            debug!("[INF] function data {} {}", name, args);
130            if !self.context.functions.borrow().contains_key(&name) { return Err(FunctionNotFound(format!("function call \"{}\" but function \"{}\" not found", token, &name))); }
131            let func = { self.context.get_function(&name) };
132
133            let mut pargs: Vec<Values> = Vec::new();
134
135            for arg in args.split(",") {
136                let res = self.exec(arg);
137                if res.is_err() {
138                    return Err(res.err().unwrap())
139                } else {
140                    pargs.push(res?);
141                }
142            }
143
144            return Ok((func)(pargs, self));
145        }
146
147        // if is not key
148        debug!("[E] other tokens definition");
149        debug!("[E] getting token definition index");
150        let index = measure_time_debug!({self.context.token_index(&token)});
151        debug!("[E] getting token");
152        if let None = index { return Err(Errors::TokenNotMatched(String::from(format!("token \"{}\" not matched with the registered token samples", token)))); }
153        let def_tok = measure_time_debug!({self.context.get_token(index.unwrap())});
154
155        debug!("[E] executing function");
156        let val = measure_time_debug!({def_tok.borrow().exec(&token, self).unwrap()});
157
158        Ok(val)
159    }
160    /// Push a new token in the context
161    pub fn push_internal_token(&mut self, token: Box<dyn Token>) {
162        self.context.push_token(token);
163    }
164    /// push a new key on the context
165    pub fn push_internal_key(&mut self, key: &str, func: impl Fn(String, &mut Program) -> Values + 'static) {
166        self.context.push_key(key.to_owned(), func);
167    }
168    /// push a new value on the context
169    pub fn push_internal_memory(&mut self, key: &str, val: Values) {
170        self.context.push_memory(key, val);
171    }
172    /// push a new function on the context
173    pub fn push_internal_function(&mut self, name: &str, func: impl Fn(Vec<Values>, &mut Program) -> Values + 'static) {
174        self.context.push_function(name.to_owned(), func);
175    }
176    pub fn new_depth_context(&mut self) -> Rc<RefCell<Program>> {
177        let mut clone = self.clone();
178        clone.context.sub_context = Some(Box::new(Context::new()));
179
180        Rc::new(RefCell::new(clone))
181    }
182}
183#[derive(Clone)]
184pub enum Errors {
185    Non,
186    TokenNotMatched(String),
187    FunctionNotFound(String),
188    MemoryDefNotFound(String),
189}
190impl Errors {
191    pub fn to_str(&self) -> String {
192        let (name, message) = match self {
193            TokenNotMatched(msg) => ("ERRORS::TOKEN_NOT_FOUND", msg),
194            Errors::FunctionNotFound(msg) => ("ERRORS::FUNCTION_NOT_FOUND", msg),
195            MemoryDefNotFound(msg) => ("ERRORS::MEMORY_DEFINITION_NOT_FOUND", msg),
196            _ => { ("ERRORS::UNKNOWN", &"UNKNOWN ERROR".to_owned()) }
197        };
198        format!("ERROR PROCESSING: {} : {}", name, message)
199    }
200}
201impl Debug for Errors {
202    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
203        f.write_str(&*self.to_str())
204    }
205}
206/// Values that retune the functions, tokens, keys i that also returns the exec of ProgramBlock
207#[derive(PartialEq, Clone)]
208pub enum Values {
209    String(String),
210    Number(f64),
211    Boolean(bool),
212    Array(Vec<Values>),
213    Null
214}
215impl Debug for Values {
216    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
217        match self {
218            Values::String(v) => write!(f, "{}", v),
219            Values::Number(v) => write!(f, "{}", v),
220            Values::Boolean(v) => write!(f, "{}", v),
221            Values::Array(v) => { write!(f, "[")?; v.fmt(f) },
222            _ => { write!(f, "null") }
223        }
224    }
225}