2021-02-14 16:33:17 -08:00
|
|
|
/* relish: versatile lisp shell
|
|
|
|
|
* Copyright (C) 2021 Aidan Hahn
|
|
|
|
|
*
|
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
|
2023-03-01 11:38:02 -08:00
|
|
|
use crate::segment::{Ctr, Seg};
|
2023-03-13 15:02:19 -07:00
|
|
|
use crate::sym::{SymTable, call_lambda};
|
2021-02-14 16:33:17 -08:00
|
|
|
|
|
|
|
|
/* iterates over a syntax tree
|
|
|
|
|
* returns a NEW LIST of values
|
|
|
|
|
* representing the simplest possible form of the input
|
|
|
|
|
*/
|
2023-03-01 11:38:02 -08:00
|
|
|
pub fn eval(ast: &Seg, syms: &mut SymTable) -> Result<Box<Ctr>, String> {
|
2023-03-13 15:02:19 -07:00
|
|
|
println!("E: {}", ast);
|
2023-02-15 23:27:00 -08:00
|
|
|
// data to return
|
|
|
|
|
let mut ret = Box::from(Ctr::None);
|
2023-02-17 21:00:07 -08:00
|
|
|
let mut first = true;
|
2023-02-15 23:27:00 -08:00
|
|
|
|
|
|
|
|
// to be assigned from cloned/evaled data
|
|
|
|
|
let mut car;
|
2023-02-25 23:36:30 -08:00
|
|
|
let mut cdr;
|
2023-02-15 23:27:00 -08:00
|
|
|
|
|
|
|
|
// lets me redirect the input
|
|
|
|
|
let mut arg_car = &ast.car;
|
|
|
|
|
let mut arg_cdr = &ast.cdr;
|
|
|
|
|
|
2023-02-17 21:00:07 -08:00
|
|
|
// iterate over ast and build out ret
|
|
|
|
|
let mut none = false;
|
|
|
|
|
while !none {
|
2023-02-23 23:01:47 -08:00
|
|
|
match &**arg_car {
|
2023-03-13 15:02:19 -07:00
|
|
|
Ctr::Seg(ref inner) => {
|
|
|
|
|
let interm = eval(inner, syms)?;
|
|
|
|
|
if let Ctr::Lambda(ref l) = *interm {
|
|
|
|
|
match call_lambda(l, arg_cdr, syms) {
|
|
|
|
|
Ok(s) => return Ok(s.clone()),
|
|
|
|
|
Err(s) => return Err(format!("err in call to lambda: {}", s)),
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
car = interm;
|
|
|
|
|
}
|
|
|
|
|
},
|
2021-06-22 00:50:37 -07:00
|
|
|
|
2023-02-23 23:01:47 -08:00
|
|
|
Ctr::Symbol(ref tok) => {
|
|
|
|
|
let outer_scope_seg_holder: Seg;
|
|
|
|
|
let args: &Seg;
|
|
|
|
|
if let Ctr::Seg(ref candidate_args) = **arg_cdr {
|
|
|
|
|
args = candidate_args;
|
2021-06-22 00:50:37 -07:00
|
|
|
} else {
|
2023-02-23 23:01:47 -08:00
|
|
|
outer_scope_seg_holder = Seg::from_mono(arg_cdr.clone());
|
|
|
|
|
args = &outer_scope_seg_holder;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
match syms.call_symbol(tok, args, first) {
|
|
|
|
|
Ok(s) => car = s,
|
|
|
|
|
Err(s) => return Err(format!("error in call to {}: {}", tok, s)),
|
2021-06-22 00:50:37 -07:00
|
|
|
}
|
2023-02-25 23:36:30 -08:00
|
|
|
|
|
|
|
|
if let Some(b) = syms.is_function_type(tok) {
|
|
|
|
|
if b {
|
|
|
|
|
return Ok(car);
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-01-16 22:02:40 -08:00
|
|
|
}
|
2021-06-22 00:50:37 -07:00
|
|
|
|
|
|
|
|
_ => {
|
2023-02-15 23:27:00 -08:00
|
|
|
car = arg_car.clone();
|
2021-06-22 00:50:37 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-17 21:00:07 -08:00
|
|
|
match **arg_cdr {
|
2023-02-23 23:01:47 -08:00
|
|
|
Ctr::Symbol(ref tok) => {
|
|
|
|
|
let blank = Seg::new();
|
|
|
|
|
match syms.call_symbol(tok, &blank, false) {
|
|
|
|
|
Ok(res) => cdr = res,
|
|
|
|
|
Err(s) => return Err(format!("error fetching {}: {}", tok, s)),
|
|
|
|
|
}
|
2021-06-22 00:50:37 -07:00
|
|
|
none = true;
|
2022-01-16 22:02:40 -08:00
|
|
|
}
|
2021-06-22 00:50:37 -07:00
|
|
|
|
2023-02-15 23:27:00 -08:00
|
|
|
Ctr::Seg(ref next) => {
|
2023-02-25 23:36:30 -08:00
|
|
|
cdr = Box::from(Ctr::None);
|
2023-02-15 23:27:00 -08:00
|
|
|
arg_car = &next.car;
|
|
|
|
|
arg_cdr = &next.cdr
|
2021-06-22 00:50:37 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_ => {
|
2023-02-25 23:36:30 -08:00
|
|
|
cdr = arg_cdr.clone();
|
2021-06-22 00:50:37 -07:00
|
|
|
none = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-25 23:36:30 -08:00
|
|
|
if let Ctr::None = *ret {
|
|
|
|
|
*ret = Ctr::Seg(Seg::from(car, cdr))
|
|
|
|
|
} else if let Ctr::Seg(ref mut s) = *ret {
|
|
|
|
|
s.append(car);
|
|
|
|
|
if let Ctr::None = *cdr {
|
|
|
|
|
} else {
|
|
|
|
|
s.append(cdr);
|
2021-06-22 00:50:37 -07:00
|
|
|
}
|
|
|
|
|
}
|
2023-02-17 21:00:07 -08:00
|
|
|
|
|
|
|
|
first = false;
|
2021-06-22 00:50:37 -07:00
|
|
|
}
|
|
|
|
|
|
2023-02-17 21:00:07 -08:00
|
|
|
Ok(ret)
|
2021-03-16 22:43:46 -07:00
|
|
|
}
|