221 lines
5.2 KiB
Rust
221 lines
5.2 KiB
Rust
use crate::interpreter::has_tag;
|
|
use crate::interpreter::is_true;
|
|
use crate::parser::make_symbol;
|
|
use crate::parser::Datum;
|
|
use crate::parser::Datum::*;
|
|
use std::io;
|
|
use std::io::prelude::*;
|
|
use std::mem;
|
|
|
|
pub fn add(mut args: Vec<Datum>) -> Datum {
|
|
let mut r = 0;
|
|
for i in 1..args.len() {
|
|
let datum = mem::take(&mut args[i]);
|
|
if let Number(n) = datum {
|
|
r += n;
|
|
} else {
|
|
panic!("ADD -- not-all-args-are-numbers {:?}", args)
|
|
}
|
|
}
|
|
Number(r)
|
|
}
|
|
|
|
pub fn mul(mut args: Vec<Datum>) -> Datum {
|
|
let mut r = 1;
|
|
for i in 1..args.len() {
|
|
let datum = mem::take(&mut args[i]);
|
|
if let Number(n) = datum {
|
|
r *= n;
|
|
} else {
|
|
panic!("MUL -- not-all-args-are-numbers {:?}", args)
|
|
}
|
|
}
|
|
Number(r)
|
|
}
|
|
|
|
pub fn sub(mut args: Vec<Datum>) -> Datum {
|
|
if args.len() == 2 {
|
|
let datum = mem::take(&mut args[1]);
|
|
if let Number(n) = datum {
|
|
return Number(-n);
|
|
} else {
|
|
panic!("SUB -- not-all-args-are-numbers {:?}", args)
|
|
}
|
|
}
|
|
|
|
let mut r;
|
|
let datum = mem::take(&mut args[1]);
|
|
if let Number(n) = datum {
|
|
r = n;
|
|
} else {
|
|
panic!("SUB -- not-all-args-are-numbers {:?}", args)
|
|
}
|
|
|
|
for i in 2..args.len() {
|
|
let datum = mem::take(&mut args[i]);
|
|
if let Number(n) = datum {
|
|
r -= n;
|
|
} else {
|
|
panic!("SUB -- not-all-args-are-numbers {:?}", args)
|
|
}
|
|
}
|
|
Number(r)
|
|
}
|
|
|
|
pub fn eq(args: Vec<Datum>) -> Datum {
|
|
if args.len() == 1 {
|
|
Boolean(true)
|
|
} else {
|
|
let first = &args[1];
|
|
for i in 2..args.len() {
|
|
let current = &args[i];
|
|
if first != current {
|
|
return Boolean(false);
|
|
}
|
|
}
|
|
Boolean(true)
|
|
}
|
|
}
|
|
|
|
pub fn lt(args: Vec<Datum>) -> Datum {
|
|
if args.len() == 1 {
|
|
Boolean(true)
|
|
} else {
|
|
for i in 1..(args.len() - 1) {
|
|
if &args[i] >= &args[i + 1] {
|
|
return Boolean(false);
|
|
}
|
|
}
|
|
Boolean(true)
|
|
}
|
|
}
|
|
|
|
pub fn or(args: Vec<Datum>) -> Datum {
|
|
if args.len() == 1 {
|
|
Boolean(false)
|
|
} else {
|
|
for i in 1..args.len() {
|
|
if is_true(&args[i]) {
|
|
return args[i].clone();
|
|
}
|
|
}
|
|
Boolean(false)
|
|
}
|
|
}
|
|
|
|
pub fn and(args: Vec<Datum>) -> Datum {
|
|
if args.len() == 1 {
|
|
Boolean(true)
|
|
} else {
|
|
for i in 1..args.len() {
|
|
if !is_true(&args[i]) {
|
|
return Boolean(false);
|
|
}
|
|
}
|
|
args[args.len() - 1].clone()
|
|
}
|
|
}
|
|
|
|
pub fn not(args: Vec<Datum>) -> Datum {
|
|
if args.len() != 2 {
|
|
panic!("NOT -- takes one argument");
|
|
} else {
|
|
if is_true(&args[1]) {
|
|
Boolean(false)
|
|
} else {
|
|
Boolean(true)
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn display(args: Vec<Datum>) -> Datum {
|
|
for i in 1..args.len() {
|
|
print!("{}", args[i]);
|
|
}
|
|
io::stdout().flush().ok().expect("Could not flush stdout");
|
|
Unspecified
|
|
}
|
|
|
|
pub fn list(mut args: Vec<Datum>) -> Datum {
|
|
args[0] = make_symbol("list");
|
|
Datum::List(args)
|
|
}
|
|
|
|
pub fn cons(mut args: Vec<Datum>) -> Datum {
|
|
if args.len() != 3 {
|
|
panic!("CONS -- two args expected {:?}", args);
|
|
}
|
|
let a = std::mem::take(&mut args[1]);
|
|
let b = std::mem::take(&mut args[2]);
|
|
match b {
|
|
List(b_vec) if has_tag(&b_vec, "list") => {
|
|
let mut r_vec = vec![make_symbol("list"), a];
|
|
r_vec.append(&mut b_vec[1..].to_vec());
|
|
Datum::List(r_vec)
|
|
}
|
|
_ => Datum::Pair(Box::new((a, b))),
|
|
}
|
|
}
|
|
|
|
pub fn car(mut args: Vec<Datum>) -> Datum {
|
|
if args.len() != 2 {
|
|
panic!("CAR -- expected a single arg {:?}", args);
|
|
}
|
|
let a = std::mem::take(&mut args[1]);
|
|
match a {
|
|
List(mut v) if has_tag(&v, "list") => std::mem::take(&mut v[1]),
|
|
Pair(p) => p.0,
|
|
_ => panic!("CAR -- could not get car {:?}", a),
|
|
}
|
|
}
|
|
|
|
pub fn cdr(mut args: Vec<Datum>) -> Datum {
|
|
if args.len() != 2 {
|
|
panic!("CDR -- expected a single arg {:?}", args);
|
|
}
|
|
let a = std::mem::take(&mut args[1]);
|
|
match a {
|
|
List(v) if has_tag(&v, "list") => {
|
|
let mut v_cdr = v[1..].to_vec();
|
|
v_cdr[0] = make_symbol("list");
|
|
List(v_cdr)
|
|
}
|
|
Pair(p) => p.1,
|
|
_ => panic!("CAR -- could not get car {:?}", a),
|
|
}
|
|
}
|
|
|
|
pub fn pair(args: Vec<Datum>) -> Datum {
|
|
if args.len() != 2 {
|
|
panic!("PAIR? -- expected a single arg {:?}", args);
|
|
}
|
|
match &args[1] {
|
|
List(v) if has_tag(&v, "list") => {
|
|
if v.len() == 1 {
|
|
Boolean(false)
|
|
} else {
|
|
Boolean(true)
|
|
}
|
|
}
|
|
Pair(_) => Boolean(true),
|
|
_ => Boolean(false),
|
|
}
|
|
}
|
|
|
|
pub fn null(args: Vec<Datum>) -> Datum {
|
|
if args.len() != 2 {
|
|
panic!("PAIR? -- expected a single arg {:?}", args);
|
|
}
|
|
match &args[1] {
|
|
List(v) if has_tag(&v, "list") => {
|
|
if v.len() == 1 {
|
|
Boolean(true)
|
|
} else {
|
|
Boolean(false)
|
|
}
|
|
}
|
|
Pair(_) => Boolean(false),
|
|
_ => Boolean(false),
|
|
}
|
|
}
|