Простой (Small) машинный язык (SML)
Курсовая работа, изучающая отражение и внедрение зависимостей
- Это задание должно быть выполнено индивидуально.
- Пример кода, упомянутый в тексте, можно найти в репозитории. альтернативный текст.
Цель этого задания - дать вам попрактиковаться в
- подклассы,
- изменение существующего кода,
- тестирование,
- внедрение зависимостей,
- и использование
отражения среди прочих навыков.
Проблема
Вы напишете интерпретатор для простого машинного языка — SML.
Общая форма инструкции на машинном языке такова:
label instruction register-list
где
label
- это метка для строки. Другие инструкции могут “переходить” к этой метке.instruction
- это фактическая инструкция. В SML есть инструкции для сложения, умножения и так далее, Для хранения и извлечения целых чисел, а также для условного перехода к другим меткам (например, к оператору if).register-list
- список регистров, которыми управляет инструкция. Регистры - это простые целочисленные области хранения в памяти компьютера, очень похожие на переменные. В SML имеется 32 регистра, пронумерованных 0, 1, … , 31.
SML содержит следующие инструкции:
Инструкция | Интерпретация |
---|---|
L1 add r s1 s2 |
Добавьте содержимое регистров s1 и s2 , сохраните результат в r . |
L1 sub r s1 s2 |
Вычтите s2 из s1 , сохраните результат в r . |
L1 mul r s1 s2 |
Умножьте s1 and s2 , сохраните результат в r . |
L1 div r s1 s2 |
Разделите s1 на s2 (целочисленное деление), сохраните результат в r . |
L1 out s1 |
Распечатайте содержимое s1 на консоли. |
L1 lin r x |
Сохраняйте целое число x в r . |
L1 bnz s1 L2 |
Если s1 не равно нулю, выполните инструкцию, помеченную как L2 далее. |
где
L1
является любым идентификатором — фактически, любой последовательностью символов, не содержащих пробелов.- Каждый оператор программы должен быть помечен другим идентификатором.
- Каждый из
s1
,s2
иr
является целым числом в диапазоне 0..31 и относится к одному из 32 регистров в машине, которая выполняет язык SML.
Вот пример программы SML для вычисления факториала числа 6:
f0 lin 20 6
f1 lin 21 1
f2 lin 22 1
f3 mul 21 21 20
f4 sub 20 20 22
f5 bnz 20 f3
f6 out 21
Обратите внимание, что смежные поля инструкции (метка, код операции и операнды) разделены пробелом.
Инструкции программы выполняются по порядку (начиная с первой), если только порядок не изменен выполнением bnz
инструкции. Выполнение программы завершается, когда выполнена ее последняя инструкция (и при условии, что эта инструкция не изменяет порядок выполнения).
Ваш переводчик будет:
- Прочитайте имя файла, содержащего программу, из командной строки (через
String[] args
иMain
класс). - Прочитайте программу из файла и переведите ее во внутреннюю форму.
- Распечатайте программу.
- Запустите программу.
- Выведите окончательные значения регистров.
Это выглядит сложной задачей, но не бойтесь; мы предоставляем вам часть кода, чтобы вы могли сосредоточиться на интересном использовании подклассов, внедрении зависимостей и отражении.
Заполнение рабочих листов действительно помогает при подготовке к этому заданию.
Дизайн программы
Мы предоставляем некоторые классы, предоставляем спецификации для нескольких и оставляем несколько для вас на написание / доработку. Код, который мы предоставляем, выполняет часть грязной работы по чтению в программе и переводу ее во внутреннюю форму; вы можете сосредоточиться на коде, который выполняет программу. Сначала изучите Machine
класс, поскольку он является сердцем программы (вы также можете использовать main
метод из Main
класса, который поможет вам в этом).
Изучение программы
Вам предоставляется некоторый базовый код, который находится в репозитории.
Посмотрите на поля класса Machine
, которые содержат именно то, что необходимо для выполнения SML-программы:
- метки , определенные в программе,
- сама программа во внутренней форме,
- регистры машины и
- счетчик программы - номер следующей команды для выполнения.
Структуры, подобные массивам, используются для меток и инструкций машины, потому что нет ограничений на размер SML-программы. Массив используется для регистров, потому что всегда имеется ровно 32 регистра.
Теперь прочитайте метод Machine.execute
, который выполняет программу. Это типичный цикл выборки-декодирования-выполнения, который в той или иной форме есть у всех машин.
На каждой итерации выбирается команда для выполнения, увеличивается счетчик программы и команда выполняется. Порядок выполнения последних двух инструкций важен, потому что инструкция (например, bnz
) может изменить счетчик программы.
Класс Translator
содержит методы, которые считывают данные из программы и переводят их во внутреннюю форму; имейте в виду, здесь выполняется очень мало проверок на ошибки. Например, нет проверки на дублирование определений меток, на использование метки, которая не существует, и на регистрационный номер, не входящий в диапазон 0 ..31.
Наконец, изучите main
метод Main
класса (если вы думаете, что это вам поможет).
Класс Instruction
и его подклассы
Все программирование, которым вы занимаетесь, связано с Instruction
классом и его подклассами. Спецификация класса Instruction была предоставлена вам — откройте файл
Instruction.java
и изучите это. Этот класс абстрактный, потому что его не следует создавать. Метод execute
также абстрактен, что заставляет каждый подкласс реализовывать его.
Каждая инструкция имеет метку и операцию - это именно то, что является общим для каждой инструкции. Следовательно, эти свойства поддерживаются в базовом классе всех инструкций.
Задачи
- Дополните методы в
Instruction
классе — это может потребовать от вас добавления некоторых полей, которые должны быть защищены, чтобы они были доступны в любых подклассах. - Теперь создайте подкласс
Instruction
для каждого типа инструкций SML и исправьте методTranslator.instruction
, чтобы он правильно переводил инструкции такого типа. Рекомендуется: пишите по одной инструкции за раз и тщательно тестируйте ее, прежде чем переходить к следующей! - Начните с
add
инструкции, потому что код для ее перевода уже есть в методеTranslator.instruction
. Изначально программа не будет компилироваться, потому что для инструкции нет классаadd
; как только этот класс будет написан, программа будет компилироваться. - Для каждой инструкции подклассу требуются соответствующие поля, конструктор,
toString
метод и a methodexecute
;toString
иexecute
следует переопределять те же методы вInstruction
классе с использованием соответствующих аннотаций. - Делая это, вы увидите, что каждый последующий класс может быть написан путем дублирования предыдущего и его модификации (очевидно, избегая слишком большого количества повторяющегося кода).
- После того, как вы закончите писать подкласс для инструкции SML (за исключением
add
), вам нужно будет добавить код в методTranslator.instruction
для перевода этой инструкции. Существующий код для переводаadd
должен помочь вам в этом. - Теперь возьмите
switch
инструкцию, которая решает, какой тип инструкции создается, и измените код так, чтобы он использовал отражение для создания экземпляров, т. Е. Удалите явные вызовы подклассов. Это позволит расширять язык SML без необходимости изменять исходный код. - Наконец, измените исходный код, чтобы использовать классы dependency injection, singleton и factory там, где вы сочтете нужным. (Вам разрешается использовать другие шаблоны проектирования, если вы считаете их необходимыми.)
- Помимо конкретного кода, упомянутого выше, вы не должны изменять другие классы.
Все эти части курсовой работы должны быть полностью протестированы (вам не нужно предоставлять тесты для исходной базы кода).
Представление
Как часть вашего портфолио, ваш репозиторий будет клонирован в установленный срок.
Индивидуальная курсовая работа 2021
Описание
Простой компьютерный симулятор / A simple computer simulator