Здравствуйте, VladD2, Вы писали:
VD>Код компилятора вообще уникален. Это супер хай-тэк заключенный в обалденно малый объем исходников. Исходники компилятора 1.5 метра. А сложность превышает все что я видел. Немерле очень выразителен. Особенно если нужно описывать иерархически и дургие констуркции.
Кстати, по поводу малого объёма исходников компилятора. Вообще-то, к таким заявлениям я всегда отношусь скептически. Ничего из ничего не получается. Не бывает так, что если компилятор — это довольно сложный автомат, то в нём мало логики. Ну не бывает так. А если логики много, то как кода может быть мало? Куда он мог подеваться.
Оказалось, что так оно и есть, логики в компиляторе много, а кода действительно мало. Разработчикам удалось её
упаковать в pattern matching и варианты (алгебраические типы).
Пример.
Распаршенные выражения в компиляторе представляются классом PExpr примерно такой структуры:
public variant PExpr
{
| Array { rank : PExpr; args : PExpr; }
| Literal { val : Literal; }
| ListLiteral { elements : list [PExpr]; }
// ...
}
public variant Literal
{
| Void
| Integer { val : ulong; is_negative : bool; mutable treat_as : MType.Class; }
// ...
}
Опции варианта реализуются как сабклассы варианта. Т.е аналогичная запись на C# была бы такая:
public class PExpr
{
public class Array : PExpr
{
public PExpr rank;
public PExpr args;
}
public class Literal : PExpr
{
public Literal val;
}
public class ListLiteral : PExpr
{
public list<PExpr> elements;
}
// ...
}
public class Literal
{
public class Void : Literal
{
}
public class Integer : Literal
{
public ulong val;
public bool is_negative;
public MType.Class treat_as;
}
// ...
}
Т.е. уже здесь видна компакность записи подобных структур данных. Но это всё оказалось цветочки, по сравнению с обработкой этих данных. Вот кусочек компилятора:
match (expression)
{
// ...
| Array(Literal(Integer(r, false, _)), ListLiteral([])) =>
// ...
// ...
}
Если преобразовать этот код в C#, то мы получим примерно следующее (я попытаюсь записать в один if):
// ...
else if (
expression is PExpr.Array &&
((PExpr.Array)expression).rank is PExpr.Literal &&
((PExpr.Literal)((PExpr.Array)expression).rank).val is Literal.Integer &&
((Literal.Integer)((PExpr.Literal)((PExpr.Array)expression).rank).val).is_negative == false &&
((PExpr.Array)expression).args is PExpr.ListLiteral &&
((PExpr.ListLiteral)((PExpr.Array)expression).args).elements.Count == 0
{
ulong r = ((Literal.Integer)((PExpr.Literal)((PExpr.Array)expression).rank).val).val;
// ...
}
// ...
Желающие могут переписать это на свой лад и даже поприменять разные паттерны, но боюсь что более компактного кода, чем на Nemerle не получится.
Такой код легко писать, легко понимать. У компилятора появляются дополнительные возможности по оптимизации. А унас поднимается планка наших возможностей.
Как любил поговаривать мой первый шеф — качество/сложность чего-либо не может превышать на порядок качества/сложности инструмента, с помощью которого оно сделано.
... << RSDN@Home 1.2.0 alpha rev. 0>>