From 3864f6e60b4a944c55736756d9a14e48d860efd4 Mon Sep 17 00:00:00 2001 From: bnewbold Date: Wed, 20 Apr 2016 16:07:18 -0400 Subject: rust: start work on eval (finally) --- minimal.rs | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 81 insertions(+), 17 deletions(-) diff --git a/minimal.rs b/minimal.rs index 369b9db..c0fe3e8 100644 --- a/minimal.rs +++ b/minimal.rs @@ -4,17 +4,17 @@ use std::io; use std::io::Write; +use std::collections::HashMap; -// There doesn't seem to be a symbole or quote type in Rust, so i'm going to use strings and -// vectors +//////////// Types and Constants -// "list of tokens" implemented as a vector of String. -// AST implemented as nested tuples (immutable). +// There doesn't seem to be a symbol or quote type in Rust, so i'm going to use strings and vectors +// XXX: how to avoid the '16' here? const SCHEME_BUILTINS: [&'static str; 16] = ["lambda", "quote", "cond", "else", "cons", "car", "cdr", "null?", "eq?", "atom?", "zero?", "number?", "+", "-", "*", "/"]; -#[allow(dead_code)] +#[derive(Clone)] enum SchemeExpr<'a> { SchemeNull, SchemeTrue, @@ -27,13 +27,7 @@ enum SchemeExpr<'a> { SchemeQuote(Vec>), } -/////////////////////////////////// - -fn is_zero(n: f64) -> bool { - return n == 0.; -} - -/////////////////////////////////// +//////////// Lexing, Parsing, and Printing fn is_scheme_whitespace(c: char) -> bool{ " \r\n".find(c) != None @@ -42,6 +36,19 @@ fn is_scheme_sep(c: char) -> bool { "()".find(c) != None } +fn is_valid_symbol(s: &str) -> bool { + // TODO: this could be an 'any' or 'filter' call? + if s.len() == 0 { + return false; + } + for c in s.chars() { + if !c.is_alphabetic() && c != '-' { + return false; + } + } + return true; +} + // TODO: need to expand prefix notation stuff like `(1 2 3) to (quote 1 2 3) here? fn scheme_tokenize<'a>(raw_str: &'a str) -> Result, &'static str> { let mut ret = Vec::<&str>::new(); @@ -109,7 +116,7 @@ fn scheme_parse_token(token: &str) -> Result { } // If it's all alphas, must be a symbol - if token.is_alpha() { + if is_valid_symbol(token) { return Ok(SchemeExpr::SchemeSymbol(token)); } @@ -150,10 +157,6 @@ fn scheme_parse<'a>(tokens: &Vec<&'a str>, depth: u32) -> Result<(SchemeExpr<'a> return Ok((SchemeExpr::SchemeList(ret), rlen)); } -fn scheme_eval<'a>(ast: &SchemeExpr) -> Result, &'static str> { - return Ok(SchemeExpr::SchemeNull); -} - fn scheme_repr<'a>(ast: &SchemeExpr) -> Result { return match ast { &SchemeExpr::SchemeTrue => Ok("#t".to_string()), @@ -180,6 +183,67 @@ fn scheme_repr<'a>(ast: &SchemeExpr) -> Result { } } +//////////// Expression Evaluation + +fn quote_action<'a>(list: &'a Vec, ctx: HashMap<&str, SchemeExpr>) -> Result, &'static str> { + // XXX: why can't I '.map()' here? + let mut body = Vec::::new(); + for el in list[1..].to_vec() { + body.push(el.clone()); + } + Ok(SchemeExpr::SchemeList(body)) +} +/* +fn cond_action<'a>(list: &Vec<&'a SchemeExpr>, ctx: HashMap<&str, SchemeExpr>) -> Result, &'static str> { + Ok(SchemeExpr::SchemeQuote(list[1..].to_vec())) +} + +fn lambda_action<'a>(list: &Vec<&'a SchemeExpr>, ctx: HashMap<&str, SchemeExpr>) -> Result, &'static str> { + Ok(SchemeExpr::SchemeQuote(list[1..].to_vec())) +} +*/ + +fn scheme_meaning<'a>(ast: &'a SchemeExpr, ctx: HashMap<&str, SchemeExpr<'a>>) -> Result, &'static str> { + return match ast { + // "identity actions" + &SchemeExpr::SchemeTrue => Ok(ast.clone()), + &SchemeExpr::SchemeFalse => Ok(ast.clone()), + &SchemeExpr::SchemeNull => Ok(ast.clone()), + &SchemeExpr::SchemeStr(s)=> Ok(ast.clone()), + &SchemeExpr::SchemeNum(num) => Ok(ast.clone()), + &SchemeExpr::SchemeBuiltin(b)=> Ok(ast.clone()), + &SchemeExpr::SchemeQuote(ref list) => Ok(SchemeExpr::SchemeList(list.clone())), + &SchemeExpr::SchemeSymbol(sym)=> match ctx.get(sym) { + // the "lookup action" + Some(val) => Ok(val.clone()), + None => Err("symbol not defined"), + }, + &SchemeExpr::SchemeList(ref list) => { + if list.len() >= 2 { + match list[0] { + SchemeExpr::SchemeBuiltin("quote") => + quote_action(list, ctx), +/* + SchemeExpr::SchemeBuiltin("cond") => + cond_action(list, ctx), + SchemeExpr::SchemeBuiltin("lambda") => + lambda_action(list, ctx), +*/ + _ => Ok(SchemeExpr::SchemeNull) + } + } else { + Err("weird short expression") + }}, + } +} + +fn scheme_eval<'a>(ast: &'a SchemeExpr) -> Result, &'static str> { + let mut ctx = HashMap::<&str, SchemeExpr>::new(); + Ok(try!(scheme_meaning(ast, ctx))) +} + +//////////// Top-Level Program + fn main() { let stdin = io::stdin(); -- cgit v1.2.3