Язык FORTH был создан Чарльзом X. Муром в конце 60-х годов в результате работы по созданию простого интерпретатора, облегчающего написание программ управления астрономическим оборудованием.

Вновь созданный язык был принят в качестве основного языка программирования в Американском астрономическом обществе. В 1973 году, Чарльз Мур и Элизабет Ратер основали компанию FORTH, Inc в  котором язык был портирован на множество платформ.

В конце 1970-х годов программистами, заинтересованными в развитии языка, была создана группа FORTH Interest Group (FIG). Этой группой разработана концепция FIG Forth Model — общедоступной форт-системы. Эту эталонную форт систему — FIG-FORTH часто рассматривают как первоначальный стандарт языка.

 ФОРТ система, обычно, содержит интерпретатор и компилятор языка FORTH и поддерживает диалоговый режим и режим исполнения.

Язык FORTH основан на использовании слов (команд) из словаря, который может пополняться новыми словами. Слова принимают данные из арифметического стека LIFO и туда же возвращают значения и результаты операций. Математические, логические и другие операции, выполняющие операции с данными из стека записываются в виде обратной польской нотации. Слова и значения разделяются пробелом. 

Код Слово Перевод Стек до операции Стек после операции Примечание
A0 DROP  снять  abcd.....  bcd.....  
A1 DUP  дублировать  abcd.....  aabcd.....  
A2 SWAP  обменять  abcd.....  bacd.....  
A3 OVER  через  abcd.....  babcd.....  
A4 ROT  вращать  abcd.....  cabd.....  
A5 -ROT  вращать обратно  abcd.....  bcad.....  
A6 SP!  очистить стек      
A7 SP@  указатель стека      
A8 2DROP  снять 2 элемента      
A9 2OVER  через 2      
B0 2SWAP  обменять 2      
B1 PICK  взять      
B2 ROLL  повернуть      
B3 DEPTH  глубина      
B4 AND  И      
B5 NOT  НЕ      
B6 OR  ИЛИ      
B7 XOR  Исключающее ИЛИ      
B8 1+  плюс 1      
B9 1–  минус 1      
C0 2+  плюс 2      
C1 2–  минус 2      
C2 2*  умножить на 2      
C3 2/  делить на 2      
C4 +  сложить      
C5  вычесть      
C6 *  умножить      
C7 NEGATE  смена знака      
C8 ABS  без знака      
C9 MIN  меньшее      
D0 MAX  большее      
D1 /  делить      
D2 MOD  остаток      
D3 */  умножить и разделить      
D4 =  сравнить      
D5 <  меньше ?       
D6 >  больше ?       
D7 0=  равно 0      
D8 0<  меньше 0 ?      
D9 0>  больше 0 ?      

Табл. 1.

Рис. 1.

Рис. 2.

#include <LiquidCrystal_I2C.h>
#include <Keypad.h>

#define DROP _DROP();
#define PICK _PICK();

LiquidCrystal_I2C lcd(0x27, 16, 2);
char hexaKeys[4][4] = {
  { '1', '2', '3', 'A' },
  { '4', '5', '6', 'B' },
  { '7', '8', '9', 'C' },
  { '*', '0', '#', 'D' }
};
byte rowPins[4] = { 6, 7, 8, 9 };
byte colPins[4] = { 5, 4, 3, 2 };
Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, 4, 4);

int input_value = 0;    // Вводимое число
int input_command = 0;  // Номер вводимого слова
int Stack[128];         // Арифметический стек
int stack_depth = 0;    // Глубина арифметического стека
int error = 0;          // Номер ошибки

void _DROP() {
  stack_depth--;
}
void _DUP() {
  Stack[stack_depth] = Stack[stack_depth - 1];
  stack_depth++;
}
void _SWAP() {
  int a = Stack[stack_depth - 1];
  Stack[stack_depth - 1] = Stack[stack_depth - 2];
  Stack[stack_depth - 2] = a;
}
void _OVER() {
  Stack[stack_depth] = Stack[stack_depth - 2];
  stack_depth++;
}
void _ROT() {
  int a = Stack[stack_depth - 3];
  Stack[stack_depth - 3] = Stack[stack_depth - 2];
  Stack[stack_depth - 2] = Stack[stack_depth - 1];
  Stack[stack_depth - 1] = a;
}
void _nROT() {
  int a = Stack[stack_depth - 3];
  Stack[stack_depth - 3] = Stack[stack_depth - 1];
  Stack[stack_depth - 1] = Stack[stack_depth - 2];
  Stack[stack_depth - 2] = a;
}
void _SPi() {
  stack_depth = 0;
}
void _SPa() {
  Stack[stack_depth] = stack_depth;
  stack_depth++;
}
void _2DROP() {
  DROP DROP
}
void _2OVER() {
  Stack[stack_depth] = Stack[stack_depth - 4];
  Stack[stack_depth + 1] = Stack[stack_depth - 3];
  stack_depth += 2;
}
void _2SWAP() {
  int a = Stack[stack_depth - 1];
  Stack[stack_depth - 1] = Stack[stack_depth - 3];
  Stack[stack_depth - 3] = a;
  a = Stack[stack_depth - 2];
  Stack[stack_depth - 2] = Stack[stack_depth - 4];
  Stack[stack_depth - 4] = a;
}
void _PICK() {
  Stack[stack_depth - 1] = Stack[stack_depth - 2 - Stack[stack_depth - 1]];
}
void _ROLL() {
  int n = Stack[stack_depth - 1];
  PICK;
  for (n; n > 0; n--) {
    Stack[stack_depth - n] = Stack[stack_depth + 1 - n];
  }
  stack_depth--;
}
void _DEPTH() {
  Stack[stack_depth] = stack_depth;
  stack_depth++;
}
void _AND() {
  Stack[stack_depth - 2] &= Stack[stack_depth - 1];
  stack_depth--;
}
void _OR() {
  Stack[stack_depth - 2] |= Stack[stack_depth - 1];
  stack_depth--;
}
void _NOT() {
  Stack[stack_depth - 1] = ~Stack[stack_depth - 1];
}
void _XOR() {
  Stack[stack_depth - 2] ^= Stack[stack_depth - 1];
  stack_depth--;
}
void _1PLUS() {
  Stack[stack_depth - 1]++;
}
void _1MINUS() {
  Stack[stack_depth - 1]--;
}
void _2PLUS() {
  Stack[stack_depth - 1] += 2;
}
void _2MINUS() {
  Stack[stack_depth - 1] -= 2;
}
void _2MUL() {
  Stack[stack_depth - 1] <<= 1;
}
void _2DIV() {
  Stack[stack_depth - 1] >>= 1;
}
void _PLUS() {
  Stack[stack_depth - 2] += Stack[stack_depth - 1];
  stack_depth--;
}
void _MINUS() {
  Stack[stack_depth - 2] -= Stack[stack_depth - 1];
  stack_depth--;
}
void _MUL() {
  Stack[stack_depth - 2] *= Stack[stack_depth - 1];
  stack_depth--;
}
void _NEGATE() {
  Stack[stack_depth - 1] *= -1;
}
void _ABS() {
  Stack[stack_depth - 1] *= Stack[stack_depth - 1] < 0 ? -1 : 1;
}
void _MIN() {
  Stack[stack_depth - 2] = Stack[stack_depth - 2] < Stack[stack_depth - 1] ? Stack[stack_depth - 2] : Stack[stack_depth - 1];
  stack_depth--;
}
void _MAX() {
  Stack[stack_depth - 2] = Stack[stack_depth - 2] > Stack[stack_depth - 1] ? Stack[stack_depth - 2] : Stack[stack_depth - 1];
  stack_depth--;
}
void _DIV() {
  Stack[stack_depth - 2] /= Stack[stack_depth - 1];
  stack_depth--;
}
void _MOD() {
  Stack[stack_depth - 2] %= Stack[stack_depth - 1];
  stack_depth--;
}
void _MULDIV() {
  long a = Stack[stack_depth - 3];
  a *= Stack[stack_depth - 2];
  Stack[stack_depth - 3] = a / Stack[stack_depth - 1];
  stack_depth -= 2;
}
void _EQUAL() {
  Stack[stack_depth - 2] = Stack[stack_depth - 2] == Stack[stack_depth - 1] ? -1 : 0;
  stack_depth--;
}
void _LESS() {
  Stack[stack_depth - 2] = Stack[stack_depth - 2] < Stack[stack_depth - 1] ? -1 : 0;
  stack_depth--;
}
void _GREATER() {
  Stack[stack_depth - 2] = Stack[stack_depth - 2] > Stack[stack_depth - 1] ? -1 : 0;
  stack_depth--;
}
void _IS0() {
  Stack[stack_depth - 1] = Stack[stack_depth - 1] == 0 ? -1 : 0;
}
void _LESS0() {
  Stack[stack_depth - 1] = Stack[stack_depth - 1] < 0 ? -1 : 0;
}
void _GREATER0() {
  Stack[stack_depth - 1] = Stack[stack_depth - 1] > 0 ? -1 : 0;
}

// Словарь
void (*forth[40])() = { _DROP, _DUP, _SWAP, _OVER, _ROT, _nROT, _SPi, _SPa, _2DROP, _2OVER,
                        _2SWAP, _PICK, _ROLL, _DEPTH, _AND, _OR, _NOT, _XOR, _1PLUS, _1MINUS,
                        _2PLUS, _2MINUS, _2MUL, _2DIV, _PLUS, _MINUS, _MUL, _NEGATE, _ABS, _MIN,
                        _MAX, _DIV, _MOD, _MULDIV, _EQUAL, _LESS, _GREATER, _IS0, _LESS0, _GREATER0 };
PROGMEM const char words[] = "DROP DUP SWAP OVER ROT -ROT SP! SP@ 2DROP 2OVER "
                             "2SWAP PICK ROLL DEPTH AND OR NOT XOR 1+ 1- "
                             "2+ 2- 2* 2/ + - * NEGATE ABS MIN "
                             "MAX / MOD */ = < > 0= 0< 0> "
                             "?DUP";

void setup() {
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("     FORTH");
}

String input_word(int n) {
  char buf[16] = "Not Found";
  int i = 0;  // Счётчик букв в PROGMEM const
  int j = 0;  // Счётчик пробелов
  int k = 0;  // Счётчик букв в buf
  char a = 'x';
  while (a != 0) {
    a = pgm_read_byte_near(words + i);
    if (j == n) {
      buf[k] = a;
      k++;
    }
    if (a == ' ') {
      j++;
    }
    if (j > n) {
      buf[k] = 0;
      break;
    }
    i++;
  }
  return buf;
}

void type() {           // Вывод на экран
  lcd.setCursor(0, 0);  // Размер и содержимое стека
  lcd.print("                ");
  lcd.setCursor(0, 0);
  lcd.print(stack_depth);
  lcd.print(':');
  for (int i = stack_depth - 1; i >= 0; i--) {
    lcd.print(Stack[i]);
    if (i != 0) {
      lcd.print(',');
    }
  }
  if (input_command == 0) {  // Вывод числа или ошибки
    lcd.setCursor(0, 1);
    lcd.print("                ");
    lcd.setCursor(0, 1);
    if (!error) {
      lcd.print(input_value);
    } else {
      lcd.print("ERROR ");
      lcd.print(error);
    }
  } else {  // Вывод слова
    lcd.setCursor(0, 1);
    lcd.print("                ");
    lcd.setCursor(0, 1);
    if (input_command < 10) {
      lcd.print("Enter Word: ");
      lcd.print(char(input_command + 64));
    } else {
      lcd.print(input_word(input_command - 10));
    }
  }
}

void run(int n) {  // Обработка ошибок связанных со стеком
  forth[n]();
}

void loop() {  // Интерактивный режим
  char customKey = customKeypad.getKey();
  if (customKey) {
    error = 0;
    int x = int(customKey);
    if (input_command == 0) {  // Ввод числа
      if (x > 47 && x < 58) {
        input_value = input_value * 10 + x - 48;
      }
    }
    if (input_value == 0) {                          // Ввод слова
      if (input_command == 0 && x > 64 && x < 69) {  // Ввод буквы
        input_command = x - 64;
      }
      if (input_command < 10 && x > 47 && x < 58) {  // Ввод цифры
        input_command = input_command * 10 + x - 48;
      }
    }
    if (customKey == '#') {  // Очистить ввод
      input_value = 0;
      input_command = 0;
    }
    if (customKey == '*') {      // Выполнить (Enter)
      if (input_command == 0) {  // Положить число на стек
        Stack[stack_depth] = input_value;
        stack_depth++;
        input_value = 0;
      }
      if (input_command > 9) {  // Выполнить слово
        run(input_command - 10);
        input_command = 0;
      }
    }
    type();
  }
}

Лист. 1.

Рис. 6.

Рис. 6.

#include <LiquidCrystal_I2C.h>
#include <Keypad.h>

#define DROP _DROP();
#define PICK _PICK();

LiquidCrystal_I2C lcd(0x27, 16, 2);
char hexaKeys[4][4] = {
  { '1', '4', '7', '*' },
  { '2', '5', '8', '0' },
  { '3', '6', '9', '#' },
  { 'A', 'B', 'C', 'D' }
};
byte rowPins[4] = { 6, 7, 8, 9 };
byte colPins[4] = { 5, 4, 3, 2 };
Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, 4, 4);

int input_value = 0;    // Вводимое число
int input_command = 0;  // Номер вводимого слова
int Stack[128];         // Арифметический стек
int stack_depth = 0;    // Глубина арифметического стека
int error = 0;          // Номер ошибки

void _DROP() {
  stack_depth--;
}
void _DUP() {
  Stack[stack_depth] = Stack[stack_depth - 1];
  stack_depth++;
}
void _SWAP() {
  int a = Stack[stack_depth - 1];
  Stack[stack_depth - 1] = Stack[stack_depth - 2];
  Stack[stack_depth - 2] = a;
}
void _OVER() {
  Stack[stack_depth] = Stack[stack_depth - 2];
  stack_depth++;
}
void _ROT() {
  int a = Stack[stack_depth - 3];
  Stack[stack_depth - 3] = Stack[stack_depth - 2];
  Stack[stack_depth - 2] = Stack[stack_depth - 1];
  Stack[stack_depth - 1] = a;
}
void _nROT() {
  int a = Stack[stack_depth - 3];
  Stack[stack_depth - 3] = Stack[stack_depth - 1];
  Stack[stack_depth - 1] = Stack[stack_depth - 2];
  Stack[stack_depth - 2] = a;
}
void _SPi() {
  stack_depth = 0;
}
void _SPa() {
  Stack[stack_depth] = stack_depth;
  stack_depth++;
}
void _2DROP() {
  DROP DROP
}
void _2OVER() {
  Stack[stack_depth] = Stack[stack_depth - 4];
  Stack[stack_depth + 1] = Stack[stack_depth - 3];
  stack_depth += 2;
}
void _2SWAP() {
  int a = Stack[stack_depth - 1];
  Stack[stack_depth - 1] = Stack[stack_depth - 3];
  Stack[stack_depth - 3] = a;
  a = Stack[stack_depth - 2];
  Stack[stack_depth - 2] = Stack[stack_depth - 4];
  Stack[stack_depth - 4] = a;
}
void _PICK() {
  Stack[stack_depth - 1] = Stack[stack_depth - 2 - Stack[stack_depth - 1]];
}
void _ROLL() {
  int n = Stack[stack_depth - 1];
  PICK;
  for (n; n > 0; n--) {
    Stack[stack_depth - n] = Stack[stack_depth + 1 - n];
  }
  stack_depth--;
}
void _DEPTH() {
  Stack[stack_depth] = stack_depth;
  stack_depth++;
}
void _AND() {
  Stack[stack_depth - 2] &= Stack[stack_depth - 1];
  stack_depth--;
}
void _OR() {
  Stack[stack_depth - 2] |= Stack[stack_depth - 1];
  stack_depth--;
}
void _NOT() {
  Stack[stack_depth - 1] = ~Stack[stack_depth - 1];
}
void _XOR() {
  Stack[stack_depth - 2] ^= Stack[stack_depth - 1];
  stack_depth--;
}
void _1PLUS() {
  Stack[stack_depth - 1]++;
}
void _1MINUS() {
  Stack[stack_depth - 1]--;
}
void _2PLUS() {
  Stack[stack_depth - 1] += 2;
}
void _2MINUS() {
  Stack[stack_depth - 1] -= 2;
}
void _2MUL() {
  Stack[stack_depth - 1] <<= 1;
}
void _2DIV() {
  Stack[stack_depth - 1] >>= 1;
}
void _PLUS() {
  Stack[stack_depth - 2] += Stack[stack_depth - 1];
  stack_depth--;
}
void _MINUS() {
  Stack[stack_depth - 2] -= Stack[stack_depth - 1];
  stack_depth--;
}
void _MUL() {
  Stack[stack_depth - 2] *= Stack[stack_depth - 1];
  stack_depth--;
}
void _NEGATE() {
  Stack[stack_depth - 1] *= -1;
}
void _ABS() {
  Stack[stack_depth - 1] *= Stack[stack_depth - 1] < 0 ? -1 : 1;
}
void _MIN() {
  Stack[stack_depth - 2] = Stack[stack_depth - 2] < Stack[stack_depth - 1] ? Stack[stack_depth - 2] : Stack[stack_depth - 1];
  stack_depth--;
}
void _MAX() {
  Stack[stack_depth - 2] = Stack[stack_depth - 2] > Stack[stack_depth - 1] ? Stack[stack_depth - 2] : Stack[stack_depth - 1];
  stack_depth--;
}
void _DIV() {
  Stack[stack_depth - 2] /= Stack[stack_depth - 1];
  stack_depth--;
}
void _MOD() {
  Stack[stack_depth - 2] %= Stack[stack_depth - 1];
  stack_depth--;
}
void _MULDIV() {
  long a = Stack[stack_depth - 3];
  a *= Stack[stack_depth - 2];
  Stack[stack_depth - 3] = a / Stack[stack_depth - 1];
  stack_depth -= 2;
}
void _EQUAL() {
  Stack[stack_depth - 2] = Stack[stack_depth - 2] == Stack[stack_depth - 1] ? -1 : 0;
  stack_depth--;
}
void _LESS() {
  Stack[stack_depth - 2] = Stack[stack_depth - 2] < Stack[stack_depth - 1] ? -1 : 0;
  stack_depth--;
}
void _GREATER() {
  Stack[stack_depth - 2] = Stack[stack_depth - 2] > Stack[stack_depth - 1] ? -1 : 0;
  stack_depth--;
}
void _IS0() {
  Stack[stack_depth - 1] = Stack[stack_depth - 1] == 0 ? -1 : 0;
}
void _LESS0() {
  Stack[stack_depth - 1] = Stack[stack_depth - 1] < 0 ? -1 : 0;
}
void _GREATER0() {
  Stack[stack_depth - 1] = Stack[stack_depth - 1] > 0 ? -1 : 0;
}

// Словарь
void (*forth[40])() = { _DROP, _DUP, _SWAP, _OVER, _ROT, _nROT, _SPi, _SPa, _2DROP, _2OVER,
                        _2SWAP, _PICK, _ROLL, _DEPTH, _AND, _OR, _NOT, _XOR, _1PLUS, _1MINUS,
                        _2PLUS, _2MINUS, _2MUL, _2DIV, _PLUS, _MINUS, _MUL, _NEGATE, _ABS, _MIN,
                        _MAX, _DIV, _MOD, _MULDIV, _EQUAL, _LESS, _GREATER, _IS0, _LESS0, _GREATER0 };
PROGMEM const char words[] = "DROP DUP SWAP OVER ROT -ROT SP! SP@ 2DROP 2OVER "
                             "2SWAP PICK ROLL DEPTH AND OR NOT XOR 1+ 1- "
                             "2+ 2- 2* 2/ + - * NEGATE ABS MIN "
                             "MAX / MOD */ = < > 0= 0< 0> "
                             "?DUP";

void setup() {
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("     FORTH");
}

String input_word(int n) {
  char buf[16] = "Not Found";
  int i = 0;  // Счётчик букв в PROGMEM const
  int j = 0;  // Счётчик пробелов
  int k = 0;  // Счётчик букв в buf
  char a = 'x';
  while (a != 0) {
    a = pgm_read_byte_near(words + i);
    if (j == n) {
      buf[k] = a;
      k++;
    }
    if (a == ' ') {
      j++;
    }
    if (j > n) {
      buf[k] = 0;
      break;
    }
    i++;
  }
  return buf;
}

void type() {           // Вывод на экран
  lcd.setCursor(0, 0);  // Размер и содержимое стека
  lcd.print("                ");
  lcd.setCursor(0, 0);
  lcd.print(stack_depth);
  lcd.print(':');
  for (int i = stack_depth - 1; i >= 0; i--) {
    lcd.print(Stack[i]);
    if (i != 0) {
      lcd.print(',');
    }
  }
  if (input_command == 0) {  // Вывод числа или ошибки
    lcd.setCursor(0, 1);
    lcd.print("                ");
    lcd.setCursor(0, 1);
    if (!error) {
      lcd.print(input_value);
    } else {
      lcd.print("ERROR ");
      lcd.print(error);
    }
  } else {  // Вывод слова
    lcd.setCursor(0, 1);
    lcd.print("                ");
    lcd.setCursor(0, 1);
    if (input_command < 10) {
      lcd.print("Enter Word: ");
      lcd.print(char(input_command + 64));
    } else {
      lcd.print(input_word(input_command - 10));
    }
  }
}

void run(int n) {  // Обработка ошибок связанных со стеком
  forth[n]();
}

void loop() {  // Интерактивный режим
  char customKey = customKeypad.getKey();
  if (customKey) {
    error = 0;
    int x = int(customKey);
    if (input_command == 0) {  // Ввод числа
      if (x > 47 && x < 58) {
        input_value = input_value * 10 + x - 48;
      }
    }
    if (input_value == 0) {                          // Ввод слова
      if (input_command == 0 && x > 64 && x < 69) {  // Ввод буквы
        input_command = x - 64;
      }
      if (input_command < 10 && x > 47 && x < 58) {  // Ввод цифры
        input_command = input_command * 10 + x - 48;
      }
    }
    if (customKey == '#') {  // Очистить ввод
      input_value = 0;
      input_command = 0;
    }
    if (customKey == '*') {      // Выполнить (Enter)
      if (input_command == 0) {  // Положить число на стек
        Stack[stack_depth] = input_value;
        stack_depth++;
        input_value = 0;
      }
      if (input_command > 9) {  // Выполнить слово
        run(input_command - 10);
        input_command = 0;
      }
    }
    type();
  }
}

Лист. 2.