Ошибки на избыточные `$EXTERN`’ы
Mazdaywik opened this issue · 2 comments
Воспроизведение ошибки
Рассмотрим 4 файла:
- Файл
redudand-externs1.BAD-SYNTAX.ref
:$ENTRY Go { = } $EXTERN Go;
- Файл
redudand-externs2.BAD-SYNTAX.ref
:$EXTERN L; $ENTRY Go { = <L> } L { = }
- Файл
redudand-externs3.BAD-SYNTAX.ref
:$EXTERN Foo, Bar; $EXTERN Foo, Bar; $ENTRY Go { = <Foo> <Bar> }
- Файл
redudand-externs4.BAD-SYNTAX.ref
:$EXTERN Foo, Bar, Foo, Bar; $ENTRY Go { = <Foo> <Bar> }
Все эти файлы лежат в папке tests/parser
, т.е. могут быть запущены скриптом run.bat
или run.sh
.
Посмотрим, как эти файлы компилируются официальными реализациями Рефала:
Запуск refc
…\refal-5-framework\tests\parser>refc redudand-externs1.BAD-SYNTAX.ref
Refal-5 Compiler. Version PZ Oct 29 2004
Copyright: Refal Systems Inc.
…\refal-5-framework\tests\parser>refc redudand-externs2.BAD-SYNTAX.ref
Refal-5 Compiler. Version PZ Oct 29 2004
Copyright: Refal Systems Inc.
…\refal-5-framework\tests\parser>refc redudand-externs3.BAD-SYNTAX.ref
Refal-5 Compiler. Version PZ Oct 29 2004
Copyright: Refal Systems Inc.
Error: 201. Doubly defined function Foo . May be the function is built. on line 2.
Error: 103. Expected ';' on line 2.
2 errors found in function
2 syntax errors found.
…\refal-5-framework\tests\parser>refc redudand-externs4.BAD-SYNTAX.ref
Refal-5 Compiler. Version PZ Oct 29 2004
Copyright: Refal Systems Inc.
Error: 201. Doubly defined function Foo . May be the function is built. on line 1.
Error: 103. Expected ';' on line 1.
2 errors found in function
2 syntax errors found.
Компилятор refc
первые два файла откомпилировал, на два других выдал ошибки.
Запуск crefal
…\refal-5-framework\tests\parser>crefal redudand-externs1.BAD-SYNTAX.ref
Copyright (C): RefalScope Project, 2004-2018
Error on line 2: Redefinition of function Go .
crefal: 1 syntax error found.
…\refal-5-framework\tests\parser>crefal redudand-externs2.BAD-SYNTAX.ref
Copyright (C): RefalScope Project, 2004-2018
Error on line 3: Redefinition of external function L .
crefal: 1 error found in function L
crefal: 1 syntax error found.
…\refal-5-framework\tests\parser>crefal redudand-externs3.BAD-SYNTAX.ref
Copyright (C): RefalScope Project, 2004-2018
Warning: Repeated external declaration of Foo on line 2 .
Warning: Repeated external declaration of Bar on line 2 .
crefal: 2 warnings found.
…\refal-5-framework\tests\parser>crefal redudand-externs4.BAD-SYNTAX.ref
Copyright (C): RefalScope Project, 2004-2018
Warning: Repeated external declaration of Foo on line 1 .
Warning: Repeated external declaration of Bar on line 1 .
crefal: 2 warnings found.
Компилятор crefal
, наоборот, первые два файла отверг, два последних откомпилировал, выдав, однако, предупреждение.
Актуальная реализация парсера (85fb3dd) все четыре файла принимает:
Запуск tests\parser\run.cmd
D:\Mazdaywik\Documents\refal-5-framework\tests\parser>run.cmd redudand-externs1.BAD-SYNTAX.ref
Refal-5 Compiler. Version PZ Oct 29 2004
Copyright: Refal Systems Inc.
Parsing redudand-externs1.BAD-SYNTAX.ref...
redudand-externs1.BAD-SYNTAX.ref: PARSER MISSED ERRORS!
AST:
(Function (1 1 redudand-externs1.BAD-SYNTAX.ref)(Go)Entry (()RETURN ()))
(Extern ((2 9 redudand-externs1.BAD-SYNTAX.ref)Go))
Parser failed, see __err.txt for details
D:\Mazdaywik\Documents\refal-5-framework\tests\parser>run.cmd redudand-externs2.BAD-SYNTAX.ref
Refal-5 Compiler. Version PZ Oct 29 2004
Copyright: Refal Systems Inc.
Parsing redudand-externs2.BAD-SYNTAX.ref...
redudand-externs2.BAD-SYNTAX.ref: PARSER MISSED ERRORS!
AST:
(Extern ((1 9 redudand-externs2.BAD-SYNTAX.ref)L))
(Function (2 1 redudand-externs2.BAD-SYNTAX.ref)(Go)Entry (()RETURN ((Call (2 15 redudand-externs2.BAD-SYNTAX.ref)(L)))))
(Function (3 1 redudand-externs2.BAD-SYNTAX.ref)(L)Local (()RETURN ()))
Parser failed, see __err.txt for details
D:\Mazdaywik\Documents\refal-5-framework\tests\parser>run.cmd redudand-externs3.BAD-SYNTAX.ref
Refal-5 Compiler. Version PZ Oct 29 2004
Copyright: Refal Systems Inc.
Parsing redudand-externs3.BAD-SYNTAX.ref...
redudand-externs3.BAD-SYNTAX.ref: PARSER MISSED ERRORS!
AST:
(Extern ((1 9 redudand-externs3.BAD-SYNTAX.ref)Foo)((1 14 redudand-externs3.BAD-SYNTAX.ref)Bar))
(Extern ((2 9 redudand-externs3.BAD-SYNTAX.ref)Foo)((2 14 redudand-externs3.BAD-SYNTAX.ref)Bar))
(Function (4 1 redudand-externs3.BAD-SYNTAX.ref)(Go)Entry (()RETURN ((Call (4 15 redudand-externs3.BAD-SYNTAX.ref)(Foo))(Call (4 21 redudand-externs3.BAD-SYNTAX.ref)(Bar)))))
Parser failed, see __err.txt for details
D:\Mazdaywik\Documents\refal-5-framework\tests\parser>run.cmd redudand-externs4.BAD-SYNTAX.ref
Refal-5 Compiler. Version PZ Oct 29 2004
Copyright: Refal Systems Inc.
Parsing redudand-externs4.BAD-SYNTAX.ref...
redudand-externs4.BAD-SYNTAX.ref: PARSER MISSED ERRORS!
AST:
(Extern ((1 9 redudand-externs4.BAD-SYNTAX.ref)Foo)((1 14 redudand-externs4.BAD-SYNTAX.ref)Bar)((1 19 redudand-externs4.BAD-SYNTAX.ref)Foo)((1 24 redudand-externs4.BAD-SYNTAX.ref)Bar))
(Function (3 1 redudand-externs4.BAD-SYNTAX.ref)(Go)Entry (()RETURN ((Call (3 15 redudand-externs4.BAD-SYNTAX.ref)(Foo))(Call (3 21 redudand-externs4.BAD-SYNTAX.ref)(Bar)))))
Parser failed, see __err.txt for details
Ожидаемое поведение
Неочевидно, т.к. обе официальные реализации друг другу противоречат, а в документации об этом нюансе явно ничего не говорится.
Если во всех четырёх случаях выдавать ошибку, то текст, принимаемый этим парсером, будет совместим с обоими официальными реализациями.
Кроме того, тогда реализация будет совместимой с Рефалом-05, который в этих случаях уже выдаёт ошибки, а значит, парсер Рефала-05 можно будет упростить, удалив из него проверки.
Замечание про встроенные функции
Переопределение встроенной функции
Обе официальные реализации выдают ошибки, если пользователь старается переопределить встроенные функции:
$ENTRY Prout { = }
…\refal-5-framework\tests\parser>refc builtin-redefine-entry.BAD-SYNTAX.ref
Refal-5 Compiler. Version PZ Oct 29 2004
Copyright: Refal Systems Inc.
Error: 201. Doubly defined function Prout . May be the function is built. on line 1.
Error: 102. Expected '}' on line 1.
2 errors found in function Prout
2 syntax errors found.
…\refal-5-framework\tests\parser>crefal builtin-redefine-entry.BAD-SYNTAX.ref
Copyright (C): RefalScope Project, 2004-2018
Error on line 1: Redefinition of built-in function Prout .
crefal: 1 error found in function Prout
crefal: 1 syntax error found.
Аналогично ведёт себя и парсер фреймворка:
D:\Mazdaywik\Documents\refal-5-framework\tests\parser>run builtin-redefine-entry.BAD-SYNTAX.ref
Refal-5 Compiler. Version PZ Oct 29 2004
Copyright: Refal Systems Inc.
Parsing builtin-redefine-entry.BAD-SYNTAX.ref...
builtin-redefine-entry.BAD-SYNTAX.ref: errors was expected, found by parser:
builtin-redefine-entry.BAD-SYNTAX.ref:1:1:Redefinition of builtin function Prout
Здесь всё в порядке, проблемы нет.
$EXTERN
для встроенной функции
Аналогично все три реализации (crefal
, refc
и парсер фреймворка) одинаково ведут себя и в случае объявления встроенной функции как внешней:
…
$EXTERN Prout;
…
Все три реализации молча принимают данный файл, не вывода ошибок.
Такое поведение мне кажется неконсистентным — функция в файле может быть или встроенной (нет ни объявлений, ни определений), либо имеет единственное объявление $EXTERN
, либо единственное определение. А тут возникает исключение из общего правила для имён встроенных функций.
Что делать? Если проще будет реализовать общее правило (единственное объявление/определение), то парсер фреймворка вопреки обеим официальным реализациям будет выдавать ошибку на $EXTERN Prout;
. Если проще будет иначе — сделаю иначе.
В частной переписке обсудили этот вопрос с Андреем Петровичем Немытых и @TonitaN.
Пришли к выводу, что правильным поведением в этом случае должно быть актуальное поведение crefal
’а + предупреждение на $EXTERN Prout;
.
Однако, в рамках данной заявки я реализую выдачу ошибок во всех перечисленных случаях, т.к. в парсере отсутствует проверка предупреждений. Однако, к местам, где должны выдаваться предупреждения, я добавлю соответствующий комментарий с TODO. При реализации предупреждений ошибки станут предупреждениями.
Ошибки выдаются. В дальнейшем некоторые из них (см. комментарий #9 (comment)) нужно сделать предупреждениями — #11).