\input mmm.sty

\Theme{Описание языка MMMl}

Программа на языке \MMMl представляет собой последовательность
слов, разделенных пробелами, табуляциями, переводами строки и.т.д.
Все эти символы за исключением NL считаются равными.
Символ {\tt '\%'} считается началом комментария, который заканчивается на
ближайшем NL (переводе строки).
Последовательность любых символов, за исключением NL, между двумя
одинарными двойными кавычками считается символьной или строковой
константой соответственно.

\underbar{{\it Замечание:}} На данный момент реализовано все
    ниженаписанное за исключением команды {\tt eval}.


%&<<&\theme{Функции. }
\theme{Функции. }
Логически программа состоит из функций. Функция начинается со слова
{\tt proc}, за которым следует название функции и заканчивается словом
{\tt endp}. Весь текст, находящийся до {\tt proc} или после {\tt endp},
может рассматриваться как комментарий.
%&<<&proc Example
\halign{
  {\tt # } \hfil & {\tt \%} {\it # } \hfil \cr
proc MyProc                & начало функции MyProc \cr
  \quad \nothing           & тело функции  \cr
endp                       & \cr
}
%&>>&3 0 3 22

%&>>&5 0 5 28
%&<<&\theme{Структуры данных. }
\theme{Структуры данных. }
В распоряжение пользователя предоставлен стек, способный содержать
целые числа, строки, фолды. Также пользователь имеет доступ
к целочисленной переменной {\tt Flag}. При проверке логических условий
значению {\tt False} соответствует {\tt Flag $=$0},
значению {\tt True} соответствует {\tt Flag $\not=$0}.

%&>>&2 0 2 0
%&<<&\theme{Операторы условного перехода, цикла. }
\theme{Операторы условного перехода, цикла. }
Когда в программе встречен оператор {\tt if}, то происходит проверка
переменной {\tt Flag} и, в зависимости от этого выполняется
или группа операторов от {\tt if} до {\tt else},
или группа операторов от {\tt else} до {\tt endif}

%&<<&if/endif Example

\Example  Использование {\tt if} с {\tt else}:

\halign{
  {\tt # } \hfil & {\tt \%} {\it # } \hfil \cr
if                         & происходит проверка {\tt Flag} \cr
  \quad \nothing           & Группа операторов выполняющихся при {\tt True} \tt \cr
else                       & \cr
\quad \nothing             & Группа операторов выполняющихся при {\tt False} \tt \cr
endif                      & \cr
}

\Example  Использование {\tt if} без {\tt else}:

\halign{
  {\tt # } \hfil & {\tt \%} {\it # } \hfil \cr
if                         & происходит проверка {\tt Flag} \cr
  \quad \nothing           & Группа операторов выполняющихся при {\tt True} \tt \cr
endif                      & \cr
}

%&>>&C 0 C 9

Когда в программе встречен оператор {\tt do}, то часть программы
от {\tt do} до {\tt enddo} выполняется до тех пор, пока
значение {\tt Flag} равно {\tt True}.

%&<<&do/enddo Example

\Example Использование {\tt do}

\halign{
  {\tt # } \hfil & {\tt \%} {\it # } \hfil \cr
do                         & происходит проверка {\tt Flag} \cr
  \quad \nothing           & Тело цикла, выполняется при {\tt True} \cr
enddo                      & \cr
}

%&>>&1 0 1 9

%&>>&3 0 3 0
%&<<&\theme{Константы: }
\theme{Константы: }
Целочисленной константой в \MMMl считается слово, начинающееся с цифры.
Прочитывается в шестнадцатеричном виде.

\Examples целочисленные константы {\tt 0238, 9a5kj, 0bbb} прочитываются как
шестнадцатеричные числа 238, 9a5, bbb соответственно.

Символьной константой считается первый символ в последовательности
символов между двумя одинарными кавычками.

Строковой константой считается последовательность любых
символов, за исключением NL, между двумя двойными кавычками.
Если в строке не найден закрывающий символ {\tt "}, то
строковой константой считаются символы начиная от
открывающей кавычки до предпоследнего символа в строке.

Когда при обработке программы встречается константа, то она кладется на
стек, и при этом символьные константы, почти так же как и в языке {\tt C},
рассматриваются просто как альтернативная запись целочисленных констант.

%&>>&14 0 14 1
%&<<&\theme{Команды для работы со стеком}
\theme{Команды для работы со стеком}

{\tt swp } -- поменять местами 2 верхних элемента на стеке.

{\tt del } -- удалить верхний элемент стека.

{\tt dup } -- продублировать верхний элемент стека.

{\tt sget } -- если $a$ -- вершина стека, то снять и положить {\tt stack[$a$]}.

{\tt sput } -- извлечь из стека эл-т $a1$,  извлечь из стека эл-т $a2$,
             заменить {\tt stack[$a1$]} на $a2$.

%&>>&0 0 0 E
%&<<&\theme{Арифметические и логические операции: }
\theme{Арифметические и логические операции: }
{\tt mathop } -- снять со стека число $co$
           снять со стека число  $a1$,
           снять со стека число  $a2$,
выполнить операцию $a2 \star a1$, положить результат на стек.
Здесь $\star$ -- операция, соответствующая коду $co$.
Понятно, что все операции {\tt add, sub,} ... легко выражаются
через {\tt mathop} посредством определения соответствующих функций.

\halign{ \hskip 1 true cm {\tt #} \hfil --- & # \hfil & ({\tt #} \hfil )\cr
    0    &  Сложение                & MATHOP\_ADD  \cr
    1    &  Вычитание               & MATHOP\_SUB  \cr
    2    &  Умножение               & MATHOP\_MUL  \cr
    3    &  Деление                 & MATHOP\_DIV  \cr
    4    &  Остаток от деления      & MATHOP\_MOD  \cr
    5    &  Побитовая операция and  & MATHOP\_AND  \cr
    6    &  Побитовая операция or   & MATHOP\_OR   \cr
    7    &  Побитовая операция xor  & MATHOP\_XOR  \cr
    }

%&>>&7 0 7 3B
%&<<&\theme{Предикаты: }
\theme{Предикаты: }
{\tt predicate } --  снять со стека число $co$
                     снять со стека число $a1$,
                     снять со стека число $a2$,
    затем проверить истинность выражения
    $a1 \star a2$  и положить
    результат в {\tt Flag} (значению {\tt True} соответствует 1,
    значению {\tt False} соответствует 0).
    Здесь $\star$ -- операция, соответствующая коду $co$.
Понятно, что все предикаты  {\tt eq, ne, lt, } ... легко выражаются
через {\tt predicate } посредством определения соответствующих функций.

\halign{ \hskip 1 true cm {\tt #} \hfil --- & # \hfil & ({\tt #} \hfil )\cr
    0 & {\tt eq} Проверка на равенство   & PREDICATE\_EQ \cr
    1 & {\tt ne} Проверка на неравенство & PREDICATE\_NE \cr
    2 & {\tt lt} Проверка на ''меньше''  & PREDICATE\_LT \cr
    3 & {\tt gt} Проверка на ''больше''  & PREDICATE\_GT \cr
    }

%&>>&A 0 A 3F
%&<<&\theme{Команды опроса и преобразования типа: }
\theme{Команды опроса и преобразования типа: }

{\tt query } -- положить на стек число соответствующее типу объекта,
            лежащего на вершине стека.

\halign{ \hskip 1 true cm {\tt #} \hfil --- & # \hfil & ({\tt #} \hfil )\cr
    0 & Line   & SDATA\_LINE     \cr
    1 & int    & SDATA\_INT      \cr
    2 & string & SDATA\_STRING   \cr
    }

{\tt convert } -- снять со стека число $ct$,
              снять со стека объект $a$, выполнить над $а$ преобразование,
              соответствующее числу $ct$ и положить результат на стек.

\halign{ \hskip 1 true cm {\tt #} \hfil --- & # \hfil & ({\tt #} \hfil )\cr
    0 & преобразовать int $\to$ string (hex)   & CONVERT\_I2SH    \cr
    1 & преобразовать int $\to$ string (dec)   & CONVERT\_I2SD    \cr
    2 & преобразовать string $\to$ int (hex)   & CONVERT\_S2IH    \cr
    3 & преобразовать string $\to$ int (dec)   & CONVERT\_S2ID    \cr
    4 & преобразовать string $\to$ Line        & CONVERT\_S2L     \cr
    5 & преобразовать Line $\to$ string        & CONVERT\_L2S     \cr
    6 & преобразовать int $\to$ char           & CONVERT\_I2C     \cr
    7 & преобразовать string[1] $\to$ int      & CONVERT\_C2I     \cr
    }

%&>>&0 0 0 2E
%&<<&\theme{Команды ввода/вывода: }
\theme{Команды ввода/вывода: }

{\tt pop} -- Если на вершине стека лежит {\tt int }, то его значение
                        помещается в {\tt Flag}.
         Если на вершине стека лежит строка, то она печатается в
                        текущей позиции.
         Если на вершине стека лежит {\tt Line} или {\tt Fold}, то он
                        вставляется в текст.

%&<<&{\tt push} --  снять со стека число $ct$ и выполнить операцию {\tt push}
{\tt push} --  снять со стека число $ct$ и положить на стек объект
                соответствующий коду $ct$.

\halign{ \hskip 1 true cm {\tt #} \hfil --- & # \hfil & ({\tt #} \hfil )\cr
   0 &  {\tt Flag} (как int)                          & PUSH\_FLAG     \cr
   1 &  текущая строка или {\tt Fold} (как Line)      & PUSH\_CLINE\_L \cr
   2 &  текущая строка или {\tt Fold} (как строка)    & PUSH\_CLINE\_S \cr
   3 &  Char clipboard  (как строка)                  & PUSH\_CCB      \cr
   4 &  Line Clipboard (как Fold)                     & PUSH\_LCB      \cr
   5 &  Символ под курсором, как int                  & PUSH\_CHAR     \cr
   }

%&>>&9 0 9 48

%&<<&{\tt ioctl} -- команда для опроса состояния редактора.
{\tt ioctl} -- команда для опроса состояния редактора.
       С вершины стека команда снимает номер выполняемой команды.
      В приведенной далее таблице {\it Опросить }
      значит положить результат в {\tt Flag}.

\halign{ \hskip 1 true cm {\tt #} \hfil --- & # \hfil & ({\tt #} \hfil )\cr
  0x1 &  Опросить, включен ли режим вставки.           & IOCTL\_MODEINS     \cr
  0x2 &  Опросить, включен ли режим автоотступа.       & IOCTL\_MODEAI      \cr
  0x3 &  Опросить, режим поиска                        & IOCTL\_MODESEARCH  \cr
  0x4 &  Опросить, включен ли CAPS                     & IOCTL\_MODECAPS    \cr
  0x5 &  Опросить, включен ли ALT                      & IOCTL\_MODEALT     \cr
  0x6 &  Опросить, текущая строка -- фолд?             & IOCTL\_ISFOLD      \cr
  0x7 &  Опросить, помечена ли текущая строка.         & IOCTL\_ISMARKED    \cr
  0x9 &  Опросить, последняя строка в фолде?           & IOCTL\_ISLAST      \cr
 0x0a &  Опросить, находимся ли в {\tt SearchPage}.    & IOCTL\_INSEARCH    \cr
 0x0b &  Опросить, находимся ли в {\tt *TEMP*}.        & IOCTL\_INTEMP      \cr
 0x0c &  Положить на стек кол-во строк на экране       & IOCTL\_MAXY        \cr
 0x0d &  Положить на стек кол-во столбцов на экране    & IOCTL\_MAXX        \cr
 0x0e &  Положить на стек {\tt cx}                     & IOCTL\_CX          \cr
 0x0f &  Положить на стек {\tt sx}                     & IOCTL\_SX          \cr
 0x11 &  Положить на стек {\tt sy}                     & IOCTL\_SY          \cr
 0x12 &  Положить на стек номер строки                 & IOCTL\_LINENUM     \cr
  }

%&>>&1 0 1 1E

%&>>&B 0 B 36
%&<<&\theme{Команда {\tt eval}} Снимает со стека строку.
\theme{Команда {\tt eval}} Снимает со стека строку.
    Ищет сначала в {\tt MMMlib}, а затем среди функций пользователя
    функцию, название которой совпадает со строкой, а затем выполняет
    эту функцию. В случае, когда функция с таким именем не найдена,
    строка остается на стеке.

    Для реализации большинства функций редактирования одной строки очень
    хочется иметь команду языка, аналогичную {\tt eval}, под названием
    например {\tt forMarked}, которая бы брала со стека имя функции
    из {\tt MMMlib} или функции пользователя, а затем выполняла
    бы эту функцию для всех помеченных строк.
    Не исключено, что много разумнее сделать {\tt eval} с двумя параметрами:
    первый -- int код команды (стиль выполнения),
    второй -- имя функции.
    можно также сделать параметр по умолчанию т.е. если на стеке строка,
    то она выполняется, а если число, то снимается строка -- имя функции
    и выполняется какой-либо более сложный вариант {\tt eval }

%&>>&F 0 F 41
%&<<&\underbar{{\it Замечание:}}
\themeskip
\underbar{{\it Замечание:}}
    Все команды, зависящие от типа параметров (например, арифметические
    функции могут манипулировать только с числами), проверяют
    корректность операции и, в случае ошибки, не совершают никакого действия,
    все аргументы остаются на стеке.
    (механизм диагностики ошибок отсутствует).

%&>>&3 0 3 4
%&<<&\theme{ Функции {\tt MMMlib} }
\theme{ Функции {\tt MMMlib}. }
        Лексемы, не являющиеся константами или операторами языка, проверяются
на принадлежность к {\tt MMMlib}. Если лексема принадлежит {\tt MMMlib},
то она рассматривается как вызов соответствующей функции.

%&>>&3 0 3 31
%&<<&\theme{ Нераспознанные токены. }
\theme{ Нераспознанные токены } считаются вызовами функций, определенных
    пользователем.
    Данные функции могут изменять состояние стека и переменной {\tt Flag}.
    Если функция с таким именем не была определена пользователем, то
    состояние стека и переменной {\tt Flag} не меняется, и программа
    продолжает выполнение.

%&>>&3 0 3 9
%&<<&\theme{ Список зарезервированных слов языка. }
\theme{ Список зарезервированных слов языка. }
\halign{
    {\tt #} \hfil & {\tt #}  \hfil & {\tt #}  \hfil & {\tt #}  \hfil \cr
    break   &  convert     &  del     &  do      \cr
    dup     &  else        &  enddo   &  endif   \cr
    endp    &  if          &  ioctl   &  mathop  \cr
    pop     &  predicate   &  proc    &  push    \cr
    query   &  sget        &  sput    &  swp     \cr
    }

%&>>&A 0 A 0

\end
% ../mmmconst.h
%&>>&20 0 13 E
