bean-script 0.2.12

Simple scripting language for easy use in other projects.
Documentation
use std::{rc::Rc, sync::Mutex};

use bean_script::{
	data::Data,
	evaluator, lexer,
	modules::registry::{ModuleRegistry, RegistryFeatures},
	parser::{self, Node, PosNode},
	scope::{block_scope::BlockScope, ScopeRef},
	util::make_ref,
};
use rustyline::{error::ReadlineError, DefaultEditor};

pub fn open() -> rustyline::Result<()> {
	let registry = make_ref(ModuleRegistry::new(RegistryFeatures {
		custom_modules: false,
		import: false,
		lang_debug: false,
	}));
	let program_scope: ScopeRef =
		make_ref(BlockScope::new(Some(registry.borrow().runtime())));
	let mutex = Mutex::new(program_scope);
	let mut rl = DefaultEditor::new()?;

	loop {
		let input = rl.readline(") ");

		match input {
			Ok(line) => {
				if line == "exit" {
					break;
				}

				let _ = rl.add_history_entry(line.as_str());

				let scope_ref = Rc::clone(&mutex.lock().unwrap());

				let tree = parser::parse(lexer::tokenize(line));
				if let Err(error) = tree {
					println!("\x1b[31;1merror\x1b[0m: {}", error);
					continue;
				}
				let mut tree = tree.unwrap();

				if let PosNode {
					node: Node::Program { body },
					..
				} = tree
				{
					if body.len() == 1 {
						tree = *body[0].clone();
					} else {
						tree = PosNode {
							node: Node::Program { body },
							ln: 0,
						};
					}
				}

				let result = evaluator::evaluate(&tree, scope_ref);

				if let Ok(data) = result {
					match data {
						Data::None => (),
						_ => println!("{:?}", data),
					}
				} else if let Err(error) = result {
					println!("\x1b[31;1merror\x1b[0m: {}", error);
				}
			}
			Err(ReadlineError::Interrupted | ReadlineError::Eof) => {
				break;
			}
			Err(_) => return input.map(|_| ()),
		}
	}

	Ok(())
}