Speed sketch beginnings of a Rust implementation of new stripped-down Scheme-like Kraken
This commit is contained in:
37
kr/src/ast.rs
Normal file
37
kr/src/ast.rs
Normal file
@@ -0,0 +1,37 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Form {
|
||||
Int(i32),
|
||||
Symbol(String),
|
||||
Pair(Rc<Form>,Rc<Form>),
|
||||
PrimComb(String, fn(Rc<Form>, Rc<Form>) -> Rc<Form>),
|
||||
Nil,
|
||||
}
|
||||
impl Form {
|
||||
pub fn int(&self) -> Option<i32> {
|
||||
match self {
|
||||
Form::Int(i) => Some(*i),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn sym(&self) -> Option<&str> {
|
||||
match self {
|
||||
Form::Symbol(s) => Some(s),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn car(&self) -> Option<Rc<Form>> {
|
||||
match self {
|
||||
Form::Pair(car, cdr) => Some(Rc::clone(car)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn cdr(&self) -> Option<Rc<Form>> {
|
||||
match self {
|
||||
Form::Pair(car, cdr) => Some(Rc::clone(cdr)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
27
kr/src/grammar.lalrpop
Normal file
27
kr/src/grammar.lalrpop
Normal file
@@ -0,0 +1,27 @@
|
||||
use std::str::FromStr;
|
||||
use std::rc::Rc;
|
||||
use crate::ast::Form;
|
||||
|
||||
grammar;
|
||||
|
||||
pub Term: Form = {
|
||||
NUM => Form::Int(i32::from_str(<>).unwrap()),
|
||||
SYM => Form::Symbol(<>.to_owned()),
|
||||
"(" <ListInside?> ")" => <>.unwrap_or(Form::Nil),
|
||||
"'" <Term> => Form::Pair(Rc::new(Form::Symbol("quote".to_owned())), Rc::new(<>)),
|
||||
};
|
||||
ListInside: Form = {
|
||||
<Term> => Form::Pair(Rc::new(<>), Rc::new(Form::Nil)),
|
||||
<h: Term> <t: ListInside> => Form::Pair(Rc::new(h), Rc::new(t)),
|
||||
<a: Term> "." <d: Term> => Form::Pair(Rc::new(a), Rc::new(d)),
|
||||
}
|
||||
match {
|
||||
"(",
|
||||
")",
|
||||
".",
|
||||
"'",
|
||||
r"[0-9]+" => NUM,
|
||||
r"[a-zA-Z+*/_-][\w+*/_-]*" => SYM,
|
||||
r"(;[^\n]*\n)|\s+" => { }
|
||||
}
|
||||
|
||||
80
kr/src/main.rs
Normal file
80
kr/src/main.rs
Normal file
@@ -0,0 +1,80 @@
|
||||
#[macro_use] extern crate lalrpop_util;
|
||||
lalrpop_mod!(pub grammar);
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
mod ast;
|
||||
use crate::ast::Form;
|
||||
|
||||
#[test]
|
||||
fn parse_test() {
|
||||
assert!(grammar::TermParser::new().parse("22").is_ok());
|
||||
assert!(grammar::TermParser::new().parse("(22)").is_ok());
|
||||
assert!(grammar::TermParser::new().parse("(((22)))").is_ok());
|
||||
|
||||
assert!(grammar::TermParser::new().parse("((22)").is_err());
|
||||
|
||||
assert!(grammar::TermParser::new().parse("22").is_ok());
|
||||
assert!(grammar::TermParser::new().parse("(22)").is_ok());
|
||||
assert!(grammar::TermParser::new().parse("(22 )").is_ok());
|
||||
assert!(grammar::TermParser::new().parse("()").is_ok());
|
||||
assert!(grammar::TermParser::new().parse("( )").is_ok());
|
||||
assert!(grammar::TermParser::new().parse("( 44)").is_ok());
|
||||
assert!(grammar::TermParser::new().parse("(44 )").is_ok());
|
||||
assert!(grammar::TermParser::new().parse("(22 44 (1) 33 (4 5 (6) 6))").is_ok());
|
||||
assert!(grammar::TermParser::new().parse("hello").is_ok());
|
||||
assert!(grammar::TermParser::new().parse("-").is_ok());
|
||||
assert!(grammar::TermParser::new().parse("+").is_ok());
|
||||
assert!(grammar::TermParser::new().parse("(+ 1 ;hi
|
||||
3)").is_ok());
|
||||
assert!(grammar::TermParser::new().parse("'13").is_ok());
|
||||
assert!(grammar::TermParser::new().parse("hello-world").is_ok());
|
||||
assert!(grammar::TermParser::new().parse("_").is_ok());
|
||||
}
|
||||
|
||||
fn eval(e: Rc<Form>, f: Rc<Form>) -> Rc<Form> {
|
||||
let mut e = e;
|
||||
let mut x = Option::Some(f);
|
||||
loop {
|
||||
let cur = x.take().unwrap();
|
||||
match *cur {
|
||||
Form::Symbol(ref s) => {
|
||||
let mut t = e;
|
||||
while s != t.car().unwrap().car().unwrap().sym().unwrap() {
|
||||
t = t.cdr().unwrap();
|
||||
}
|
||||
return t.car().unwrap().cdr().unwrap();
|
||||
},
|
||||
Form::Pair(ref c, ref p) => {
|
||||
let comb = eval(Rc::clone(&e), Rc::clone(c));
|
||||
match *comb {
|
||||
Form::PrimComb(ref n, ref f) => return f(e, Rc::clone(p)),
|
||||
_ => panic!("Tried to call not a PrimComb {:?}", comb),
|
||||
}
|
||||
},
|
||||
_ => return cur,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
fn assoc(kvs: Vec<(&str, Rc<Form>)>) -> Rc<Form> {
|
||||
let mut to_ret = Rc::new(Form::Nil);
|
||||
for (k, v) in kvs {
|
||||
to_ret = Rc::new(Form::Pair(
|
||||
Rc::new(Form::Pair(
|
||||
Rc::new(Form::Symbol(k.to_owned())),
|
||||
v)),
|
||||
to_ret));
|
||||
}
|
||||
to_ret
|
||||
}
|
||||
let env = assoc(vec![
|
||||
("+", Rc::new(Form::PrimComb("+".to_owned(), |e, p| {
|
||||
Rc::new(Form::Int(p.car().unwrap().int().unwrap() + p.cdr().unwrap().car().unwrap().int().unwrap()))
|
||||
})))
|
||||
]);
|
||||
let input = "(+ 2 2)";
|
||||
let result = eval(env, Rc::new(grammar::TermParser::new().parse(input).unwrap()));
|
||||
println!("Result is {:?}", result);
|
||||
}
|
||||
Reference in New Issue
Block a user