232 lines
6.1 KiB
Rust
232 lines
6.1 KiB
Rust
use crate::{Ast, Error};
|
|
|
|
#[derive(Debug)]
|
|
pub(crate) enum Hir<'s> {
|
|
Call(Box<Hir<'s>>, Vec<Hir<'s>>),
|
|
If(Box<(Hir<'s>, Hir<'s>, Hir<'s>)>),
|
|
Define(&'s str, Box<Hir<'s>>),
|
|
Ident(&'s str),
|
|
Lit(Lit<'s>),
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub(crate) enum Lit<'s> {
|
|
Str(&'s str),
|
|
Num(f64),
|
|
}
|
|
|
|
#[derive(Debug, Default)]
|
|
pub(crate) struct Lowerer {
|
|
errors: Vec<Error>,
|
|
}
|
|
|
|
impl Lowerer {
|
|
pub(crate) fn ast<'s>(&mut self, a: &Ast<'s>) -> Option<Hir<'s>> {
|
|
match a {
|
|
Ast::Tree(tree) => self.tree(tree),
|
|
Ast::Leaf(leaf) => self.leaf(leaf),
|
|
}
|
|
}
|
|
|
|
fn leaf<'a>(&mut self, leaf: &'a str) -> Option<Hir<'a>> {
|
|
// TODO
|
|
let fst = leaf.chars().next().unwrap();
|
|
|
|
if fst == '"' {
|
|
return self.str(leaf);
|
|
} else if fst.is_digit(10) {
|
|
return self.num(leaf);
|
|
}
|
|
|
|
Some(Hir::Ident(leaf))
|
|
}
|
|
|
|
fn str<'a>(&mut self, leaf: &'a str) -> Option<Hir<'a>> {
|
|
assert_eq!(leaf.chars().next().unwrap(), '"');
|
|
assert_eq!(leaf.chars().last().unwrap(), '"');
|
|
|
|
Some(Hir::Lit(Lit::Str(&leaf[1..leaf.len() - 1])))
|
|
}
|
|
|
|
fn num<'a>(&mut self, leaf: &str) -> Option<Hir<'a>> {
|
|
match leaf.parse() {
|
|
Ok(n) => Some(Hir::Lit(Lit::Num(n))),
|
|
Err(_) => {
|
|
self.errors.push(format!("Invalid float `{}`", leaf));
|
|
None
|
|
}
|
|
}
|
|
}
|
|
|
|
fn tree<'a>(&mut self, tree: &[Ast<'a>]) -> Option<Hir<'a>> {
|
|
let first = tree.first().unwrap();
|
|
if let Some(sf) = Self::get_special_form(first) {
|
|
self.special_form(sf, &tree[1..])
|
|
} else {
|
|
self.call(tree)
|
|
}
|
|
}
|
|
|
|
fn get_special_form(a: &Ast<'_>) -> Option<SpecialForm> {
|
|
use SpecialForm::*;
|
|
|
|
let leaf = match a {
|
|
Ast::Leaf(l) => *l,
|
|
Ast::Tree(_) => return None,
|
|
};
|
|
|
|
Some(match leaf {
|
|
"define" => Define,
|
|
"lambda" => Lambda,
|
|
"cond" => Cond,
|
|
"begin" => Begin,
|
|
"when" => When,
|
|
"unless" => Unless,
|
|
"set" => Set,
|
|
_ => return None,
|
|
})
|
|
}
|
|
|
|
fn special_form<'a>(&mut self, sf: SpecialForm, tree: &[Ast<'a>]) -> Option<Hir<'a>> {
|
|
match sf {
|
|
SpecialForm::Lambda => self.sf_lambda(tree),
|
|
SpecialForm::If => self.sf_if(tree),
|
|
SpecialForm::Set => self.sf_set(tree),
|
|
SpecialForm::Define => self.sf_define(tree),
|
|
SpecialForm::Cond => self.sf_cond(tree),
|
|
SpecialForm::Case => self.sf_case(tree),
|
|
SpecialForm::And => self.sf_and(tree),
|
|
SpecialForm::Or => self.sf_or(tree),
|
|
SpecialForm::When => self.sf_when(tree),
|
|
SpecialForm::Unless => self.sf_unless(tree),
|
|
SpecialForm::Begin => self.sf_begin(tree),
|
|
}
|
|
}
|
|
|
|
fn call<'a>(&mut self, tree: &[Ast<'a>]) -> Option<Hir<'a>> {
|
|
let func = tree.first().unwrap();
|
|
let args = &tree[1..];
|
|
|
|
let func = self.ast(func)?;
|
|
let args = args.iter().map(|arg| self.ast(arg)).collect_opt()?;
|
|
|
|
Some(Hir::Call(Box::new(func), args))
|
|
}
|
|
|
|
// ===== Begin Special Forms =====
|
|
// ===== Begin Special Forms =====
|
|
fn sf_lambda<'a>(&mut self, tree: &[Ast<'a>]) -> Option<Hir<'a>> {
|
|
todo!()
|
|
}
|
|
fn sf_if<'a>(&mut self, tree: &[Ast<'a>]) -> Option<Hir<'a>> {
|
|
let [test, when, unless] = self.n_args(tree, "if")?;
|
|
let test = self.ast(test)?;
|
|
let when = self.ast(when)?;
|
|
let unless = self.ast(unless)?;
|
|
Some(Hir::If(Box::new((test, when, unless))))
|
|
}
|
|
fn sf_set<'a>(&mut self, tree: &[Ast<'a>]) -> Option<Hir<'a>> {
|
|
todo!()
|
|
}
|
|
fn sf_define<'a>(&mut self, tree: &[Ast<'a>]) -> Option<Hir<'a>> {
|
|
let what = &tree[0];
|
|
let rest = &tree[1..];
|
|
match what {
|
|
Ast::Tree(nameargs) => self.define_func(nameargs, rest),
|
|
Ast::Leaf(name) => self.define_val(name, rest),
|
|
}
|
|
}
|
|
|
|
fn define_func<'a>(&mut self, nameargs: &[Ast<'a>], rest: &[Ast<'a>]) -> Option<Hir<'a>> {
|
|
todo!()
|
|
}
|
|
|
|
fn define_val<'a>(&mut self, name: &'a str, rest: &[Ast<'a>]) -> Option<Hir<'a>> {
|
|
let [val] = self.n_args(rest, "define(value)")?;
|
|
let val = self.ast(val)?;
|
|
|
|
Some(Hir::Define(name, Box::new(val)))
|
|
}
|
|
|
|
fn sf_cond<'a>(&mut self, tree: &[Ast<'a>]) -> Option<Hir<'a>> {
|
|
todo!()
|
|
}
|
|
fn sf_case<'a>(&mut self, tree: &[Ast<'a>]) -> Option<Hir<'a>> {
|
|
todo!()
|
|
}
|
|
fn sf_and<'a>(&mut self, tree: &[Ast<'a>]) -> Option<Hir<'a>> {
|
|
todo!()
|
|
}
|
|
fn sf_or<'a>(&mut self, tree: &[Ast<'a>]) -> Option<Hir<'a>> {
|
|
todo!()
|
|
}
|
|
fn sf_when<'a>(&mut self, tree: &[Ast<'a>]) -> Option<Hir<'a>> {
|
|
todo!()
|
|
}
|
|
fn sf_unless<'a>(&mut self, tree: &[Ast<'a>]) -> Option<Hir<'a>> {
|
|
todo!()
|
|
}
|
|
fn sf_begin<'a>(&mut self, tree: &[Ast<'a>]) -> Option<Hir<'a>> {
|
|
todo!()
|
|
}
|
|
// ===== End Special Forms =====
|
|
|
|
fn n_args<'a, 'b, const N: usize>(
|
|
&mut self,
|
|
tree: &'b [Ast<'a>],
|
|
name: &str,
|
|
) -> Option<&'b [Ast<'a>; N]> {
|
|
match tree.try_into() {
|
|
Ok(arr) => Some(arr),
|
|
Err(_) => {
|
|
self.errors
|
|
.push(format!("{} need {} args, but got {}", name, N, tree.len()));
|
|
None
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
enum SpecialForm {
|
|
Lambda,
|
|
If,
|
|
// TODO: Define vs set.
|
|
Set,
|
|
Define,
|
|
|
|
Cond,
|
|
Case,
|
|
And,
|
|
Or,
|
|
When,
|
|
Unless,
|
|
|
|
// Let,
|
|
// LetStar,
|
|
// Letrec,
|
|
// LetrecStar,
|
|
// LetValues,
|
|
// LetStarValues,
|
|
Begin,
|
|
// Do,
|
|
// Only needed if we do the lazy lib
|
|
// Delay,
|
|
// DelayForce,
|
|
// Force,
|
|
// Guard,
|
|
}
|
|
|
|
trait IterExt: Iterator {
|
|
fn collect_opt<T>(self) -> Option<Vec<T>>
|
|
where
|
|
Self: Sized,
|
|
Option<Vec<T>>: FromIterator<Self::Item>,
|
|
{
|
|
// TODO: Customize this to not early return, so we get errors from
|
|
// later parts even if we know theirs already an error.
|
|
self.collect()
|
|
}
|
|
}
|
|
|
|
impl<T: Iterator> IterExt for T {}
|