2013-10-24 16 views
13

Nếu tôi có một vĩ mô mà tranforms mã như:Tại sao vũ trụ phản xạ thời gian chạy và vũ trụ macro tạo ra hai cây khác nhau cho scala.None?

(src: a.b.c.TestEntity) => 
    { 
     z.y.TestTable(None) 
    } 

Để phù hợp với Không một phần của AST mà tôi có thể sử dụng một vắt như:

object NoneExtractor { 
    def unapply(t: Tree): Boolean = t match { 
     case Select(Ident(scala), none) if scala.encoded == "scala" && none.encoded == "None" => true 
     case _ => false 
    } 
    } 

Khi showRaw của Không phần của AST trông giống như:

Select(Ident(scala), None) 

Tuy nhiên, nếu tôi muốn viết kiểm tra đơn vị của NoneExtractor Tôi không muốn biên dịch và xây dựng lại các macro và lưu trữ thử nghiệm trong dự án macro đang biên dịch. Tôi muốn kiểm tra đơn vị vắt trong dự án của vĩ mô mà cho thấy sự phản ánh thời gian chạy là cách để đi với:

val t = reify { 

    (src: a.b.c.TestEntity) => 
    { 
     z.y.TestTable(None) 
    } 

}.tree 

Tuy nhiên, cây là hoàn toàn khác nhau và trong các showRaw đó cây None trông giống như:

Ident(scala.None) 

Đây là tin xấu để viết các kiểm tra tiêu cực và kiểm tra xử lý lỗi của macro của tôi. Bạn không thể viết kiểm tra tiêu cực cho một macro bằng cách sử dụng macro từ một dự án khác vì mã sẽ không biên dịch (và bạn không thể gỡ lỗi thử nghiệm âm tính của mình với các lỗi biên dịch).

Tại sao các biểu diễn của một cái gì đó là cơ bản như Không có gì khác biệt giữa phản ánh thời gian biên dịch và phản ánh thời gian chạy? Có cách nào để tạo ra các đoạn cây có thể kiểm thử trong dự án macro có cùng AST như được trao cho macro trong khi phản ánh thời gian biên dịch không?

+0

Chọn ra một giá trị cụ thể dựa trên đại diện cây của nó luôn luôn là một chút khó khăn, ngay cả khi bạn đang hoàn toàn trong đất vĩ mô. Bạn có thể làm điều gì đó như 't.tpe =: = typeOf [None.type]' thay thế không? –

+0

Tôi thực sự cần phải làm cấu trúc phù hợp với AST với các câu lệnh lồng nhau. Tôi mới đến chức năng vì vậy tôi đã bắt đầu với if/then/else/gọi mã phong cách bắt buộc. Đó là khoảng năm lần mã bây giờ mà tôi đang tái cấu trúc để phù hợp với chức năng/trường hợp/trận đấu/trường hợp/.... api vũ trụ vĩ mô có một số lượng lớn các bộ giải nén được xây dựng trong. Vì vậy, sự hiểu biết của tôi rằng vắt và kết hợp lồng nhau là cách kinh điển để làm điều này. Câu hỏi của tôi là làm thế nào để kiểm tra cách kinh điển hơn là một câu hỏi về cách thực hiện một cách tiếp cận hoàn toàn khác. – simbo1905

Trả lời

0

Để giải quyết sự không thống nhất này, bạn có thể sử dụng quasiqoutes sắp tới trong kết hợp mẫu của bạn. Họ trừu tượng đi những AST và do đó sẽ làm việc với cả hai cơ quan đại diện (AST là trình biên dịch cụ thể dù sao, Scala là một ngôn ngữ biên dịch duy nhất cho bây giờ nhưng nó không phải là quá tốt đẹp để dựa vào biểu nội bộ của trình biên dịch):

case q"_root_.scala.None" => ... 

sẽ khớp với cả hai AST. Ngoài ra, bạn có thể tạo cây với q"_root_.scala.None" để bạn không phải lo lắng về biểu diễn. Reify sẽ trở nên lỗi thời khi quasiquotes được phát hành với scala 2.11. Để sử dụng quasiquotes với scala 2.10 bạn có thể sử dụng macro paradise.

Here is a nice WIP guide on scala quasiquotes.

Các vấn đề liên quan