[lexer,types] Move named_char to types as types/char/names.rs

Move char.rs to be char/mod.rs
This commit is contained in:
Eryn Wells 2017-04-23 10:41:47 -07:00
parent 5cb66d932f
commit fd5df91e27
4 changed files with 116 additions and 92 deletions

View file

@ -1,60 +0,0 @@
/* lexer/src/named_char.rs
* Eryn Wells <eryn@erynwells.me>
*/
use std::collections::HashMap;
use std::sync::{Once, ONCE_INIT};
const ALARM: &'static str = "alarm";
const BACKSPACE: &'static str = "backspace";
const DELETE: &'static str = "delete";
const ESCAPE: &'static str = "escape";
const NEWLINE: &'static str = "newline";
const NULL: &'static str = "null";
const RETURN: &'static str = "return";
const SPACE: &'static str = "space";
const TAB: &'static str = "tab";
/// Mapping of names to `char` values. Returns the name of the given character, if a name exists.
/// Otherwise, returns `None`.
fn char_for(named: &str) -> Option<char> {
static ONCE = ONCE_INIT;
static mut names_to_chars: HashMap<&'static str, char>;
unsafe {
ONCE.call_once(|| {
names_to_chars = HashMap::new();
names_to_chars.insert(ALARM, '\x07');
names_to_chars.insert(BACKSPACE, '\x08');
names_to_chars.insert(DELETE, '\x7F');
names_to_chars.insert(ESCAPE, '\x1B');
names_to_chars.insert(NEWLINE, '\n');
names_to_chars.insert(NULL, '\0');
names_to_chars.insert(RETURN, '\r');
names_to_chars.insert(SPACE, ' ');
names_to_chars.insert(TAB, '\t');
});
names_to_chars.get(named)
}
}
/// Mapping of `char` values to names. Returns the name of the given character, if a name exists.
/// Otherwise, returns `None`.
fn name_of(c: char) -> Option<&'static str> {
static ONCE = ONCE_INIT;
static mut chars_to_names: HashMap<char, &'static str>;
unsafe {
ONCE.call_once(|| {
chars_to_names = HashMap::new();
chars_to_names.insert('\x07', ALARM);
chars_to_names.insert('\x08', BACKSPACE);
chars_to_names.insert('\x7F', DELETE);
chars_to_names.insert('\x1B', ESCAPE);
chars_to_names.insert('\n', NEWLINE);
chars_to_names.insert('\0', NULL);
chars_to_names.insert('\r', RETURN);
chars_to_names.insert(' ', SPACE);
chars_to_names.insert('\t', TAB);
});
chars_to_names.get(c)
}
}

View file

@ -1,32 +0,0 @@
/* types/char.rs
* Eryn Wells <eryn@erynwells.me>
*/
use object::Object;
use predicates::IsChar;
impl IsChar for Object {
fn is_char(&self) -> bool {
match *self {
Object::Char(_) => true,
_ => false,
}
}
}
#[cfg(test)]
mod tests {
use object::Object;
use predicates::{IsBool, IsChar};
#[test]
fn chars_are_chars() {
assert_eq!(Object::Char('a').is_char(), true);
assert_eq!(Object::Char('a').is_bool(), false);
}
#[test]
fn equal_chars_are_equal() {
assert_eq!(Object::Char('a'), Object::Char('a'));
}
}

51
types/src/char/mod.rs Normal file
View file

@ -0,0 +1,51 @@
/* types/char.rs
* Eryn Wells <eryn@erynwells.me>
*/
mod names;
use object::Object;
use predicates::IsChar;
impl IsChar for Object {
fn is_char(&self) -> bool {
match *self {
Object::Char(_) => true,
_ => false,
}
}
}
impl Object {
pub fn from_char(c: char) -> Object {
Object::Char(c)
}
pub fn from_char_name(name: &str) -> Option<Object> {
names::char_for(name).map(|c| Object::from_char(c))
}
}
#[cfg(test)]
mod tests {
use object::Object;
use predicates::{IsBool, IsChar};
#[test]
fn chars_are_chars() {
assert_eq!(Object::from_char('a').is_char(), true);
assert_eq!(Object::from_char('a').is_bool(), false);
}
#[test]
fn equal_chars_are_equal() {
assert_eq!(Object::from_char('a'), Object::from_char('a'));
}
#[test]
fn named_chars_are_created() {
assert_eq!(Object::from_char_name("newline"), Some(Object::from_char('\n')));
assert_eq!(Object::from_char_name("asdf"), None);
}
}

65
types/src/char/names.rs Normal file
View file

@ -0,0 +1,65 @@
/* types/src/char/names.rs
* Eryn Wells <eryn@erynwells.me>
*/
use std::collections::HashMap;
use std::mem;
use std::sync::{Once, ONCE_INIT};
const ALARM: &'static str = "alarm";
const BACKSPACE: &'static str = "backspace";
const DELETE: &'static str = "delete";
const ESCAPE: &'static str = "escape";
const NEWLINE: &'static str = "newline";
const NULL: &'static str = "null";
const RETURN: &'static str = "return";
const SPACE: &'static str = "space";
const TAB: &'static str = "tab";
/// Mapping of names to `char` values. Returns the name of the given character, if a name exists.
/// Otherwise, returns `None`.
pub fn char_for(name: &str) -> Option<char> {
type NameMap = HashMap<&'static str, char>;
static ONCE: Once = ONCE_INIT;
static mut NAMES_TO_CHARS: *const NameMap = 0 as *const NameMap;
unsafe {
ONCE.call_once(|| {
let mut map = NameMap::new();
map.insert(ALARM, '\x07');
map.insert(BACKSPACE, '\x08');
map.insert(DELETE, '\x7F');
map.insert(ESCAPE, '\x1B');
map.insert(NEWLINE, '\n');
map.insert(NULL, '\0');
map.insert(RETURN, '\r');
map.insert(SPACE, ' ');
map.insert(TAB, '\t');
NAMES_TO_CHARS = mem::transmute(Box::new(map));
});
(*NAMES_TO_CHARS).get(name).map(|c| *c)
}
}
/// Mapping of `char` values to names. Returns the name of the given character, if a name exists.
/// Otherwise, returns `None`.
pub fn name_of(c: char) -> Option<&'static str> {
type CharMap = HashMap<char, &'static str>;
static ONCE: Once = ONCE_INIT;
static mut CHARS_TO_NAMES: *const CharMap = 0 as *const CharMap;
unsafe {
ONCE.call_once(|| {
let mut map = CharMap::new();
map.insert('\x07', ALARM);
map.insert('\x08', BACKSPACE);
map.insert('\x7F', DELETE);
map.insert('\x1B', ESCAPE);
map.insert('\n', NEWLINE);
map.insert('\0', NULL);
map.insert('\r', RETURN);
map.insert(' ', SPACE);
map.insert('\t', TAB);
CHARS_TO_NAMES = mem::transmute(Box::new(map));
});
(*CHARS_TO_NAMES).get(&c).map(|s| *s)
}
}