Mazdaywik/refal-5-framework

Ошибки на избыточные `$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).