Skip to content

Commit 99394f5

Browse files
committed
Added keywords
1 parent 37312c8 commit 99394f5

File tree

5 files changed

+61
-0
lines changed

5 files changed

+61
-0
lines changed

src/keyword.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
use crate::symbol::Symbol;
2+
use std::fmt;
3+
use std::hash::Hash;
4+
5+
#[derive(Hash, PartialEq, Eq, Clone, Debug)]
6+
pub struct Keyword {
7+
// In Clojure proper, a Keyword wraps a Symbol to share their ..symbolic functionality
8+
pub sym: Symbol,
9+
}
10+
impl Keyword {
11+
pub fn intern(name: &str) -> Keyword {
12+
Keyword {
13+
sym: Symbol {
14+
name: String::from(name),
15+
}
16+
}
17+
}
18+
}
19+
impl fmt::Display for Keyword {
20+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
21+
write!(f, ":{}", self.sym.name)
22+
}
23+
}

src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ mod reader;
1414
mod repl;
1515
mod rust_core;
1616
mod symbol;
17+
mod keyword;
1718
mod type_tag;
1819
mod util;
1920
mod value;

src/reader.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use crate::persistent_list::ToPersistentList;
1818
use crate::persistent_list_map::ToPersistentListMap;
1919
use crate::persistent_vector::ToPersistentVector;
2020
use crate::symbol::Symbol;
21+
use crate::keyword::Keyword;
2122
use crate::value::{ToValue, Value};
2223
use std::rc::Rc;
2324

@@ -198,6 +199,23 @@ pub fn try_read_i32(input: &str) -> IResult<&str, Value> {
198199
to_value_parser(integer_parser)(input)
199200
}
200201

202+
// Perhaps generalize this into reader macros
203+
/// Tries to parse &str into Value::Keyword
204+
/// Example Successes:
205+
/// :a => Value::Keyword(Keyword { sym: Symbol { name: "a" })
206+
/// :cat-dog => Value::Keyword(Keyword { sym: Symbol { name: "cat-dog" })
207+
/// Example Failures:
208+
/// :12 :'a
209+
pub fn try_read_keyword(input: &str) -> IResult<&str, Value> {
210+
named!(keyword_colon<&str, &str>, preceded!(consume_clojure_whitespaces, tag!(":")));
211+
212+
let (rest_input, _) = keyword_colon(input)?;
213+
let (rest_input,symbol) = symbol_parser(rest_input)?;
214+
215+
let keyword_value = Keyword { sym: symbol }.to_value();
216+
Ok((rest_input,keyword_value))
217+
}
218+
201219
/// Tries to parse &str into Value::Symbol
202220
/// Example Successes:
203221
/// a => Value::Symbol(Symbol { name: "a" })
@@ -306,6 +324,7 @@ pub fn try_read(input: &str) -> IResult<&str, Value> {
306324
try_read_string,
307325
try_read_i32,
308326
try_read_symbol,
327+
try_read_keyword,
309328
try_read_list,
310329
try_read_vector,
311330
)),

src/type_tag.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::fmt;
44
pub enum TypeTag {
55
I32,
66
Symbol,
7+
Keyword,
78
IFn,
89
Condition,
910
PersistentList,
@@ -21,6 +22,7 @@ impl fmt::Display for TypeTag {
2122
let str = match self {
2223
I32 => std::string::String::from("rust.std.i32"),
2324
Symbol => std::string::String::from("clojure.lang.Symbol"),
25+
Keyword => std::string::String::from("clojure.lang.Keyword"),
2426
IFn => std::string::String::from("clojure.lang.Function"),
2527
Condition => std::string::String::from("clojure.lang.Condition"),
2628
PersistentList => std::string::String::from("clojure.lang.PersistentList"),

src/value.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::persistent_list::{PersistentList, ToPersistentList, ToPersistentListI
77
use crate::persistent_list_map::{PersistentListMap, ToPersistentListMapIter};
88
use crate::persistent_vector::PersistentVector;
99
use crate::symbol::Symbol;
10+
use crate::keyword::Keyword;
1011
use crate::type_tag::TypeTag;
1112

1213
extern crate rand;
@@ -28,6 +29,7 @@ use std::rc::Rc;
2829
pub enum Value {
2930
I32(i32),
3031
Symbol(Symbol),
32+
Keyword(Keyword),
3133
IFn(Rc<dyn IFn>),
3234
//
3335
// Special case functions
@@ -77,6 +79,12 @@ impl PartialEq for Value {
7779
return sym == sym2;
7880
}
7981
}
82+
83+
if let Keyword(kw) = self {
84+
if let Keyword(kw2) = other {
85+
return kw == kw2;
86+
}
87+
}
8088
// Equality not defined on functions, similar to Clojure
8189
// Change this perhaps? Diverge?
8290
if let IFn(_) = self {
@@ -173,6 +181,7 @@ impl Hash for Value {
173181
match self {
174182
I32(i) => i.hash(state),
175183
Symbol(sym) => sym.hash(state),
184+
Keyword(kw) => kw.hash(state),
176185
IFn(_) => {
177186
let mut rng = rand::thread_rng();
178187
let n2: u16 = rng.gen();
@@ -208,6 +217,7 @@ impl fmt::Display for Value {
208217
let str = match self {
209218
I32(val) => val.to_string(),
210219
Symbol(sym) => sym.to_string(),
220+
Keyword(kw) => kw.to_string(),
211221
IFn(_) => std::string::String::from("#function[]"),
212222
LexicalEvalFn => std::string::String::from("#function[lexical-eval*]"),
213223
PersistentList(plist) => plist.to_string(),
@@ -245,6 +255,7 @@ impl Value {
245255
match self {
246256
Value::I32(_) => TypeTag::I32,
247257
Value::Symbol(_) => TypeTag::Symbol,
258+
Value::Keyword(_) => TypeTag::Keyword,
248259
Value::IFn(_) => TypeTag::IFn,
249260
Value::LexicalEvalFn => TypeTag::IFn,
250261
Value::PersistentList(_) => TypeTag::PersistentList,
@@ -594,6 +605,11 @@ impl ToValue for Symbol {
594605
Value::Symbol(self.clone())
595606
}
596607
}
608+
impl ToValue for Keyword {
609+
fn to_value(&self) -> Value {
610+
Value::Keyword(self.clone())
611+
}
612+
}
597613
impl ToValue for Rc<dyn IFn> {
598614
fn to_value(&self) -> Value {
599615
Value::IFn(Rc::clone(self))

0 commit comments

Comments
 (0)