Компиляторы, 3 курс, 5 семестр, 2016/17

Материал из SEWiki
Версия от 00:43, 30 октября 2016; E.f.suvorov (обсуждение | вклад) (Поддержка функций)

Перейти к: навигация, поиск

Лектор: Булычев Дмитрий Юрьевич.

https://github.com/dboulytchev/sample-compiler

Образ с настроенным софтом для виртуальной машины: OVA (логин внутри: me, пароль: me).

Результаты

Вся информация на этой странице сдублирована из почты!

Домашние задания

Домашнее задание от 13.09.2016

  1. Дописать интерпретатор стековой машины с символическим стеком (там надо поддержать оставшиеся 5 инструкций).
  2. Реализовать печать инструкций в правильном формате ассемблера x86 (см., например, https://en.wikibooks.org/wiki/X86_Assembly/GAS_Syntax).
  3. Реализовать правильное "обрамление" порожденной программы:
            .text
            .globl main

main:
            <тут идет текст ассемблерного порождения>
            ret

Конструкции управления

Базовые:

  1. if E then S1 else S2 fi, где E — выражение, а S1 и S2 — операторы. Если значение E вычисляется не в ноль, то исполняется <code>S1, иначе — S2.
  2. while E do S od</code, где <code>E — выражение, <code>S — оператор. Если значение E вычисляется в не ноль, то исполняется S, а потом весь while заново; иначе не делается ничего.

Дополнительные:

  1. if E1 then S1 {elif E2 then S2 elif E3 then S3} ... [else Sk] fi эквивалентно:
    if E1 then S1
    else if E2 then S2
           else if E3 then S3
           ....
           [else Sk]
    fi 
  1. repeat S until E эквивалентно S; while E == 0 do S od
  2. for S1, E, S2 do S od эквивалентно S1; while E do S; S2 od

Поддержка функций

На уровне выражений язык расширяется конструкцией вызова функции: <ident> (<expr>, <expr>, ...). Список аргументов может быть пустым, но скобки нужны в любом случае.

На уровне операторов язык расширяется двумя конструкциями:

  1. <ident> (<expr> , <expr>, ... ) — вызов функции. Список аргументов может быть пустым, но скобки нужны в любом случае.
  2. return <expr> — возврат значения. Выполнение функции должно всегда заканчиваться выполнением оператора return; если функция вызывается как оператор, то её результат теряется.


Кроме того, теперь перед самой программой может идти одно или несколько описаний функций. Каждое описание имеет следующий вид:

fun <ident> (<ident> , <ident>, ... )
begin
    <stmt>
end

Список формальных параметров може быть пуст, но скобки нужны в любом случае.

Правила видимости для переменных внутри функции: каждая функция "видит" свои параметры; все остальные используемые переменные считаются локальными для данного вызова функции. Глобальные переменные не видны. Функции могут быть рекурсивными, в том числе взаимно-рекурсивными.

Расширение системы команд стековой машины:

  1. CALL of string * string list — инструкция вызова. Получает имя функции и список имен её параметров.
  2. RET — возврат из функции.
  3. END — конец программы (завершает выполнение, даже если "хвост" инструкций не пуст).

Пример:

fun fact (n)
begin
  if n < 2
     then return 1
     else return n * fact (n-1)
  fi
end

read (n);
write (fact (n))

Документация

Система сборки (новая)

Используется opam - это пакетный менеджер для OCaml.

Подготовка (альтернативно можно запустить скрипт от Димы):

  1. Требуется установить opam версии хотя бы 1.2.2. Есть в репозиториях Debian/Ubuntu (sudo apt-get install opam).
  2. Должен автоматически поставится компилятор ocaml. Проверяем версию: ocaml -version.
  3. Если версия хотя бы 4.02 - запускаем из домашнего каталога opam init. Если версия древнее — запускаем opam init --comp 4.03.0.
  4. Чтобы подцепить изменения в окружении в текущей сессии, надо запустить eval `opam config env`. Теперь версия компилятора точно должна быть хотя бы 4.02.
  5. Выполняем команды:
opam pin add logger https://github.com/dboulytchev/logger.git -y -n
opam pin add GT https://github.com/dboulytchev/GT.git -y -n
opam pin add ostap https://github.com/dboulytchev/ostap.git -y -n
opam pin add ocanren https://github.com/dboulytchev/ocanren.git -y -n 
opam install ostap
opam install ocanren
  1. Также для сборки runtime.o на Debian/Ubuntu может потребоваться пакет g++-multilib.

Как собирать:

  • Если вы находитесь в корне репозитория: make -f Makefile.ob.
  • Если вы находитесь не в корне, а, скажем, в папке src, то надо добавить параметр -C <путь-до-корня>: make -C .. -f Makefile.ob.