shad-go/forth
2021-03-01 19:39:25 +03:00
..
eval.go Resolve "add forth task" 2021-02-18 20:13:55 +00:00
eval_test.go Resolve "add forth task" 2021-02-18 20:13:55 +00:00
main.go Resolve "add forth task" 2021-02-18 20:13:55 +00:00
README.md Update README.md 2021-03-01 19:39:25 +03:00

forth

В этой задаче нужно написать интерпретатор языка программирования Forth.

Forth - это стек-ориентированный, конкатенативный (конкатенация двух фрагментов кода выражает их композицию) язык программирования.

В нашем примитивном случае язык состоит из стека, хранящего целые числа, и словаря известных операций. Каждая операция вынимает некоторое (возможно нулевое) количество чисел со стека и кладёт некоторое (возможно нулевое) количество чисел на стек.

Полноценный Forth, с ячейками памяти, циклами, условными переходами и множеством стандартных операций позволяет писать довольно сложные программы и используется в микропроцессорах.

Примеры программ

В каждом примере на последней строке приведено результирующее значение стека.

Положить 3 числа на стек:

1 2 3
Stack: 1, 2, 3

Положить 2 числа на стек, исполнить операцию + (достать 2 числа со стека и положить на стек их сумму)

1 2 +
Stack: 3

Положить число на стек и выполнить операцию drop (достать верхнее значение из стека)

1 drop
Stack:

Определить операцию ("слово" в терминологии Forth) drop2 для удаления двух верхних значений со стека, положить 2 числа на стек и воспользоваться drop2:

: drop2 drop drop ;
1 2 drop2
Stack: 

Грамматика

У языка нет официальной грамматики. Она определяется простым алгоритмом. Интерпретатор считывает строку ввода, разбивает на части, используя пробелы в качестве разделителя, анализирует каждую часть на принадлежность к лексемам языка ("словам").

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

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

Что нужно сделать?

Нужно написать реализацию функций NewEvaluator и Evaluator.Process. Первая создаёт объект исполнителя Forth кода, а вторая парсит и исполняет.

Требуется поддержать следующие слова:

  • +, -, *, / удаляют со стека два верхних значения и кладут результат соответствующей целочисленной арифметической операции
  • dup кладёт на стек верхнее значение
  • over кладёт на стек второе сверху значение
  • drop удаляет верхнее значение со стека
  • swap меняет два верхних значения стека местами

При нехватке аргументов Process должна возвращать ошибки.

Также нужно поддержать определение новых слов.

: word definition ;

где word -- это case-insensitive имя новой операции, а definition состоит из известных слов и чисел, разделённых пробелами. Слова можно переопределять.

Проверка решения

Для запуска тестов нужно выполнить следующую команду:

go test -v ./forth/...

Интерактивная среда

В main.go написана небольшая обёртка вашей реализации, позволяющая интерактивно взаимодействовать с интерпретатором.

go build . && ./forth
Welcome to Forth evaluator! To exit type "bye".
>1 2 +
Stack: 3
>

Ссылки