Điều này bắt đầu như một câu hỏi SO nhưng tôi nhận ra rằng nó khá độc đáo và dựa trên mô tả thực tế trên các trang web, nó có thể phù hợp hơn với các lập trình viên. Vì câu hỏi này có trọng lượng lớn về mặt khái niệm.
Tôi đã học clang LibTooling và nó là một công cụ rất mạnh có khả năng phơi bày toàn bộ "gritty" của mã theo cách thân thiện, nghĩa là, theo cách ngữ nghĩa , và không phải bằng cách đoán. Nếu clang có thể biên dịch mã của bạn, thì clang chắc chắn về ngữ nghĩa của mỗi ký tự bên trong mã đó.
Bây giờ cho phép tôi lùi lại một lát.
Có nhiều vấn đề thực tế phát sinh khi một người tham gia vào siêu lập trình mẫu C ++ (và đặc biệt là khi mạo hiểm vượt ra ngoài các mẫu vào lãnh thổ của các macro thông minh mặc dù đáng sợ). Thành thật mà nói, đối với nhiều lập trình viên, bao gồm cả tôi, nhiều cách sử dụng thông thường của các mẫu cũng có phần đáng sợ.
Tôi đoán một ví dụ tốt sẽ là chuỗi thời gian biên dịch . Đây là một câu hỏi đã hơn một năm tuổi, nhưng rõ ràng C ++ tính đến thời điểm hiện tại không làm cho điều này trở nên dễ dàng đối với những người bình thường. Mặc dù nhìn vào các tùy chọn này không đủ để gây buồn nôn cho tôi, tuy nhiên tôi vẫn không tự tin về việc có thể tạo ra mã máy hiệu quả, tối đa để phù hợp với bất kỳ ứng dụng ưa thích nào tôi có cho phần mềm của mình.
Ý tôi là, hãy đối mặt với nó, folks, chuỗi khá đơn giản và cơ bản. Một số người trong chúng ta chỉ muốn một cách thuận tiện để phát ra mã máy có một số chuỗi nhất định "được nướng" nhiều hơn đáng kể so với khi chúng ta mã hóa nó theo cách đơn giản. Trong mã C ++ của chúng tôi.
Nhập clang và LibTooling, hiển thị cây cú pháp trừu tượng (AST) của mã nguồn và cho phép ứng dụng C ++ tùy chỉnh đơn giản xử lý chính xác và đáng tin cậy mã nguồn thô (sử dụng Rewriter
) cùng với mô hình hướng đối tượng ngữ nghĩa phong phú của mọi thứ trong AST. Nó xử lý rất nhiều thứ. Nó biết về các mở rộng vĩ mô và cho phép bạn theo các chuỗi đó. Vâng, tôi đang nói về chuyển đổi hoặc dịch mã nguồn-nguồn.
Luận điểm cơ bản của tôi ở đây là clang bây giờ cho phép chúng ta tạo ra các tệp thực thi mà chính chúng có thể hoạt động như các giai đoạn tiền xử lý tùy chỉnh lý tưởng cho phần mềm C ++ của chúng ta và chúng ta có thể thực hiện các giai đoạn siêu lập trình này với C ++. Chúng tôi chỉ đơn giản bị hạn chế bởi thực tế là giai đoạn này phải lấy đầu vào là mã C ++ hợp lệ và tạo ra như đầu ra mã C ++ hợp lệ hơn. Cộng với bất kỳ hạn chế nào khác hệ thống xây dựng của bạn áp dụng.
Đầu vào ít nhất phải rất gần với mã C ++ hợp lệ bởi vì, sau tất cả, clang là giao diện của trình biên dịch và chúng tôi chỉ chọc vào và sáng tạo với API của nó. Tôi không biết có bất kỳ quy định nào để có thể xác định cú pháp mới để sử dụng hay không, nhưng rõ ràng chúng tôi phải phát triển các cách phân tích chính xác và thêm nó vào dự án clang để thực hiện điều này. Mong đợi nhiều hơn là có một cái gì đó trong dự án clang nằm ngoài phạm vi.
Không thành vấn đề. Tôi sẽ tưởng tượng rằng một số chức năng macro không có op có thể xử lý công việc này.
Một cách khác để xem những gì tôi mô tả là triển khai các cấu trúc siêu lập trình bằng cách sử dụng thời gian chạy C ++ bằng cách thao tác AST của mã nguồn của chúng tôi (nhờ clang và API của nó) thay vì triển khai chúng bằng các công cụ hạn chế hơn có sẵn trong ngôn ngữ. Điều này cũng có các lợi ích hiệu suất biên dịch rõ ràng (các tiêu đề nặng mẫu chậm biên dịch chậm tỷ lệ thuận với mức độ thường xuyên bạn sử dụng chúng. Rất nhiều công cụ được biên dịch sau đó được liên kết cẩn thận và bỏ đi bởi trình liên kết).
Tuy nhiên, điều này phải trả giá bằng việc giới thiệu một hoặc hai bước bổ sung trong quá trình xây dựng và cả yêu cầu viết một số phần mềm dài dòng (thừa nhận) phần nào (nhưng ít nhất đó là thời gian chạy đơn giản C ++) như một phần của công cụ của chúng tôi .
Đó không phải là toàn bộ bức tranh. Tôi khá chắc chắn rằng có một không gian chức năng lớn hơn nhiều có thể có được từ việc tạo mã cực kỳ khó khăn hoặc không thể với các tính năng ngôn ngữ cốt lõi. Trong C ++, bạn có thể viết mẫu hoặc macro hoặc kết hợp cả hai, nhưng trong công cụ clang, bạn có thể sửa đổi các lớp và hàm theo bất kỳ cách nào bạn có thể đạt được với C ++, trong thời gian chạy , trong khi có quyền truy cập đầy đủ vào nội dung ngữ nghĩa, ngoài mẫu và macro và mọi thứ khác.
Vì vậy, tôi tự hỏi tại sao mọi người không làm điều này. Có phải chức năng này từ clang rất mới và không ai quen thuộc với hệ thống phân cấp lớp khổng lồ của AST của clang? Đó không thể là nó.
Có lẽ tôi chỉ đánh giá thấp độ khó của điều này một chút, nhưng thực hiện "thao tác chuỗi thời gian biên dịch" với một công cụ clang thì gần như đơn giản. Thật dài dòng, nhưng nó hoàn toàn đơn giản. Tất cả những gì cần thiết là một loạt các hàm macro không hoạt động, ánh xạ tới các std::string
hoạt động thực tế thực sự . Plugin clang thực hiện điều này bằng cách tìm nạp tất cả các lệnh gọi macro không liên quan và thực hiện các thao tác với chuỗi. Công cụ này sau đó được chèn vào như một phần của quá trình xây dựng. Trong quá trình xây dựng, các lệnh gọi hàm macro không op này được tự động đánh giá vào kết quả của chúng và sau đó được chèn lại dưới dạng các chuỗi thời gian biên dịch cũ đơn giản trong chương trình. Chương trình sau đó có thể được biên dịch như bình thường. Trong thực tế, chương trình kết quả này cũng dễ mang theo hơn nhiều, do đó không yêu cầu trình biên dịch mới lạ mắt hỗ trợ C ++ 11.