diff options
| author | Edvard Thörnros <edvard.thornros@gmail.com> | 2021-03-07 17:50:18 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-03-07 17:50:18 +0100 |
| commit | 09c830296fdb55efbc7f590337ce72f5ec75c04b (patch) | |
| tree | 2411baac44a8ce88fcb90e35db68fba018aefb81 /sylt_macro | |
| parent | a9d943e2d93be0e741874cb1ef85488dacc6eeab (diff) | |
| parent | eab567c57dd41439ad4328a287baddda3e3270a8 (diff) | |
| download | sylt-09c830296fdb55efbc7f590337ce72f5ec75c04b.tar.gz | |
Merge pull request #91 from FredTheDino/compiler-rewrite
WIP: Rewrite the compiler
Diffstat (limited to 'sylt_macro')
| -rw-r--r-- | sylt_macro/Cargo.lock | 45 | ||||
| -rw-r--r-- | sylt_macro/Cargo.toml | 5 | ||||
| -rw-r--r-- | sylt_macro/src/lib.rs | 104 |
3 files changed, 145 insertions, 9 deletions
diff --git a/sylt_macro/Cargo.lock b/sylt_macro/Cargo.lock new file mode 100644 index 0000000..137e02a --- /dev/null +++ b/sylt_macro/Cargo.lock @@ -0,0 +1,45 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "proc-macro2" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "sylt_macro" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "1.0.62" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "123a78a3596b24fee53a6464ce52d8ecbf62241e6294c7e7fe12086cd161f512" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "unicode-xid" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" diff --git a/sylt_macro/Cargo.toml b/sylt_macro/Cargo.toml index 9ac045e..6d3c75f 100644 --- a/sylt_macro/Cargo.toml +++ b/sylt_macro/Cargo.toml @@ -10,5 +10,6 @@ proc-macro = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -syn = { version = "1.0", features=["full"] } -quote = "1.0" +syn = { version = "1", features=["full"] } +proc-macro2 = "1" +quote = "1" diff --git a/sylt_macro/src/lib.rs b/sylt_macro/src/lib.rs index 3b8b37c..95b79c6 100644 --- a/sylt_macro/src/lib.rs +++ b/sylt_macro/src/lib.rs @@ -1,5 +1,6 @@ -use proc_macro::TokenStream; -use quote::quote; +use std::path::Path; + +use quote::{format_ident, quote}; use syn::{Expr, Pat, Token, parse::{Parse, ParseStream, Result}, parse_macro_input}; struct ExternBlock { @@ -43,7 +44,7 @@ impl Parse for ExternFunction { } #[proc_macro] -pub fn extern_function(tokens: TokenStream) -> TokenStream { +pub fn extern_function(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream { let parsed: ExternFunction = parse_macro_input!(tokens); let function = parsed.function; @@ -89,7 +90,7 @@ pub fn extern_function(tokens: TokenStream) -> TokenStream { } } }; - TokenStream::from(tokens) + proc_macro::TokenStream::from(tokens) } struct LinkRename { @@ -137,9 +138,8 @@ impl Parse for Links { } } - #[proc_macro] -pub fn link(tokens: TokenStream) -> TokenStream { +pub fn link(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream { let links: Links = parse_macro_input!(tokens); let links: Vec<_> = links.links.iter().map(|link| { @@ -157,5 +157,95 @@ pub fn link(tokens: TokenStream) -> TokenStream { let tokens = quote! { vec![ #(#links),* ] }; - TokenStream::from(tokens) + proc_macro::TokenStream::from(tokens) +} + +struct TestSettings { + errors: Option<String>, + print: bool, +} + +impl Default for TestSettings { + fn default() -> Self { + Self { + errors: None, + print: true, + } + } +} + +fn parse_test_settings(contents: String) -> TestSettings { + let mut settings = TestSettings::default(); + + for line in contents.split("\n") { + if line.starts_with("// errors: ") { + settings.errors = Some(line.strip_prefix("// errors: ").unwrap().to_string()); + } else if line.starts_with("// flags: ") { + for flag in line.split(" ").skip(2) { + match flag { + "no_print" => { + settings.print = false; + } + _ => { + panic!("Unknown test flag '{}'", flag); + } + } + } + } + } + + settings +} + +fn find_test_paths(directory: &Path) -> proc_macro2::TokenStream { + let mut tests = quote! {}; + + for entry in std::fs::read_dir(directory).unwrap() { + let path = entry.unwrap().path(); + let file_name = path.file_name().unwrap().to_str().unwrap(); + + if file_name.starts_with("_") { + continue; + } + + if path.is_dir() { + tests.extend(find_test_paths(&path)); + } else { + assert!(!path.to_str().unwrap().contains(","), "You should be ashamed."); + + let path_string = path.to_str().unwrap(); + let test_name = format_ident!("file_{}", file_name.replace(".sy", "")); + + let settings = parse_test_settings(std::fs::read_to_string(path.clone()).unwrap()); + let print = settings.print; + let tokens = if let Some(wanted_errs) = settings.errors { + let wanted_errs: proc_macro2::TokenStream = wanted_errs.parse().unwrap(); + quote! { + test_file!(#test_name, #path_string, #print, #wanted_errs); + } + } else { + quote! { + test_file!(#test_name, #path_string, #print); + } + }; + + tests.extend(tokens); + } + } + + let directory = directory.file_name().unwrap().to_str().unwrap().replace("/", ""); + let directory = format_ident!("{}", directory); + quote! { + mod #directory { + #tests + } + } +} + +#[proc_macro] +pub fn find_tests(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream { + assert!(tokens.is_empty()); + + let tokens = find_test_paths(Path::new("progs/")); + proc_macro::TokenStream::from(tokens) } |
