Ошибки PascalABC.NET

В Turbo/Borland Pascal была директива {Q+}, использование которой приводило к вызову исключения, в частности, при переполнении разрядной сетки в целочисленных операциях. В PascalABC.NET я не нашел эквивалента. Возможно потому, что в .NET нет механизма для обнаружения таких ситуаций (при целочисленном переполнении интеловский процессор не выдает аппаратное прерывание, следовательно, ситуацию можно отследить только путем программного анализа, что ведет к огромным накладным расходам).

Это да, в C++ без этой проверки работает на много быстрее. Но бывают случаи когда всё же отследить переполнение нужно, а без такой директивы получается очень громоздкий код.

Так и есть. Поэтому обсуждать бессмысленно

Я конечно ничего не имею против Вас и Windows XP, но разве не пора бы перейти на более новые версии Windows? Например Win 10. Она хорошая, стабильная, а самое главное, она “легче” для ПК, так как более оптимизирована. И, кстати, в моей школе тоже до сих пор стоит XP на всех ПК и ноутбуках (Но там они очень древние, уже почти умерли, хотя наверное уже могли умереть, так как уже не учусь в школе и могу не знать)) :slight_smile:

нет, поддержка в .NET имеется. в IL есть специальные команды для этого, а в C# конструкция checked.

Но если есть, непонятно, почему в PascalABC.NET не сделали опциональную поддержку.

Сын спрашивает отца-программиста

  • Папа, а почему солнце встает на востоке?
  • Ты это проверял?
  • Да
  • Работает?
  • Да
  • Каждый день работает?
  • Да
  • Тогда сынок, ради бога, ничего не трогай, а то сломается!

Это к вопросу об issue на GitHub “Сделать оператор возведения в степень ** enhancement” от 27 мая 2016 года.

потому что мало кому нужно

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

2 лайка

6 сообщений перенесены в новую тему: Арифметика указателей в PascalABC.NET

Type
  ИмяКласса_1 = class
    А, Б, Ц: integer;
    ИмяКласса_2 := new class(Д := 'Е', А, Б, Ц);
  end;
Begin
End.

31.12.2017 4:25:34 PascalABCCompiler.Core v3.3.0.1600 (23.12.2017), debug version Runtime version: 4.0.30319.42000 OS version: Microsoft Windows NT 6.2.9200.0 Processor count: 4 WorkingSet: 83960 kb StatesList: BeginCompileFile Program1.pas BeginParsingFile Program1.pas EndParsingFile Program1.pas SyntaxTreeConversion Standard ReadPCUFile PABCSystem.pcu ReadDLL System.dll ReadDLL mscorlib.dll ReadDLL System.Core.dll ReadDLL System.Numerics.dll ReadPCUFile PABCExtensions.pcu ReadPCUFile __RedirectIOMode.pcu ReadDLL System.Windows.Forms.dll CompileInterface Program1.pas CompilationFinished Program1.pas Ready

Error[0]: Внутренняя ошибка компилятора в модуле [pabcnetc.exe] :‘System.Exception: Compile internal error: For cycle in class body’

Последняя сборка вообще 1603 но на ней тоже воспроизводится. Сделал issue. Разработчики просят писать на гитхаб сразу если ошибка явная потому что на форуме сообщение может отмотаться из за обсуждений.

Исправлено. Новая версия - на сайте

1 лайк

В приведённом примере, в списке свойств внутреннего класса IntelliSense отображает только Д, хотя остальные тоже выводятся, редактируются и т.д.

Вот такая программа нормально работает.

type
  R=sequence of integer;

begin
  var a:=ArrRandom(ReadInteger('n='),-99,99); a.Println;
  var P:R->BigInteger:=t->t.Aggregate(BigInteger(1),(p,q)->p*q);
  if P(a.Where(t->t.IsEven))>P(a.Where(t->t.IsOdd))
  then Writeln('Номер максимального элемента: ',a.IndexMax+1)
  else Writeln('Номер минимального элемента: ',a.IndexMin+1)
end.

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

А вот в такой программе выдается ошибка

begin
  var a:=ArrRandom(ReadInteger('n='),-99,99); a.Println;
  var P:function(t:sequence of integer):=t->t.Aggregate(BigInteger(1),(p,q)->p*q);
  if P(a.Where(t->t.IsEven))>P(a.Where(t->t.IsOdd))
  then Writeln('Номер максимального элемента: ',a.IndexMax+1)
  else Writeln('Номер минимального элемента: ',a.IndexMin+1)
end.

eArrRandom.pas(7) : Ожидалась функция, встречена процедура Invoke

Если это не ошибка, хотелось бы иметь более внятное описание ошибки.

P.S. Я уже интересовался насчет сахарка с функцией Prod, возвращающей произведение элементов последовательности. Было отказано, потому что есть Aggregate. Ну вот как раз иллюстрация мучений с Aggregate, потому что не сами произведения нужны, а их значения в выражении. Разве не лучше бы смотрелось так?

begin
  var a:=ArrRandom(ReadInteger('n='),-99,99); a.Println;
  if a.Where(t->t.IsEven)).ProdBigInteger > a.Where(t->t.IsOdd).ProdBigInteger
  then Writeln('Номер максимального элемента: ',a.IndexMax+1)
  else Writeln('Номер минимального элемента: ',a.IndexMin+1)
end.

Ведь готовая функция могла бы и вырожденный случай обработать, когда на вход поступает пустая последовательность…

Ну, здесь и ваша ошибка (не указан тип возвращаемого значения function(t:sequence of integer)), и ошибка компилятора (не в том месте указывает на ошибку)

Автовывод типа не работает тут? Тогда неправ, конечно…

Увидел, что добавили оператор возведения в степень- решил опробовать, написал:

begin
  (2**7)
end.

Нажал F9 - естественно выдало ошибку, хотел дописать .ToString.Print - компилятор повиc и упал… Повторил всё выше перечисленное - ошибка не воспроизводится. Эта ошибка у меня уже давно проскакивает, на Вин7 и Вин10. Как правило, ломается после ошибки компиляции. Запустил, где-то ошибся - компилятор упал, последние изменения не сохранились…

Объясните, пожалуйста, есть существенная разница между этим кодом:

Case self.Расположение of
  33:
    Begin
      Смещение := ШиринаЭкрана-Ширина-Смещение;
      if (Высота+Сдвиг > ВысотаЭкрана) then Высота := ВысотаЭкрана-Сдвиг;
      if (Ширина+Смещение > ШиринаЭкрана) then Ширина := ШиринаЭкрана-Смещение;
      
      if (self.КоличествоСтолбцов = 0) then
      begin
        Assert((РазмерКнопок <> 0)and(ОтступОтКнопок <> 0),'33');
        КоличествоСтолбцов := (Ширина-ОтступОтКнопок) div (РазмерКнопок+ОтступОтКнопок);
      end;
    End;
End;

И этим:

Case self.Расположение of
  33:
    Begin
      Смещение := ШиринаЭкрана-Ширина-Смещение;
      if (Высота+Сдвиг > ВысотаЭкрана) then Высота := ВысотаЭкрана-Сдвиг;
      if (Ширина+Смещение > ШиринаЭкрана) then Ширина := ШиринаЭкрана-Смещение;
      
    End;
End;

if (self.КоличествоСтолбцов = 0) then
begin
  Assert((РазмерКнопок <> 0)and(ОтступОтКнопок <> 0),'33');
  КоличествоСтолбцов := (Ширина-ОтступОтКнопок) div (РазмерКнопок+ОтступОтКнопок);
end;

Этот код находится в одном из методов класса. Первый вариант кода работает, как должен. Разница только в том, что во втором случае, блок if вынесен за пределы case. НО, начинает срабатывать Assert - на пару мгновений - после чего вылетает ошибка “Ошибка времени выполнения: System.NullReferenceException: Ссылка на объект не указывает на экземпляр объекта.”, причём в другом методе этого же класса. Оказывается, компилятор просто игнорирует создание экземпляра класса и следующие за ним задания значений свойств, и происходит это уже в другом месте. Отладчик доходит до этого места и просто пролетает его, и всё что следует после.


Нашёл с утра по раньше ошибку у себя. Возник другой вопрос, как работает assert? Он вроде должен останавливать работу программы, а вместо этого программа продолжает работать и отладка прерывается.

assert используется в программах для тестирования паскаля, чтоб когда разработчики добавляют фичу - проверить не сломала ли она что то. Вот к примеру, это вроде последний добавленный такой файл. System.Diagnostics.Debug.Assert должна работать понятнее.

Для чего он - знаю, а вот как работает? Может он только в консольных приложениях работу программы прерывает, а в оконных его использовать вообще нельзя? Или я что-то делаю не правильно…