Skip to content

Latest commit

 

History

History
295 lines (222 loc) · 20 KB

File metadata and controls

295 lines (222 loc) · 20 KB

Описание конструкций Forth-подобного языка

Оглавление

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

Операции по работе с данными

  • Загрузка числа на стек

    • Синтаксис: <number>
    • Описание: загрузить на стек число <number>
    • Операция: dataStack.push(<number>)
  • Загрузка адреса переменной на стек

    • Синтаксис: <var>
    • Описание: загрузить на стек адрес переменной <var>
    • Операция: dataStack.push(addrof(<var>))
  • Сохранение значения по адресу

    • Синтаксис: !
    • Описание: по адресу значения первого элемента стека сохранить значение второго элемента стека
    • Операция: M[dataStack.pop()] = dataStack.pop()
  • Загрузка значения по адресу

    • Синтаксис: @
    • Описание: загрузить на стек значение по адресу значения первого элемента стека
    • Операция: dataStack.push(M[dataStack.pop()])
  • Загрузка значения константы

    • Синтаксис: <const>
    • Описание: загрузить на стек значение константы <const>
    • Операция: dataStack.push(<const>)
  • Объявление переменной

    • Синтаксис: var <ident>
    • Описание: объявить переменную <ident>; определённая ячейка памяти привязывается к имени переменной
  • Объявление переменной с заданным значением

    • Синтаксис: var <ident> <number>
    • Описание: объявить переменную <ident> и присвоить значение <number>; определённая ячейка памяти привязывается к имени переменной
  • Объявление константы

    • Синтаксис: const <ident> <number>
    • Описание: объявить константу <ident> значением <number>
  • Объявление блока памяти

    • Синтаксис: alloc <ident> <number>
    • Описание: выделить блок памяти <ident> длины <number>; размер указывается в ячейках памяти; определённая ячейка памяти начала блока привязывается к имени переменной
  • Объявление строкового литерала

    • Синтаксис: str <ident> <string>
    • Описание: объявить строковый литерал <ident> и значением <string>; определённая ячейка памяти начала литерала привязывается к имени переменной; литерал хранится в памяти в виде паскаль-строки (то есть, в первой ячейке непрерывного блока памяти литерала хранится размер строки)

Арифметические операции

  • Сложение

    • Синтаксис: +
    • Описание: сложить первое и второе значение со стека и положить результат обратно на стек
    • Операция: dataStack.push(dataStack.pop() + dataStack.pop())
  • Вычитание

    • Синтаксис: -
    • Описание: вычесть первое значение на стеке из второго и положить результат обратно на стек
    • Операция: dataStack.push(-dataStack.pop() + dataStack.pop())
  • Умножение

    • Синтаксис: *
    • Описание: перемножить первое и второе значение со стека и положить результат обратно на стек
    • Операция: dataStack.push(dataStack.pop() * dataStack.pop())
  • Деление нацело

    • Синтаксис: /
    • Описание: разделить нацело второе значение со стека на первое и положить результат обратно на стек
    • Операция: dataStack.push(1 / dataStack.pop() * dataStack.pop())
  • Остаток от деления

    • Синтаксис: mod
    • Описание: разделить нацело второе значение со стека на первое и положить остаток обратно на стек
    • Операция: swap; dataStack.push(dataStack.pop() % dataStack.pop())

Побитовые операции

  • И

    • Синтаксис: and
    • Описание: выполнить побитовое И между двумя первыми элементами стека и положить результат обратно на стек
    • Операция: dataStack.push(dataStack.pop() & dataStack.pop())
  • ИЛИ

    • Синтаксис: or
    • Описание: выполнить побитовое ИЛИ между двумя первыми элементами стека и положить результат обратно на стек
    • Операция: dataStack.push(dataStack.pop() | dataStack.pop())
  • ИСКЛЮЧАЮЩЕЕ ИЛИ

    • Синтаксис: ^
    • Описание: выполнить побитовое ИСКЛЮЧАЮЩЕЕ ИЛИ между двумя первыми элементами стека и положить результат обратно на стек
    • Операция: dataStack.push(dataStack.pop() ^ dataStack.pop())
  • НЕ

    • Синтаксис: not
    • Описание: выполнить побитовое НЕ над первым элементом стека и положить результат обратно на стек
    • Операция: dataStack.push(~dataStack.pop())
  • Отрицательное значение

    • Синтаксис: negate
    • Описание: выполнить побитовое НЕ над первым элементом стека, прибавить единицу и положить результат обратно на стек
    • Операция: dataStack.push(~dataStack.pop() + 1)
  • Абсолютное значение

    • Синтаксис: abs
    • Описание: взять абсолютное значение от первого элемента стека и положить обратно на стек
    • Операция: dataStack.push(abs(dataStack.pop()))
  • Максимум

    • Синтаксис: max
    • Описание: взять максимум из значений первых двух элементов стека и положить обратно на стек
    • Операция: dataStack.push(max(dataStack.pop(), dataStack.pop()))
  • Минимум

    • Синтаксис: min
    • Описание: взять минимум из значений первых двух элементов стека и положить обратно на стек
    • Операция: dataStack.push(min(dataStack.pop(), dataStack.pop()))

Операции манипуляции со стеком (данных)

Примечание: для описания стандартных потоков ввода/вывода зарезервированы переменные stdin/stdout, стандартные значения которых равны 1 и 2 соответственно. Эти значения соответствуют номерам внешних устройств (в текущей реализации номер устройства равен номеру порта, к которому оно подключено). Программист может их самостоятельно переопределять, изменяя значения переменных stdin/stdout.

  • Дублирование (первого)

    • Синтаксис: dup
    • Описание: продублировать первый элемент стека
    • Операция: dataStack.push(dataStack.top())
  • Дублирование (второго)

    • Синтаксис: over
    • Описание: продублировать второй элемент стека
    • Операция: FV <- dataStack.pop(), SV <- dataStack.pop(); dataStack.push(SV), dataStack.push(FV), dataStack.push(SV)
  • Обмен

    • Синтаксис: swap
    • Описание: обменять значения первых двух элементов стека
    • Операция: FV <- dataStack.pop(), SV <- dataStack.pop(); dataStack.push(FV), dataStack.push(SV)
  • Поворот

    • Синтаксис: rot
    • Описание: "повернуть" три первых элемента стека: третий элемент окажется на первом месте, остальные два останутся в том же порядке
    • Операция: FV <- dataStack.pop(), SV <- dataStack.pop(), TV <- dataStack.pop(); dataStack.push(SV), dataStack.push(FV), dataStack.push(TV)
  • Удаление первого элемента стека

    • Синтаксис: drop
    • Описание: удалить первый элемент со стека
    • Операция: dataStack.pop()
  • Удаление второго элемента стека

    • Синтаксис: nip
    • Описание: удалить второй элемент со стека
    • Операция: TV <- dataStack.pop(), SV <- dataStack.pop(); SV.drop(); dataStack.push(TV)
  • Вывод символа на стандартный поток вывода

    • Синтаксис: .
    • Описание: взять первый элемент со стека и передать на стандартный поток вывода
    • Операция: STDOUT <- dataStack.pop()
  • Вывод символа на стандартный поток вывода (ascii)

    • Синтаксис: emit
    • Описание: взять первый элемент со стека и передать на стандартный поток вывода, интерпретировав этот символ как символ таблицы ascii
    • Операция: STDOUT <- ascii[dataStack.pop()]
  • Вывод символа перевода каретки на стандартный поток вывода

    • Синтаксис: cr
    • Описание: передать на стандартный поток вывода символ перевода каретки
    • Операция: STDOUT <- \r
  • Вывод строки на стандартный поток вывода

    • Синтаксис: ."
    • Описание: передать на стандартный поток вывода все символы; ." отмечает начало строки для вывода, а конец строки определяется по "
    • Операция: STDOUT <- some string
    • Пример: при вводе ." Hello!" на стандартный поток вывода будет подано Hello!
  • Чтение символа со стандартного потока ввода

    • Синтаксис: key
    • Описание: получить со стандартного потока ввода один символ и положить его на вершину стека (значение символа будет взято из таблицы ascii)
    • Операция: dataStack.push(STDIN[0])

Операции манипуляции со стеком адресов возврата

  • Перенос первого элемента со стека (данных) на стек адресов возврата

    • Синтаксис: >r
    • Описание: взять первый элемент со стека (данных) и положить на стек адресов возврата
    • Операция: returnStack.push(dataStack.pop())
  • Перенос первого элемента со стека адресов возврата на стек (данных)

    • Синтаксис: r>
    • Описание: взять первый элемент со стека адресов возврата и положить на стек данных
    • Операция: dataStack.push(returnStack.pop())
  • Дублирование первого элемента стека адресов возврата на стек (данных)

    • Синтаксис: r@
    • Описание: взять первый элемент со стека адресов возврата и продублировать на стек данных
    • Операция: dataStack.push(returnStack.top())

Операции сравнения

Раздел Описание для каждой из операций этого типа будет почти идентичным, поэтому вынесен в начало:

  • Описание: сравнить два первых элемента стека и положить результат обратно на стек

  • Равно

    • Синтаксис: =
    • Операция: dataStack.push(dataStack.pop() == dataStack.pop())
  • Меньше или равно

    • Синтаксис: <=
    • Операция: dataStack.push(dataStack.pop() >= dataStack.pop())
  • Больше или равно

    • Синтаксис: >=
    • Операция: dataStack.push(dataStack.pop() <= dataStack.pop())
  • Меньше

    • Синтаксис: <
    • Операция: dataStack.push(dataStack.pop() > dataStack.pop())
  • Больше

    • Синтаксис: >
    • Операция: dataStack.push(dataStack.pop() < dataStack.pop())

Операции управления потоком

  • Условный переход

    • Синтаксис: if <body> then
    • Описание: если на вершине стека находится значение истина, то выполнить набор инструкций из <body>
  • Условный переход с альтернативой

    • Синтаксис: if <body#1> else <body#2> then
    • Описание: если на вершине стека находится значение истина, то выполнить набор инструкций из <body#1>, иначе выполнить набор инструкций из <body#2>
  • Цикл с постусловием

    • Синтаксис: begin <body> until
    • Описание: выполнить набор инструкций из <body>, если после этого на вершине стека находится значение ложь, то перейти к следующей итерации, иначе - выйти из цикла
  • Цикл со счётчиком

    • Синтаксис: <number> "times" <body> "next"
    • Описание: вначале взять значение со стека (данных) и поместить на стек адресов возврата; затем выполнить набор инструкций из <body>, отнять 1 от вершины со стека адресов возврата, если вершина больше нуля, то перейти к следующей итерации, иначе - удалить вершину со стека адресов возврата и выйти из цикла
  • Объявление процедуры

    • Синтаксис: : <ident> <body> ;
    • Описание: объявить процедуру <ident> с набором инструкций <body>
  • Завершение программы

    • Синтаксис: _exit_
    • Описание: завершить программу

Операции обработки прерываний

Примечание: обработка прерываний требует их ручного включения. То есть, на момент начала исполнения программы, прерывания отключены.

  • Включение прерываний

    • Синтаксис: _enable_int_
    • Описание: включить прерывания
  • Отключение прерываний

    • Синтаксис: _disable_int_
    • Описание: отключить прерывания
  • Возвращение из процедуры-обработчика

    • Синтаксис: _iret_
    • Описание: вернуться из процедуры-обработчика и вернуть состояние, которое было до входа в данную процедуру
  • Определение векторов прерываний

    • Синтаксис: vector <number> : <ident>
    • Описание: определить для устройства <number> (в текущей реализации номер устройства равен номеру порта, к которому оно подключено) процедуру-обработчик

Комментарии

Начинаются с символа \ и заканчиваются там, где заканчивается строка

Включение кода

С помощью директивы #require <string> (где <string> - имя включаемого файла) можно включать код из других модулей .forth. Включение - подстановка всего содержимого файла.

Булевы значения

  • истина - любое значение, кроме 0 (каноническое значение - -1)
  • ложь - 0