Перейти к основному содержимому

Директивы компилятора

warning

Эта страница переведена сообществом на русский язык, но нуждается в улучшениях. Если вы хотите принять участие в переводе свяжитесь с @alexgton.

Это ключевые слова, которые начинаются с # и предписывают компилятору выполнить некоторые действия, проверки или изменить параметры.

Эти директивы можно использовать только на самом внешнем уровне (не внутри определения какой-либо функции).

#include

Директива #include позволяет включить другой файл исходного кода FunC, который будет проанализирован вместо include.

Синтаксис: #include "filename.fc";. Файлы автоматически проверяются на повторное включение, и попытки включить файл более одного раза будут игнорироваться по умолчанию с предупреждением, если уровень детализации не ниже 2.

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

#pragma

Директива #pragma используется для предоставления компилятору дополнительной информации, выходящей за рамки того, что передает сам язык.

#pragma version

Pragma Version используется для принудительного применения определенной версии компилятора FunC при компиляции файла.

Версия указывается в формате semver, то есть a.b.c, где a — основная версия, b — дополнительная, а c — патч.

Разработчику доступно несколько операторов сравнения:

  • a.b.c или =a.b.c — требует именно a.b.c версию компилятора
  • >a.b.c — требует, чтобы версия компилятора была выше a.b.c,
    • >=a.b.c — требует, чтобы версия компилятора была выше или равна a.b.c
  • <a.b.c — требует, чтобы версия компилятора была ниже a.b.c,
    • <=a.b.c — требует, чтобы версия компилятора была ниже или равна a.b.c
  • ^a.b.c — требует, чтобы основная версия компилятора была равна части a, а второстепенная — не ниже части b,
    • ^a.b — требует, чтобы основная версия компилятора была равна части a, а второстепенная — не ниже части b
    • ^a — требует, чтобы основная версия компилятора была не ниже части a

Для других операторов сравнения (=, >, >=, <, <=) короткий формат предполагает нули в пропущенных частях, то есть:

  • >a.b совпадает с >a.b.0 (и поэтому НЕ соответствует версии a.b.0)
  • <=a совпадает с <=a.0.0 (и поэтому НЕ соответствует версии a.0.1)
  • ^a.b.0 НЕ совпадает с ^a.b

Например, ^a.1.2 совпадает с a.1.3 но не a.2.3 или a.1.0, однако ^a.1 соответствует им всем.

Эту директиву можно использовать несколько раз; версия компилятора должна удовлетворять всем предоставленным условиям.

#pragma not-version

Синтаксис этой директивы такой же, как и у директивы version, но она завершается неудачей, если условие выполняется.

Например, ее можно использовать для внесения в черный список определенной версии, известной своими проблемами.

#pragma allow-post-modification

funC v0.4.1

По умолчанию запрещено использовать переменную до ее изменения в том же выражении. Другими словами, выражение (x, y) = (ds, ds~load_uint(8)) не будет скомпилировано, в то время как (x, y) = (ds~load_uint(8), ds) допустимо.

Это правило может быть заменено #pragma allow-post-modification, которое позволяет изменять переменную после использования в массовых назначениях и вызовах функций; как обычно, вложенные выражения будут вычисляться слева направо: (x, y) = (ds, ds~load_bits(8)) приведет к x, содержащему начальную ds; f(ds, ds~load_bits(8)) первый аргумент f будет содержать начальную ds, а второй - 8 бит ds.

#pragma allow-post-modification работает только для кода после директивы.

#pragma compute-asm-ltr

funC v0.4.1

Объявления Asm могут перезаписывать порядок аргументов, например, в следующем выражении

idict_set_ref(ds~load_dict(), ds~load_uint(8), ds~load_uint(256), ds~load_ref())

порядок разбора будет: load_ref(), load_uint(256), load_dict() и load_uint(8) из-за следующего объявления asm (обратите внимание asm(value index dict key_len)):

cell idict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTISETREF";

Это поведение можно изменить на строгий порядок вычислений слева направо с помощью #pragma compute-asm-ltr

В результате в

#pragma compute-asm-ltr
...
idict_set_ref(ds~load_dict(), ds~load_uint(8), ds~load_uint(256), ds~load_ref());

порядок разбора будет load_dict(), load_uint(8), load_uint(256), load_ref() и все перестановки asm будут происходить после вычислений.

#pragma compute-asm-ltr работает только для кода после директивы.