Ошибки компилятора PascalABC.Net

А по моему вы таки не попытались понять что я написал…

procedure Test(from, &to: integer);
begin
  var s := '012';
  s.Substring(from-1,&to-from).Length.Println;
  s[from:&to].Length.Println;
end;

begin
  Test(1,4);
  Test(2,4);
  Test(3,4);
  Test(4,4);
end.

.SubString как раз работает ожидаемо, поэтому я и привёл его как пример:
Если начинать после последнего символа но брать 0 символов - ошибки нет. Если начинать на символ дальше и брать всё равно 0 символов - ошибку уже выдаёт.

Это правильная обработка пограничного значения, принятая в современных языках, вам уже показали выше.

1 лайк

А как вы собираете сборку и прогоняете тесты? Вызывая _RebuildReleaseAndRunTests.bat?

В dll попадают не все функции. Такое ощущение, что вы компилируете RebuildStandartModules.pas без флага /rebuild. Но во всех bat-файлах он присутствует

Нет, вы собираете без флага Rebuild

Обновитесь и проверьте, работает ли сейчас

Чтобы из модулей в сборку попадал весь функционал, а не только используемый, нужно запускать консольный компилятор с аргументами: <полное имя .pas-файла> /rebuild

Есть разные языки. Вы показали в двух языках, в которых не так как у нас.

У нас логика простая. Есть срезы и есть безопасные срезы.

В срезах первый индекс ведет себя так как если мы обращались бы по индексу. В s=‘123’ s[4] - это выход за диапазон. s[4:], s[4:4] - это всё выход за диапазон по первому индексу. Неверно указывать первый индекс, выходящий за пределы диапазона. Если указал - исключение.

Если нужно другое поведение, используются безопасные срезы: s?[4:] s?[4:4]

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

Так что указывать, что что-то по-вашему там не так - странно

Было бы проще выравнять ментальные модели для соседних языков. А так выходит как с Windows/Linux: кнопка закрытия окна, кнопки Ok/Cancel лево/право специально перепутано, чтобы затруднить переход пользователей между платформами.

Интересно было бы посмотреть запись семинара.

1 лайк

При любой попытке запустить удаленно на гитхабе pabcnetc <anything>.pas /rebuild возникает исключение:

Unhandled Exception: System.IO.IOException: The handle is invalid.
     at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
     at System.Console.GetBufferInfo(Boolean throwOnNoConsole, Boolean& succeeded)
     at PascalABCCompiler.ConsoleCompiler.Main(String[] initialArgs)

@admin pabcnetcclear.exe при этом работает удаленно без проблем – может быть проблема в перехвате на виртуалке гитхаба ввода/вывода консоли для создания реал-тайм лога?

Локально у меня таких ошибок не возникает, но никакой разницы с pabcnetcclear.exe (который не имеет опции /rebuild) я не вижу – PABCRtl.dll все равно получается битый:

pabcrtl.dll (396.5 КБ)

Лог
>"C:\Program Files (x86)\pascalabc.net\pabcnetc" PABCRtl.pas /rebuild
Loading core...
Подключен парсер PascalABC.NET Language Parser v1.2
Подключен парсер Documentation Comments Tag Parser v0.9
PascalABCCompiler.Core v3.7.1.2677
Copyright (c) 2005-2020 by Ivan Bondarev, Stanislav Mikhalkovich
OK 439,252ms
Connected parsers: PascalABC.NET (*.pas);
Connected conversions: Optimizer;
Compiling assembly PABCRtl.pas...
[1]CompilationStarting PABCRtl.pas...
[1]BeginCompileFile PABCRtl.pas...
[0]BeginParsingFile PABCRtl.pas...
[28]EndParsingFile PABCRtl.pas...
[0]SyntaxTreeConversion Standard...
[2]BeginCompileFile __RtlUtils.pas...
[0]BeginParsingFile __RtlUtils.pas...
[1]EndParsingFile __RtlUtils.pas...
[0]SyntaxTreeConversion Standard...
[935]ReadPCUFile PABCSystem.pcu...
[89]ReadDLL System.dll...
[0]ReadDLL mscorlib.dll...
[1]ReadDLL System.Core.dll...
[0]ReadDLL System.Numerics.dll...
[8]ReadPCUFile PABCExtensions.pcu...
[11]CompileInterface __RtlUtils.pas...
[18]CompileImplementation __RtlUtils.pas...
[1]EndCompileFile __RtlUtils.pas...
[6]ReadPCUFile __RunMode.pcu...
[217]ReadPCUFile __RedirectIOMode.pcu...
[2]ReadDLL System.Windows.Forms.dll...
[394]ReadPCUFile GraphWPFBase.pcu...
[2]ReadDLL PresentationFramework.dll...
[2]ReadDLL WindowsBase.dll...
[0]ReadDLL PresentationCore.dll...
[1]ReadPCUFile GraphWPF.pcu...
[96]ReadPCUFile Graph3D.pcu...
[2]ReadDLL System.Xml.dll...
[97]ReadDLL HelixToolkit.Wpf.dll...
[18]ReadPCUFile WPFObjects.pcu...
[3]ReadPCUFile ClientServer.pcu...
[8]ReadPCUFile Arrays.pcu...
[7]ReadPCUFile Collections.pcu...
[92]ReadPCUFile FormsABC.pcu...
[2]ReadDLL System.Drawing.dll...
[2]ReadPCUFile RBDMUtils.pcu...
[7]ReadPCUFile PT4TaskMakerNET.pcu...
[8]ReadPCUFile Timers.pcu...
[3]ReadPCUFile VCL.pcu...
[2]ReadPCUFile Utils.pcu...
[2]ReadPCUFile Sockets.pcu...
[47]ReadPCUFile GraphABCHelper.pcu...
[2]ReadPCUFile GraphABC.pcu...
[9]ReadPCUFile IniFile.pcu...
[0]ReadPCUFile RobotField.pcu...
[1]ReadPCUFile RobotTaskMaker.pcu...
[0]ReadPCUFile RobotZadan.pcu...
[6]ReadPCUFile Robot.pcu...
[3]ReadPCUFile PointRect.pcu...
[8]ReadPCUFile PointerTools.pcu...
[7]ReadPCUFile FilesOperations.pcu...
[2]ReadPCUFile Events.pcu...
[14]ReadPCUFile DMCollect.pcu...
[1]ReadPCUFile DrawManField.pcu...
[15]ReadPCUFile DMTaskMaker.pcu...
[1]ReadPCUFile DMZadan.pcu...
[2]ReadPCUFile Drawman.pcu...
[8]ReadPCUFile CRT.pcu...
[15]ReadPCUFile ABCObjects.pcu...
[0]ReadPCUFile ABCSprites.pcu...
[7]ReadPCUFile ABCHouse.pcu...
[9]ReadPCUFile ABCButtons.pcu...
[1]CompileInterface PABCRtl.pas...
[1]CompileImplementation PABCRtl.pas...
[0]EndCompileFile PABCRtl.pas...
[645]SavePCUFile __RtlUtils.pcu...
[4]SemanticTreeConversion Optimizer...
[2]CodeGeneration PABCRtl.dll...
[513]CompilationFinished PABCRtl.pas...
Ready.
OK 3394,0757ms (48lines)

У вас PABCRtl собирается нормально? А на гитхабе или каком другом CI/CD сервисе пробовали?

нет, в сокращённом виде

Но, если честно, я не особо понял как это всё работает, если запускать батник, то всё нормально.

image

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

pabcnetc использует Console.Clear. И Console.ReadKey, который не совместим с перенаправлением вывода. Зато он выводит разноцветные буквы.

Он и не рассчитан на запуск из другой программы. Для компиляции из отдельной программы - используйте или pabcnetcclear, или делайте свою программу и подключайте к ней .dll компилятора.

Взаимно. Интересно было бы посмотреть запись митапов разработчиков тех языков, где допускается обращение по несуществующему индексу.

Вы должны компилировать pabcnetc из репозитория, а не из инсталлята.

Но обращение то идёт к области, а не к элементу. Главное чтоб область которую представляет срез не выходила за область элементов строки. А у вас получается, что вы не разрешаете индекс в конце строки потому что “религия не позволяет”.

1 лайк
  1. “Так вон оно чо, Михалыч!” :man_facepalming:t2: Ну, наконец-то, тайна этого Бермудского треугольника разгадана! :nerd_face: Т.е. проблема (одна из 2 основных) этой оболочки компилятора в том, что, по крайней мере в режиме /rebuild, она ищет исходники стандартных модулей только в \Lib (строго как оно лежит в репе), напрочь игнорируя при этом папку \LibSource (как оно потом уже поставляется в дистре)! И в итоге, будучи запущенной из любого места вне родной репы, втихую собирает PABCRtl.dll в режиме /rebuild в непригодном урезанном виде, читая только самый минимум готовых .pcu из папки \Lib и, похоже, не включая большую часть кода из них из соображений оптимизации (т.е. как в режиме обычной компиляции!).

По этой же причине, видимо, и в IDE сейчас нет никакой заметной разницы в результате работы между кнопками “Компилировать” и “Компилировать все”, т.е. аналога опции /rebuild. Кто-то совсем недавно тут про это спрашивал “Как оно работает и зачем оно тогда надо?” :slight_smile:

Но, похоже, проблема элементарно решается путем поиска компилятором исходников нужных модулей сначала в тек. папке основного файла, потом в \LibSource и только затем уже в \Lib. Это позволит pabcnetc.exe полноценно функционировать откуда угодно (при наличии рядом папки \Lib и/или \LibSource).

  1. 2-ая серьезная проблема – работа с перенаправлением ввода/вывода. Может стоит реализовать опцию /rebuild в pabcnetcclear.exe (уже совместимой с перенаправлением) или проще добиться совместимости с ним pabcnetc.exe только в командном (не интерактивном!) режиме, чтобы оно работало и в батниках из-под виртуалки? А то разбираться в чужом коде и писать свою отдельную консольную оболочку компилятора при наличии уже целых 2-х официальных будет как-то странно.

Вот, в сравниваемом вами C# это падает:

    class Program
    {
        static void Main(string[] args)
        {
            int[] a = new int[] { 1, 2, 3 };
            Console.WriteLine(a[4..3]);
        }
    }

Для нас - всегда - первый индекс - это индекс элемента - это то, чему нельзя позволять выходить за пределы. Если хотите - это религия. На этапе обучения обучаемый должен запомнить - первый параметр это индекс, за пределы его изменения выходить нельзя.

Ещё раз повторюсь - хотите чтобы было по-вашему - используйте безопасный срез. Тогда человек ясно отдаёт себе отчёт, что ошибки не будет - будет пустой массив

Это когда человек себе говорит: вот так прошло на этот раз - и ладно! Алгоритм у меня дырявый - да пофигу! Все как у врачей: “Хорошо зафиксированный больной в анестезии не нуждается!”

Да, это хорошая и правильная идея. Пишите Issue.

Папка Libsource всегда была лишь для изучения исходников ну и еще для того чтобы в случае ошибки туда перенаправлялся показ компилятором строчки, где произошла ошибка. То есть, ни о какой перекомпиляции исходников из LibSource после того как приложение инсталлировано речи не идет.

Безопасно работают в частности все старые строковые функции: Pos, Insert, Delete. Они легки в изучении именно потому что не падают со страшным лязгом. Безопасные срезы - аналоги таких функций. Все споры - это попытка позиционирования срезов и безопасных срезов не так как, как их задумывали разработчики.