1
06. Создание новых операторов и выражений с помощью библиотеки Sage++.
xnpster edited this page 2024-01-12 17:13:22 +00:00
This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

В данном разделе рассмотрено изменение дерева разбора, представленное с помощью библиотеки Sage++. Добавление нового оператора или выражения состоит из следующих шагов:

  • Необходимо определить вариант (variant()) добавляемого оператора или выражения
  • Необходимо определить класс добавляемого оператора или выражения. Можно использовать как базовые классы (SgStatement / SgExpression), либо производные, например, SgForStmt.
  • Выделить память для нового выражения или оператора. Все операторы и выражения (да и вообще все сущности Sage++) могут использовать только по указателю.
  • Вставить полученный оператор или выражения в дерево разбора.
  • После вставки оператора в дерево его также можно наполнить выражениями в соответствии с правилами формирования конкретного оператора. С помощью функции SgStatement::setExpression(int i, SgExpression &e) - можно вставить соответствующее выражение в позицию i = 0, 1, 2.

Вставка оператора делается с помощью следующих основных функций:

  • InsertStmtBefore - вставить до текущего оператора, и InsertStmtAfter - вставить после текущего оператора. Данные функции принимают первым параметром новый оператор и вторым - оператор родитель. Второй параметр рекомендуется указывать явно для исключения ошибки в структуре полученного кода.

Вставка выражения делается с помощью следующих основных функций:

  • setLsh() - установить (добавить ссылку) в левое поддерево, и setRsh() - установить (добавить ссылку) в правое поддерево.

Также есть возможность вставить в дерево разбора копию оператора или выражения. Для этого необходимо использовать функции copy(), copyPtr() для того, чтобы создать соответствующую копию для вставки в дерево разбора. Необходимо следить за тем, чтобы в дереве разбора не было вставлено, например, одно выражение в нескольких местах (одна и та же ссылка в разных местах дерева). Для этих целей необходимо создавать копию.

Например, для того, чтобы создать следующий код на языке Фортран:

DO i_=1,N
   DO j_=1,N
     A = A + B
   ENDDO
ENDDO

необходимо в проходе SAPFOR использовать следующий код на C++:

SgSymbol* N_symb = ...;
SgSymbol* i_ = findSymbolOrCreate(file, "i_" + to_string(i), SgTypeInt(), scope);
SgSymbol* j_ = findSymbolOrCreate(file, "j_" + to_string(i), SgTypeInt(), scope);

SgStatement* body=new SgAssignStmt(*new SgVarRef(A), &(*new SgVarRef(A)+*new SgVarRef(B)));
SgForStmt* newLoop = new SgForStmt (*j_, *new SgValueExp(1), *new SgVarRef(N_symb), *body);

newLoop = new SgForStmt (*i_, *new SgValueExp(1), *new SgVarRef(N_symb), *newLoop);

Далее необходимо выполнить вставку оператора newLoop в код перед или после необходимого оператора с помощью описанных выше функций insertAfter/insertBefore. Также нужно объявить новые переменные i_, j_, если они не были ранее объявлены. Данное действие выполняется с помощью функции makeDeclaration(currStat, vector<SgSymbol*> { i_, j_});, в которую первым параметром передается текущий оператор, по которому будет вычислена позиция вставки нового объявления, вторым - набор новых только что созданных символов. Если символы уже созданы и используются, то объявлять их не нужно.

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