В этом вопросе язык для надёжного программирования ближе всего к Оберону, но с более жёсткими условиями по недопущению перекрытия.
Все используемые идентификаторы кроме предопределённых должны быть предварительно объявлены. Имя, использованное для объявления на уровне раздела или функции, должно быть уникальным в одной области видимости, за исключением предварительного объявления функции, что нужно для возможности косвенной рекурсии. Имя объявления, сделанного внутри функции также должно быть уникальным во всей функции, в том числе и для не пересекающихся областей видимости внутри неё.
Объявление-d, сделанное на уровне раздела-s доступно по имени от начала его появления в тексте до конца s. В других разделах-so d доступно только в том случае, если оно было помечено как экспортируемое в s, и только в тех из них, где s был импортирован. Доступ к d в so осуществляется черезимпортированное имя s - ins, следующей за ним разделяющей точкой и именем d
section s {
const(c = d + 1; // ошибка - d ещё не объявлена
+d = 0; // пометка объявления "+" как экспортированное
e = d + 1)
proc p() {
const(f = d;
e = 6) // ошибка - е уже объявлено в этой области уровнем выше
...
}
}.
section so {
import (ins = so) // переименовываем, s недоступна для использования
const (d = ins.d;
e = so.d; // ошибка, раздел s был переименован для использования
f = ins.e) // ошибка, объявление е не было экспортировано в s
proc p() {
{ const (a = 3)
...
}
{ const (a = 0.6)// ошибка - хотя a=0.6 объявлена в другой области
... // видимости, но в пределах одной процедуры,
} // что запрещено
}
}.
Имя объявления, сделанного на уровне структуры должно быть уникальным лишь в пределах самой структуры. Имя может совпадать как с предопределёнными именами, так и с именами, объявленными на уровне раздела, функций и других структур, в том числе вложенных, так как из-за строго иерархического обращения к элементам структуры не может быть никакого кофликта имён.
section a {
const (b = 1)
var (r struct {
r struct {
r, b int
}
}
)
proc p() {
r.r.r = 0;
r.r.b = b
}
}
В языке нет разновидности импорта, позволяющей включать экспортированные объявления других разделов в область видимости импортирующего раздела так, как будто они являются его собственными. Это сомнительное удобство вносит неразбириху относительно принадлежности используемых сущностей и создаёт возможность для появления ошибок в результате манипуляций с импортом и расширения интерфейса используемых разделов.
Из заданных ограничений следует, что имена объявлений, сделанные внутри функции могут совпадать с именами объявлений, сделанных в других функциях. Также, имя внутри функции может совпадать с именем одной из функций, объявленных ниже по тексту. Это послабление нужно для возможности создания однопроходного транслятора.
section a {
const(+a = 10)// обращение к собственному модулю не предусмотрено,
// поэтому имя объявления может совпадать с именем модуля.
proc +b() {
const(c = a;
d = 4)// d объявлена ниже, поэтому не входит в текущую
... // область видимости
}
proc +d() { // область видимости d = 4 закончилась внутри b()
const(c = a + 1)// хотя с уже встречается в b(), но так как области
// b() и d() не пересекаются, то объявление правильно.
...
}
}
Запрет на перекрытие имён и возможность иметь несколько конкретизаций синтаксисов создают трудности, требующие разрешения:
- Невозможность использования подходящего имени, если оно уже занято предопределённым идентификатором, что может быть неприятным, если их будет много.
- Невозможность использования объявления с именем, совпадающим с ключевым словом, от модуля, написанного под другой синтаксис.
Для разрешния этого можно использовать спец-символ, обозначающий, что помеченное имя имеет пользовательское происхождение.
section @const { // @ как в C#
const (+@section = 1)
}
Можно рассмотреть и другую возможность — отказ от ключевых слов и ограниченное число предопределённых имён. При необходимости добавления новых в обновлённой версии языка, они добавляются в псевдораздел, чтобы исключить пересечение с именами в разделе, написанном ранее. Но это решение пока кажется сложней и проблематичней. Вариант, в котором наоборот — все ключевые слова и предопределённые идентификаторы помечены, кажется слишком неудобным и уродливым.
@section m {
@const (c = 1)
@type (t @int)
@var (v t)
@func f(i t) (res @bool) {
res = i < @max(t) / 2
}
}
Комментариев нет:
Отправить комментарий