июня 14, 2011

DEmbro: классы для исходного кода

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

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

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

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

Самый главный класс — TSource, отвечает за промежуточное хранение исходного кода (последовательности символов) в оперативной памяти, и делегирует выполнение операций с исходным кодом вспомогательным классам. Пока что исходный код хранится только в памяти, и поэтому TSource может хранить в буфере его целиком, но в будущем будет возможность получать исходники и из других мест: из файла, из произвольного потока, по сети и т.д. Идея этого заключается в том, что так как нам не нужно хранить весь исходный код целиком в оперативке, а нужен только небольшой фрагмент, то разумно этим воспользоваться и в качестве бонуса получить малое потребление оперативной памяти. Кроме того, пользуясь особенностями конкретных источников исходника, можно оптимизировать чтение и выиграть в скорости (например, если исходный код приходит по сети, то можно выполнять по мере поступления приходящие куски). Кроме того, TSource должен хранить название источника кода (имя файла, например).

У этого класса есть два вспомогательных — TSpaceSkipper и TNameReader. Первый, как нетрудно догадаться, нужен для того, чтобы пропускать пробелы. Пока что пробелами считаются символы в диапазоне от 0 до 32, но при необходимости можно будет унаследовать своё поведение. Кроме того, в TSpaceSkipper можно будет добавить функциональность по подсчёту числа пробелов, и этим воспользоваться в DEmbro (например, в языке программирования питон для выделение блоков вместо ограничителей begin...end или {...} используются отступы — что достаточно удобно и наглядно. При записывании уровня игры символами в виде псевдографики проще пользоваться пробелами, чем какими-то другими символами). TNameReader, в свою очередь, читает имена. В имя могут входить только символы не из диапазона от 0 до 32, но можно будет унаследовать класс, который, например, будет воспринимать слова с пробелами, если слово заключено в одинарные кавычки.

Наконец, есть дополнительный класс — TLineReader. Он выделяет строки, считает номер текущей строки, и позицию в строке. Если это нужно, конечно, — класс можно будет отключить для ускорения работы.

Вроде как получилось расширяемо и ортогонально, но немного муторно.


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

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

Постоянные читатели

Обо мне

Моя фотография
Мой e-mail: vitek_03(at)mail(dot)ru