Провел масштабную модернизацию механизма связывания (binding-а).
Зачем это нужно и что это дает?
В Nitra биндинг встроен в библиотеки. Код биндинга зашит в библиотечный ast
Reference.
Это дает некоторую автоматику и обобщенный принцип. Но это несло в себе существенный недостаток. Дело в том, что связывание всегда производится с базовым типом символа DeclarationSymbol. Это значит, что связывании проводится с первым попавшимся символом. В дальнейшем, во время резолва, можно уточнить тип символа, но если в области видимости был символ неподходящего типа, то мы получали ошибку, так как информация о затененных (этим символом) других символов терялась.
Я долго думал что сделать, чтобы можно было производить связывание (или уточнение связывания) с затененными сиволами. В итоге остановился на следующем решении.
Теперь связывание проходит не с конкретным символом или их списком (в случае неоднозначности), а со специальным типом способным хранить иерархию символов. Это вариантный тип
BindResult[TSymbol]. Он может хранить следующие варианты (и их комбинации):
| Single
| Multiple
| Hiding
| Union
| Nil
Можно сказать, что этот тип повторяет иерархию областей видимости (Scope-в), но без излишних деталей и вложенности.
Этот тип сам по себе может отражать пустое связывание (т.е. отсутствие подходящих символов), неоднозначное связывание, а так же отражает информацию о сокрытии и объединение символов.
Для этого типа доступны методы:
public Filter[TConcreteSymbol]() : BindResult[TConcreteSymbol]
where TConcreteSymbol : DeclarationSymbol
/// Filter by predicate. Filter by TConcreteSymbol If predicate is null.
public Filter[TConcreteSymbol](predicate : Predicate[TConcreteSymbol]) : BindResult[TConcreteSymbol]
where TConcreteSymbol : DeclarationSymbol
public Map[TConcreteSymbol](algorithm : ResolutionAlgorithm[TSymbol, TConcreteSymbol]) : BindResult[TConcreteSymbol]
where TConcreteSymbol : DeclarationSymbol
Которые позволяют фильтровать BindResult[TSymbol] по типу и значению символов и отображать BindResult[X] на BindResult[Y].
Связывание более 1 символа не является автоматически ошибкой, так как в процессе резолва лишние символы могут быть отброшены.
То что BindResult хранит иерархию сокрытия позволяет процедуре резолва пройти по иерархии вниз отбросив скрывающие символы и взять скрытые. Так если произошло связывание с локальной переменной, но процедура резолва хочет произвести связывание с одноименным типом, она может отфильтровать BindResult по типу и отбросить, таким образом, локальные переменные и поля.
Так же BindResult удобен и для связывания с членами (members) типов, так как естественным образом представляет как неоднозначность, так и сокрытие одноименных символов базового типа.
Претерпел изменения и
Ref[TSymbol] используемый в Nitra при резолве. Ref[TSymbol] перестал быть вариантным, так как за хранение информации о неоднозначности и неудаче резолва или связывания переехала в BindResult.
В задачи Ref теперь входит кэширование значения символов, описание взаимосвязей резовлва (по средствам свойства ResolvedTo) и информировании пользователя о неудаче связывания.
У Ref[TSymbol] есть ряд наследников оптимизирующих хранение и кэширование данных.
Ну, и Ref[TSymbol] по-прежнему реализуют псевдо-зависимые свойства позволяющие использовать их в коде вычисления зависимых свойств.
Немного изменился интерфейс ast-а Reference и типа Scope. Их методы Bind, как бы, вывернуты наизнанку.
Теперь методы Bind у Scope возвращают BindResult[TSymbol], а метод Reference.Bind принимает в качестве параметра Scope и возвращает Ref[TSymbol].
public partial class Reference : AstBase
{
public Bind[TSymbol](scope : Scope) : Ref[TSymbol]
where TSymbol : DeclarationSymbol
...
}
public abstract class Scope : ISerializable
{
public abstract Bind[TSymbol](reference : Reference) : BindResult[TSymbol] where TSymbol : DeclarationSymbol;
public abstract Bind[TSymbol](isMatch : Predicate[TSymbol]) : BindResult[TSymbol] where TSymbol : DeclarationSymbol;
...
}
Кроме того был убран метод Scope.BindMany. Зато появился метод Bind принимающий предикат. Так же бы удален метод автодополнение при вводе. Теперь его роль будет играть метод Bind принимающий предикат.
Здравствуйте, VladD2, Вы писали:
VD>VD>| Single
VD>| Multiple
VD>| Hiding
VD>| Union
VD>| Nil
VD>
Почему Nil? У нас везде для обозначения отсутствия значения используется None.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Здравствуйте, WolfHound, Вы писали:
WH>Почему Nil? У нас везде для обозначения отсутствия значения используется None.
Как говорится — я знал, что по другим вопросам вопросов не будет. (ц)
Ну, как-то у списков и деревьев это принято было называть Nil. Если честно, особо не задумывался. Если это претит твоему чувству прекрасного, можешь переименовать.
Но нам сейчас намного важнее, чтобы заработал атрибут разрешающий неоднозначность. До этого грамматика шарпа будет неоднозначной.