```python
x = """Lambda,
    If,
    Set,
    Define,
    Cond,
    Case,
    And,
    Or,
    When,
    Unless,
    Begin,"""

x = x.replace(" ", "").replace(",", "").replace("\r", "")
x = x.splitlines()

print("// ===== Begin Special Forms =====")

for i in x:
    i = i.lower()

    print(f"fn sf_{i}<'a>(&mut self, tree: &[Ast<'a>]) -> Option<Hir<'a>> {{")
    print("todo!()")
    print("}")

print("// ===== End Special Forms =====")
```
trunk
Alona EM 2022-01-01 18:38:43 +00:00
parent c98550907d
commit 0b82031e1b
6 changed files with 326 additions and 2 deletions

62
SCHEMES.md Normal file
View File

@ -0,0 +1,62 @@
## Chez
- `chezscheme`
- `M-x run-chez`
-
```lisp
> (expand '(define (f x) (cond (a b) (c d) (else e))))
(begin
(set! f
(lambda (#{x kbvpqn6dj3c6k95f21kwqmji8-1})
(if a b (if c d e))))
(#2%void))
```
## Chicken
- `csi`
-
```lisp
#2> (import expand-full) ; May need to be `chicken-installed` first
; loading /var/lib//chicken/11/expand-full.import.so ...
; loading /var/lib//chicken/11/expand-full.so ...
; loading /var/lib//chicken/11/srfi-1.so ...
#3> (ppexpand* '(define (f x) (cond (a b) (c d) (else e))))
(##core#begin
(##core#ensure-toplevel-definition f)
(##core#set!
f
(##core#lambda
(x)
(##core#if
a
(##core#begin b)
(##core#if c (##core#begin d) (##core#begin e))))))
```
## Racket
`racket
## Chibi
- `chibi-scheme`
- `M-x run-chibi`
-
```lisp
> (import (chibi ast))
> (macroexpand '(define (f x) (cond (a b) (c d) (else g))))
(set! f (lambda (x) (if a b (if c d g))))
```
## Gambit
## Gauche
## Guile
## MIT-scheme
## Racket

5
basic.scm Normal file
View File

@ -0,0 +1,5 @@
(+ 1 2 (/ 3 4))
(if (= 2 "hello world")
(display f x)
1)

View File

@ -9,3 +9,17 @@
(set! f f_)))
(f)
(fffo
(ddssd))
(define (fx)
(+ x x))
(defin)
(def)
(define (f x)
(+ 2 3 4 x))

231
src/hir.rs Normal file
View File

@ -0,0 +1,231 @@
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 {}

View File

@ -1,7 +1,11 @@
mod hir;
mod parser;
use anyhow::bail;
use fs_err as fs;
type Error = String;
#[derive(Debug, PartialEq, logos::Logos)]
enum Kind {
#[token("(")]
@ -33,7 +37,15 @@ fn main() -> anyhow::Result<()> {
let src = fs::read_to_string(&arg)?;
dbg!(parser::parse(&src));
let (trees, errs) = dbg!(parser::parse(&src));
if !errs.is_empty() {
bail!("Got some parse errors");
}
for tree in trees {
dbg!(hir::Lowerer::default().ast(&tree));
}
Ok(())
}

View File

@ -4,7 +4,7 @@ use logos::Logos;
use crate::{Ast, Kind};
type Error = String;
use crate::Error;
struct Parser<'s> {
lex: Peekable<Lexer<'s>>,