Добавить 6. Создание новых операторов и выражений с помощью библиотеки Sage++.

2023-09-14 17:17:43 +00:00
parent 6a1068756b
commit f8c00cd2b8

@@ -0,0 +1,39 @@
В данном разделе рассмотрено изменение дерева разбора, представленное с помощью библиотеки 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_});`, в которую первым параметром передается текущий оператор, по которому будет вычислена позиция вставки нового объявления, вторым - набор новых только что созданных символов. Если символы уже созданы и используются, то объявлять их не нужно.
Создание других операторов происходит примерно по таким же принципам. Существует набор производных классов, которые позволяют легко создавать новые операторы и наполнять их соответствующими выражениями.