Cách thực hiện đánh giá lười biếng của if ()


10

Tôi hiện đang triển khai một trình đánh giá biểu thức (biểu thức dòng đơn, như công thức) dựa trên các điều sau đây:

  • biểu thức đã nhập được mã hóa để phân tách booleans theo nghĩa đen, số nguyên, số thập phân, chuỗi, hàm, định danh (biến)
  • Tôi đã triển khai thuật toán Shunting-yard (được sửa đổi nhẹ để xử lý các hàm với số lượng đối số thay đổi) để loại bỏ dấu ngoặc đơn và ra lệnh cho các toán tử có mức độ ưu tiên theo thứ tự hậu tố
  • sân shunting của tôi chỉ đơn giản tạo ra một hàng mã thông báo (mô phỏng) (bằng một mảng, ngôn ngữ Powerbuilder Classic của tôi có thể định nghĩa các đối tượng, nhưng chỉ có mảng động là lưu trữ gốc - không phải danh sách thật, không có từ điển) mà tôi đánh giá tuần tự với máy xếp đơn giản

Người đánh giá của tôi đang làm việc tốt, nhưng tôi vẫn còn thiếu if()và tôi đang tự hỏi làm thế nào để tiến hành.

Với đánh giá dựa trên tiền tố và ngăn xếp shunting-yard của tôi, nếu tôi thêm if()dưới dạng một hàm khác với các phần đúng và sai, một đơn if(true, msgbox("ok"), msgbox("not ok"))sẽ hiển thị cả hai thông báo trong khi tôi chỉ muốn hiển thị một thông báo. Điều này là do khi tôi cần đánh giá một hàm, tất cả các đối số của nó đã được đánh giá và đặt vào ngăn xếp.

Bạn có thể cho tôi một số cách để thực hiện if()một cách lười biếng?

Tôi mặc dù về việc xử lý chúng như là một loại vĩ mô, nhưng tại thời điểm đầu tôi chưa đánh giá điều kiện. Có lẽ tôi cần sử dụng một loại cấu trúc khác ngoài hàng đợi để tách riêng điều kiện và biểu thức đúng / sai? Bây giờ biểu thức được phân tích cú pháp trước khi đánh giá, nhưng tôi cũng có kế hoạch lưu trữ biểu diễn trung gian dưới dạng biểu thức được biên dịch trước để đánh giá trong tương lai.

Chỉnh sửa : sau một số vấn đề, tôi nghĩ rằng tôi có thể xây dựng một biểu diễn cây biểu hiện của tôi (AST thay vì luồng mã thông báo tuyến tính), từ đó tôi có thể dễ dàng bỏ qua một hoặc một nhánh khác của tôi if().

Câu trả lời:


9

Có hai lựa chọn ở đây.

1) Đừng thực hiện ifnhư một chức năng. Làm cho nó trở thành một tính năng ngôn ngữ với ngữ nghĩa đặc biệt. Dễ làm, nhưng ít "tinh khiết" hơn nếu bạn muốn mọi thứ là một chức năng.

2) Thực hiện ngữ nghĩa "gọi theo tên", phức tạp hơn nhiều, nhưng cho phép ma thuật trình biên dịch xử lý vấn đề đánh giá lười biếng trong khi vẫn giữ ifchức năng thay vì yếu tố ngôn ngữ. Nó như thế này:

iflà một hàm có hai tham số, cả hai đều được khai báo là "theo tên". Khi trình biên dịch thấy rằng nó chuyển một cái gì đó đến một tham số theo tên, nó sẽ thay đổi mã được tạo. Thay vì đánh giá biểu thức và truyền giá trị, nó tạo ra một bao đóng để đánh giá biểu thức và thay vào đó chuyển biểu thức đó. Và khi gọi một tham số by-name bên trong hàm, trình biên dịch sẽ tạo mã để đánh giá việc đóng.


Tôi không chắc chắn, nhưng "đóng cửa" có nên "thunk" không? Hmm, có thể không; chỉ cần nhìn vào trang wikipedia: "một thunk là một đóng cửa không tham số".

Khi bạn nói "gọi theo tên" bạn đang đề cập đến trên toàn cầu? Ngoài ra, đối với tên gọi toàn cầu chỉ là thực hiện một kiểu đóng, thì hàm if chỉ mất 3 lần đóng và đánh giá hai (điều kiện và sau đó hoặc khác), nhưng không phải mọi thứ đều cần được công nhận là một bao đóng như gọi toàn bộ tên ngữ nghĩa
Jimmy Hoffa

@Matt: Thuật ngữ "thunk" có thể có nghĩa là một số điều khác trong bối cảnh lập trình và "đóng cửa không tham số" không phải là từ đầu tiên tôi nghĩ đến khi nghe nó. "Đóng cửa" rõ ràng hơn nhiều.
Mason Wheeler

1
@JimmyHoffa: Khi tôi nói "gọi theo tên", tôi đang đề cập đến một kiểu cụ thể để thiết lập một đối số chức năng, nên là tùy chọn. Giống như nhiều ngôn ngữ hiện tại sẽ cho phép bạn chọn chuyển một tham số theo giá trị hoặc theo tham chiếu, đối với kịch bản này, bạn cần lựa chọn để chuyển theo tên.
Mason Wheeler

Mặc dù đề xuất của bạn về ngữ nghĩa "gọi theo tên" đã cho tôi thấy một số điểm thú vị, nhưng nó hơi quá mức đối với người đánh giá của tôi không phải là trình biên dịch hoàn chỉnh, vì các lệnh gọi hàm của tôi là một dòng (nghĩ về các công thức MS-excel). Tôi nghĩ rằng tôi có thể thêm một bước sau khi xếp hàng các mã thông báo bằng cách thực hiện đánh giá giả về ngăn xếp để suy ra cây gọi. Nó sẽ dễ dàng hơn để biết từ cây để loại bỏ.
Seki

3

Thay vì chức năng có chữ ký:

object if(bool, object, object)

Cho nó chữ ký:

object if(bool, object function(), object function())

Sau đó, ifchức năng của bạn sẽ gọi chức năng phù hợp dựa trên điều kiện, chỉ đánh giá một trong số họ.


1

Nó khá dễ dàng, nếu bạn biên dịch mọi thứ một cách lười biếng. Bạn phải có một số phương tiện để xem nếu một giá trị đã được đánh giá, hoặc nếu nó cần thêm sự thay đổi.

Sau đó, bạn có thể làm như sau: Nếu đó là một chữ hoặc biến (bạn có những cái đó không?, Tức là tên của các hàm?), Đẩy nó lên ngăn xếp. Nếu nó là một ứng dụng của hàm, hãy biên dịch nó một cách riêng biệt và đẩy điểm vào trên ngăn xếp.

Sau đó, việc thực hiện một chương trình chỉ đơn thuần là lặp cho đến khi đỉnh của ngăn xếp được ước tính và không phải là một hàm. Nếu nó không được đánh giá hoặc một hàm, hãy gọi mã trên cùng của các điểm xếp chồng tới.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.