Именование объектов
В качестве имен объектов и типов данных можно использовать буквы, цифры и знаки подчеркивания в любых комбинациях, при условии, что первый символ имени не является цифрой.
Все идентификаторы должны быть уникальны, а для избежания коллизий можно использовать пространство имен и модульную структуру кода, которые NewLang поддерживает одновременно.
Перегрузка функций по типам аргументов NewLang отсуствует, поэтому несколько функций с однинаковым именем но разными аругментами определить нельзя, но можно переопределить функцию, в том числе и расширив типы принимаемых аргументов или увеличив их количество.
Идентификатор объекта может содержать один или несколько специальных символов - квалификаторов (или сигилов), за которыми закрепелено определенное значение. Идентификатор объекта который не содержит квалификатора, называется простым:
Квалификаторы имен:
- ‘@’ — префикс собачка используется для указания имени макроса, который обрабатыватся препроцессором до начала синтаксического анализа исходного текста программы.
- ‘$’ — знак доллара в начале имени объекта обозначает автоматичекое имя временной переменной, область памяти для которой выделяется динамически во время выполнения приложения, а время жизни ограничено семантикой яызка
- ‘::’ — двойное двоеточие является разделителем пространства имен, и является признаком статического объекта, область памяти для которого выделяется во время компиляции приложения или модуля. Если имя начинается на ‘::’, то область видимости объекта будет глобальной и он будет доступен в рамках всего приложения. В противном случае, видимость объекта будет ограничена только текущим программным модулем.
- ‘.’ — префикс точка используется при обращении к полю модуля или класса (ограничивает область видимости текущим объектом). Префикс точка может использоваться при определении (вызове) функции для явной идентификации именованного аргумента, чтобы его нельзя было перекрыть макросом препроцессора.
- ‘\’ — обратный слеш в начале термина обозначает имя программного модуля, а так же разделяет имена каталогов в иерархии размещения программных модулей.
- ‘:’ — двоеточие в начале термина обозначает имя типа данных или конструктор класса
- ‘%’ — префикс знак процента указывается для импортируемых символов (нативных переменных и функций)
- ‘^’ — символ карет (крышечка/домик) после имени используется для придания объекту иммутабельности (константности, не изменяемости).
Разрешение имен (name lookup)
Если имя объекта не содержит квалификатора, оно называется простым. Создание объекта с указанием простого имени равнозначно созданию локального объекта.
В других случаях, когда NewLang встречает простое имя объекта без квалификатора (сигила), то в дело вструпает специальный алгоритм, который связывает простое имя, встретившееся в исходном тексте программы, с его декларацией или конкретным объектом по его внутреннему имени.
Разрешение простых имен без квалификатора (name lookup, или поиск имени функции/переменной) происходит всегда в строго определенном порядке:
- в первую очередь происходит поиск имени среди макросов
- далее выполняется поиск имени среди локальных объектов до объектов текущего модуля
- в последнюю очередь выполняется поиск среди глобальных объетов с постепенным расширением пространства имен области поиска от текущей до глобальной
Такая последовательность разрешение имен всегда предоставляет возможность переопределить глобальные/локальные объекты или имена аргументов у функций для уже существующего кода без его серъезных изменений.
Например, для имени name
в области имен ns
поиск происходит в следующей последовательности:
@name
-> $name
-> ns::name
-> ::ns::name
-> ::name
,
а для имени arg
проверяется только @arg
:
ns:: {
name(arg="value");
};
И в тоже время, всегда остатся возможность указать конкретный объект не зависимо от работы алгоритма разрешение простых имен. Достаточно указать квалификатор в имени объекта в явном виде.
Например, обратиться к глобальному объекту name из пространства имен ns из примера выше, нужно по полному имени объекта ::ns::name
,
а именованнй аргумент ’. arg’ не будет заменен макросом @arg
, если такой будет определен:
::ns::name(.arg="value");
Предварительное объявление
В тексте программы можно ссылаться только на реально существующие (созданные) объекты. Но для тех случаев, когда требуется сослаться на объект, который создан в другом модуле или будет создан позже, можно сделать предварительное объявление, при котором компилятор регистриурет имя и тип объекта без его реального создания.
За счет предварительного объявления можно ссылаться только на статические объекты (типы данных), или локальные поля класса о которых компилятор ещё не знает, но которые будут определены в процессе компиляции позже.
Для предварительного объявления можно использовать только полное квалифцированное имя, которое должно будет в точности совпадать с именем обекта при его последующем создании.
Для предварительного объявления используется точто такой же синтаксис, как и при реальном создании объекта, только с права от операторо создания должно быть указано многоточие.
Область видимости предварительное объявения соответствует области видимости его размещенея, а не реальвой области видимости объекта (это касается даже глобальных объектов).
# Предварительное определение переменной модуля
# Действует для всего модуля
var_module:Int32 := ...;
func() ::= {
# Предварительное объявление с помощью DSL
# (действует только внутри тела функции)
@declare( func2(arg:Int32):Int32 );
var_module = func2(var_module);
@return var_module;
};
func2(arg:Int32):Int32 ::= {
@return $arg*$arg;
}
var_module:Int32 := 1;
Имена аргументов, специальные, системные имена
Обозначение имен аргументов у функций очень похоже на обращение к аргументы в bash скриптах, где “$1” или “$name” — порядковый номер или имя соответствующего аргумента.
Зарезервированное имя “$0” обозначает текущий объект, а именем “$$” обозначается родительский объект.
Все аргументы функции собранны в одном словаре со специальным имеенм $*
Неизменяемая переменная “$^” содержит результат выполнения последнего оператора или блока кода.
Полное имя текущего модуля содержится в переменной @\\, а текущая область имен в переменной @::, т.е.:
# Имя файла filename.src в каталоге dir
ns:: { # Использовать пространство имен ns
name:: {
# Команда препроцессора "@#" - преобразовать в символьную строку
ns_str := @# @::; # Строка с областью имен "::ns::name::"
mod_str := @# @\\; # Строка с именем модуля "\\dir\filename"
};
};
Области видимости
Символ подчерка, а так же подчерк в начале имени или двойные подчерки в начале и в конце имени имеют специальное значение.
Один подчерк соответствует защищенной, а два подчерка - приватной области видимости объекта в модуле или классе, что соответствует принятым соглашениям в языке Python.
Но так же, как и в языке Python, области видимости больше соответствуют “джентльменской” договоренности и при явном указании имени, доступ к защищенным объектам можно получить, просто указав полное имя объекта.
В дополнении к этому, существуют еще системные поля и объекты, которые начинаются и заканчиваются на два подчерка.
- ‘$’ — знак доллара в начале имени обозначает системное (локальное) имя временной переменной, область памяти для которой выделяется во время выполнения, а время жизни ограничено семантикой яызка
- ‘::’ — двойное двоеточие являются разделителем при указании пространства имен. Явное указание пространства имен является признаком статического объекта, область памяти для которого выделяется во время компиляции приложения или модуля.