@@ -277,4 +277,87 @@ Declarative makrolar ile aralarında bazı farklılıklar da vardır. Bunlar aş
277
277
278
278
Procedural Macro'lar, proc-macro crate olarak adlandırılan ayrı bir kütüphanede yazılırlar. Rust söz dizimi üzerinde
279
279
TokenStream 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