@@ -277,4 +277,87 @@ Declarative makrolar ile aralarında bazı farklılıklar da vardır. Bunlar aş
277277
278278Procedural Macro'lar, proc-macro crate olarak adlandırılan ayrı bir kütüphanede yazılırlar. Rust söz dizimi üzerinde
279279TokenStream kullanılarak işlem yapılması bazı durumlarda zorlayıcı olabilir. syn ve quote gibi küfeler genellikle işi
280- kolaylaştıran enstrümanlar içerirler.
280+ kolaylaştıran enstrümanlar içerirler.
281+
282+ ## Örnek Procedural Macro
283+
284+ Öncelikle bir kütüphane oluşturulmalıdır.
285+
286+ ``` bash
287+ cargo new --lib procs
288+
289+ # Yardımcı küfeler
290+ cargo add quote
291+ cargo add syn -F full
292+ ```
293+
294+ Ardından toml dosyasında bu küfenin bir procedural macro olarak ele alınması gerektiği bildirilir.
295+
296+ ``` toml
297+ [lib ]
298+ proc-macro = true
299+ ```
300+
301+ Aşağıda kodun çalışma zamanının ölçen bir işlevselliğin procedural macro olarak nasıl yazılabileceği örneklenmektedir.
302+
303+ ``` rust
304+ extern crate proc_macro;
305+ use proc_macro :: TokenStream ;
306+ use quote :: quote;
307+ use syn :: {ItemFn , parse_macro_input};
308+
309+ #[proc_macro_attribute]
310+ pub fn work_time_effort (_attr : TokenStream , item : TokenStream ) -> TokenStream {
311+ let input = parse_macro_input! (item as ItemFn );
312+ let fn_name = & input . sig. ident;
313+ let fn_block = & input . block;
314+
315+ let expanded = quote! {
316+ fn #fn_name () {
317+ let start = std :: time :: Instant :: now ();
318+ #fn_block
319+ let duration = start . elapsed ();
320+ println! (" Total execution time {}: {:?}" , stringify! (#fn_name ), duration );
321+ }
322+ };
323+
324+ expanded . into ()
325+ }
326+ ```
327+
328+ İlgili makro parametre olarak TokenStream'ler alır. Özellikle item değişkeni kod içerisinde kullanılır. item değişkeni
329+ ile gelen TokenStream parse_macro_input! makrosu kullanılarak içeriği ele alınabilir bir türe dönüştürülür. Buradan
330+ hareketle makronun uygulandığı metodun adı ve gövdesi yakalanbilir.
331+
332+ İlerleyen adımda quote! makrosu ile yeni bir fonksiyon hazırlanır. Dikkat edileceği üzere gelen fonksiyon bloğunun
333+ öncesine ve sonrasına yeni kod parçaları eklenmektedir. Makro çıktı olarak üretilen yeni kod parçasını yine bir
334+ TokenStream olarak dışarı verir.
335+
336+ Bu makro herhangibir metot için aşağıdaki gibi kullanılabilir.
337+
338+ ``` rust
339+ mod samples ;
340+
341+ use procs :: work_time_effort;
342+
343+ #[work_time_effort]
344+ fn find_total () {
345+ let mut total = 0 ;
346+ for i in 0 .. 1000 {
347+ total += i ;
348+ }
349+ println! (" Result: {}" , total );
350+ }
351+
352+ fn main () {
353+ let _total = find_total ();
354+ }
355+ ```
356+
357+ Bir procedural macro küfesini kullanmak için ilgili projeye dependency olarak bildirilmesi gerekir. Bunun için toml
358+ dosyasındaki ilgili kısım değiştirilmelidir. Örneğin,
359+
360+ ``` toml
361+ [dependencies ]
362+ procs = { path = " ../procs" }
363+ ```
0 commit comments