mangle 0.0.5

Exolang that can take any utf8 text as valid code and return some result out of it
Documentation
use rustyline::error::ReadlineError;
use rustyline::Editor;

extern crate dirs;
use std::fs;
use unicode_segmentation::UnicodeSegmentation;

struct Value {
    value: String,
    type_: String,
}

struct OpResult {
    result: Result<String, String>,
    assignment: bool,
    assign_to: String,
    assign_value: Value,
}

struct Operator {
    num_args: usize,
    func: fn(Vec<String>) -> OpResult,
}

fn get_operator(op: &str) -> Option<Operator> {
    match op.graphemes(true).count() {
    3 => Some(Operator {  // 0
        num_args: 1,
        func: |args| {
            let mut result = OpResult {
                result: Ok(args[0].clone()),
                assignment: false,
                assign_to: String::new(),
                assign_value: Value {
                    value: String::new(),
                    type_: String::new(),
                },
            };
            result
        },
    })
        _ => None,
}

struct Scope {}

struct Interpreter {
    word_separator: char,
    scope: Scope,
}

impl Interpreter {
    fn new(word_separator: char) -> Interpreter {
        Interpreter {
            scope: Scope {},
            word_separator,
        }
    }

    fn eval(&mut self, input: &str) -> Result<String, String> {
        let inputlist = input.split(self.word_separator).collect::<Vec<&str>>();
        // OP var1 var2
        match inputlist[..] {
            [op, var1, var2, ..] => Ok(format!("{} {} {}", var1, op, var2)),
            _ => Err(format!("{}", input)),
        }
    }
}

fn make_cache() -> Result<String, std::io::Error> {
    let system_cache_dir = dirs::cache_dir().unwrap();
    let cache_path = system_cache_dir.join("mangle");
    fs::create_dir_all(&cache_path)?;
    Ok(cache_path.to_str().unwrap().to_string())
}

struct Context {
    cache_dir: String,
}

fn repl(context: Context) {
    // `()` can be used when no completer is required
    let mut rl = Editor::<()>::new();
    let cache_file_path = context.cache_dir.clone() + "/history";
    if rl.load_history(&cache_file_path).is_err() {
        println!("No previous history.");
    }
    let mut interpreter = Interpreter::new(' ');
    loop {
        let readline = rl.readline(">> ");
        match readline {
            Ok(line) => {
                rl.add_history_entry(line.as_str());
                let result = match interpreter.eval(&line) {
                    Ok(result) => result,
                    Err(err) => err,
                };
                println!("Line: {}", result);
            }
            Err(ReadlineError::Interrupted) => {
                println!("CTRL-C");
                break;
            }
            Err(ReadlineError::Eof) => {
                println!("CTRL-D");
                break;
            }
            Err(err) => {
                println!("Error: {:?}", err);
                break;
            }
        }
    }
    rl.save_history(&cache_file_path).unwrap();
}

fn main() {
    let cache_dir = make_cache().unwrap();
    let context = Context { cache_dir };
    repl(context);
}