계속·경기 프로그래밍에 procedural macro를 반입
전회의 기사에서는 경기 프로그래밍에 수속형 매크로를 반입하고 싶은 동기와, 그것을 이루기 위한(별로 스마트라고는 할 수 없는) 방법을 소개했습니다. 그리고 요전날 "그렇다면 rust-analzyer (RA)는 어떻게 프로 시저 매크로를 다루고 있습니까?",
rpc
, msg
라는 단어가 눈에 들어왔습니다. 혹시 생각 아 r 지어 c 동반. MD 을 읽으면 이런 것이 쓰여져 있지 않습니까.For proc macros, the client-server model are used. We pass an argument
stdin
to stdout
binary to start a separate process ( --proc-macro
). And the client ( rust-analyzer
) provides an interface to server separately.(지금은
proc_macro_srv
가 아닌 부속 명령 proc_macro_api
와 같습니다만) 시도에 쿼리 --proc-macro
의 JSON 을 던져 버렸는데 보통으로 결과를 돌려주었습니다.$ echo '{"ListMacro":{"lib":"./target/debug/deps/libfastout-2dbcc333cc21dae5.so"}}' | rust-analyzer proc-macro
{"ListMacro":{"macros":[["fastout","Attr"]]}}
또 다른 쿼리
proc-macro
에 대해서도 ListMacro
에서 잘 JSON으로 직렬화하면 됩니다. 이제 ExpansionMacro
를 요청하지 않아도 됩니다. 이번 cargo-equip에 RA를 사용한 프로시저 매크로의 배포 기능 구현 하고, v0.10.0 로서 릴리스 했습니다. 본 기사에서는 그에 부딪힌 문제와 그 해결 방법을 써 가려고 합니다.proc-macro2 다운로드
JSON 형식은 문서화되지 않았으며 사용자가 사용하는 것도 예상되지 않습니다. 따라서 앞으로 할 일은 hack이며 단순히
watt
안의 rust-analzyer(.exe)
를 사용하면 RA 업데이트로 인해 작동하지 않을 가능성이 있습니다. 그래서 특정 버전의 바이너리를 GitHub Releases메시지 스키마
상호 작용하는 메시지의 스키마는
$PATH
에 정의되어 있습니다. rust-analzyer(.exe)
를 모방한 형태를 만들고 proc_macro_api::msg::{요청, Response}
와 tt::Subtree
와 Serialize
의 상호 Deserialize
를 구현하면 나머지는 간단하게 취급할 수 있습니다.proc_macro2::Group 크레이트의 DLL 위치
From
상자는 동적 링크 라이브러리로 컴파일됩니다. 이 위치이지만 proc-macro
의 출력을 cargo_metadata 크레이트 으로 파스하면 얻을 수 있습니다. 목표 proc-macro
는 컴파일이 건너 뛴 경우에도 포함되므로 재 컴파일을 시도 할 필요가 없습니다.cargo check --message-format json 크레이트를 컴파일하는 Rust 버전
compiler-artifact
상자는 1.47.0 이상의 Rust로 컴파일되어야합니다. 1.42.0으로 컴파일한 것을 RA에 건네주면 이렇게 됩니다.이번에는 active toolchain이 1.47.0 미만이면 rustup에 있는 툴체인을 찾아 그것을 사용하는 형태로 했습니다.
동작 예
proconio-derive 과 memoise 가 AtCoder 이외에서 사용할 수 있게 되었습니다.
#[macro_use]
extern crate memoise as _;
#[macro_use]
extern crate proconio_derive as _;
#[fastout]
fn main() {
for i in 0..=100 {
println!("{}", fib(i));
}
}
#[memoise(n <= 100)]
fn fib(n: i64) -> i64 {
if n == 0 || n == 1 {
return n;
}
fib(n - 1) + fib(n - 2)
}
↓
Output
//! # Procedural macros
//!
//! - `memoise 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)` licensed under `BSD-3-Clause`
//! - `proconio-derive 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)` licensed under `MIT OR Apache-2.0`
/*#[macro_use]
extern crate memoise as _;*/
/*#[macro_use]
extern crate proconio_derive as _;*/
/*#[fastout]
fn main() {
for i in 0..=100 {
println!("{}", fib(i));
}
}*/
fn main() {
let __proconio_stdout = ::std::io::stdout();
let mut __proconio_stdout = ::std::io::BufWriter::new(__proconio_stdout.lock());
#[allow(unused_macros)]
macro_rules ! print { ($ ($ tt : tt) *) => { { use std :: io :: Write as _ ; :: std :: write ! (__proconio_stdout , $ ($ tt) *) . unwrap () ; } } ; }
#[allow(unused_macros)]
macro_rules ! println { ($ ($ tt : tt) *) => { { use std :: io :: Write as _ ; :: std :: writeln ! (__proconio_stdout , $ ($ tt) *) . unwrap () ; } } ; }
let __proconio_res = {
for i in 0..=100 {
println!("{}", fib(i));
}
};
<::std::io::BufWriter<::std::io::StdoutLock> as ::std::io::Write>::flush(
&mut __proconio_stdout,
)
.unwrap();
return __proconio_res;
}
/*#[memoise(n <= 100)]
fn fib(n: i64) -> i64 {
if n == 0 || n == 1 {
return n;
}
fib(n - 1) + fib(n - 2)
}*/
thread_local ! (static FIB : std :: cell :: RefCell < Vec < Option < i64 > > > = std :: cell :: RefCell :: new (vec ! [None ; 101usize]));
fn fib_reset() {
FIB.with(|cache| {
let mut r = cache.borrow_mut();
for r in r.iter_mut() {
*r = None
}
});
}
fn fib(n: i64) -> i64 {
if let Some(ret) = FIB.with(|cache| {
let mut bm = cache.borrow_mut();
bm[(n) as usize].clone()
}) {
return ret;
}
let ret: i64 = (|| {
if n == 0 || n == 1 {
return n;
}
fib(n - 1) + fib(n - 2)
})();
FIB.with(|cache| {
let mut bm = cache.borrow_mut();
bm[(n) as usize] = Some(ret.clone());
});
ret
}
// The following code was expanded by `cargo-equip`.
#[allow(clippy::deprecated_cfg_attr)]#[cfg_attr(rustfmt,rustfmt::skip)]#[allow(unused)]pub mod memoise{}
#[allow(clippy::deprecated_cfg_attr)]#[cfg_attr(rustfmt,rustfmt::skip)]#[allow(unused)]pub mod proconio_derive{}
Reference
이 문제에 관하여(계속·경기 프로그래밍에 procedural macro를 반입), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/qryxip/items/d9d5eec478891a8a8c98텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)