aboutsummaryrefslogtreecommitdiff
path: root/guests_macro
diff options
context:
space:
mode:
authorKamen Mladenov <kamen@syndamia.com>2025-01-09 14:42:47 +0200
committerKamen Mladenov <kamen@syndamia.com>2025-01-09 14:42:47 +0200
commit0d400d4c400928af565cb8de39556a2170846da1 (patch)
tree79d4c514d474ad45bbbea3769865d1069cbfc0ca /guests_macro
parentaa38a1ab0c64473bc6de7e3a5f25b416910ad235 (diff)
downloadzkVMs-benchmarks-0d400d4c400928af565cb8de39556a2170846da1.tar
zkVMs-benchmarks-0d400d4c400928af565cb8de39556a2170846da1.tar.gz
zkVMs-benchmarks-0d400d4c400928af565cb8de39556a2170846da1.zip
feat(guests_macro): Add initial implementation
Diffstat (limited to 'guests_macro')
-rw-r--r--guests_macro/Cargo.toml7
-rw-r--r--guests_macro/src/lib.rs9
-rw-r--r--guests_macro/src/parse_fn.rs138
3 files changed, 154 insertions, 0 deletions
diff --git a/guests_macro/Cargo.toml b/guests_macro/Cargo.toml
new file mode 100644
index 0000000..4a2e538
--- /dev/null
+++ b/guests_macro/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "guests_macro"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+proc-macro = true
diff --git a/guests_macro/src/lib.rs b/guests_macro/src/lib.rs
new file mode 100644
index 0000000..84f2365
--- /dev/null
+++ b/guests_macro/src/lib.rs
@@ -0,0 +1,9 @@
+use proc_macro::TokenStream;
+mod parse_fn;
+
+#[proc_macro_attribute]
+pub fn proving_entrypoint(_: TokenStream, mut item: TokenStream) -> TokenStream {
+ let (name, args, ret) = parse_fn::split_fn(&item);
+ item.extend(format!("#[macro_export] macro_rules! entrypoint_expr {{ () => {{ make_wrapper!({}{} {}) }}; }}", name, args, ret).parse::<TokenStream>());
+ item
+}
diff --git a/guests_macro/src/parse_fn.rs b/guests_macro/src/parse_fn.rs
new file mode 100644
index 0000000..e78fb1b
--- /dev/null
+++ b/guests_macro/src/parse_fn.rs
@@ -0,0 +1,138 @@
+use proc_macro::{ TokenStream, TokenTree, Delimiter, Spacing, Group };
+
+/// Input: "fn name(...) -> ... { ... }"
+/// Output: "name", "(...)", "-> ..."
+pub fn split_fn(item: &TokenStream) -> (TokenStream, TokenStream, TokenStream) {
+ let item = item.clone().into_iter();
+
+ let mut name = TokenStream::new();
+ let mut args = TokenStream::new();
+ let mut ret = TokenStream::new();
+ let mut out: &mut TokenStream = &mut name;
+
+ for tt in item {
+ match tt {
+ // The conditions will later be used to return
+ // errors when incorrect function type is used
+ TokenTree::Ident(ref ident) => {
+ if ident.to_string() == "fn" || ident.to_string() == "pub" {
+ continue;
+ }
+ },
+ TokenTree::Punct(ref punct) => {
+ if punct.as_char() == '-' {
+ out = &mut ret;
+ }
+ },
+ TokenTree::Group(ref group) => {
+ if group.delimiter() == Delimiter::Brace {
+ break;
+ }
+ if ! out.is_empty() {
+ out = &mut args;
+ }
+ },
+ TokenTree::Literal(_) => unreachable!("Cannot have literal inside def!"),
+ }
+ out.extend([tt].into_iter());
+ }
+
+ (name, args, ret)
+}
+
+/// Input: "(p1 : t1, p2: t2, ...)"
+/// Output: "p1 : t1", "p2: t2", ...
+pub fn args_split(item: &TokenStream) -> Vec<TokenStream> {
+ let contents;
+ if let TokenTree::Group(group) = item.clone().into_iter().next().unwrap() {
+ contents = group.stream().into_iter();
+ }
+ else {
+ unreachable!();
+ }
+
+ let mut args = Vec::new();
+ let mut ts = TokenStream::new();
+
+ for tt in contents {
+ match tt {
+ TokenTree::Punct(ref punct) =>
+ if punct.as_char() == ',' {
+ args.push(ts);
+ ts = TokenStream::new();
+ continue;
+ },
+ _ => {},
+ }
+
+ ts.extend([tt].into_iter());
+ }
+
+ if ! ts.is_empty() {
+ args.push(ts);
+ }
+ args
+}
+
+/// Input: (p1 : t1, p2: t2, ...)
+/// Output: (p1, p2, ...), (t1, t2, ...)
+pub fn args_divide(item: &TokenStream) -> (Vec<TokenStream>, Vec<TokenStream>) {
+ let contents;
+ if let TokenTree::Group(group) = item.clone().into_iter().next().unwrap() {
+ contents = group.stream().into_iter();
+ }
+ else {
+ unreachable!();
+ }
+
+ let mut patterns = Vec::new();
+ let mut types = Vec::new();
+ let mut ts = TokenStream::new();
+ let mut ignore_next = false;
+
+ for tt in contents {
+ match tt {
+ TokenTree::Punct(ref punct) => {
+ if punct.spacing() == Spacing::Joint {
+ ignore_next = true;
+ }
+ else if !ignore_next {
+ match punct.as_char() {
+ ':' => {
+ patterns.push(ts);
+ ts = TokenStream::new();
+ continue;
+ },
+ ',' => {
+ types.push(ts);
+ ts = TokenStream::new();
+ continue;
+ },
+ _ => {},
+ }
+ }
+ else {
+ ignore_next = false;
+ }
+ },
+ _ => {},
+ }
+
+ ts.extend([tt].into_iter());
+ }
+
+ types.push(ts);
+ (patterns, types)
+}
+
+/// Input: "p1 p2 ..."
+/// Output: "(p1, p2, ...)"
+pub fn group_streams(patterns: &Vec<TokenStream>) -> TokenStream {
+ let mut inner_ts = TokenStream::new();
+ inner_ts.extend(patterns.clone().into_iter().flat_map(|i| [i, ",".parse().unwrap()]));
+
+ let mut out = TokenStream::new();
+ out.extend([TokenTree::Group(Group::new(Delimiter::Parenthesis, inner_ts))].into_iter());
+
+ out
+}