Эти рекомендации относятся только к оформлению исходных текстов Рефала-05, его рантайма и библиотеки встроенных функций, а также любых других программ, которые будут включаться в этот репозиторий (за исключением подключения других программ как подмодулей).
Рекомендации не навязываются как единственно верные при написании любых других программ на Рефале-05 или C.
Это рекомендации, т.е. применять их следует в соответствии со здравым смыслом. Например, длина строки не должна превышать 80 символов, но если написалась строчка длиной 82 символа и попытки её сократить или разбить на несколько ухудшают читабельность, то её лучше оставить такой «длинной».
Но злоупотреблять отступлениями от рекомендаций тоже нельзя.
*.md
) следует использовать символы Юникода вместо их
суррогатов из ASCII: «
, »
, ’
, …
, —
и т.д. вместо "
, '
, ...
,
-
, --
, ---
. Неразрывный пробел, там где он должен быть (после коротких
союзов и предлогов, перед единицами измерения, частицами «бы» и «же» и т.д.),
должен быть всегда. Для правки документации следует использовать текстовые
редакторы, которые не портят неразрывные пробелы.Хорошо:
+<FooBar
+ текст внутри идёт с отступом 2 пробела
+>
+void foo_bar(
+ int foo,
+ int bar
+) {
+x = bar_foo(
+ foo, bar
+);
Плохо:
-<FooBar текст выравнивается
- по имени функции>
-void foo_bar(int foo,
- int bar)
-{
-x = bar_foo(foo,
- bar);
temp
, tmp
, e.Temporary
и т.д.
В остальных случаях имена типа temp
или tmp
являются недопустимыми.Func
, Func1
, Func2
следует давать имена вида Func
для «основной» функции и Func-Пояснение
для вспомогательных. -Пояснение
должно отражать смысл этой вспомогательной функции, например,
ProcessFileNames-CheckInvalid
. Часто, когда вспомогательная функция одна,
можно использовать суффикс -Aux
.$EXTERN
-объявлению должен предшествовать комментарий *$FROM
,
содержащий имя файла (без расширения), в котором определены эти функции.
$EXTERN
не следует включать имена функций,
импортируемых из разных файлов.$EXTERN
-объявления пишутся в самом начале файла.$ENTRY Go
, то её определение следует непосредственно
после всех $EXTERN
объявлений.
$ENUM
, $EENUM
, $SWAP
или $ESWAP
,
описываются перед первым их использованием.CamelCase
. Дефис используется для
отделения крупных смысловых частей, обычно для вспомогательных функций это имя
«главной» функции и пояснение предназначения вспомогательной.
Для поиска в ассоциативных списках началу и концу списка даётся одно и то же
имя, с суффиксами -B
и -E
, соответственно. Например:
e.Names-B (e.Name s.Index) e.Names-E
Если ассоциативный список содержит 3 компоненты, средняя получает суффикс
-M
:
e.Names-B (e.Name s.Index1) e.Names-M (e.Name s.Index2) e.Names-E
Кстати, здесь оправдано использование чисел в именах переменных: два вхождения одинаковой по смыслу сущности.
Map
, Reduce
, MapAccum
, начинаются
имени исходного файла в нижнем регистре, за которым следует прочерк
и содержательное имя функции с большой буквы. Например:
generator_GenTreeItem
.ИмяФункции {
тело функции
}
=
, ,
, :
всегда ставится один пробел. Перед =
ставится
пробел. Перед ,
, ;
пробел не ставится.Таким образом, предложение выглядит так:
ИмяФункции {
…
ЛеваяЧасть = ПраваяЧасть;
ДлиннаяДлиннаяЛеваяЧасть =
ДлиннаяДлиннаяПраваяЧасть;
ДлиннаяДлиннаяЛеваяЧасть =
ДлиннаяДлиннаяДлиннаяДлинная
ДлиннаяДлиннаяДлиннаяПраваяЧасть;
}
Правильно (скобочные термы не разбиваются):
+ (e.ОднаждыВ t.Студёную s.Зимнюю) s.Пору
+ (t.ЯИзЛесу e.Вышел t.Был s.СильныйМороз)
Неправильно (один скобочный терм разбивается):
- (e.ОднаждыВ t.Студёную s.Зимнюю) s.Пору (t.ЯИзЛесу e.Вышел
- t.Был s.СильныйМороз)
Правильно:
+<НарезатьСалатРекурсивный
+ <ПомытьОвощи
+ e.Огурцы e.Помидоры t.Салат
+ >
+ (Специи
+ (
+ <Майонез>
+ <Сметана>
+ )
+ (
+ (Соль)
+ (Перец
+ Чёрный
+ Красный
+ )
+ )
+ )
+>
Неправильно:
-<НарезатьСалатРекурсивный <ПомытьОвощи e.Огурцы
- e.Помидоры t.Салат>
- (Специи (<Майонез>
- <Сметана>)
- ((Соль)
- (Перец Чёрный
- Красный)))>
Вспомогательные функции, реализующие цикл на хвостовой рекурсии
(остаточно-рекурсивный цикл), начинаются с префикса Do
:
Fact {
0 = 1;
s.N = <DoFact 1 1 s.N>;
}
DoFact {
s.N s.Prod s.N = <Mul s.N s.Prod>;
s.K s.Prod s.N
= <DoFact <Inc s.K> <Mul s.K s.Prod> s.N>;
}
Sw
.Map
, MapAccum
или Reduce
, если это не снижает
читабельность кода.в_нижнем_регистре_с_подчёркиваниями
.в_нижнем_регистре_с_подчёркиваниями
.БОЛЬШИМИ_БУКВАМИ
.if (x != 0) {
y = x;
}
else
пишется после закрывающей фигурной скобки:if (x != 0) {
y = x;
} else {
z = y;
}
s_
.switch
должны быть явным образом перечислены все допустимые
варианты. Если переход на ветку default:
никогда не должен происходить,
то в ней располагается вызов макроса
r05_switch_default_violation(выражение_внутри_switch)
,
который при передаче управления на него, выбрасывает исключение. Таким
образом выявляются ошибки в программе, связанные с передачей неверных данных.Директивы условной компиляции препроцессора, в отличие от обычного кода на C, работают на более низком семантическом уровне — оперируют с текстом как с набором строк и «нарезают» его в зависимости от макросов препроцессора.
Поэтому они не подчиняются обычным правилам отступов и пишутся сразу от начала строки
R05_NORETURN void r05_exit(int retcode) {
fflush(stderr);
fflush(stdout);
end_profiler();
#ifdef R05_SHOW_STAT
fprintf(stderr, "Step count %lu\n", s_step_counter);
#endif /* R05_SHOW_STAT */
free_memory();
fflush(stdout);
exit(retcode);
}
#endif
должен располагаться комментарий с текстом условия
в соответствующем #if
или #ifdef
. Пример — см. выше.