treescript-interpreter 0.1.1

TreeScript interpreter, with some built-in libraries and API to create more
Documentation
#![feature(try_trait)]

use std::collections::HashSet;
use std::ops::Try;
use std::option::NoneError;
use treescript_interpreter::lib_process::{BasicLibProcessError, Config, LibProcess};
use treescript_interpreter::session::LibrarySpec;
use treescript_interpreter::value::{Prim, Value};

struct LibGen {
  ast: Option<Vec<Value>>,
  used_idxs: HashSet<usize>,
}

impl LibGen {
  fn new() -> LibGen {
    return LibGen {
      ast: None,
      used_idxs: HashSet::new(),
    };
  }

  fn cant_read_ast_err() -> BasicLibProcessError {
    return BasicLibProcessError::Unsupported(String::from("can't read AST"));
  }

  fn free_string_lit(i: usize) -> String {
    return format!("free{}", i);
  }

  fn free_string(&mut self, template: Value) -> Result<Value, BasicLibProcessError> {
    let ast = self
      .ast
      .as_ref()
      .into_result()
      .map_err(|NoneError| LibGen::cant_read_ast_err())?;
    let mut i = 0;
    let mut res = template.clone();
    res.subst(
      &Value::hole(1),
      &Value::Prim(Prim::String(LibGen::free_string_lit(i))),
    );
    loop {
      if self.used_idxs.contains(&i) {
        i += 1;
        res = template.clone();
        res.subst(
          &Value::hole(1),
          &Value::Prim(Prim::String(LibGen::free_string_lit(i))),
        );
        continue;
      }
      for val in ast {
        if val == &res {
          i += 1;
          res = template.clone();
          res.subst(
            &Value::hole(1),
            &Value::Prim(Prim::String(LibGen::free_string_lit(i))),
          );
          continue;
        }
        for sub in val.breadth_first() {
          if sub == &res {
            i += 1;
            res = template.clone();
            res.subst(
              &Value::hole(1),
              &Value::Prim(Prim::String(LibGen::free_string_lit(i))),
            );
            continue;
          }
        }
      }
      break;
    }
    self.used_idxs.insert(i);
    return Ok(res);
  }
}

impl LibProcess for LibGen {
  type Error = BasicLibProcessError;

  fn dependencies() -> Vec<LibrarySpec> {
    return Vec::new();
  }

  fn configure(&mut self, config: Config) {
    self.ast = config.read_ast();
  }

  fn call_fun(&mut self, name: String, args: Vec<Value>) -> Result<Value, Self::Error> {
    match name.as_str() {
      "FreeString" => {
        if args.len() != 1 {
          return Err(BasicLibProcessError::InvalidNumArgs {
            fun: String::from("FreeString"),
            expected: 1,
            actual: args.len(),
          });
        }
        let mut args_iter = args.into_iter();
        let arg0 = args_iter.next().unwrap();
        return self.free_string(arg0);
      }
      _ => return Err(BasicLibProcessError::UnknownFunction(name)),
    };
  }
}

fn main() {
  LibGen::new().run_main();
}