Re[22]: Оффтопик: Nemerle
От: IT Россия linq2db.com
Дата: 10.09.06 05:53
Оценка: 8 (2) +1
Здравствуйте, 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>>
Если нам не помогут, то мы тоже никого не пощадим.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.