shad-go/forth/README.md
2021-03-01 19:39:25 +03:00

104 lines
5.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## forth
В этой задаче нужно написать интерпретатор [языка программирования Forth](https://en.wikipedia.org/wiki/Forth_(programming_language)).
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](./main.go) написана небольшая обёртка вашей реализации,
позволяющая интерактивно взаимодействовать с интерпретатором.
```
go build . && ./forth
Welcome to Forth evaluator! To exit type "bye".
>1 2 +
Stack: 3
>
```
### Ссылки
* https://en.wikipedia.org/wiki/Forth_(programming_language)
* https://golang.org/pkg/strings/