воскресенье, 22 января 2012 г.

ТЯП часть 3. Семантический анализатор

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

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

Очень важное замечание от Дмитрия Мамонтова:"Количество проверок возрастает экспоненциально от числа фич!"

Проверки
1) Если используется переменная - проверить, что она объявлена
2) При объявлении переменной проверить её тип
2) Проверить, что типы объектов при операциях с ними приводимы\одинаковы(в т.ч полученные при вызовах функций и методов класса)
3) Проверить правильность объявления и описания методов\функций, их аргументы(количество и типы).
4) Проверить, что при доступе к элементу массива его индекс(или выражение, которое там может быть) приводимы к целочисленному типу
5) Проверить, что выражение, стоящее внутри if\while приводимо к целочисленному типу



Теперь поговорим о составлении таблиц и вообще о структурах данных.

Программа(struct SemanticProgram в semanticStructs.h)
Её, как таковую, нужно будет собирать из объявлений\описаний классов, функций, enum'ов и так далее. С её помощью можно контролировать существование классов и их методов, функций\enum'ов и т.д. Для свободных функций так же будет необходимо создать какой-либо универсальный класс, в который они будут записываться.

(functionsTable, объявленный в SemanticProgram, не используется!)


Каждый класс должен иметь:
- таблицу констант
- таблицу полей
- таблицу методов



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



Рассмотрим таблицы подробнее.

1. Таблица констант
Основные типы констант описаны в файле semanticStructs.h в самом верху.
Нужно обратить внимание, что константа может хранить в себе строку\число\указатели на другие константы.
Например, константа Метод хранит 2 указателя
а)Указатель на константу класса(CONSTANT_Class)
б) Указатель на константу имя и тип(CONSTANT_NameAndType).
Константа класса в свою очередь хранит указатель на константу CONSTANT_Utf8, в которой
хранится имя класса, к которому принадлежит метод.
А константа CONSTANT_NameAndType хранит 2 указателя:
а) CONSTANT_Utf8, хранящую имя метода в обычном виде
б) CONSTANT_Utf8, хранящую дескриптор метода в специальном виде(можно посмотреть в методичке).


Сначала совсем непонятно, зачем это нужно. Понимание приходит на этапе генерации кода.
Приведу пример:
Чтобы вызвать метод, на этапе генерации кода мы должны записать номер объекта, метод которого вызываем, а затем номер метода в таблице констант класса.
То же происходит при присваивании большого числа и операций над строками, обращении к полям\методам текущего\не текущего класса.

Чтобы правильно заполнить таблицу, нужно занести в неё следующие данные:
1. Константа Code
2. Константа класса(название класса->CONSTANT_Class)
3. Константа класса-родителя(название класса-родителя->CONSTANT_Class)
4. Поля(название класса + (имя+дескриптор)->CONSTANT_Fieldref)
5. Методы(название класса + (имя+дескриптор)->CONSTANT_Methodref
6. Числа больше 2х байтов(CONSTANT_Integer) (!Внимание! целые числа > 2х байтов нельзя занести напрямую при генерации кода, поэтому это сделать обязательно!)
7. Строки(CONSTANT_String)

2. Таблица полей
Существует  в основном для того, чтобы можно было проверить наличие данного поля у класса\быстрого доступа к его константе и проверки её типа.

3. Таблица методов
Проверка типа возвращаемого значения в return'ах, хранилище локальных переменных.

Зачем нужна таблица локальных переменных?
В Java нет имён переменных, есть только их номера. Т.е. если вы захотите присвоить что-то переменной a, то нужно получить её номер в таблице локальных переменных и работать с ним.



Важная информация!
Порядок переменных в таблице:
0. ссылка на this
далее - аргументы метода
далее - все остальные внутренние переменные метода.


Если метод статический, переменной this нет! Но нумерация происходит так же, т.е. в общем случае переменная с номером 0 в статическом методе будет ссылаться на его первый аргумент! 

Что нужно будет сделать при прохождении всех выражений и операторов в методах?
а) Проверить типы данных выражений, существование переменных, полей, методов.
При этом нужно будет дополнить каждое выражение типом(особенно важно, если метод возвращает объект класса).
б) Всем локальным переменным приписать их номера в таблицах констант.
в) Все вызовы методов\обращения к полям нужно будет записать в таблицу констант класса и тут же выражениям, в которых они происходят, записать номера этих констант(см. выше). Причём если вызывается поле другого класса, нужно сначала добавить класс в таблицу констант, а затем поле. То же самое с методами.
Подробнее это описано в методичке.


В конце концов мы должны таблицу, при поддержке которой мы бы смогли написать на последнем этапе рабочий компилятор.



Ссылка на репозиторий
http://code.google.com/p/vstu-objective-c/
Папка с семантикой
trunk/Sem

Комментариев нет:

Отправить комментарий