Як реалізувати ледачу оцінку if ()


10

Зараз я впроваджую оцінювач виразів (однорядкові вирази, як формули) на основі наступного:

  • введений вираз є токенізованим для розділення буквальних булевих, цілих чисел, десяткових знаків, рядків, функцій, ідентифікаторів (змінних)
  • Я реалізував алгоритм Shunting-ярда (злегка модифікований для обробки функцій зі змінною кількістю аргументів), щоб позбутися дужок і замовити операторів з гідним пріоритетом у постфікс-порядку
  • мій маневровий двір просто створює (змодельовану) чергу з лексем (за допомогою масиву моя мовою Powerbuilder Classic може визначати об'єкти, але мати лише динамічні масиви як власне сховище - не справжній список, ні словник), який я оцінюю послідовно простий автомат

Мій оцінювач працює непогано, але мені все одно не вистачає if()і мені цікаво, як діяти далі.

З моїм маневровим оцінкою на постфіксах та на основі стека, якщо я додаю if()як іншу функцію з істинними та хибними частинами, одиниця if(true, msgbox("ok"), msgbox("not ok"))покаже обидва повідомлення, тоді як я хотів би показати лише одне. Це тому, що коли мені потрібно оцінити функцію, всі її аргументи вже були оцінені та розміщені у стеці.

Не могли б ви дати мені якийсь спосіб здійснити if()ледачий спосіб?

Я хоч і оброблю їх як своєрідний макрос, але на ранній стадії ще не маю оцінку стану. Можливо, мені потрібно використовувати інший тип структури, крім черги, щоб окремо зберегти умову та істинні / хибні вирази? Наразі вираз проаналізовано перед оцінкою, але я також планую зберігати проміжне представлення як вид попередньо складеного виразу для подальшої оцінки.

Редагувати : після деяких проблем, я думаю, що я міг би створити дерево зображення мого виразу (AST замість лінійного потоку токенів), з якого я міг легко ігнорувати ту чи іншу гілку мого if().

Відповіді:


9

Тут є два варіанти.

1) Не реалізуйте ifяк функцію. Зробіть це мовною особливістю із особливою семантикою. Це легко зробити, але менш "чисто", якщо ви хочете, щоб усе було функцією.

2) Запровадити семантику "виклик по імені", що набагато складніше, але дозволяє магіці компілятора піклуватися про проблему ледачого оцінювання, зберігаючи ifяк функцію замість мовного елемента. Виходить так:

ifце функція, яка приймає два параметри, обидва з яких оголошуються як "по імені". Коли компілятор бачить, що він передає щось параметру імені, він змінює код, який буде генеруватися. Замість того, щоб оцінювати вираз і передавати значення, він створює завершення, яке оцінює вираз, і передає це натомість. І коли викликає параметр імені всередині функції, компілятор генерує код для оцінки закриття.


Я не впевнений, але чи варто "закриття" бути "громом"? Хм, може, ні; щойно переглянув сторінку вікіпедії: "громовідвід - це параметр, який не має значення параметрів".

Коли ви говорите "дзвоніть по імені", ви маєте на увазі глобально? Альтернативно глобальному дзвінку за іменем є лише реалізація типу закриття, тоді функція if просто займає 3 закриття та оцінює дві (умова, а потім чи інше), але не все потрібно визнати закриттям, таким як повне виклик- ім'я семантики
Джиммі Хоффа

@Matt: Термін "громоподібний" може означати кілька інших речей в контексті програмування, і "закриття параметрів" - це не перше, про що я думаю, коли чую це. "Закриття" набагато більш однозначне.
Мейсон Уілер

1
@JimmyHoffa: Коли я кажу "зателефонуй по імені", я маю на увазі конкретний стиль настройки аргументу функції, який повинен бути необов'язковим. Так само, як і багато існуючих мов дозволять вам вибрати параметр за значенням або посиланням, для цього сценарію вам потрібен вибір для передачі імені.
Мейсон Вілер

Хоча Ваша пропозиція щодо семантики "дзвінок по імені" показала мені кілька цікавих моментів, для мого оцінювача це є трохи надмірним, але це не повний компілятор, оскільки виклики моїх функцій однолінійні (подумайте про формули MS-excel). Я думаю, що міг би додати крок після черги жетонів, зробивши псевдооцінку стека, щоб вивести дерево виклику. Слід від дерева простіше дізнатись, які гілки відкинути.
Секі

3

Замість функції, що має підпис:

object if(bool, object, object)

Дайте йому підпис:

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

Тоді ваша ifфункція викличе відповідну функцію на основі умови, оцінюючи лише одну з них.


1

Це досить просто, якщо скласти все ліниво. Ви повинні мати певні засоби, щоб побачити, чи значення вже оцінено, чи воно потребує більшої евлауації.

Тоді ви можете зробити наступне: Якщо це буквальна чи змінна (у вас є такі? Тобто імена функцій?), Натисніть її на стек. Якщо це додаток функції, компілюйте її окремо і натисніть на точку входу на стеку.

Виконання програми - це лише циклічне циклування, доки не буде оцінено верхню частину стека, а не функція. Якщо він не оцінений або функція, зателефонуйте до коду, який вказує вгорі стека.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.