Робота з квазіцітатамі в nemerle

Вступ
Посилання на імена
дозвіл імен
Як влаштовані імена?
Проблеми, які можуть виникнути при використанні квазіцітат
Зміни в сплайсов

Робота з квазіцітатамі в nemerle

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

Приставка «квазі» означає, що цитати можуть мати точки заповнення (placeholders), в які можна вставляти готовий AST. Такі точки в Nemerle називаються сплайсов (splice).

У Nemerle весь код представляється у вигляді AST. Це дозволяє комбінувати код, вручну написаний програмістом, з кодом, отриманим за допомогою цитат.

У цій статті мова піде про нові або нетривіальних особливості роботи з квазіцітатамі Nemerle. Так що якщо вам потрібно загальне введення в це питання, пошукайте інший матеріал.

Посилання на імена

Мабуть, найскладнішою і в той же час цікавою темою є тема формування посилань на імена всередині квазіцітат.

Nemerle підтримує так звану гігієну. На практиці це означає, що ім'я, введене в макросі (в квазіцітате всередині макросу), не може перетнутися з ім'ям, яке ввів програміст в рукописному коді. Наприклад, якщо ми створимо макрос:

У наших прикладах кінцевий колір і usesite, і global один і той же. Але це зовсім не обов'язково має бути так. Сплайс global завжди буде давати «глобальний колір», в той час як значення Сплайс usesite залежить від того, де застосовується макрос, в якому оголошено квазіцітата. Наприклад, якщо звернутися до макросу з квазіцітати, що знаходиться в іншому макросі, то кольором global буде колір макросу.

Як же визначитися з тим, який з типів сплайсов використовувати?

Моя відповідь проста - намагайтеся взагалі обійтися без слайсів. Якщо вам потрібно послатися на ім'я з іншого контексту, то спробуйте використовувати сплайс типу usesite. Якщо вам потрібно оголошувати глобально видимі імена, то скористайтеся global. А якщо вам потрібно послатися на ім'я, і ​​ніякий інший тип Сплайс використовувати не вдається, то використовуйте dyn.

Загалом, пам'ятайте, що dyn - це повне порушення правил гігієни. Використовувати його можна тільки в самому крайньому випадку.

дозвіл імен

Хоча це і не заборонено, але в макросах зовсім не обов'язково завжди писати повністю кваліфіковані імена (наприклад, для типів). Замість цього ви можете відкрити необхідні типи за допомогою директиви using і використовувати прості (складаються з одного ідентифікатора) або відносні імена:

Крім перерахованих типів сплайсов є також сплайс типу name. Він дозволяє підставити в цитату об'єкт типу Name. Про це об'єкті розказано в наступному розділі. Крім того, в цій статті є розділ, присвячений проблемам, які можуть виникнути при використанні квазіцітат, пов'язаних з цим об'єктом.

Як влаштовані імена?

Кожен макрос рівня вираження в Nemerle утворює свій унікальний контекст, з яким асоціюється унікальний «колір». «Колір» - це образний вислів, за яким ховається цілочисельний ідентифікатор, який отримують простим збільшенням.

Призначений для користувача код має колір з фіксованим ідентифікатором, який має значення «1».

Імена, що формуються в квазіцітатах, отримують колір, закріплений за конкретним контекстом. Таким чином кольору у всіх макросах рівня вираження і в рукописному коді не перетинаються. Це і називається «гігієною». Гігієна запобігає труднообнаружімие помилки, які часто зустрічаються в текстуальних макросах C / C ++ і в макросах Lisp (де ця проблема обходиться, але не так елегантно як в Nemerle).

Ім'я в Nemerle представлено класом Name:

Ось опис його полів:

  • idl - безпосередньо ім'я.
  • color - колір імені.
  • context - контекст, в якому було оголошено ім'я. Контекст зберігає інформацію, необхідну для зв'язування імені. З його допомогою можна «зв'язати» ім'я з його визначенням, не перебуваючи при цьому в процесі типізації.
  • ParsedId - ім'я в такому вигляді, в якому воно було отримано під час парсинга. Це значення іноді може відрізнятися від значення «idl», а також може бути не завжди задано.
  • Location - властивість, яка визначена базовому класі. Воно дозволяє дізнатися місце розташування ідентифікатора в коді. Якщо ідентифікатор визначений в рукописному коді, то він буде вказувати на місце його визначення. Якщо в макросі, то на місце застосування макросу або на згенерований для макросу код, якщо творець макросу захотів це зробити. Це властивість можна використовувати в повідомленнях про помилки, воно також використовується IDE для отримання метаінформації про коді.

Інформація про клас Name наводиться виключно для освітніх цілей. На практиці треба намагатися не використовувати його безпосередньо.

Проблеми, які можуть виникнути при використанні квазіцітат

Незважаючи на те, що використання квазіцітат дуже зручно і може значно спростити генерацію коду, при його використанні в Nemerle можуть виникати проблеми. Причина практично всіх цих проблем криється в спробі повторного використання об'єктів типу Name в різних місцях цитати або в різних цитатах. По суті, це помилка компілятора. Але це досить системна помилка, і усунути її не так-то просто. Поки вона не усунуто, потрібно пам'ятати про неї і робити дії, щоб вона не з'являлася.

Повторне використання може відбуватися як внаслідок ручної маніпуляції об'єктом типу Name, наприклад: