Ошибки PascalABC.NET

label 10;
begin
  var i := 20;
  while true do 
  begin
    i -= 1;
    if i = 10 then break;
    if i = 12 then goto 10;
    continue;
    10:
    i -= 1;
    Writeln('Here we are!')
  end;
  Writeln('Finish')
end.

Ложное предупреждение при компиляции: Program1.pas(10) : Обнаружен недостижимый код Ругается на строку после continue. Да, этот код плохой, даже очень плохой, но он имеет право на существование без подобных “ворнингов”. Потому что программа на самом деле работает и “достигает”:

Here we are! Finish

Наткнулся, портируя дремучую фортрановскую программу, где метка на метке и довольно долго разбирался, кто у нас дурачок - я или компилятор. А вдруг и правда код недостижим? (там было довольно сложное условие попадания на метку)…

Ещё подобная ошибка:

Procedure A(n:integer);
Begin
if n < 0 then Exit;
A(n-1)
End;
Begin
End.

“Program8.pas(4) : Обнаружена бесконечная рекурсия”

Тут правильное сообщение, видимо, “ВОЗМОЖНА бесконечная рекурсия”

Да это баг просто. Предупреждение о бесконечной рекурсии выдается, если нет веток

это довольно часто встречающаяся ситуация, очень похоже на эту:

function a:array of byte;
begin
SetLength(a,0);
end;

возвращаемое значение a не определено это сообщение можно легко убрать написав a := a или a := nil, но вот с рекурсивной функцией это так просто не уберёшь, а когда появляется предупреждение в списке ошибок это очень мешает, отвлекается от программирования, а если привыкнуть к тому что оно появляется - не будет замечать ошибок… лично мне нравится когда панелька с ошибками и вводом/выводом авто сворачивается и в таком случае она ещё и будет разворачиваться каждый раз когда появляется предупреждение…

это страница с ошибками и поэтому предлагаю тут же: если результат функции используется в её теле подпрограммой то не показывать предупреждение о возвращаемом значении, и если в подпрограмме есть exit или стоит вызов себя же под if то не показывать предупреждение о бесконечной рекурсивности

этот код вообще не компилируется и не должен. А предупреждение SetLength(Result,0); уже не выдается. Не знаю, выложено ли исправление в релиз или нет. В любом случае в следующей версии предупреждения.

это как? компилятор не даст скомпилировать :slight_smile:

всм тот кто программирует не будет замечать, если привыкнет не замечать предупреждение

а почему название функции не может быть передано как var параметр если Result может, а если присваивать то оба работают одинаково?

Имя функции может использоваться только в левой части оператора присваивания. И вообще это атавизм турбо паскаля. И надо всегда использовать Result.

я не против результа и всегда им пользовался, но вспомнилась учительница информатики из 8 класса, когда я только узнал на практике что такое программирование и она лично предпочитала использовать название функции, а паскальABC.Net вроде бы пытается не отбегать от старых паскалей в стиле чтоб не путать учителей… ну про турбо паскаль я согласен, я изи перевожу код с C++ но мучаюсь если приходится переводить с турбо паскаля :slight_smile:

это печально, конечно.

Лямбды не хотят уживаться с переходами по меткам. С одной стороны это хорошо, как бы подталкивает держаться в рамках структурного программирования, но с другой…

"Употребление слов из четырех букв типа goto может иногда быть уместным даже в самом лучшем обществе." Donald E.Knuth, “Structured Programming with go to statements”

Вот так программа работает.

label 10;
function f(i:integer):=i+i;
begin
  //var f:integer->integer:=i->i+i;
  var s:=0;
  for var i:=1 to 10 do begin
    if i>6 then goto 10;
    s:=s+f(i);
    end;
10:
  Print(s)
end.

А вот так уже нет. При этом выдается диагностика, по-видимому, предназначенная не рядовому пользователю. Т.е. понятно, что это связано с реализацией лямбд, т.е. сообщение идет не по исходному тексту программы, а по преобразованному, но все же первые несколько минут я усиленно искал упомянутый “составной оператор”, благо программа была весьма внушительных размеров (портировал монстрика из Фортрана, где “мильён” меток - нормальная практика)

label 10;
//function f(i:integer):=i+i;
begin
  var f:integer->integer:=i->i+i;
  var s:=0;
  for var i:=1 to 10 do begin
    if i>6 then goto 10;
    s:=s+f(i);
    end;
10:
  Print(s)
end.

Сообщение компилятора:

Program1.pas(7) : Переход внутрь составного оператора на метку 10 невозможен

Спасибо. Понятно.

Моя голубая мечта - чтобы Вы писали сюда: https://github.com/pascalabcnet/pascalabcnet/issues/434

да, запретить совместное использование современных лямбд и запрещенного goto, выдавая соответственное сообщение об ошибке.

А сюда не писать? Я туда пишу тоже временами, когда мне кажется, что это ошибка. А тут я сомневался, может это “фича, а не бага”. И потом, туда ведь не станешь цитировать Кнута, а без этого как-то постно )))

Запретить проще всего… эх, не любите вы пользователей! )))

Вуз - отличное место работы. А если бы там еще и студентов не было… (подслушано в коридоре вуза)

1 лайк

begin Println('1'*0); end. Program2213.pas(2) : Ошибка времени выполнения: Значение MaxCapacity должно быть больше или равно единице. Имя параметра: maxCapacity

begin Println('10'*0); end. А так нет ошибки.

Исправили

Справка → Классы → Переменная Self, опечатка в последнем предложении: Фактически в любом нестатическом методе перед именем любого поля и методу этого класса неявно присутствует Self.

К сожалению, в справке еще полно неточностней и опечаток. Вот, еще, к примеру:

  1. На странице “Условная операция”, в строке var min := a < b & a : b; стоит знак & вместо ?

  2. На странице “Подпрограммы для работы с динамическими массивами” – неточное описание параметров процедуры:

Должно быть: “Изменяет порядок элементов на противоположный в диапазоне динамического массива длины count, начиная с индекса index” (там еще и запятой не было);

  1. + Там же рядом:

Должно быть: “Изменяет порядок элементов на противоположный в диапазоне списка длины count, начиная с индекса index”

  1. Раздел “Справочник по языку / Структура программы / Идентификаторы и ключевые слова” – устаревшая информация насчет обязательной латиницы:
  1. Раздел справки “Справочник по языку / Типы данных / Процедурный тип” – ошибки в определении:

Должно быть:

  1. В справке нет информации о новой “безопасной” форме срезов: a?[from:to] и a?[from:to:step]

  2. С справке в дереве Содержание (Contents) нет ни одного раздела или страницы, с которой была бы прямая ссылка на страницу описания директив компилятора – её можно найти только через индексированный поиск.

  3. В свою очередь, уже на самой этой странице нет даже краткого упоминания (или ссылки) о существовании директив OpenMP, хотя есть целый раздел про это в главном дереве.

@Admin Похоже, вы не до конца с этим багом разобрались, по-прежнему чертовщина какая-то творится при попытке выполнения:

begin // Компилируется всё всегда ОК
  var x := 123;
  var y := object(x);
  writeln(x, y);            // Здесь всё без проблем печатается -> 123123
  //writeln(x, object(x));  // Тут уже -> Ошибка времени выполнения: Ссылка на объект не указывает на экземпляр объекта.
  writeln(x, y, object(x)); // А здесь вообще сразу вылет -> Exception processing message 0xC0000005 ...
end.

@Admin Вот еще кое-какие странности обнаружил с проверками на недостижимость кода (см. комментарии):

label _1, _2;
begin
  loop 2 do
  begin
    writeln('In cycle A');
    break;
    writeln('unreachable code'); // OK, недостижимый код обнаружен
  end;
  loop 2 do
  begin
    writeln('In cycle B');
    continue;;
    writeln('unreachable code'); // ??? недостижимый код уже НЕ обнаруживается из-за пустого оператора выше (;)
  end;
  loop 2 do
  begin
    writeln('In cycle C');
    goto _1;
    var x := 'unreachable definition'; // !!! эта строка уже достижима для определения переменной и вывода её типа?
    goto _2;
    _1:
    writeln(x); // ??? это нормально, что i=nil, а не "Неизвестная переменная x"?
  end;
  _2: 
end.