Logo

14 мая 2015 г.

Фрактальная модель: теория объектно-ориентированной ОС

Эта статья продолжает серию публикаций о фрактальной модели, лежащей в основе объектно-ориентированной ОС, реализация которой запланирована в рамках проекта. Предыдущие статьи серии давали определение объектно-ориентированной ОС и подчеркивали важность наследования в ООП.

Данная статья основана на материалах 2012 года, публиковавшихся на предыдущем сайте проекта и даже упомянутом в качестве литературы к одной из статей конференции «Объектные системы — 2013» (см. ссылки в конце статьи).

Сейчас текст адаптирован под текущую ситуацию в проекте и публикуется как предварительный материал к описанию фрактальной модели как ключевой концепции. Изначально планировалось разбить его на несколько частей, но поскольку тема не развивалась с 2013 года, решено опубликовать всё в одной статье, закрыв технический долг по теориям ООП.

21 марта 2015 г.

Множественное наследование и взаимная абстрактность

Этот пост по-быстрому адаптирован из моего ответа на «Тостере» ради краткого изложения некоторых принципов ООП в Канторе.

Принципы SOLID покрывают общий случай наследования в ООП, когда классы могут наследоваться друг от друга без посредничества интерфейсов. Следование SOLID должно способствовать нормализации классов, чтобы получилась сбалансированная ОО-система. При этом в самих SOLID явного правила нормализации нет, оно появляется в конкретной реализации:
Множественное наследование допустимо только от взаимно-абстрактных классов, — то есть классов, не имеющих реализации одинаковых методов. Одинаковость методов в языке определяется совместимостью по присваиванию с учетом ООП.
В языках с интерфейсами интерфейсы всегда взаимно-абстрактны реализующим их классам, поэтому классы могут реализовывать любое количество интерфейсов, принципы SOLID от этого не пострадают. Собственно, интерфейсы были введены в языки программирования ради упрощения модели наследования.

В Канторе интерфейсов нет, поэтому модель наследования — общий случай, регулируемый SOLID. Взаимная абстрактность в Канторе — отношение между классами, вычисляемое в момент компиляции. Класс-наследник не может иметь реализации свойств с одинаковыми сигнатурами, полученных от предков. Сигнатура — это комбинация имени и параметров свойства, ее уникальность определяется правилами перегрузки (overload).

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

13 февраля 2015 г.

Неоднозначность разбора и возможный возврат elsif

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

Неоднозначность

Без elsif при синтаксическом разборе всегда возникает неоднозначность, поскольку на момент входа в оператор еще не известно, единственный он во вложенном блоке или нет. Все последующие блоки также под вопросом, поскольку теперь не понятно, какой end какой блок завершает:
if условие1 then
  операторы;
else if условие2 then
  операторы;
end;
  операторы;
end; /* это лишний end или завершение предыдущего if,
        не единственного в блоке? */
С привычными отступами выглядит понятней:
if условие1 then
  операторы;
else
  if условие2 then
    операторы;
  end;
  операторы;
end;
Проблема характерна для любого языка с блочными операторами ветвления и свободной записью: SQL, Модула-2, частично Ада.

В Канторе я вижу два выхода:
  • Вернуть elsif и получить тонны ненависти от программистов, не любящих это ключевое слово.
  • Не бояться «лишних» end при разборе. Тут нужен дополнительный анализ — что делать с возможными неоднозначностями. В любом случае это усложнит компилятор и затруднит проверку синтаксиса.
Возвращение elsif, если случится, может быть частичным, — только для алгоритмических блоков. В выражениях с if/case вполне может остаться принудительное совмещение.

Принудительное совмещение в выражениях

В выражениях с if/case внутри веток могут стоять только одиночные значения или кортежи, поэтому принудительное совмещение не приводит к неоднозначности и elsif не нужен:
a = if условие1 then
  значение1 // в выражениях точка с запятой не ставится
else if условие1 then
  значение2
  // из-за отсутствия точки с запятой никакие другие операторы
  // тут недопустимы
end;
Пример с кортежем отличается только числом значений:
a, b, c = if условие1 then
  значение1, значение2, значение3 // точка с запятой опять не ставится
else if условие2 then
  значение4, значение5, значение6
end;

31 января 2015 г.

Этюд 9. Группировка свойств класса

Этот этюд перекликается со вторым этюдом, где аналог типа WordRec из Delphi описывался с использованием оператора частичного применения в Канторе. Сейчас же будет рассмотрен прямой аналог вариантной записи Delphi — при помощи ключевого слова else в теле класса. Поскольку все типы в Канторе являются классами, возможность группировки свойств добавлена прямо в классы, отдельный тип «запись» отсутствует.

На Delphi

Код на Delphi полностью взят из второго этюда:
type
  WordRec = packed record
    case Byte of
      0: (Lo, Hi: Byte);
      1: (Bytes: array [0..1] of Byte);
  end;

  LongRec = packed record
    case Byte of
      0: (Lo, Hi: Word);
      1: (Words: array [0..1] of Word);
      2: (Bytes: array [0..3] of Byte);
  end;

На Канторе

Предполагается, что аналогичная возможность в Канторе будет реализована ключевым словом else в теле класса:
public class ShortRec public of
  var Core:Byte Lo, Hi;
else
  var Core:Byte Bytes[2];
end;

public class LongRec public of
  var Core:ShortWord Lo, Hi;
else
  var Core:ShortWord ShortWords[2];
else
  var Core:Byte Bytes[4];
end;
Синтаксис пока сильно экспериментальный, поэтому пример схематичен.

Особености реализации

Запланированы следующие низкоуровневые возможности:
  • Выравнивание — конструкция align by.
  • Группировка только части свойств-переменных — полный аналог union из Си — конструкция group by.
Использованная в этюде конструкция с else может считаться упрощенной записью group by или ее совмещением с телом класса. Возможна также явная форма совмещения (экспериментальный синтаксис):
public class ShortRec public group by 1 of // совмещение, выравнивание 
  var Core:Byte Lo, Hi;                    // на 1 байт
else
  var Core:Byte Bytes[2];
end;
Группировку части свойств можно показать на примере реального класса API Windows — DRIVE_LAYOUT_INFORMATION_EX:
public class DRIVE_LAYOUT_INFORMATION_EX public align by 8 of
  var Core:LongWord PartitionStyle, PartitionCount;   // ^-- для IOCtrl
  group
    var DRIVE_LAYOUT_INFORMATION_MBR Mbr;
  else
    var DRIVE_LAYOUT_INFORMATION_GPT Gpt;
  end;
  var PARTITION_INFORMATION_EX PartitionEntry[1];
end;
Точная семантика предложенных тут конструкций еще должна быть доработана.

1 января 2015 г.

Отказ от ключевого слова elsif

Синтаксис Кантора вновь подвергся небольшому пересмотру: исключено ключевое слово elsif. Спасибо коллеге Zealint за наводку. На смену elsif приходит совмещение блоков, не требующее отдельного end. Это означает, что теперь вместо elsif нужно писать else case или else if, и ничего за это не будет.

Совмещение блоков

Совмещение блоков — синтаксический механизм в языке Кантор, позволяющий совмещать идущие друг за другом или вложенные блочные операторы с целью завершения их одним end.
В данный момент совмещение работает для блочных объявлений с of, блоков where all и where any, а теперь еще и для else case и else if.

Совмещение блоков of

// Без совмещения
public class ScreenInfo of
  final of
    var Core:Word Width, Height;
    var Core:ShortWord PixelsPerInch;
  end;
end;

// Совмещение
public class ScreenInfo final of
  var Core:Word Width, Height;
  var Core:ShortWord PixelsPerInch;
end;

Совмещение блочных условий where

Синтаксис контейнерной арифметики до конца не проработан, поэтому пример схематичен:
with
  lst = {'C', 'Cantor', 'Pascal'};
return group from lst inner where all // совмещение
  row.Length == 6;
  row.First == 'C';
end;
Идущие друг за другом операторы where all и where any совмещаются принудительно, поэтому примера без совмещения нет.

Оператор case

Объединенный оператор ветвления (следования), полученный в результате приведения if к case, теперь выглядит так:
case выражение
  when значение1 then
    ветвь;
  when значение2 then
    ветвь;
  when значение3 then
    ветвь;
else
  ветвь;
end;
При этом ветвь else совмещается, если в ней находится единственный case или if:
// Совмещение else case
case выражение1
  when значение1_1 then
    ветвь;
  when значение1_2 then
    ветвь;
  when значение1_3 then
    ветвь;
else case выражение2
  when значение2_1 then
    ветвь;
  when значение2_2 then
    ветвь;
  when значение2_3 then
    ветвь;
else
  ветвь;
end;

// Совмещение else if
case выражение1
  when значение1_1 then
    ветвь;
  when значение1_2 then
    ветвь;
  when значение1_3 then
    ветвь;
else if выражение2 then
  ветвь;
else
  ветвь;
end;
Поскольку ранее предполагалось, что записи с elsif в байт-коде должны быть неотличимы от вложенных ветвлений, совмещение лишь приближает текстовую запись к байт-коду, что улучшает воплощение концепции «Кантор — высокоуровневый ассемблер».

Оператор if

Поскольку пересмотр синтаксиса затрагивает и оператор if, его тоже приходится описывать заново:

// Одиночный оператор
if условие then
  ветвь;
else
  ветвь;
end;

// Совмещение else case
if условие then
  ветвь;
else case выражение
  when значение1 then
    ветвь;
  when значение2 then
    ветвь;
  when значение3 then
    ветвь;
else
  ветвь;
end;

// Совмещение else if
if условие1 then
  ветвь;
else if условие2 then
  ветвь;
else
  ветвь;
end;
Еще в прошлой ревизии оператор if был признан синтаксическим сахаром case, поэтому предыдущий код может быть отекстован и так:
// Одиночный оператор
case условие 
  when True then
    ветвь;
else
  ветвь;
end;

// Совмещение else case
case условие 
  when True then
    ветвь;
else case выражение
  when значение1 then
    ветвь;
  when значение2 then
    ветвь;
  when значение3 then
    ветвь;
else
  ветвь;
end;

// Совмещение else if → else case
case условие1 
  when True then
    ветвь;
else case условие2 
  when True then
    ветвь;
else
  ветвь;
end;

Строчные case и if

Строчные case и if аналогичны блочным с той разницей, что на месте ветвей выполнения стоят одиночные выражения или кортежи.

Happy = 2014++;

Казалось бы, что общего между Новым годом и разработкой ОС? А я вот недавно узнал, что новогодняя (рождественская) ёлка по-немецки — Tannenbaum, про нее даже одноименная песенка есть, у немцев она вроде нашей «В лесу родилась ёлочка». Glückliches neues Jahr an alle, то есть...

Всех с Новым годом!

Пусть в наступившем 2015-м году будет еще больше открытий и достижений!