Изучаем макросы Nemerle
От: VladD2 Российская Империя www.nemerle.org
Дата: 18.02.06 16:45
Оценка: 180 (16)
Единственный способ развеить скепсис — это попробовать.

Я решил попробовать макросы Nemerle в более-менее реальной задаче. Цель две.
1. Изучить собственно Nemerle и его макросы.
2. Продемонстрировать его возможности на этом форуме.

Я планирую несколько сообщений которые будут являться подсообщениями этого.

Так как многие из вас захотят попробовать приводимый мною код, то начнем пожалуй с подготовительного этапа. Конечно в реальных условиях многие из вас предпочту полноценную IDE и какую-нибудь утилиту сборки (make, Ant или MSBuild), но учитывая, что для данного случая скорее важна простота вхождения, я решил остановиться на Сцинтиле как редакторе и обычном бач-файле для сборки проекта. Ведь нам пока что достаточно компилировать два файла (сборку с макросами и целевую сборку).

Итак, для экспериментов вам понадобится:
1. .NET Framework 2.0 (и возможно SDK). Лучше конечно если на машине просто установлена VS 2005.
2. Компилятор Nemerle и сопутствующая ему байда. Все это можно взять на их сайте http://nemerle.org. Так здесь http://nemerle.org/download/msi/nemerle-0.9.2.msi лежит инсталлятор для Виндовс. А здесь http://nemerle.org/download/ можно взять более свежую рабочую версию причем вместе с исходниками. Очень советую это сделать даже если вы выберете инсталляцию msi-я, так как поглядеть на исходники макросво и вообще на исподники созданные авторами языка очень полезно. Полноценной документации ведь пока нет, а исходники говорят о многом.
2. Сцинтила или другой редактор который упростить ввод и тестирование кода. Сцентилу можно взять здесь: http://prdownloads.sourceforge.net/scintilla/wscite167.zip?use_mirror=heanet
Файлы для обеспечения подсветки синтаксиса Nemerle для Сцинтылы можно взять здесь:
http://nemerle.org/svn/nemerle/trunk/misc/scintilla/SciTEGlobal.properties
http://nemerle.org/svn/nemerle/trunk/misc/scintilla/nemerle.properties
их нужно скопировать в каталог где лежат другие properties-файлы Сцинтилы.
3. Для упрощения компиляции и запуска файлов я написал простенький cmd-файлик для ХРюши:
@echo off

SET FileName=%1

SET MacroOutFileName=%FileName%-macro.dll
SET MacroSourceFileName=%FileName%-macro.n

SET SourceFileName=%FileName%.n
SET OutFileName=%FileName%.exe

if exist %MacroSourceFileName% (
  @echo --# Compiling Macro-assembly #---
  @echo ---------------------------------
  ncc.exe -no-color -debug+ -r Nemerle.Compiler.dll -t:dll %MacroSourceFileName% -out %MacroOutFileName%
  if not errorlevel 1 (
    @echo --- Compiling target assembly ---
    @echo ---------------------------------
    ncc.exe -no-color  -debug+ -r %MacroOutFileName% -t exe %SourceFileName% -o %OutFileName%
    rem -r System.Windows.Forms -r System.Data 
    if errorlevel 1 (
      @echo -------------------------------------
      @echo !!! Error detected in targer code !!!
    ) else (
      @echo --------------- OK -----------------
      @echo --Run: %OutFileName%
      @echo .
      %OutFileName%
    )
  ) else (
    @echo ------------------------------------
    @echo !!! Error detected in macro-code !!!
  )
) else (
  @echo ----- No Macro-assembly found ------
  @echo ------------------------------------
  if not errorlevel 1 (
    @echo --- Compiling target assembly ---
    @echo ---------------------------------
    ncc.exe -no-color  -debug+ -t exe %SourceFileName% -o %OutFileName%
    rem -r System.Windows.Forms -r System.Data 
    if errorlevel 1 (
      @echo -------------------------------------
      @echo !!! Error detected in targer code !!!
    ) else (
      @echo --------------- OK -----------------
      @echo --- Run: %OutFileName%
      @echo .
      %OutFileName%
    )
  ) else (
    @echo ------------------------------------
    @echo --! Error detected in macro-code !--
  )
)

Его нужно сохранить под именеме build-and-run.cmd в каталог где лежат бинарники Нэмерла (файл ncc.exe и т.п.).
Далее нужно отредактировать файл nemerle.properties добавив в него примерно такие строчки:
#Extra tool: Build With Macro and Run
#Build macro and target for console application"
command.name.6.*.n=Build With Macro and Run
command.6.*.n=build-and-run.cmd $(FileName)
command.6.subsystem.*.n=0
command.save.before.6.*.n=1
command.shortcut.6.*.n=F5

При этом, если что, нужно или изменить F5 на удобную для себя кнопку, или убрать/изменить аналогичный шорткат у имеющегся в nemerle.properties пункта.

Теперь открыв в Сцинтиле файл с расширением .n вы можете просто нажатием на F5 скомпилировать его и запустить на выполнение.
Если при этом рядом с компилируемым файлом будет лежать файл начальная часть имени которого совпадает с компилируемым, и оно оканчивается на «-macro», то сначала будет произведена компиляция этого файла. А потом, вслучае успеха будет откомплирован вайл без суффикса «–macro». Причем при его компиляции будет подключаться макросборка получившаяся на первом этапе. Например, если имеются файлы:
test-001.n
test-001-macro.n

если активизировать в Сцинтиле файл test-001.n и нажать F5, то будет сначала произвдена компиляция макросборки test-001-macro.dll (на базе файла test-001-macro.n), а потом будет произведена компиляция сборки test-001.exe (на базе файла test-001.n). Причем при компиляции test-001.exe будет использована макро-сборк полученная на первом этапе.
Если все скомпилируется, то будет произведен запуск test-001.exe. Иначе будет выданы сообщения об ошибке.

Для того, чтобы убедиться, что все работает создайте простенькую тестовую пару файлов:
Test-001.n – содержащий следующий код:
// abstract, and, array, as, base, catch, class, def, delegate, do, else, enum, event, extern, false, finally, for, foreach, fun, if, implements, in, interface, internal, lock, macro, match, module, mutable, namespace, new, null, out, override, params,  
// WriteLine public private protected internal

TestMacro();

Примечание: Коментарии с лабудой нужны для того, чтобы можно было пользоваться недо-интелисенсом. Если в Сцинтиле написат первые буквы слова и нажать Ctrl+Enter, то она выдаст список слов начинающихся на эти буквы.


И файл test-001-macro.n содержащий следующий код:
using System.Console;
// abstract, and, array, as, base, catch, class, def, delegate, do, else, enum, event, extern, false, finally, for, foreach, fun, if, implements, in, interface, internal, lock, macro, match, module, mutable, namespace, new, null, out, override, params,  
// WriteLine public private protected internal

macro TestMacro()
{
  WriteLine("compile-time\n");
  <[ WriteLine("run-time\n") ]>;
}

Теперь откройте Сцинтилой файл Test-001.n и нажмите F5.
Если в ответ вы увидите следующее:
>build-and-run.cmd test-001
--# Compiling Macro-assembly #---
---------------------------------
--- Compiling target assembly ---
---------------------------------
compile-time

--------------- OK -----------------
--Run: test-001.exe
.
run-time

>Exit code: 0

Значит вы все сделали верно и первый этап знакомства с Нэмерлом и его макросами пройдет.

Если вам сказали, что мол файл не найдет, то пропишите путь к каталогу с бинарниками Нэмерла в переменную PATH окружения.

Теперь прокомментирую, что вы видите на экране. Вывод:
---------------------------------
--- Compiling target assembly ---
---------------------------------
compile-time

Означает что началась компиляция основной сборки (сборки которую мы будем запускать на исполнение) и вызвался макрос. Который вывел информацию о себе на констоль. Надпись:
run-time

Ввел код сгенерированный макросом. Если вы теперь откроете полученный исполнимый файл Рефлектором, то увидите, что в функции Main() присутствует вызов:
Console.WriteLine("run-time\n");

а от макроса не осталось и следа. Это и есть чудесное действие макросов.

Продолжение следует.
... << RSDN@Home 1.2.0 alpha rev. 637>>

14.03.06 11:09: Перенесено из 'Философия программирования'
30.01.07 18:23: Перенесено модератором из 'Декларативное программирование' — IT
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.