Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
Grinkers committed Sep 17, 2024
1 parent 75bed24 commit c3642a9
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 1 deletion.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Cargo.lock
/target/
/.lsp/
/.clj-kondo/
/.clj-kondo/
/constexpr_edn/target/*
Empty file added constexpr_edn/.gitignore
Empty file.
10 changes: 10 additions & 0 deletions constexpr_edn/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "constexpr_edn"
version = "0.1.0"
edition = "2021"

[lib]
proc-macro = true

[dependencies]
clojure-reader = { path = ".." }
28 changes: 28 additions & 0 deletions constexpr_edn/examples/example.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use clojure_reader::edn::Edn;
use constexpr_edn::edn;

use std::collections::{BTreeMap, BTreeSet};

fn main() {
let edn: Edn = edn!([1 2 3]);
// Vector([Int(1), Int(2), Int(3)])
println!("{edn:?}");

let edn: Edn = edn!(#{ 1 2 3 #{4 5 6}});
// Set({Set({Int(4), Int(5), Int(6)}), Int(1), Int(2), Int(3)})
println!("{edn:?}");

let edn: Edn = edn!({:foo #{42 43 44}});
// Map(Map({":bar": List(List([UInt(1), UInt(2), UInt(3)])), ":foo": Set(Set({UInt(42), UInt(43), UInt(44)}))}))
println!("{edn:?}");

let edn: Edn = edn!([42, "foobar",,,,, ,, ; 424242
#_ ignoreme
,, yaycats 16r9001]);
// Vector([Int(42), Str("foobar"), Symbol("yaycats"), Int(36865)])
println!("{edn:?}");

let edn: Edn = edn!(42 43 44);
// Int(42)
println!("{edn:?}");
}
81 changes: 81 additions & 0 deletions constexpr_edn/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
use proc_macro::TokenStream;
use std::str::FromStr;

use clojure_reader::edn::{self, Edn};

fn as_code(edn: Edn) -> String {
match edn {
Edn::Vector(vec) => {
let mut code = String::from("Edn::Vector(vec![");
for v in vec {
code.push_str(&as_code(v));
code.push(',');
}
code.push_str("])");
code
}
Edn::Set(set) => {
let mut code = String::from("Edn::Set(BTreeSet::from([");
for s in set {
code.push_str(&as_code(s));
code.push(',');
}
code.push_str("]))");
code
}
Edn::Map(map) => {
let mut code = String::from("Edn::Map(BTreeMap::from([");
let mut it = map.iter().peekable();
while let Some(m) = it.next() {
let (k, v) = m;
code.push('(');
code.push_str(&as_code(k.clone()));
code.push(',');
code.push_str(&as_code(v.clone()));
code.push(')');
if it.peek().is_some() {
code.push(',');
} else {
code.push_str("]))");
}
}
code
}
Edn::List(list) => {
let mut code = String::from("Edn::List(vec![");
for l in list {
code.push_str(&as_code(l));
code.push(',');
}
code.push_str("])");
code
}
Edn::Symbol(sy) => format!("Edn::Symbol(\"{sy}\")"),
Edn::Key(k) => format!("Edn::Key(\"{k}\")"),
Edn::Str(s) => format!("Edn::Str(\"{s}\")"),
Edn::Int(i) => format!("Edn::Int({i})"),
Edn::Double(d) => format!("Edn::Double({d})"),
Edn::Rational((n, d)) => format!("Edn::Rational({n}, {d})"),
Edn::Bool(b) => format!("Edn::Bool({b})"),
Edn::Char(c) => format!("Edn::Char({c})"),
Edn::Nil => String::from("Edn::Nil"),
e => todo!("Unexpected non-exhaustive Edn value: {e:?}."),
}
}

#[proc_macro]
pub fn edn(input: TokenStream) -> TokenStream {
let mut edn_str = String::new();
for i in input.into_iter() {
let s = i.span().source_text().unwrap();
edn_str.push_str(&s);
if !(s.starts_with('#') || s.starts_with(':')) {
edn_str.push(' ');
}
}

let edn = edn::read_string(&edn_str).unwrap();
let code = as_code(edn);

proc_macro::TokenStream::from_str(&code).unwrap()
}

0 comments on commit c3642a9

Please sign in to comment.