using System.Collections.Generic;
namespace Oyster.Units.Macros
{
/// Stores compile-time information for UnitsDefinition macromodule CompileTimeInfo
{
/// List of basis unit names in correct orderpublic mutable BasisUnits : list[string] = [];
/// List of all common units (including basis ones)public mutable CommonUnits : list[string] = [];
/// Map of common unit powerspublic PowersMap : Dictionary[string, list[int]] = Dictionary();
}
}
IUnit.n:
namespace Oyster.Units
{
/// Interface for all unitspublic interface IUnit {}
}
NormCoefAttribute.n:
using System;
namespace Oyster.Units
{
/// Unit normalization coefficient attribute
[AttributeUsage(AttributeTargets.Class)]
public class NormCoefAttribute : Attribute
{
public NormCoef : double;
public this (normCoef : double)
{
NormCoef = normCoef
}
}
}
, как подоспела следующая. В версии 0.03 использован workaround, предложенный разработчиками Nemerle для обхода бага и, как результат, я избавился от боксинга в конструкторе, т.е. теперь решение действительно на 100% на value-типах
Новую версию забираем тут: Oyster.Units.0.03.zip. Для сборки надо использовать Nemerle билд r6176 — не ниже (как и для предыдущей версии).
PS: Исходники текстом не выкладываю — они почти не изменились.
Re: Версия 0.03 - скажем "нет" боксингу :)
От:
Аноним
Дата:
10.04.06 08:52
Оценка:
Здравствуйте, Oyster, Вы писали:
O>Новую версию забираем тут: Oyster.Units.0.03.zip. Для сборки надо использовать Nemerle билд r6176 — не ниже (как и для предыдущей версии).
Для того, чтобы проинсталлировать билд, что должно уже стоять на машине? Необходимо ли наличие питона, antlr и ряда прочих вещей, которые проверяются в ./configure? Какую версию make.exe следует использовать?
Здравствуйте, <Аноним>, Вы писали:
А>Для того, чтобы проинсталлировать билд, что должно уже стоять на машине? Необходимо ли наличие питона, antlr и ряда прочих вещей, которые проверяются в ./configure? Какую версию make.exe следует использовать?
У меня WinXP и я просто поставил cygwin, как советуют сами разработчики. Поэтому я не знаю, что ещё надо ставить — ставил почти всё по умолчанию (кроме make — см. ниже).
Знаю точно, что нужен gmake, а не стандартный make, — это было написано где-то в доках.
Re[3]: установка Nemerle
От:
Аноним
Дата:
10.04.06 10:00
Оценка:
Здравствуйте, Oyster, Вы писали:
O>У меня WinXP и я просто поставил cygwin, как советуют сами разработчики. Поэтому я не знаю, что ещё надо ставить — ставил почти всё по умолчанию (кроме make — см. ниже).
O>Знаю точно, что нужен gmake, а не стандартный make, — это было написано где-то в доках.
Спасибо.
Случаем не встречались с такой проблемой: make останавливается на 3-ем stage после компиляции ncc.exe с ошибкой
*** No rule to make target '../../ncc/out.stage/', needed by 'Nemerle.dll'. Stop.
Здравствуйте, Vermicious Knid, Вы писали:
VK>Но есть идея и более простая. И макрос, и оператор можно зарегистрировать вручную через API компилятора(см. модуль MacroRegistry). Макрос это по сути экземпляр некого класса, реализовывающего интерфейс IMacro. Нужно просто написать собственную реализацию IMacro вручную(т.е. не использовать встроенную в компилятор генерацию этого класса), которая в зависимости от того как ее инициализируют будет вести себя как разные макросы(т.е. с разными именами и генерировать различный код).
Как ты уже знаешь, эта идея мне понравилась. В общем, я начал думать о том, как реализовать unit-алиасы с её помощью и столкнулся с маленькой проблемкой. Дело в том, что в текущей версии библиотеки
unit-типы можно определять как в той же сборке, где они используются, так и в другой сборке, и я хочу сохранить такое поведение. Вот в варианте с другой сборкой и возникает проблема — надо как-то создать и загеристрировать макросы при загрузке сборки компилятором.
Я думал над этой проблемой и пришёл к такому вот решению:
Unit-алиасы (такие как kg — клиограммы — или m — метры, — например) сохраняются в неком атрибуте уровня сборки (или в любом другом хранилище в сборке с unit-типами).
Также в этой сборке создаётся псевдо-макрос, который ничего не умеет и в конструкторе которого создаются и регистрируются макросы для unit-алиасов. На сборку цепляется ContainsMacroAttribute и, как результат, конструктор этого псевдо-макроса выполняется при загрузке сборки LibraryLoader-ом.
Конечно, возможен и другой вариант — генерация классов макросов для unit-алиасов, но этого не хочется делать из-за желания использовать код повторно.
Собственно, мой вопрос звучит так — можно ли то же самое сделать как-то иначе? Т.е. существует ли какой-нибудь другой способ выполнить код при загрузке сборки кроме ContainsMacroAttribute и конструктора макроса?
Re[7]: [Nemerle] Семантический контроль над размерностями
Здравствуйте, Oyster, Вы писали:
O>Конечно, возможен и другой вариант — генерация классов макросов для unit-алиасов, но этого не хочется делать из-за желания использовать код повторно.
На самом деле, мы можем просто создавать типы для макросов, регистрировать их ручками, если в той же сборке, и не мучаться с добавлением ещё каких-то вспомогательных атрибутов (кроме [ContainsMacro] и [Operator]). Естественно, это возможно только при условии, если мы можем из макроса добавить атрибуты сборке — я ещё не разбирался с этим вопросом. Кстати, это утверждение также справедливо для варианта из предыдущего сообщения.
При таком подходе снова встаёт вопрос — а могу ли я просто создать новый макрос внутри макроса, используя знакомый мне синтаксис macro и не переопределяя IMacro вручную?
Ну вот и следующий билд библиотеки подоспел: Oyster.Units.0.04.zip (собирать на Nemerle версии r6192, не ниже).
В этом билде разработчики языка исправили кое-какие баги, поэтому код библиотеки тоже был исправлен местами. Но самое главное, конечно, не это. Самое главное то, что этот билд добавляет возможность работы с физическими литералами, о которых в этом топике уже писали. В общем, теперь можно писать код вроде такого:
def m3 = 1 g;
def m4 = Si.Mass(m1);
WriteLine($"Mass in SI: $m4, in CGS: $m3");
def x1 = Si.Area(1 cm * 10 m);
WriteLine($"Area of 1 cm * 10 m = $x1 m")
1 g, 1 cm и 10 m из примера выше — это как раз физические литералы. Задаются они непосредственно в DSL вот таким вот образом:
basisUnits (Si)
(
Mass[ kg ],
Length[ m ],
Time[ sec ],
Temperature[ K ],
CurrentStrength[ A ],
LightIntensity,
QuantityOfSubstance
)
Т.е. после любого имени юнита можно указать имя литерала в квадратных скобках (уникальное в пределах данного описания). При этом в библиотеку, в которой находится описание юнитов, будет скомпилирован соответствующий макро-оператор, доступный при подключении пространства имён Oyster.Units.Macros.
У решения всё равно есть некоторые недостатки:
На данный момент нельзя навесить атрибут на сборку из макро-атрибута, который сам навешен на сборку. Не знаю, исправят ли это в будущем (т.е. баг ли это), но сейчас макро-атрибут UnitsDefinition (в котором задаётся описание юнитов) задан с MacroTargets.Class (т.е. его обязательно надо вешать на какой-то — неважно, какой — класс).
Принципиально нельзя использовать юнит-литералы из той же сборки, в которой расположено описание юнитов. Это связано с тем, что юнит-литералы определяются как макро-операторы (использована идея
Vermicious Knid-а), а оператор нельзя создать и использовать в той же сборке (поскольку информация об операторе должна быть известна на этапе парсинга, а создаётся он в макросе, который выполняется уже после парсинга).
В описании физических юнитов заданы не все литералы (лень). Надеюсь, описание будет наполнено теми людьми, которым действительно будет нужна эта библиотека (если таковые найдутся).
Тем не менее, все эти недостатки достаточно невелики и не мешают пользоваться библиотекой.
В заключение хочу сказать, что библиотека подобралась к своему логическому завершению и вряд ли будет развиваться дальше. Возможно, будут исправляться ошибки, но не более того.
Re[2]: [Nemerle] Семантический контроль над размерностями
В общем, хотя реально сама библиотека будет бесполезна для 99% программистов и проектов, но 3 огромные задачи ты ею решил:
1. Нашел кучу багов в компиляторе.
2. Создал изумительный пример разработки DSL. Очень советую, кстати, запостить его в форум Немерла посвященный примерам. Можно со ссылкой на С++-ный аналог.
3. Доказал приемущество макросов над шаблонным метапрограммированием и вообще их гибкость.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: [Nemerle] Семантический контроль над размерностями
Здравствуйте, VladD2, Вы писали:
O>>Знаю точно, что нужен gmake, а не стандартный make, — это было написано где-то в доках. VD>Стандартного мэйка нет в природе.
Да, глупость сказал... Я имел в виду, "нужен не тот make, который ставится с cygwin по умолчанию, а gmake".
Здравствуйте, VladD2, Вы писали:
VD>2. Создал изумительный пример разработки DSL. Очень советую, кстати, запостить его в форум Немерла посвященный примерам. Можно со ссылкой на С++-ный аналог.
Да, это я как раз и хотел сделать. Вот найду время, поперевожу некоторые комменты на англицкий, получу разрешение у CrystaX и сделаю, мабуть.
Здравствуйте, Oyster, Вы писали:
O>Да, это я как раз и хотел сделать. Вот найду время, поперевожу некоторые комменты на англицкий, получу разрешение у CrystaX и сделаю, мабуть.
Давай. Зело полезное дело!
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.