use std::env;
use std::path::{Path, PathBuf};
use super::error::{EvalResult, Flow, signal};
use super::value::{Value, ValueKind};
use crate::tagged::header::VecLikeType;
fn expect_args(name: &str, args: &[Value], n: usize) -> Result<(), Flow> {
if args.len() != n {
Err(signal(
"wrong-number-of-arguments",
vec![Value::symbol(name), Value::fixnum(args.len() as i64)],
))
} else {
Ok(())
}
}
fn expect_range_args(name: &str, args: &[Value], min: usize, max: usize) -> Result<(), Flow> {
if args.len() < min || args.len() > max {
Err(signal(
"wrong-number-of-arguments",
vec![Value::symbol(name), Value::fixnum(args.len() as i64)],
))
} else {
Ok(())
}
}
fn expect_string(value: &Value) -> Result<String, Flow> {
if value.is_string() {
Ok(value.as_str().unwrap().to_owned())
} else {
Err(signal(
"wrong-type-argument",
vec![Value::symbol("stringp"), *value],
))
}
}
fn expect_subr(value: &Value) -> Result<(), Flow> {
match value.kind() {
ValueKind::Veclike(VecLikeType::Subr) => Ok(()),
other => Err(signal(
"wrong-type-argument",
vec![Value::symbol("subrp"), *value],
)),
}
}
fn absolutize_path(path: &str) -> PathBuf {
let p = Path::new(path);
if p.is_absolute() {
p.to_path_buf()
} else {
env::current_dir()
.unwrap_or_else(|_| PathBuf::from("."))
.join(p)
}
}
fn ensure_existing_file(path: &str) -> Result<PathBuf, Flow> {
let abs = absolutize_path(path);
if abs.exists() {
Ok(abs)
} else {
Err(signal(
"file-missing",
vec![Value::string(abs.display().to_string())],
))
}
}
pub(crate) fn builtin_comp_compile_ctxt_to_file0(args: Vec<Value>) -> EvalResult {
expect_args("comp--compile-ctxt-to-file0", &args, 1)?;
Ok(Value::T)
}
pub(crate) fn builtin_comp_init_ctxt(args: Vec<Value>) -> EvalResult {
expect_args("comp--init-ctxt", &args, 0)?;
Ok(Value::T)
}
pub(crate) fn builtin_comp_install_trampoline(args: Vec<Value>) -> EvalResult {
expect_args("comp--install-trampoline", &args, 2)?;
Ok(Value::NIL)
}
pub(crate) fn builtin_comp_late_register_subr(args: Vec<Value>) -> EvalResult {
expect_args("comp--late-register-subr", &args, 7)?;
Ok(Value::NIL)
}
pub(crate) fn builtin_comp_register_lambda(args: Vec<Value>) -> EvalResult {
expect_args("comp--register-lambda", &args, 7)?;
Ok(Value::NIL)
}
pub(crate) fn builtin_comp_register_subr(args: Vec<Value>) -> EvalResult {
expect_args("comp--register-subr", &args, 7)?;
Ok(Value::NIL)
}
pub(crate) fn builtin_comp_release_ctxt(args: Vec<Value>) -> EvalResult {
expect_args("comp--release-ctxt", &args, 0)?;
Ok(Value::T)
}
pub(crate) fn builtin_comp_subr_signature(args: Vec<Value>) -> EvalResult {
expect_args("comp--subr-signature", &args, 1)?;
expect_subr(&args[0])?;
Ok(Value::NIL)
}
pub(crate) fn builtin_comp_el_to_eln_filename(args: Vec<Value>) -> EvalResult {
expect_range_args("comp-el-to-eln-filename", &args, 1, 2)?;
let file = expect_string(&args[0])?;
let mut out = ensure_existing_file(&file)?;
out.set_extension("eln");
Ok(Value::string(out.display().to_string()))
}
pub(crate) fn builtin_comp_el_to_eln_rel_filename(args: Vec<Value>) -> EvalResult {
expect_args("comp-el-to-eln-rel-filename", &args, 1)?;
let file = expect_string(&args[0])?;
let _ = ensure_existing_file(&file)?;
let mut out = PathBuf::from(file);
out.set_extension("eln");
Ok(Value::string(out.display().to_string()))
}
pub(crate) fn builtin_comp_libgccjit_version(args: Vec<Value>) -> EvalResult {
expect_args("comp-libgccjit-version", &args, 0)?;
Ok(Value::list(vec![
Value::fixnum(14),
Value::fixnum(3),
Value::fixnum(0),
]))
}
pub(crate) fn builtin_comp_native_compiler_options_effective_p(args: Vec<Value>) -> EvalResult {
expect_args("comp-native-compiler-options-effective-p", &args, 0)?;
Ok(Value::T)
}
pub(crate) fn builtin_comp_native_driver_options_effective_p(args: Vec<Value>) -> EvalResult {
expect_args("comp-native-driver-options-effective-p", &args, 0)?;
Ok(Value::T)
}
#[cfg(test)]
#[path = "comp_test.rs"]
mod tests;