Здесь смысл не в 1/0, а в том что в одном блоке существует два присвоение одной и той же переменной. То есть, значение было ранее присвоено, но где-то ниже переопределено ещё раз(без всяких проверок и тд).
Вид для печати
Не только можно, но и я его уже реализовал ещё осенью прошлого года (и, к слову о warning 210, многие куски кода таки были позаимствованы оттуда), просто дело так и не дошло до PR, да и не уверен, есть ли вообще смысл что-то предлагать сейчас разработчикам компилятора, если они до сих пор не решаются принять warning 210, и при этом не могут дать вразумительного аргумента против этой фичи (ИМХО, "инициализация нулём по умолчанию хорошо определена" - очень сомнительный аргумент, т.к. этому в официальной документации (Pawn Language Guide) посвящено всего одно предложение (которое дословно так и переводится "все переменные по умолчанию равны нулю"), без какого-либо объяснения, чем оправдана такая логика и чем это лучше предупреждений о неинициализированных переменных).
Касаемо самой проблемы, я так понимаю, можно упростить пример до
main() { new x = 0; x = 1; // warning 240: previously assigned value is unused return x; }
На днях, как будет время (может быть даже на этих выходных), попробую сделать PR с этой фичей, а заодно и issue по switch-выражениям.
Эм... никак? Ибо компилятор не может знать о контексте применения кода, это задача пользователя.
Nice job ;)
Будем надеяться, что разработчики таки примут предложение от юзеров и внесут изменение в компилятор. А если же этого не случится - будем использовать твой вариант на постоянной основе.
И да, я думаю комьюнити оценит любые доработки. Тем более, мы не платим за его использование и имеем право выбора. А экспериментировать и обсуждать никто не запрещал)
@Daniel_Cortez, не планируешь в своем форке сделать инициализацию "саб-массивов" через прогрессию? (...)
new array_3d[5][3][3] = { { {1, 2, 3}, {4, 5, ...}, ... }, { {1, 2, 3}, ... }, ... }; main() { for (new i = 0; i < sizeof(array_3d); i++) { for (new j = 0; j < sizeof(array_3d[]); j++) { for (new g = 0; g < sizeof(array_3d[][]); g++) { } } } }
Сейчас это выдает ошибку при компиляции:
error 001: expected token: "{", but found "..."
error 001: expected token: "}", but found ";"
Во-первых, нет, не планирую, ибо понятия не имею, как работает тот спагетти-код для инициализации массивов.
Во-вторых, нет никакого "моего форка", была только пара-тройка неофициальных релизов с исправленными багами. Даже если бы я и захотел создать свой форк, была бы проблема с тем, как отличить его от форка Zeex'а - в последнем есть константы "__Pawn" и "__PawnBuild", но мне пришлось бы вводить свои константы и свою нумерацию версий, чтобы избежать "пересечений" с тем форком, не говоря уже о том, чтобы убедить скриптеров по всему миру переписать свои скрипты с учётом этих новых констант (в то время, как ещё со стокового компилятора 3.2.3664 не все хотят слезать).
Не припоминаю, чтобы мы обсуждали какие-то "подводные камни" по warning 240. Разве что единственный недостаток, что моя реализация пока что обнаруживает неиспользуемые присвоения только к одиночным переменных. Для массивов потребовалось бы гораздо больше изменений как в структурах хранения данных, так и в логике компилятора.
Как бы то ни было, пока что я оставлю реализацию как есть, т.е. только для одиночных переменных. Если примут её в таком виде, то тогда и только тогда будет смысл пытаться что-то химичить с массивами, иначе это будет просто пустая трата времени.
А что конкретно не понятно? Да это усложняет чтение кода, но это было бы круто, если бы была такая возможность инициализации массивов. Это идею предлагал и @ziggi
Вышла новая версия 3.10.10.
Скачать: https://github.com/Zeex/pawn/releases/tag/v3.10.10
Примечание: Начиная с данной версии требуется использовать модифицированные инклуды SA-MP, иначе у вас появится куча новых warning 239 (т.к. в стандартных инклудах не исправлена проблема с const-корректностью). Просто скачайте их по этой ссылке (click) и скопируйте инклуды из архива в папку "pawno/include".
Изменения:
- Добавлены новые директивы #pragma unread и #pragma unwritten, которые позволяют подавить предупреждения о том, что значение символа (переменной/константы/функции) нигде не считывается или не изменяется соответственно.
Принцип работы этих директив схож с уже существующей #pragma unused, однако позволяют подавлять отдельно только предупреждения о том, что значение символа не считывается, и отдельно, что не изменяется, тем самым лучше показывая намерения скриптера.
- Добавлена директива #pragma nodestruct, которая инструктирует компилятор не вызывать деструктор при уничтожении локальной переменной.
Примечание (DC): Да, оказывается, в Pawn для переменных с любым тегом, кроме "_", можно создать деструктор - функцию, которая автоматически вызывается по окончании существования локальных переменных с заданным тегом.
- Исправлен выход за пределы массива в коде упаковки данных (функция encode_cell()), который в редких случаях мог спровоцировать отключение сжатия файла *.amx с выводом сообщения "warning 232: output file is written, but with compact encoding disabled".
- Добавлен оператор __addressof (#445).
- Препроцессорный листинг (файл *.lst) теперь записывается после второго прохода препроцессора, т.е. именно в таком виде, в каком код в дальнейшем компилируется.
- Обеспечено игнорирование неизвестных препроцессорных директив внутри #if/endif (#427).
- Серия исправлений и улучшений, связанных с оператором __emit:
- Добавлены псевдо-опкоды, которые можно использовать в макросах с операндами любого типа:
- load.u.pri/alt - загрузить значение операнда (может быть выражением) в PRI/ALT.
- stor.u.pri/alt - сохранить значение PRI/ALT в операнд.
- addr.u.pri/alt - загрузить адрес операнда в PRI/ALT.
- push.u - сохранить значение (может быть выражением) в стек.
- push.adr.u - сохранить адрес операнда в стек.
- zero.u - обнулить операнд.
- inc.u/dec.u - увеличить/уменьшить значение операнда на 1.
Пример использования:
#define getval(%0) __emit(load.u.pri %0) #define addrof(%0) __emit(addr.u.pri %0) const global_const = 0x1234; new global_var = 0x5678; main() { const local_const = 0x4321; new local_var = 0x8765; static local_static_var = 0x9ABC; static local_static_array[2]; }- Компилятор теперь выдаёт ошибку, если смещение в стеке или адрес данных не кратен размеру ячейки (т.е. 4 байтам).
__emit load.s.pri 5; // error 011: stack offset/data address must be a multiple of cell size- Устранено падение, возникавшее когда с помощью __emit вызывается нативная функция, которая ранее ещё нигде не вызывалась.
- Удалена проверка значений операндов (индексов) для инструкций lctrl и sctrl.
- Опкоды stor.s.pri/alt, inc.s, dec.s, и zero.s больше не принимают аргументы функций, переданные по ссылке.
- Разрешены отрицательные смещения для аргументов типа "локальная переменная" (такие смещения требуются для доступа к аргументам функций).
- Исправлено множество случаев, когда при несоответствии типов аргументов в сообщениях об ошибках выводились неправильные названия типов.
- Удалёно ключевое слово emit, оставлено только __emit (для соответствия новому правилу, согласно которому новые операторы должны начинаться с "__").
- Исправлено падение компилятора, происходившее при использовании #error и #warning без указания текста ошибки/предупреждения.
- Исправлено падение компилятора, когда после #pragma option параметр был длиннее 31 символа.
- Исправлен неправильный вывод названия массива, когда оператор sizeof использовался на массиве неопределённого размера.
Func(const arr[]) { // До исправления: warning 224: indeterminate array size in "sizeof" expression (symbol "") // После: warning 224: indeterminate array size in "sizeof" expression (symbol "arr") return sizeof(arr); }- Исправлены ложные предупреждения о const-корректности (warning 239) в функциях, имеющих несколько реализаций для разных состояний автоматонов (state).
- Исправлен баг, из-за которого компилятор при опечатке предлагал переменную до того, как она была реализована (#374).
GetValue() { return value; // error 017: undefined symbol "value"; did you mean "value"? // Очевидно, что переменная "value" не должна быть видна отсюда, т.к. она объявлена только ниже. } new value = 0; main() { GetValue(); }- Исправлен баг, из-за которого компилятор при опечатке не предлагал функцию, если ошибка допущена перед реализацией функции (#397).
main() { // Здесь компилятор должен предложить функцию "DoNothing", но он этого не делает, // хоть в Pawn функции и могут вызываться до своего объявления и реализации. DoNothin(); // error 017: undefined symbol "DoNothin" } DoNothing(){}
- Устранено падение компилятора из-за попытке при опечатки предложить переменную с пустым названием (#451).
- Исправлено некорректное сообщение об ошибке, выдаваемое, когда переменная, имеющая состояние, используется вне своей области видимости (т.е. вне функции, имеющей то же состояние).
new var <state_a>; main() { // До исправления: test.pwn(5) : error 017: undefined symbol "var"; did you mean "var"? // После: test.pwn(5) : error 017: undefined symbol "var"; state variable out of scope var = 5; }- Исправлено некорректное сообщение об ошибке, выдаваемое, когда функции, принимающей массив, передаётся ячейка массива, переданного из другой функции по ссылке.
Func2(const arr[3]) { return arr[0]; } Func1(const arr[]) { // До исправления: error 007: operator cannot be redefined // После: error 047: array sizes do not match, or destination array is too small Func2(arr[0]); } main() { static const arr[1]; Func1(arr); }- Исправлена некорректная фатальная ошибка (error 106), выдаваемая, когда компактное кодирование (LEB128) файла *.amx неэффективно и разница между сжатыми и несжатыми данными составляет меньше 63 байт (вместо ошибки компилятор должен выдавать только предупреждение, что компактное кодирование оказалось невыгодно и файл записан несжатым (warning 232)).
main() { // Примечание: При компактном кодировании '0xAABBCCDD' плохо сжимается // и занимает 5 байт вместо 4, тем самым делая сжатие неэффективным. static const a[32] = { 0xAABBCCDD, ... }; return a[0]; // До исправления: fatal error 106: compiled script exceeds the maximum memory size (1521262808 bytes) // После: warning 232: output file is written, but with compact encoding disabled }- Исправлена фатальная ошибка, возникавшая при компиляции кода, в котором используется хотя бы одна из встроенных строковых констант (__file, __date, __time) и есть хотя бы одна функция, имеющая состояния.
#include <a_samp> main() { // /home/travis/build/Zeex/pawn/source/compiler/sc4.c:76: writeleader: Assertion `glb_declared==0' failed. }
Баг не проявлялся под Windows, однако ему были подвержены релизы компилятора для Linux и OS X.
- Исправлен баг с возможностью для локальных переменных инициализироваться самими собой.
main() { // До исправления: нет сообщения об ошибках // После: error 017: undefined symbol "test" new test = test; }
Что интересно, до исправления компилятор не выдавал даже предупреждения о том, что переменная в данном примере никак не использоована. Это связано с тем, что при такой инициализации компилятор засчитывал и чтение, и запись в переменную, и потому считал, что она полноценно используется.
- Исправлен баг с игнорированием тегов в анонимных enum.
enum // Название не указано, тег тоже (следовательно, { // все константы внутри enum будут с тегом "_") Float:DRAW_DISTANCE = 100.0 // ДО ИСПРАВЛЕНИЯ: код скомпилируется, но компилятор молча проигнорирует тег "Float:", // и если кто-то попытается использовать эту константу, то вместо вещественного "100.0" // получит целочисленное "_:100.0" (т.е. "1120403456", ибо приведение тега - это не конверсия). // ПОСЛЕ ИСПРАВЛЕНИЯ: error 001: expected token: "-identifier-", but found "-label-" };
(Если вы ещё не видели, выше пост с релизом компилятора 3.10.10).
От себя добавлю, что процесс работы над компилятором всё ещё оставляет желать лучшего:
- Мейнтейнеры подготовили релиз только после того, как я вчера "как бы невзначай" напомнил им, что прошло уже полтора года и, может быть, пора бы уже что-нибудь выкатить. (Я мог бы и раньше это сделать, создав отдельный issue, но это, как минимум, выглядело бы некрасиво.)
- Куча PR'ов, находящихся в очереди на принятие, были попросту проигнорированы перед релизом - включая даже те из них, которые уже были рассмотрены и одобрены.
В ближайшее время попробую подготовить неофициальный билд с теми PR'ами, которые не расширяют сам язык Pawn и не ломают совместимость.