Implement display and string support resolves #10

This commit is contained in:
2021-05-30 22:49:31 -04:00
parent a7caac30f9
commit 2e67e1220c
5 changed files with 65 additions and 2 deletions

View File

@@ -20,6 +20,10 @@ pub fn get_global_environment<'a>() -> Env<'a> {
(make_symbol("-"), Datum::Procedure(primitives::sub)),
(make_symbol("="), Datum::Procedure(primitives::eq)),
(make_symbol("<"), Datum::Procedure(primitives::lt)),
(
make_symbol("display"),
Datum::Procedure(primitives::display),
),
],
outer: None,
}

View File

@@ -83,6 +83,10 @@ fn interpret_define(args: &Vec<Datum>, env: &mut Env) -> Datum {
}
}
fn interpret_cond(_vec: &Vec<Datum>, _env: &mut Env) -> Datum {
Datum::Unspecified
}
fn interpret_begin(vec: &Vec<Datum>, env: &mut Env) -> Datum {
let mut r = Datum::Unspecified;
for i in 1..vec.len() {
@@ -127,16 +131,17 @@ pub fn interpret(exp: &Datum, env: &mut Env) -> Datum {
match exp {
Boolean(_) => exp.clone(),
Number(_) => exp.clone(),
Unspecified => Unspecified,
String(_) => exp.clone(),
Symbol(_) => environment::lookup_variable_value(exp, env),
List(v) if has_tag(v, "if") => interpret_if(v, env),
List(v) if has_tag(v, "set!") => interpret_set(v, env),
List(v) if has_tag(v, "define") => interpret_define(v, env),
List(v) if has_tag(v, "cond") => panic!("cond-not-supported"),
List(v) if has_tag(v, "cond") => interpret_cond(v, env),
List(v) if has_tag(v, "let") => panic!("let-not-supported"),
List(v) if has_tag(v, "begin") => interpret_begin(v, env),
List(v) if has_tag(v, "quote") => v[1].clone(),
List(v) => interpret_application(v, env),
Unspecified => Unspecified,
_ => panic!("unknown-expression {:?}", exp),
}
}

View File

@@ -3,6 +3,7 @@ pub enum Token {
Identifier(String),
Boolean(bool),
Number(i64),
String(String),
LeftRoundBracket,
RightRoundBracket,
Quote,
@@ -33,6 +34,8 @@ fn scan(code: &str, mut ix: usize, mut tokens: Tokens) -> Tokens {
return scan_boolean(code, ix, tokens);
} else if c == ';' {
return scan_comment(code, ix, tokens);
} else if c == '"' {
return scan_string(code, ix, tokens);
} else if c.is_ascii_digit() {
return scan_number(code, ix, tokens);
} else if c.is_ascii_alphabetic() || SPECIAL_INITIAL.contains(&c) {
@@ -95,6 +98,39 @@ fn scan_comment(code: &str, mut ix: usize, tokens: Tokens) -> Tokens {
scan(code, ix, tokens)
}
fn scan_string(code: &str, mut ix: usize, mut tokens: Tokens) -> Tokens {
let mut s = String::new();
let mut chars = code[ix..].chars();
let c = chars.next().unwrap();
assert!(c == '"');
ix += 1;
while let Some(c) = chars.next() {
ix += 1;
if c == '"' {
break;
} else if c == '\\' {
ix += 1;
if let Some(next_c) = chars.next() {
let escaped_c = match next_c {
'n' => '\n',
'"' => '"',
'\\' => '\\',
_ => panic!("SCAN-STRING -- cannot escape {}", next_c),
};
s.push(escaped_c);
} else {
panic!("SCAN-STRING -- found escape at eof")
}
} else {
s.push(c);
}
}
let token = Token::String(s);
tokens.push(token);
scan(code, ix, tokens)
}
fn scan_number(code: &str, mut ix: usize, mut tokens: Tokens) -> Tokens {
let start_ix = ix;
let mut chars = code[ix..].chars();

View File

@@ -6,6 +6,7 @@ use std::cmp::Ordering;
pub enum Datum {
Boolean(bool),
Number(i64),
String(String),
Symbol(String),
List(Vec<Datum>),
Procedure(fn(Vec<Datum>) -> Datum),
@@ -52,6 +53,7 @@ fn parse_datum(tokens: &Tokens, ix: usize) -> (Datum, usize) {
Token::Identifier(s) => (Datum::Symbol(s.to_string()), ix + 1),
Token::Boolean(b) => (Datum::Boolean(*b), ix + 1),
Token::Number(n) => (Datum::Number(*n), ix + 1),
Token::String(s) => (Datum::String(s.to_string()), ix + 1),
Token::Quote => parse_quote(tokens, ix + 1),
Token::LeftRoundBracket => parse_list(tokens, ix + 1),
_ => panic!("Unexpected token {:?}", tokens[ix]),

View File

@@ -1,5 +1,7 @@
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 {
@@ -84,3 +86,17 @@ pub fn lt(args: Vec<Datum>) -> Datum {
Boolean(true)
}
}
pub fn display(args: Vec<Datum>) -> Datum {
for i in 1..args.len() {
match &args[i] {
Boolean(b) => print!("{}", b),
Number(n) => print!("{}", n),
String(s) => print!("{}", s),
List(v) => print!("{:?}", v),
_ => panic!("DISPLAY -- cannot-print {:?}", args[1]),
};
}
io::stdout().flush().ok().expect("Could not flush stdout");
Unspecified
}