| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
mixguile, виртуальная машина на основе Scheme
Эта глава содержит описание использования mixguile и библиотеки
функций Scheme, дающих доступ к виртуальной машине MIX в эмуляторах
MDK (mixguile, mixvm и gmixvm). См. в
3.4 Использование mixguile учебное пошаговое введение в mixguile
и использование Scheme как языка расширения виртуальных машин MIX MDK.
8.1 Вызов mixguileПараметры командной строки. 8.2 Описание функций Scheme
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
mixguile
При вызове mixguile без аргументов она после загрузки файла
инициализации `~/.mdk/mixguile.scm' (если он существует), войдёт
в Guile REPL (read-eval-print loop, цикл ввода, обработки и вывода).
mixguile принимает те же параметры командной строки, что и
Guile:
mixguile [-s SCRIPT] [-c EXPR] [-l FILE] [-e FUNCTION] [-qhv]
[--help] [--version]
|
Значение этих параметров таково:
#! /usr/bin/mixguile \
-e main -s
!#
;;; выполнить заданную программу и вывести содержимое регистров.
(define main
(lambda (args)
;; загрузить файл, указанный в аргументе командной строки
(mix-load (cadr args))
;; выполнить его
(mix-run)
;; вывести содержимое регистров
(mix-pall)))
|
$ ./foo hello |
main со списком
параметров командной строки в качестве аргумента (в вышеприведённом
примере ("./foo" "hello)). Заметьте, что параметры командной
строки для mixguile должны находиться в отдельной строке после
символа \.
mixguile она проверяет наличие файла `mixguile.scm' в
каталоге конфигурации `~/.mdk' и, если он существует, загружает
его. Этот параметр велит mixguile не загружать файл
инициализации.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Как мы указали выше, mixguile содержит встроенную виртуальную
машину MIX, доступ к которой возможен через набор функций Scheme,
т.е. через библиотеку Scheme. С другой стороны, mixvm и
gmixvm содержат интерпретатор Guile и могут использовать
ту же библиотеку Scheme, равно как и все остальные примитивы Guile/Scheme
и любые определённые пользователем функции. Поэтому в вашем распоряжении
находится мощный язык программирования -- Scheme -- позволяющий расширять
возможности эмуляторов виртуальной машины в составе MDK (см. примеры
в 3.5 Использование Scheme в mixvm и gmixvm).
Следующие подразделы описывают доступные функции библиотеки MIX/Scheme.
8.2.1 Оболочка команд mixvmФункции, вызывающие команды mixvm. 8.2.2 Функции-ловушки Добавление ловушек к командам mixvm. 8.2.3 Дополнительные функции ВМ Функции доступа к виртуальной машине MIX.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
mixvm
Каждой из команд mixvm, перечисленных в 6.2 Интерактивные команды, соответствует
функция Scheme, название которой образовано добавлением к имени команды
префикса mix- (например, mix-load, mix-run и т.д.).
Эти оболочки команд реализованы единой функцией передачи команды:
argument должны быть строками. Результат
будет тот же, что и выполнение "command argument" из
командной строки mixvm или gmixvm.
Например, вы может вызвать команду run из приглашения mixvm
тремя разными способами:
MIX > run hello MIX > (mix-run "hello") MIX > (mixvm-cmd "run" "hello") |
mixguile или в скрипте Scheme могут быть
использованы только две последние формы).
Функции mix- не вычисляют значений. Если вы хотите проверять
результаты вызова команд mixvm, используйте функцию
mix-last-result:
mixvm
было успешным, #f в противном случае.
#! /usr/bin/mixguile \
-e main -s
!#
;;; выполнить заданную программу и вывести содержимое регистров.
(define main
(lambda (args)
;; загрузить файл, указанный в аргументе командной строки
(mix-load (cadr args))
;; выполнить его, если команда mix-load сработала
(if (mix-last-result) (mix-run))
;; вывести содержимое регистров, если вышеприведённые
;; команды успешно завершили работу
(if (mix-last-result) (mix-pall))))
|
Список доступных команд см. в 6.2 Интерактивные команды. Там дано описание команд
mixvm, соответствующие команды Scheme используются точно так же,
и поэтому мы не приводим здесь полного описания этих функций. Вместо
этого мы лишь укажем те оболочки, поведение которых чем-то отличается от
соответсвующих команд.
(mix-preg 'I1) (mix-preg "I1") |
pmem принимает один аргумент -- либо номер ячейки, либо
диапазон в виде FROM-TO. Функция же принимает один аргумент,
если запрашивается содержимое одной ячейки памяти, и два, если
запрашивается диапазон. Например, следующие команды эквивалентны:
MIX > pmem 10-12 0010: + 00 00 00 00 00 (0000000000) 0011: + 00 00 00 00 00 (0000000000) 0012: + 00 00 00 00 00 (0000000000) MIX > (mix-pmem 10 12) 0010: + 00 00 00 00 00 (0000000000) 0011: + 00 00 00 00 00 (0000000000) 0012: + 00 00 00 00 00 (0000000000) MIX > |
sover принимает в качестве аргумента либо строку T,
либо строку F, чтобы установить, соответственно, триггер переполнения
истинным или ложным. Соответствующая функция Scheme, mix-sover,
принимает в качестве аргумента логическое значение Scheme: #t
(истина) или #f.
С остальными функциями достаточно принимать в расчёт, что когда аргументами команды служат числа, соответствующая функция Scheme принимает в качестве аргументов числовые литералы Scheme. В то же время, если аргументом команды служит строка, аргументом связанной с ней функции Scheme будет строка Scheme. Например, следующие вызовы попарно эквивалентны:
MIX > load ../samples/hello MIX > (mix-load "../samples/hello) MIX > next 5 MIX > (mix-next 5) |
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Ловушки -- это функции, вычисляемые перед выполнением команды mixvm
(или соответствующей функции-оболочки Scheme) или после него, либо
после обнаружения во время выполнения программы MIX обязательной или
условной точки останова. Следующие функции позволяют устанавливать
ловушки:
mixvm, а hook -- функция, принимающая в качестве
единственного аргумента строку-список аргументов команды. Следующий код
Scheme определяет простую ловушку и связывает её с командой run:
(define run-hook
(lambda (args)
(display "argument list: ")
(display args)
(newline)))
(mix-add-pre-hook "run" run-hook)
|
Ловушки перед командой выполняются в порядке, в котором они были добавлены, перед вызовом соответствующей команды (или связанной с ней функции-оболочки Scheme).
mix-add-pre-hook.
mixvm или функции-оболочки. В этом случае hook
принимает два аргумента: строку с именем вызванной команды и
строку-список её аргументов.
(define break-hook
(lambda (line address)
(display "Breakpoint at line ") (display line)
(display " and address ") (display address)
(newline)))
(mix-add-break-hook break-hook)
|
Функции-ловушки остановов реализованы в Scheme через обычные ловушки
после команды для команд next и run. Если вас это
удивляет, вы можете посмотреть исходный код Scheme в файле
`префикс/share/mdk/mixguile-vm-stat.scm' (где префикс
соответствует корневому каталогу установки, обычно /usr или
/usr/local).
См. другие примеры использования функций-ловушек в 3.4.4 Функции-ловушки.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
При написании нетривиальных расширений Scheme с использованием библиотеки
MIX/Scheme, вам, вероятно, будет нужно определять содержимое компонентов
виртуальной машины (регистры, ячейки памяти и т.д.). Например, вам может
понадобиться сохранить содержимое регистра A в переменной.
Функции Scheme, описанные до сих пор, не помогут -- вы можете вывести
содержимое A функцией (mix-preg 'A), но не можете присвоить
значение A переменной. Для решения этой проблемы библиотека
MIX/Scheme предоставляет следующие дополнительные функции:
mixvm-status) или символа (mix-vm-status). Возможные
возвращаемые значения:
(mixvm-status) | (mix-vm-status) | |
| 0 | MIX_ERROR | Ошибка загрузки или выполнения |
| 1 | MIX_BREAK | Обнаружена точка останова |
| 2 | MIX_COND_BREAK | Условная точка останова |
| 3 | MIX_HALTED | Выполнение прервано |
| 4 | MIX_RUNNING | Выполнение по next остановлено |
| 5 | MIX_LOADED | Программа успешно загружена |
| 6 | MIX_EMPTY | Программа не загружена |
MIX_ERROR, MIX_BREAK и т.д.
mix-reg возвращает содержимое указанного регистра в виде
числа. mix-set-reg приравнивает значение указанного регистра
заданному. Регистр может быть задан либо в виде строки ("A",
"X" и т.д.), либо в виде символа ('A, 'X и т.д.).
Например:
guile> (mix-reg 'A) 2341 guile> (mix-set-reg! "A" 2000) ok guile> (define reg-a (mix-reg 'A)) guile> (display reg-a) 2000 guile> |
mix-over возвращает #t, если триггер переполнения
установлен, и #f в противном случае. Значение триггера
переполнения может быть изменено функцией mix-set-over!.
L (меньше), E (равно) и
G (больше).
run или next.
mix-src-line-no во время выполнения программы возвращает номер
текущей строки исходного кода. mix-src-line возвращает строку,
содержащую строку исходного файла номер lineno, а при вызове
без аргументов возвращает (mix-src-line (mix-src-line-no)).
| [ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |