Skip to content

Commit

Permalink
fix: test stack overflow
Browse files Browse the repository at this point in the history
* add `erg_proc_macros` crate
  • Loading branch information
mtshiba committed Sep 11, 2023
1 parent 136d1b5 commit d04329e
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 5 deletions.
29 changes: 25 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ members = [
"crates/erg_compiler",
"crates/erg_parser",
"crates/els",
"crates/erg_proc_macros/",
]

[workspace.package]
Expand Down Expand Up @@ -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 }
Expand Down
5 changes: 4 additions & 1 deletion crates/els/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down
2 changes: 2 additions & 0 deletions crates/els/tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -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()?;
Expand Down
18 changes: 18 additions & 0 deletions crates/erg_proc_macros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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
56 changes: 56 additions & 0 deletions crates/erg_proc_macros/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use proc_macro::TokenStream;

use quote::quote;
use syn::{PathArguments, ReturnType, Type, TypePath};

/// ```ignore
/// #[exec_new_thread]
/// fn foo() -> Result<isize, Box<dyn std::error::Error>> {
/// ...
/// }
/// ```
/// ↓ ↓
/// ```ignore
/// 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()
}

0 comments on commit d04329e

Please sign in to comment.