fix: test stack overflow

* add `erg_proc_macros` crate
This commit is contained in:
Shunsuke Shibayama 2023-09-11 16:24:37 +09:00
parent 136d1b56f6
commit 1e0985e6c3
6 changed files with 107 additions and 5 deletions

29
Cargo.lock generated
View file

@ -101,6 +101,7 @@ version = "0.1.33-nightly.1"
dependencies = [
"erg_common",
"erg_compiler",
"erg_proc_macros",
"lsp-types",
"molc",
"serde",
@ -143,6 +144,15 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "erg_proc_macros"
version = "0.6.21-nightly.1"
dependencies = [
"erg_common",
"quote",
"syn 1.0.109",
]
[[package]]
name = "form_urlencoded"
version = "1.2.0"
@ -247,9 +257,9 @@ dependencies = [
[[package]]
name = "molc"
version = "0.1.0"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a19b669aab31ca7552fc43cb9ab08e325113aa090f7bf97a2112b3d6241ba898"
checksum = "9485212d67a88d2169ee683420e1a2fe763afb96a3901ebfabb5ba095d0d2eaa"
dependencies = [
"lsp-types",
"serde",
@ -375,7 +385,7 @@ checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.31",
]
[[package]]
@ -397,7 +407,7 @@ checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.31",
]
[[package]]
@ -436,6 +446,17 @@ version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.31"

View file

@ -17,6 +17,7 @@ members = [
"crates/erg_compiler",
"crates/erg_parser",
"crates/els",
"crates/erg_proc_macros/",
]
[workspace.package]
@ -68,6 +69,7 @@ erg_common = { version = "0.6.21-nightly.1", path = "./crates/erg_common" }
erg_parser = { version = "0.6.21-nightly.1", path = "./crates/erg_parser" }
erg_compiler = { version = "0.6.21-nightly.1", path = "./crates/erg_compiler" }
els = { version = "0.1.33-nightly.1", path = "./crates/els" }
erg_proc_macros = { version = "0.6.21-nightly.1", path = "./crates/erg_proc_macros" }
[dependencies]
erg_common = { workspace = true }

View file

@ -23,11 +23,14 @@ experimental = ["erg_common/experimental", "erg_compiler/experimental"]
[dependencies]
erg_common = { workspace = true, features = ["els"] }
erg_compiler = { workspace = true, features = ["els"] }
molc = { version = "0.1.0" }
molc = { version = "0.2" }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.85"
lsp-types = { version = "0.93.2", features = ["proposed"] }
[dev-dependencies]
erg_proc_macros = { workspace = true }
[lib]
path = "lib.rs"

View file

@ -9,6 +9,7 @@ const FILE_B: &str = "tests/b.er";
const FILE_IMPORTS: &str = "tests/imports.er";
use els::{NormalizedUrl, Server};
use erg_proc_macros::exec_new_thread;
use molc::{add_char, oneline_range};
#[test]
@ -146,6 +147,7 @@ fn test_goto_definition() -> Result<(), Box<dyn std::error::Error>> {
}
#[test]
#[exec_new_thread]
fn test_folding_range() -> Result<(), Box<dyn std::error::Error>> {
let mut client = Server::bind_fake_client();
client.request_initialize()?;

View file

@ -0,0 +1,18 @@
[package]
name = "erg_proc_macros"
version.workspace = true
authors.workspace = true
license.workspace = true
edition.workspace = true
repository.workspace = true
homepage.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
erg_common = { workspace = true }
syn = { version = "1.0", features = ["full"] }
quote = "1.0"
[lib]
proc-macro = true

View file

@ -0,0 +1,56 @@
use proc_macro::TokenStream;
use quote::quote;
use syn::{PathArguments, ReturnType, Type, TypePath};
/// ```rust_
/// #[exec_new_thread]
/// fn foo() -> Result<isize, Box<dyn std::error::Error>> {
/// ...
/// }
/// ```
/// ↓ ↓
/// ```rust_
/// fn foo() -> Result<isize, Box<dyn std::error::Error>> {
/// fn error(msg: impl Into<String>) -> std::io::Error {
/// std::io::Error::new(std::io::ErrorKind::Other, msg.into())
/// }
/// fn f() -> Result<(), Box<dyn std::error::Error + Send>> {
/// {...}.map_err(|e| Box::new(error(e.to_string())) as _)
/// }
/// exec_new_thread(f, "foo").map_err(|e| e as _)
/// }
/// ```
#[proc_macro_attribute]
pub fn exec_new_thread(_attr: TokenStream, item: TokenStream) -> TokenStream {
let mut item_fn = syn::parse_macro_input!(item as syn::ItemFn);
let name = item_fn.sig.ident.to_string();
let ReturnType::Type(_, out) = &item_fn.sig.output else {
todo!()
};
let Type::Path(TypePath { path, .. }) = out.as_ref() else {
todo!()
};
let result_t = path.segments.first().unwrap();
let PathArguments::AngleBracketed(args) = &result_t.arguments else {
todo!()
};
let t = args.args.first().unwrap();
let name = syn::LitStr::new(&name, item_fn.sig.ident.span());
let block = item_fn.block;
let block = syn::parse_quote! {{
fn error(msg: impl Into<String>) -> std::io::Error {
std::io::Error::new(std::io::ErrorKind::Other, msg.into())
}
fn _f() -> Result<#t, Box<dyn std::error::Error>> {
#block
}
fn f() -> Result<#t, Box<dyn std::error::Error + Send>> {
_f().map_err(|e| Box::new(error(e.to_string())) as _)
}
erg_common::spawn::exec_new_thread(f, #name).map_err(|e| e as _)
}};
item_fn.block = Box::new(block);
let item = quote! { #item_fn };
item.into()
}