• Nenhum resultado encontrado

Р ЕЗУЛЬТАТЫ Р АЗРАБОТКИ A. Размещение Переменных в Памяти

ТАБЛИЦА I Координаты зданий

IV. Р ЕЗУЛЬТАТЫ Р АЗРАБОТКИ A. Размещение Переменных в Памяти

Для современных языков программирования характер- на перегрузка знаков операций. Один и тот же знак опе- рации в зависимости от сочетания типов и мутабельно- сти обрабатываемых данных может интерпретироваться различными последовательностями процессорных инст- рукций.

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

В силу этого возникает необходимость для каждой пере- менной помимо ее значения хранить некоторые мета- данные о ней. На Рис. 2. отображена структура, исполь- зуемая в runtime-библиотеке языка Elдля хранения мета- данных о переменной в памяти программы.

Рис. 2. Структура, представляющая переменную в памяти.

Структура T_VARIABLE содержит следующие поля:

flags – набор битовых полей, содержащих информацию о статичности/динамичности типа данных переменной, ее мутабельности, а также дополнительную служебную информацию;

type – поле содержит закодированный целым числом тип данных текущего значения, присвоенного переменной;

value – содержит адрес, по которому в памяти размещено текущее значение переменной.

Структура T_VARIABLE размещается статически в стеке, выделение места для нее осуществляется в момент компиляции. Размещение значений переменных осуще- ствляется в куче, выделение памяти происходит во время инициализации переменных вместе с заполнением полей flags и type. На Рис. 3. Для примера приведено схематич- ное размещение в памяти переменной типа «список».

B. Позднее Связывание

Язык El является интерпретируемым в том смысле, что выполнению полезных вычислений над сложными типа- ми данных и переменных, для которых тип не задан в программе явно, предшествует анализ операндов, выбор конкретной реализации некоторой языковой операции, вызов соответствующей библиотечной функции. Такую

обработку объектов в программе принято называть позд- ним связыванием.

Рис. 3. Схематичное размещение переменной в памяти.

В самом простом случае в библиотеке языка El позднее связывание реализуется следующим образом. Компиля- тор в том месте программы, где должна выполняться определенная языковаяоперация, вставляет вызов соот- ветствующей библиотечной функции. Эта функция при- нимает в качестве аргументов указатели на операнды, т.е. на структурыT_VARIABLE. Она анализирует значе- ния полей структуры, после чего осуществляет выбор конкретной функции, реализующей требуемую опера- цию над значениями именно этих типов и выполняется ее вызов. На Рис. 4. показан пример реализации позднего связывания.

Рис. 4. Пример реализации позднего связывания.

Функция dtype_variable_init предназначена для выде- ления памяти под значение переменной и создание ее структуры в том случае, если тип данных является со- ставным. В зависимости от установленного типа данных переменной функция выделяет необходимое количество памяти под значение, после чего вызывает функцию, которая занимается конструированием значения указан- ного типа данных.

C. Конструирование и Уничтожение Объектов В библиотеке реализованы функции для работы с па- мятью – ее выделения и освобождения. Поскольку язык El не предусматривает явного управления памятью, а также сборки мусора, компилятор должен вставлять вы- зовы этих функций таким образом, чтобы при входе в определенную область видимости под значения пере-

XIV Международная научно-техническая конференция АПЭП – 2018

132

менных выделялась память, а при выходе из нее память освобождалась.

Прежде, чем сконструировать непосредственно объект, хранящийся в переменной, требуется заполнить поля структуры T_VARIABLE. На Рис. 5 отображены прото- типы функций, предназначенных для инициализации структуры.

Рис. 5. Функции для инициализации структуры T_VARIABLE.

Для захвата памяти под значения переменных и их конструирование компилятор должен поместить в код (после заполнения структуры T_VARIABLE) вызов функции dtype_variable_init. Для уничтожения перемен- ной нужно вызвать одну из предназначенных для этого функций. Их прототипы приведены на Рис. 6.

Рис. 6. Прототипы функций управления памятью.

Функция dtype_variable_init в зависимости от типа данных переменной выделяет под значение память в ку- че, после чего вызывает функцию, которая конструирует переменную. Например, если переменная имеет тип

«Список», то при конструировании нужно создать струк- туру двусвязного списка, готового к добавлению в него узлов.

Функция dtype_variable_clear деконструирует значение переменной. При этом память, занимаемая структурой T_VARIABLE, не освобождается.

Для пояснения действий, выполняемых при деконст- руировании переменной, рассмотрим пример работы с переменной типа «Список». Для уничтожения перемен- ной этого типа в первую очередь следует освободить память, занимаемую, которые являются элементами спи- скаобъектами (вызвать для них функцию dtype_variable_destroy), затем освободить память, зани- маемую структурами, представляющими узлысписка, затем освободить память, занимаемую структурой, хра- нящей информацию о самом списке.

Функция dtype_variable_destroy также деконструирует значение переменной. Однако, если структура T_VARIABLE была создана в куче, а не на стеке, то па- мять, занимаемая структурой, также освобождается. Та- кие переменные могут появляться в ходе выполнения

программы, являются служебными и недоступны про- граммисту.

Функция dtype_variable_destroy_structure предназначе- на для уничтожения таких объектов, как кортежи, спи- ски, вектора, но без уничтожения хранимых в них объек- тов. Пример ситуации, когда такая операция может по- надобиться – использование списков в цикле. Например, на определенной итерации цикла в некоторой перемен- ной должен быть создан новый список, старый больше не нужен и должен быть уничтожен. Однако хранимые в нем переменные пока должны быть доступны, поскольку процесс выполнения программы еще не достиг точки выхода из текущей области видимости.

D. Неявные Приведения Типов

При выполнении тех или иных операций (арифметиче- ских, операций сравнения и других) возникает необхо- димость неявного приведения типов операндов. Для это- гоиспользуется следующий алгоритм.

1. Подготовить временные переменные, в которые бу- дут помещены приведенные значения операндов;

2. Вызвать функцию dtype_cast (ее прототип отображен на Рис. 7). Функция принимает операнды, которые нужно привести, указатели на временные перемен- ные, где должны быть размещены приведенные зна- чения и код операции, для которой выполняется при- ведение операндов;

3. Проверить, были ли заполнены временные перемен- ные приведенными значениями. Если да, то исполь- зовать эти значения в качестве операндов, в против- ном случае, использовать переданные начальные зна- чения операндов;

4. В зависимости от типов операндов вызвать ту или иную реализацию языковой операции.

5. В случае, если были приведены значения операндов, освободить память, выделенную под них.

В библиотеке присутствует набор классов, которые по- зволяют по коду операции, типам операндов получить набор правил для приведения типов данных. Правило указывает, что операнд типа T1 должен быть приведен к операнду типа T2.

Рис. 7. Прототип функции dtype_cast.

Функция dtype_cast получает из таблицы набор правил, перебирает операнды и выполняет приведения операн- дов в соответствии с полученными правилами, вызывая соответствующие библиотечные функции.

E. Методика ТестированияКомпилятора

Поскольку управление памятью полностью возложено на компилятор и библиотеку поддержки языка, возника-

133

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

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

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

Кроме того, разработана утилита, позволяющая в ав- томатическом режиме запускать компилятор языка El для каждой из накопленного набора тестовых программ, запускать скомпилированную программу и сверять ее вывод с эталонным. Данный вид тестирования позволяет убедиться в том, что реализация новых возможностей в компиляторе и runtime-библиотеке не привела к некор- ректной работе функций, реализованных ранее.

V.

О

БСУЖДЕНИЕ

Р

ЕЗУЛЬТАТОВ

На данный момент реализована начальная версия ком- пилятора и библиотеки поддержки языка. Реализованы такие возможности, присущие функциональным языкам, как сопоставление с образцом, вызов перегруженных функций на основе сопоставления с образцом, аноним- ные функции, замыкания. Помимо этого реализованы некоторые типы данных, часть арифметических опера- ций, операции сравнения, управляющие конструкции.

VI. В

ЫВОДЫ И

З

АКЛЮЧЕНИЕ

В данной работе изложены основные подходы, приме- ненные при разработке библиотеки поддержки языка программирования El.

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

С

ПИСОК

Л

ИТЕРАТУРЫ

[1] Малявко А.А. Функционально-императивный язык программирования El. – Научный вестник НГТУ, № 1(70), 2018, С.

117-136.

[2] Малявко А.А., Журкин П.А., НагорновН.С.Функционально- императивный язык программирования El и его реализация. – Автоматика и программная инженерия, № 1(23) – Новосибирск, 2018, С. 34-46.

[3] Ахо А, Сети Р., Ульман Дж. Компиляторы: принципы, технологии, инструменты. М.: Издательский дом "Вильямс", 2003.

– 768 с.

[4] The GCC low-level runtime library[Electronic resource]// URL:

https://gcc.gnu.org/onlinedocs/gccint/Libgcc.html, (accessed 18.04.2018)

[5] Valgrind User Manual [Electronic resource]// URL:

http://valgrind.org/docs/manual/manual.html, (accessed 18.04.2018) Журкин Павел Андреевич – студент НГТУ Область научных интересов: системное про- граммное обеспечение

email: zhur.pav@yandex.ru

XIV Международная научно-техническая конференция АПЭП – 2018

134 978-1-5386-7054-5/18/$31.00 ©2018 IEEE

Преобразователь типовых конструкций языка Java в аннотации библиотеки Lombok

Дмитрий Ю. Индикеев, Александр А. Малявко

Новосибирский государственный технический университет, Новосибирск, Россия

Аннотация – В статье рассматривается разработанный преобразователь типовых конструкций языка Java в анно- тации библиотеки Lombok.Описываются особенности реа- лизации преобразователя и требования, которые предъяв- лялись к нему при реализации. Так же в статье описано как преобразователь можетупростить процесс конвертации уже написанного кода в код, использующий Lombok аннотаци- ии, как он может помочь при разработке новых программ.

Ключевые слова Шаблонный код, аннотация, плагин,Lombok.

I.

В

ВЕДЕНИЕ

ЗЫК и платформа Java [1]разрабатываются уже более 20 лет. За это время язык очень сильно эволю- ционировал, но из-за желания разработчиков языка под- держивать совместимость между старыми версиями и новыми в языке накопилось большое количество реше- ний, которые сейчас выглядят не элегантно.

Сейчас при написании программ наJavaпрограммист, как правило,должен написать большой объем шаблонно- го кода (boilerplatecode[2]). Обычно этот код загромож- дает программу и не несет в себе пользы. Читать про- грамму, загроможденyю таким кодом сложноиз-за того, что он скрывает бизнес-логику программы.

Сегодня одним из средств борьбы с шаблонным кодом в Java является библиотека Lombok [3]. Она позволяет снизить объем шаблонного кода при написании про- граммы. Однако для того, чтобы избавиться от шаблон- ного кода в уже написанных программах, программисту все равно нужно приложить довольно много усилий.

Идеей, лежащей в основе работы, былостремление создать средство, которое бы облегчилопроцесс внедре- ния библиотеки Lombok вуже реализованные проекты.