Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Вставки кода на C++ #11

Closed
Mazdaywik opened this issue Dec 20, 2015 · 1 comment
Closed

Вставки кода на C++ #11

Mazdaywik opened this issue Dec 20, 2015 · 1 comment
Assignees
Labels
Milestone

Comments

@Mazdaywik
Copy link
Member

Mazdaywik commented Dec 20, 2015

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

Другой сценарий: в ходе развития компонента, изначально написанного на чистом C++ (такого, как стандартная библиотека Library) может так оказаться, что некоторые функции разумнее выразить на Рефале как комбинацию более низкоуровневых компонент. В рамках текущей парадигмы или придётся разбивать компонент на два, или вставлять в него фрагмент скомпилированного кода.

Также, написание компонентов целиком на C++ имеет высокую акцидентную сложность (в терминологии Брукса). Если функция использует такие примитивные объекты как метки и пустые функции (можно добавить и статические ящики, но так обычно не пишут), то их приходится вручную описывать на языке C++. Недавняя попытка перейти от хранения в узлах списка пары указателей (указатель на функцию и указатель на строку — имя функции) к хранению указателя на дескриптор функции (константную статическую структуру, содержащую указатель на функцию и строку символов) потребовала много тупой шаблонной работы (upd: #46).

Предлагаемый синтаксис: вставка кода на C++ оформляется как фрагмент кода между двумя строками вида %%. Вставки допустимы как на верхнем уровне программы между глобальными объявлениями, так и в качестве тела функции между фигурными скобками. Предполагается, что внутри вставки можно использовать все имена, объявленные/определённые выше по тексту, при этом во вставке, описывающей имя функции также доступны две переменные refalrts::Iter arg_begin и refalrts::Iter arg_end, хранящие указатели на угловые скобки вызова функции.

Пример:

$EXTERN Foo;

$LABEL Alpha, Beta, Gamma;

Bar { … }

%%
static int x = 0;
// В этом месте кода доступны имена Foo, Alpha, Beta, Gamma и Bar
%%

Baz {
%%
  ++x;
  if (arg_begin->next->next == arg_end) {
    return refalrts::cRecognitionImpossible;
  }
  …
  // Здесь доступны имена Foo, Alpha, Beta, Gamma, Bar, Baz, arg_begin и arg_end
  …
  return refalrts::cSuccess;
%%
}

Аргументы за:

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

Аргументы против:

  • Усложняется сам компилятор (против I цели).

Субъективно, аргументы «за» перевешивают.

@Mazdaywik Mazdaywik added the task label Dec 20, 2015
@Mazdaywik Mazdaywik self-assigned this Dec 20, 2015
@Mazdaywik Mazdaywik added this to the summer 2016 milestone Jul 29, 2016
Mazdaywik added a commit that referenced this issue Aug 9, 2016
Фактически, изменилось только оформление. Принципиально не трогал код,
поскольку для этого есть другая задача, «Рефакторинг Library» (#10).
@Mazdaywik
Copy link
Member Author

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

А именно, директивы $FORWARD и $LABEL, обычно эквивалентные пустому месту, при наличии сишных вставок.

Если в исходном тексте присутствуют вставки верхнего уровня, то в ней может быть определена функция. Чтобы сообщить коду на Рефале, что там есть функция, следует использовать директивы $EXTERN (для entry-функций) или $FORWARD (для локальных функций). Обычно, если локальная функция объявлена как $FORWARD и при этом не определена, выводится сообщение об ошибке. В случае вставки кода на верхнем уровне такая диагностика подавляется по вышеуказанным причинам.

Кстати, таким образом, директива $FORWARD перестала быть эквивалентна пустому месту. Если она ссылается на неопределённую функцию или на функцию, помеченную как $ENTRY, происходит синтаксическая ошибка. Так было сделано в рамках задачи #6, но ещё нигде не было задокументировано.

При наличии вставки любого вида для идентификаторов, определённых через $LABEL создаётся определение в целевом коде. Очевидно, из-за того, что во вставке могут быть ссылки на них, которые компилятор не способен распознать. В остальных случаях директива по-прежнему эквивалентна пустому месту.

Помимо этого, библиотечный модуль Library.cpp стал Library.sref.

P.S. При применении старого коммита для задачи #46 и разрешения конфликтов, оказалось, что фиксация вносит минимальные изменения в Library.sref, причём только по сути задачи (изменилась структура узлов поля зрения, изменились обращения к ним).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant