diff --git a/lexer/src/named_char.rs b/lexer/src/named_char.rs deleted file mode 100644 index b07e6f0..0000000 --- a/lexer/src/named_char.rs +++ /dev/null @@ -1,60 +0,0 @@ -/* lexer/src/named_char.rs - * Eryn Wells - */ - -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 { - 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; - 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) - } -} diff --git a/types/src/char.rs b/types/src/char.rs deleted file mode 100644 index 647d798..0000000 --- a/types/src/char.rs +++ /dev/null @@ -1,32 +0,0 @@ -/* types/char.rs - * Eryn Wells - */ - -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')); - } -} diff --git a/types/src/char/mod.rs b/types/src/char/mod.rs new file mode 100644 index 0000000..35042f3 --- /dev/null +++ b/types/src/char/mod.rs @@ -0,0 +1,51 @@ +/* types/char.rs + * Eryn Wells + */ + +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 { + 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); + } +} diff --git a/types/src/char/names.rs b/types/src/char/names.rs new file mode 100644 index 0000000..420bb44 --- /dev/null +++ b/types/src/char/names.rs @@ -0,0 +1,65 @@ +/* types/src/char/names.rs + * Eryn Wells + */ + +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 { + 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; + 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) + } +}