Tôi bắt đầu thêm các bao đóng (lambdas) vào ngôn ngữ của tôi sử dụng LLVM làm phụ trợ. Tôi đã triển khai chúng cho các trường hợp đơn giản, nơi chúng có thể luôn được gạch chân, tức là mã cho định nghĩa đóng cửa chính nó không cần phải được tạo ra, vì nó được gạch chân ở nơi được sử dụng.Làm thế nào để thực hiện hiệu quả các bao đóng trong LLVM IR?
Nhưng cách tạo mã để đóng trong trường hợp đóng không phải lúc nào cũng được gạch chân (ví dụ, nó được chuyển đến một hàm khác không được gạch chân). Tốt hơn là, các trang web cuộc gọi không nên quan tâm liệu chúng có được truyền các chức năng hay đóng cửa thông thường hay không và sẽ gọi chúng là các hàm bình thường.
Tôi có thể tạo hàm có tên tổng hợp, nhưng sẽ phải lấy môi trường tham chiếu làm đối số bổ sung và hàm đó không thể được chuyển cho hàm khác không biết về đối số thừa cần thiết.
Tôi đã nghĩ về một giải pháp có thể sử dụng nội tại trampoline của LLVM, "excise" một tham số duy nhất từ một hàm, trả về một con trỏ tới hàm trampoline có một tham số ít hơn. Trong trường hợp này, nếu hàm được tạo ra cho việc đóng cửa lấy môi trường tham chiếu làm tham số đầu tiên, tôi có thể loại bỏ nó và lấy lại một hàm lấy chính xác nhiều tham số như việc đóng thực sự khai báo. Âm thanh này có thể thực hiện được không? Hiệu quả? Có giải pháp nào tốt hơn không?
Mã dụ:
def applyFunctionTo(value: Int, f: (Int) -> Int) = f(value)
def main() = {
val m := 4;
val n := 5;
val lambda := { (x: Int) => x + m + n };
applyFunctionTo(3, lambda)
}
Bây giờ, cho phép tưởng tượng rằng điều này sẽ không nhận được inlined để def main() = 3 + 4 + 5
, và rằng applyFunctionTo
sẽ có thể được biên dịch riêng biệt, và chúng ta không thể thay đổi địa điểm cuộc gọi đó. Với trampolining, tôi tưởng tượng mã được tạo ra sẽ giống như thế này (được biểu thị bằng mã giả, * có nghĩa là con trỏ):
def main$lambda$1(env: {m: Int, n: Int}*, x: Int) = x + env.m + env.n
def main() = {
m = 4
n = 5
env* = allocate-space-for {Int, Int}
env = {m, n}
tramp* = create-trampoline-for(main$lambda$1*, env*)
return applyFunctionTo(3, tramp*)
// release memory for env and trampoline if the lambda didn't escape
}
Điều này có đúng không?
Không có sự khác biệt giữa việc triển khai các đóng và thực hiện các đối tượng bằng các phương thức ảo. –
Có thể bạn đã đúng, tuy nhiên, ngôn ngữ sẽ không có các phương thức ảo (chưa). Ít nhất nó sẽ có bao đóng và rất nhiều thứ khác trước đó. Tôi có thể thêm một số tính năng theo thứ tự ngu ngốc bởi vì tôi chỉ làm nó cho mục đích học tập, chủ yếu. Tôi chỉ hy vọng rằng một cái gì đó hữu ích đến từ nó cuối cùng. –
Tôi có nghĩa là không có lý do để phát minh ra bất cứ điều gì mới cho đóng cửa: bạn chỉ có thể làm điều tương tự như, nói, một trình biên dịch C + + đã làm.Rất có thể là nó đã là điều hiệu quả nhất để làm. –