fall back on shell command behaviour for undefined variables

Signed-off-by: Ava Hahn <ava@sunnypup.io>
This commit is contained in:
Ava Apples Affine 2023-10-12 20:50:27 -07:00
parent 0babc1986a
commit c05b94e92a
5 changed files with 84 additions and 15 deletions

View file

@ -18,6 +18,7 @@
use crate::eval::eval;
use crate::error::{Traceback, start_trace};
use crate::segment::{Ctr, Seg, Type};
use crate::stl::posix::POSIX_LOAD_NAME;
use std::collections::HashMap;
use std::fmt;
use std::rc::Rc;
@ -129,8 +130,42 @@ impl SymTable {
args: &Seg,
call_func: bool,
) -> Result<Box<Ctr>, Traceback> {
let outer_scope_seg: Seg;
let mut call_args = args;
let mut name_token = name.to_string();
let mut symbol = match self.remove(name) {
Some(s) => s,
/* implicit load:
* on a call to an undefined function
* assume a shell command is being run
*/
None if cfg!(feature="implicit-load")
&& call_func => match self.remove(&POSIX_LOAD_NAME.to_string()) {
Some(s) => {
name_token = String::from(POSIX_LOAD_NAME);
/* highly unfortunate circumstance
* we must now rebuild the original ast
* costs a whole clone of the args
* this feature is non-standard
*/
outer_scope_seg = Seg::from(
Box::from(Ctr::Symbol(name.to_string())),
if let Ctr::None = *args.car {
Box::from(Ctr::None)
} else {
Box::from(Ctr::Seg(args.clone()))
},
);
call_args = &outer_scope_seg;
s
},
None => return Err(
Traceback::new()
.with_trace(("(implicit load)", "(load function not found)").into())
)
},
None => return Err(
Traceback::new()
.with_trace((name, "(is an undefined symbol)").into())
@ -139,7 +174,7 @@ impl SymTable {
// will re-increment when inserted
// but we dont want to increment it
symbol.__generation -= 1;
self.insert(name.to_string(), symbol.clone());
self.insert(name_token, symbol.clone());
if let ValueType::VarForm(ref val) = symbol.value {
match **val {
Ctr::Lambda(ref l) if call_func => {
@ -165,7 +200,7 @@ impl SymTable {
}
}
if call_func {
symbol.call(args, self)
symbol.call(call_args, self)
} else {
// its a function but call_func is off
Ok(Box::new(Ctr::Symbol(name.to_string())))
@ -173,14 +208,19 @@ impl SymTable {
}
pub fn is_function_type(&self, name: &String) -> Option<bool> {
if let ValueType::VarForm(ref val) = self.get(name)?.value {
match **val {
Ctr::Lambda(_) => Some(true),
Ctr::Symbol(ref n) => self.is_function_type(n),
_ => Some(false),
}
} else {
Some(true)
match self.get(name) {
/* implicit-load: assume you just drew load function */
None if cfg!(feature="implicit-load") => Some(true),
Some(value) => if let ValueType::VarForm(ref val) = value.value {
match **val {
Ctr::Lambda(_) => Some(true),
Ctr::Symbol(ref n) => self.is_function_type(n),
_ => Some(false),
}
} else {
Some(true)
},
None => None,
}
}
}