Moving some functios

- Some functions moved from core.rs to core.mal
- Separating MAL_HOME setting from core/config loading

Signed-off-by: teo3300 <matteo.rogora@live.it>
This commit is contained in:
teo3300
2024-01-17 12:07:06 +09:00
parent e6924d42b4
commit 9491983a05
6 changed files with 49 additions and 28 deletions

View File

@ -53,13 +53,12 @@ pub fn ns_init() -> Env {
"println" => Fun(|a| {a.iter().for_each(|a| print!("{} ", pr_str(a, false))); println!(); Ok(Nil) }, "Print readably all the arguments"),
"list" => Fun(|a| Ok(List(MalArgs::new(a.to_vec()))), "Return the arguments as a list"),
"list?" => Fun(|a| Ok(Bool(a.iter().all(|el| matches!(el, List(_))))), "Return true if the first argument is a list, false otherwise"),
"empty?" => Fun(|a| Ok(Bool(car(a)?.if_list()?.is_empty())), "Return true if the first parameter is an empty list, false otherwise, returns an error if the element is not a list"),
// "empty?" => implemented through "count" in core.mal
"count" => Fun(|a| Ok(Int(car(a)?.if_list()?.len() as isize)), "Return the number of elements in the first argument"),
"and" => Fun(|a| Ok(Bool(a.iter().all(|a| !matches!(a, Nil | Bool(false))))), "Returns false if at least one of the arguments is 'false' or 'nil', true otherwise"),
"or" => Fun(|a| Ok(Bool(a.iter().any(|a| !matches!(a, Nil | Bool(false))))), "Returns false if all the arguments are 'false' or 'nil', true otherwise"),
"xor" => Fun(|a| Ok(Bool(a.iter().filter(|a| !matches!(a, Nil | Bool(false))).count() == 1)), "Returns true if one of the arguments is different from 'nil' or 'false', false otherwise"),
// "not" defined inside mal itself
// "not" => Fun(|a| Ok(Bool(matches!(car(a)?, Nil | Bool(false)))), "Negate the first argument"),
// "not" => implemented throught "if" in core.mal
"=" => Fun(mal_comp, "Return true if the first two parameters are the same type and content, in case of lists propagate to all elements"),
"assert" => Fun(mal_assert, "Return an error if assertion fails"),
"assert-eq" => Fun(mal_assert_eq, "Return an error if arguments are not the same"),

View File

@ -12,12 +12,15 @@ mod step6_file;
mod types;
use core::ns_init;
use parse_tools::{interactive, load_conf, load_core, load_file};
use parse_tools::{interactive, load_conf, load_core, load_file, set_home_path};
fn main() {
// Initialize ns environment
let reply_env = ns_init();
// Set the "MAL_HOME" symbol to the specified directory or the default one
set_home_path(&reply_env);
// load "$MAL_HOME/core.mal"
load_core(&reply_env);
// Load config files ($MAL_HOME/config.mal, or default $HOME/.config/mal/config.mal)

View File

@ -5,8 +5,9 @@ mod functional {
($file:expr) => {{
use crate::core::ns_init;
use crate::load_file;
use crate::parse_tools::load_core;
use crate::parse_tools::{load_core, set_home_path};
let env = ns_init();
set_home_path(&env);
load_core(&env);
assert!(matches!(
load_file(format!("tests/{}.mal", $file).as_str(), &env),

View File

@ -1,4 +1,4 @@
use crate::env::Env;
use crate::env::{env_get, Env};
use crate::eval::eval;
use crate::reader::{read_str, Reader};
use crate::step6_file::rep;
@ -10,33 +10,33 @@ use std::io::{BufRead, BufReader, Read};
use std::path::Path;
use std::process::exit;
pub fn load_core(env: &Env) {
eval_str("(def! not (fn* [x] (if x nil true)))", env).unwrap();
eval_str(
"(def! load-file (fn* [f] (eval (read-string (str \"(do \" (slurp f) \"\nnil)\")))))",
env,
)
.unwrap();
eval_str(
"(def! conf-reload (fn* [] (load-file (str MAL_HOME \"/\" \"config.mal\"))))",
env,
)
.unwrap();
}
fn eval_str(line: &str, env: &Env) -> MalRet {
eval(&read_str(Reader::new().push(line))?, env.clone())
}
pub fn load_conf(work_env: &Env) {
const CONFIG: &str = "config.mal";
pub fn set_home_path(env: &Env) {
let home = match env::var("MAL_HOME") {
Ok(s) => s,
Err(_) => env::var("HOME").unwrap() + "/.config/mal",
};
// Add config path to mal
eval_str(format!("(def! MAL_HOME \"{home}\")").as_str(), work_env).unwrap();
let config = home + "/" + CONFIG;
eval_str(format!("(def! MAL_HOME \"{home}\")").as_str(), env).unwrap();
}
fn get_home_path(env: &Env) -> Result<String, MalErr> {
Ok(env_get(env, "MAL_HOME")?.if_string()?.to_string())
}
pub fn load_core(env: &Env) {
let mut home_path = get_home_path(env).unwrap();
home_path.push_str("/core.mal");
load_file(&home_path, env).unwrap();
}
pub fn load_conf(work_env: &Env) {
const CONFIG: &str = "config.mal";
let config = get_home_path(work_env).unwrap() + "/" + CONFIG;
if Path::new(&config).exists() {
if let Err(e) = load_file(&config, work_env) {
@ -127,7 +127,7 @@ pub fn interactive(env: Env) {
// TODO: remove unwrap and switch to a better error handling
let mut rl = DefaultEditor::new().unwrap();
if rl.load_history(HISTORY_PATH).is_err() {
eprintln!("Failed to load history");
eprintln!("; Failed to load history");
}
let mut num = 0;
@ -169,12 +169,12 @@ pub fn interactive(env: Env) {
}
Err(ReadlineError::Interrupted) => {
parser.clear();
eprintln!("; ... Interrupted");
// eprintln!("; ... Interrupted");
continue;
}
Err(ReadlineError::Eof) => exit(0),
Err(err) => {
eprint!("Error reading lnie: {:?}", err);
eprint!("; Error reading lnie: {:?}", err);
break;
}
}

View File

@ -66,5 +66,6 @@ pub fn print_malfun(sym: &str, params: Rc<MalType>, ast: Rc<MalType>) {
.if_list()
.unwrap_or(&[])
.iter()
.for_each(|el| println!("; {}\n", pr_str(el, true)));
.for_each(|el| println!("; {}", pr_str(el, true)));
println!();
}