diff --git a/frontend/src/app/components/editor/statements/selection-statement/selection-statement.component.scss b/frontend/src/app/components/editor/statements/selection-statement/selection-statement.component.scss
deleted file mode 100644
index 4cc7d2cc..00000000
--- a/frontend/src/app/components/editor/statements/selection-statement/selection-statement.component.scss
+++ /dev/null
@@ -1,36 +0,0 @@
-$refinementBoxAccentColor: rgb(87, 87, 87);
-.statements {
- display: flex;
- flex-direction: column;
- width: 400px;
- overflow: visible;
-
- .first-row {
- height: 3em;
- display: grid;
- place-items: center;
- color: #e0e0e0;
- }
-
- .statement-container {
- height: 5em;
- display: flex;
- flex-direction: row;
- align-content: center;
-
- .guard {
- display: flex;
- flex-grow: 3;
- position: relative;
- height: 100%;
- }
-
- .statement {
- align-content: center;
- flex-grow: 1;
- width: 100px;
- display: grid;
- place-items: center;
- }
- }
-}
\ No newline at end of file
diff --git a/frontend/src/app/components/editor/statements/selection-statement/selection-statement.component.ts b/frontend/src/app/components/editor/statements/selection-statement/selection-statement.component.ts
index e563e938..3fe1d4cb 100644
--- a/frontend/src/app/components/editor/statements/selection-statement/selection-statement.component.ts
+++ b/frontend/src/app/components/editor/statements/selection-statement/selection-statement.component.ts
@@ -19,6 +19,7 @@ import {
import { Position } from "../../../../types/position";
import { SelectionStatementNode } from "../../../../types/statements/nodes/selection-statement-node";
import { HandleComponent } from "ngx-vflow";
+import {Button} from "primeng/button";
/**
* Component in the graphical editor to represent the {@link SelectionStatement}
@@ -37,6 +38,7 @@ import { HandleComponent } from "ngx-vflow";
MatButtonModule,
ConditionEditorComponent,
HandleComponent,
+ Button,
],
templateUrl: "./selection-statement.component.html",
styleUrl: "./selection-statement.component.css",
@@ -74,12 +76,11 @@ export class SelectionStatementComponent extends Refinement implements OnInit {
this._node.addSelection();
}
- public removeSelection() {
- const length = this._node.children.length;
- if (this._node.children[length - 1]) {
- this.treeService.deleteStatementNode(this._node.children[length - 1]!);
+ public removeSelection(index: number) {
+ if (this._node.children[index]) {
+ this.treeService.deleteStatementNode(this._node.children[index]!);
}
- this._node.removeSelection();
+ this._node.removeSelectionAtIndex(index);
}
public override resetPosition(position: Position, offset: Position): void {
diff --git a/frontend/src/app/services/tree/tree.service.ts b/frontend/src/app/services/tree/tree.service.ts
index 0309cb23..3504972a 100644
--- a/frontend/src/app/services/tree/tree.service.ts
+++ b/frontend/src/app/services/tree/tree.service.ts
@@ -1,483 +1,503 @@
-import { Injectable, signal, Signal, WritableSignal } from "@angular/core";
-import { Subject } from "rxjs";
+import {Injectable, signal, Signal, WritableSignal} from "@angular/core";
+import {Subject} from "rxjs";
import {
- AbstractStatement,
- IAbstractStatement,
- StatementType,
+ AbstractStatement,
+ IAbstractStatement,
+ StatementType,
} from "../../types/statements/abstract-statement";
-import { JavaVariable, JavaVariableKind } from "../../types/JavaVariable";
-import { Renaming } from "../../types/Renaming";
-import { Condition } from "../../types/condition/condition";
-import { LocalCBCFormula } from "../../types/CBCFormula";
-import { ICompositionStatement } from "../../types/statements/composition-statement";
-import { IRepetitionStatement } from "../../types/statements/repetition-statement";
-import { ISelectionStatement } from "../../types/statements/selection-statement";
-import { AbstractStatementNode } from "../../types/statements/nodes/abstract-statement-node";
-import { statementNodeUtils } from "../../types/statements/nodes/statement-node-utils";
+import {JavaVariable, JavaVariableKind} from "../../types/JavaVariable";
+import {Renaming} from "../../types/Renaming";
+import {Condition} from "../../types/condition/condition";
+import {LocalCBCFormula} from "../../types/CBCFormula";
+import {ICompositionStatement} from "../../types/statements/composition-statement";
+import {IRepetitionStatement} from "../../types/statements/repetition-statement";
+import {ISelectionStatement} from "../../types/statements/selection-statement";
+import {AbstractStatementNode} from "../../types/statements/nodes/abstract-statement-node";
+import {statementNodeUtils} from "../../types/statements/nodes/statement-node-utils";
import {
- IRootStatement,
- RootStatement,
+ IRootStatement,
+ RootStatement,
} from "../../types/statements/root-statement";
-import { RootStatementNode } from "../../types/statements/nodes/root-statement-node";
-import { RepetitionStatementNode } from "../../types/statements/nodes/repetition-statement-node";
+import {RootStatementNode} from "../../types/statements/nodes/root-statement-node";
+import {RepetitionStatementNode} from "../../types/statements/nodes/repetition-statement-node";
/**
* Service for the context of the tree in the graphical editor.
*/
@Injectable({
- providedIn: "root",
+ providedIn: "root",
})
export class TreeService {
- private readonly _verifyNotifier: Subject
;
- private readonly _exportNotifier: Subject;
- private readonly _resetVerifyNotifier: Subject;
- private readonly _verificationResultNotifier: Subject;
- private readonly _finalizeNotifier: Subject;
- private _globalConditions: string[] = [];
- private _renames: Renaming[] = [];
- private _statementNodes: WritableSignal = signal([]);
- private rootStatementNode: RootStatementNode | undefined;
- private _urn = "";
-
- public constructor() {
- this._verificationResultNotifier = new Subject();
- this._verifyNotifier = new Subject();
- this._exportNotifier = new Subject();
- this._resetVerifyNotifier = new Subject();
- this._finalizeNotifier = new Subject();
- }
-
- setFormula(newFormula: LocalCBCFormula, urn: string) {
- this._urn = urn;
- this._rootFormula = newFormula;
- this._variables = [];
- this._renames = [];
- this._globalConditions = [];
- newFormula.javaVariables.forEach((variable) => {
- this.addVariable(variable.name, variable.kind);
- });
- if (newFormula.renamings) {
- newFormula.renamings.forEach((renaming) => {
- this.addRenaming(renaming.type, renaming.function, renaming.newName);
- });
- }
- newFormula.globalConditions.forEach((condition) => {
- this.addGlobalCondition(condition.condition);
- });
-
- try {
- this.generateStatementNodes();
- } catch (e) {
- console.error(
- "TreeService.setFormula: failed to initialize statement nodes",
- e,
- );
- }
- }
-
- private _rootFormula: LocalCBCFormula | undefined;
-
- public get rootFormula() {
- return this._rootFormula;
- }
-
- private _variables: JavaVariable[] = [];
-
- public get variables(): string[] {
- const variablesArray: string[] = [];
- this._variables.forEach((javaVariable) =>
- variablesArray.push(javaVariable.toString()),
- );
- return variablesArray;
- }
-
- public get exportNotifier(): Subject {
- return this._exportNotifier;
- }
-
- public get urn() {
- return this._urn;
- }
-
- public get conditions(): Condition[] {
- const conditionsArray: Condition[] = [];
- this._globalConditions.forEach((condition) =>
- conditionsArray.push(new Condition(condition)),
- );
- return conditionsArray;
- }
-
- public get renaming(): Renaming[] {
- const renames: Renaming[] = [];
- this._renames.forEach((rename) =>
- renames.push(new Renaming(rename.type, rename.function, rename.newName)),
- );
- return renames;
- }
-
- public get verificationResultNotifier() {
- return this._verificationResultNotifier;
- }
-
- public get verifyNotifier() {
- return this._verifyNotifier;
- }
-
- public get resetVerifyNotifier() {
- return this._resetVerifyNotifier;
- }
-
- public get finalizeNotifier() {
- return this._finalizeNotifier;
- }
-
- public get rootStatement() {
- return this.rootStatementNode;
- }
-
- public export(): void {
- this._exportNotifier.next();
- }
-
- public addVariable(name: string, kind: JavaVariableKind): boolean {
- const sizeBeforeAdd = this._variables.length;
- const newVariable = new JavaVariable(name, kind);
-
- let isDuplicate: boolean = false;
- this._variables.forEach((val) => {
- if (val.equalName(newVariable)) {
- isDuplicate = true;
- }
- });
-
- if (!isDuplicate) {
- this._variables.push(newVariable);
- }
-
- return this._variables.length != sizeBeforeAdd;
- }
-
- public removeVariables(names: string[]): void {
- const variablesToBeRemoved: string[] = [];
- names.forEach((name) => {
- const variableName = name.includes(" ")
- ? name.split(" ").slice(1).join(" ")
- : name;
- variablesToBeRemoved.push(variableName);
- });
- this._variables = this._variables.filter(
- (val) => !variablesToBeRemoved.includes(val.name),
- );
- }
-
- public removeAllVariables(): void {
- this._variables = [];
- }
-
- public addGlobalCondition(name: string): boolean {
- const sizeBeforeAdd = this._globalConditions.length;
-
- let isDuplicate: boolean = false;
- this._globalConditions.forEach((val) => {
- if (val == name) {
- isDuplicate = true;
- }
- });
-
- if (!isDuplicate) {
- this._globalConditions.push(name);
- }
-
- return this._globalConditions.length != sizeBeforeAdd;
- }
-
- public removeGlobalCondition(name: string): void {
- this._globalConditions = this._globalConditions.filter(
- (val) => val !== name,
- );
- }
-
- public statements(): IAbstractStatement[] {
- const statements: IAbstractStatement[] = [];
- if (this.rootFormula && this.rootFormula.statement) {
- this.collectStatements(this.rootFormula.statement, statements);
- }
- return statements;
- }
-
- public getStatementsFromFormula(
- formula: LocalCBCFormula,
- ): IAbstractStatement[] {
- const statements: IAbstractStatement[] = [];
- if (formula && formula.statement) {
- this.collectStatements(formula.statement, statements);
- }
- return statements;
- }
-
- public refreshNodes(): void {
- this._statementNodes.update((old) => [...old]);
- }
-
- public addStatementNode(statementNode: AbstractStatementNode) {
- if (this._statementNodes()) {
- this._statementNodes.update((oldNodes) => [...oldNodes, statementNode]);
- } else {
- this._statementNodes.set([statementNode]);
- }
- }
-
- public createNodeForStatement(
- parent: AbstractStatementNode,
- statementType: StatementType,
- index?: number,
- ): AbstractStatementNode {
- const child = parent.createChild(statementType, index);
- this.addStatementNode(child);
- return child;
- }
-
- public deleteStatementNode(statementNode: AbstractStatementNode) {
- if (statementNode.statement.type === "ROOT") {
- return;
- }
- if (this._statementNodes().includes(statementNode)) {
- if (statementNode.statement.type === "REPETITION") {
- (statementNode as RepetitionStatementNode).destroy();
- }
- statementNode.parent?.deleteChild(statementNode);
- this._statementNodes.update((old) =>
- old.filter((node) => node != statementNode),
- );
- }
- }
-
- public generateStatementNodes(): Signal {
- const rootStatementNode = this.rootFormula?.statement
- ? new RootStatementNode(
- this.rootFormula.statement as RootStatement,
- undefined,
- )
- : statementNodeUtils(
- new RootStatement(
- "",
- new Condition(""),
- new Condition(""),
- undefined,
- ),
+ private readonly _verifyNotifier: Subject;
+ private readonly _exportNotifier: Subject;
+ private readonly _resetVerifyNotifier: Subject;
+ private readonly _verificationResultNotifier: Subject;
+ private readonly _finalizeNotifier: Subject;
+ private _globalConditions: string[] = [];
+ private _renames: Renaming[] = [];
+ private _statementNodes: WritableSignal = signal([]);
+ private rootStatementNode: RootStatementNode | undefined;
+ private _urn = "";
+
+ public constructor() {
+ this._verificationResultNotifier = new Subject();
+ this._verifyNotifier = new Subject();
+ this._exportNotifier = new Subject();
+ this._resetVerifyNotifier = new Subject();
+ this._finalizeNotifier = new Subject();
+ }
+
+ setFormula(newFormula: LocalCBCFormula, urn: string) {
+ this._urn = urn;
+ this._rootFormula = newFormula;
+ this._variables = [];
+ this._renames = [];
+ this._globalConditions = [];
+ newFormula.javaVariables.forEach((variable) => {
+ this.addVariable(variable.name, variable.kind);
+ });
+ if (newFormula.renamings) {
+ newFormula.renamings.forEach((renaming) => {
+ this.addRenaming(renaming.type, renaming.function, renaming.newName);
+ });
+ }
+ newFormula.globalConditions.forEach((condition) => {
+ this.addGlobalCondition(condition.condition);
+ });
+
+ try {
+ this.generateStatementNodes();
+ } catch (e) {
+ console.error(
+ "TreeService.setFormula: failed to initialize statement nodes",
+ e,
+ );
+ }
+ }
+
+ private _rootFormula: LocalCBCFormula | undefined;
+
+ public get rootFormula() {
+ return this._rootFormula;
+ }
+
+ private _variables: JavaVariable[] = [];
+
+ public get variables(): string[] {
+ const variablesArray: string[] = [];
+ this._variables.forEach((javaVariable) =>
+ variablesArray.push(javaVariable.toString()),
+ );
+ return variablesArray;
+ }
+
+ public get exportNotifier(): Subject {
+ return this._exportNotifier;
+ }
+
+ public get urn() {
+ return this._urn;
+ }
+
+ public get conditions(): Condition[] {
+ const conditionsArray: Condition[] = [];
+ this._globalConditions.forEach((condition) =>
+ conditionsArray.push(new Condition(condition)),
+ );
+ return conditionsArray;
+ }
+
+ public get renaming(): Renaming[] {
+ const renames: Renaming[] = [];
+ this._renames.forEach((rename) =>
+ renames.push(new Renaming(rename.type, rename.function, rename.newName)),
+ );
+ return renames;
+ }
+
+ public get verificationResultNotifier() {
+ return this._verificationResultNotifier;
+ }
+
+ public get verifyNotifier() {
+ return this._verifyNotifier;
+ }
+
+ public get resetVerifyNotifier() {
+ return this._resetVerifyNotifier;
+ }
+
+ public get finalizeNotifier() {
+ return this._finalizeNotifier;
+ }
+
+ public get rootStatement() {
+ return this.rootStatementNode;
+ }
+
+ public export(): void {
+ this._exportNotifier.next();
+ }
+
+ public addVariable(name: string, kind: JavaVariableKind): boolean {
+ const sizeBeforeAdd = this._variables.length;
+ const newVariable = new JavaVariable(name, kind);
+
+ let isDuplicate: boolean = false;
+ this._variables.forEach((val) => {
+ if (val.equalName(newVariable)) {
+ isDuplicate = true;
+ }
+ });
+
+ if (!isDuplicate) {
+ this._variables.push(newVariable);
+ }
+
+ return this._variables.length != sizeBeforeAdd;
+ }
+
+ public removeVariables(names: string[]): void {
+ const variablesToBeRemoved: string[] = [];
+ names.forEach((name) => {
+ const variableName = name.includes(" ")
+ ? name.split(" ").slice(1).join(" ")
+ : name;
+ variablesToBeRemoved.push(variableName);
+ });
+ this._variables = this._variables.filter(
+ (val) => !variablesToBeRemoved.includes(val.name),
);
- if (this._rootFormula) {
- this._rootFormula.statement =
- rootStatementNode.statement as IRootStatement;
- }
- this._statementNodes.set(
- [rootStatementNode].concat(
- this.collectStatementNodeChildren([rootStatementNode]),
- ),
- );
- this.rootStatementNode = rootStatementNode as RootStatementNode;
- return this._statementNodes;
- }
-
- public addRenaming(type: string, original: string, newName: string): void {
- this._renames.push(new Renaming(type, original, newName));
- }
-
- public removeRenaming(type: string, original: string, newName: string): void {
- this._renames = this._renames.filter(
- (val) => !val.equal(new Renaming(type, original, newName)),
- );
- }
-
- private collectStatementNodeChildren(
- parentNodes: (AbstractStatementNode | undefined)[],
- ): AbstractStatementNode[] {
- let childNodes: AbstractStatementNode[] = [];
- for (const parentNode of parentNodes) {
- if (parentNode) {
- childNodes = childNodes
- .concat(parentNode.children.filter((child) => child != undefined) as AbstractStatementNode[])
- .concat(this.collectStatementNodeChildren(parentNode.children));
- }
- }
- return childNodes;
- }
-
- private collectStatements(
- statement: IAbstractStatement | undefined,
- statements: IAbstractStatement[],
- ) {
- if (statement && statements) {
- switch (statement.type) {
- case "STATEMENT":
- statements.push(statement);
- return;
- case "COMPOSITION":
- statements.push(statement);
- this.collectStatements(
- (statement as ICompositionStatement).firstStatement,
- statements,
- );
- this.collectStatements(
- (statement as ICompositionStatement).secondStatement,
- statements,
- );
- return;
- case "REPETITION":
- statements.push(statement);
- this.collectStatements(
- (statement as IRepetitionStatement).loopStatement,
- statements,
- );
- return;
- case "RETURN":
- statements.push(statement);
- return;
- case "SKIP":
- statements.push(statement);
- return;
- case "SELECTION":
- statements.push(statement);
- (statement as ISelectionStatement).commands.forEach((command) =>
- this.collectStatements(command, statements),
- );
- return;
- case "ROOT":
- statements.push(statement);
- this.collectStatements(
- (statement as IRootStatement).statement,
- statements,
- );
- }
- }
- }
-
- finalizeStatements() {
- this.rootStatementNode?.finalize();
- if (this.rootFormula) {
- this.rootFormula.javaVariables = this._variables;
- this.rootFormula.renamings = this._renames;
- this.rootFormula.globalConditions = this._globalConditions.map(
- (condition) => new Condition(condition),
- );
- }
- this.finalizeNotifier.next()
- }
-
- public findStatementNodeById(id: string): AbstractStatementNode | undefined {
- const nodes = this._statementNodes();
- for (const node of nodes) {
- if (node.statement.id === id) {
- return node;
- }
- const found = this.findNodeInSubtree(node, id);
- if (found) {
- return found;
- }
- }
- return undefined;
- }
-
- private findNodeInSubtree(
- node: AbstractStatementNode,
- id: string,
- ): AbstractStatementNode | undefined {
- for (const child of node.children) {
- if (child) {
- if (child.statement.id === id) {
- return child;
+ }
+
+ public removeAllVariables(): void {
+ this._variables = [];
+ }
+
+ public addGlobalCondition(name: string): boolean {
+ const sizeBeforeAdd = this._globalConditions.length;
+
+ let isDuplicate: boolean = false;
+ this._globalConditions.forEach((val) => {
+ if (val == name) {
+ isDuplicate = true;
+ }
+ });
+
+ if (!isDuplicate) {
+ this._globalConditions.push(name);
}
- const found = this.findNodeInSubtree(child, id);
- if (found) {
- return found;
+
+ return this._globalConditions.length != sizeBeforeAdd;
+ }
+
+ public removeGlobalCondition(name: string): void {
+ this._globalConditions = this._globalConditions.filter(
+ (val) => val !== name,
+ );
+ }
+
+ public statements(): IAbstractStatement[] {
+ const statements: IAbstractStatement[] = [];
+ if (this.rootFormula && this.rootFormula.statement) {
+ this.collectStatements(this.rootFormula.statement, statements);
}
- }
- }
- return undefined;
- }
-
- public collectSubtreeNodes(
- node: AbstractStatementNode,
- ): AbstractStatementNode[] {
- const nodes: AbstractStatementNode[] = [node];
- for (const child of node.children) {
- if (child) {
- nodes.push(...this.collectSubtreeNodes(child));
- }
- }
- return nodes;
- }
-
- public markSubtreeUnverified(node: AbstractStatementNode): void {
- const subtreeNodes = this.collectSubtreeNodes(node);
- subtreeNodes.forEach((subtreeNode) => {
- subtreeNode.statement.isProven = false;
- subtreeNode.statement.nodeState = 'unverified'
- });
- if (this.rootFormula) {
- this.rootFormula.isProven = false;
- }
- this.refreshNodes();
- }
-
- public markWholeTreeUnverified(): void {
- if (!this.rootStatementNode) {
- return;
- }
- this.markSubtreeUnverified(this.rootStatementNode);
- }
-
- public createTempFormulaFromNode(
- node: AbstractStatementNode,
- ): LocalCBCFormula {
- node.finalize();
-
- let rootStatement: IRootStatement;
-
- if (node.statement.type === "ROOT") {
- rootStatement = node.statement as IRootStatement;
- } else {
- rootStatement = new RootStatement(
- node.statement.name || "temp",
- node.statement.preCondition,
- node.statement.postCondition,
- node.statement,
- );
- }
-
- const tempFormula = new LocalCBCFormula(
- node.statement.name || "temp",
- rootStatement,
- this.rootFormula?.javaVariables || [],
- this.rootFormula?.globalConditions || [],
- this.rootFormula?.renamings || null,
- false,
- );
-
- return tempFormula;
- }
-
- public dump() {
- return {
- rootStatementNode: JSON.stringify(
- this.rootStatementNode,
- (key, value) => {
- if (key == "parent") {
- return undefined;
- }
- return value;
- },
- ),
- rootFormula: this.rootFormula,
- statementNodes: JSON.stringify(this._statementNodes(), (key, value) => {
- if (key == "parent") {
- return undefined;
+ return statements;
+ }
+
+ public getStatementsFromFormula(
+ formula: LocalCBCFormula,
+ ): IAbstractStatement[] {
+ const statements: IAbstractStatement[] = [];
+ if (formula && formula.statement) {
+ this.collectStatements(formula.statement, statements);
}
- return value;
- }),
- variables: this._variables,
- globalConditions: this._globalConditions,
- renames: this._renames,
- };
- }
+ return statements;
+ }
+
+ public refreshNodes(): void {
+ this._statementNodes.update((old) => [...old]);
+ }
+
+ public addStatementNode(statementNode: AbstractStatementNode) {
+ if (this._statementNodes()) {
+ this._statementNodes.update((oldNodes) => [...oldNodes, statementNode]);
+ } else {
+ this._statementNodes.set([statementNode]);
+ }
+ }
+
+ public createNodeForStatement(
+ parent: AbstractStatementNode,
+ statementType: StatementType,
+ index?: number,
+ ): AbstractStatementNode {
+ const child = parent.createChild(statementType, index);
+ this.addStatementNode(child);
+ return child;
+ }
+
+ public deleteStatementNode(statementNode: AbstractStatementNode) {
+ if (statementNode.statement.type === "ROOT") {
+ return;
+ }
+ if (this._statementNodes().includes(statementNode)) {
+ if (statementNode.statement.type === "REPETITION") {
+ (statementNode as RepetitionStatementNode).destroy();
+ }
+ statementNode.parent?.deleteChild(statementNode);
+ this._statementNodes.update((old) =>
+ old.filter((node) => node != statementNode),
+ );
+ }
+ }
+
+ public generateStatementNodes(): Signal {
+ const rootStatementNode = this.rootFormula?.statement
+ ? new RootStatementNode(
+ this.rootFormula.statement as RootStatement,
+ undefined,
+ )
+ : statementNodeUtils(
+ new RootStatement(
+ "",
+ new Condition(""),
+ new Condition(""),
+ undefined,
+ ),
+ );
+ if (this._rootFormula) {
+ this._rootFormula.statement =
+ rootStatementNode.statement as IRootStatement;
+ }
+ this._statementNodes.set(
+ [rootStatementNode].concat(
+ this.collectStatementNodeChildren([rootStatementNode]),
+ ),
+ );
+ this.rootStatementNode = rootStatementNode as RootStatementNode;
+ return this._statementNodes;
+ }
+
+ public addRenaming(type: string, original: string, newName: string): void {
+ this._renames.push(new Renaming(type, original, newName));
+ }
+
+ public removeRenaming(type: string, original: string, newName: string): void {
+ this._renames = this._renames.filter(
+ (val) => !val.equal(new Renaming(type, original, newName)),
+ );
+ }
+
+ private collectStatementNodeChildren(
+ parentNodes: (AbstractStatementNode | undefined)[],
+ ): AbstractStatementNode[] {
+ let childNodes: AbstractStatementNode[] = [];
+ for (const parentNode of parentNodes) {
+ if (parentNode) {
+ childNodes = childNodes
+ .concat(parentNode.children.filter((child) => child != undefined) as AbstractStatementNode[])
+ .concat(this.collectStatementNodeChildren(parentNode.children));
+ }
+ }
+ return childNodes;
+ }
+
+ private collectStatements(
+ statement: IAbstractStatement | undefined,
+ statements: IAbstractStatement[],
+ ) {
+ if (statement && statements) {
+ switch (statement.type) {
+ case "STATEMENT":
+ statements.push(statement);
+ return;
+ case "COMPOSITION":
+ statements.push(statement);
+ this.collectStatements(
+ (statement as ICompositionStatement).firstStatement,
+ statements,
+ );
+ this.collectStatements(
+ (statement as ICompositionStatement).secondStatement,
+ statements,
+ );
+ return;
+ case "REPETITION":
+ statements.push(statement);
+ this.collectStatements(
+ (statement as IRepetitionStatement).loopStatement,
+ statements,
+ );
+ return;
+ case "RETURN":
+ statements.push(statement);
+ return;
+ case "SKIP":
+ statements.push(statement);
+ return;
+ case "SELECTION":
+ statements.push(statement);
+ (statement as ISelectionStatement).commands.forEach((command) =>
+ this.collectStatements(command, statements),
+ );
+ return;
+ case "ROOT":
+ statements.push(statement);
+ this.collectStatements(
+ (statement as IRootStatement).statement,
+ statements,
+ );
+ }
+ }
+ }
+
+ finalizeStatements() {
+ this.rootStatementNode?.finalize();
+ if (this.rootFormula) {
+ this.rootFormula.javaVariables = this._variables;
+ this.rootFormula.renamings = this._renames;
+ this.rootFormula.globalConditions = this._globalConditions.map(
+ (condition) => new Condition(condition),
+ );
+ }
+ this.finalizeNotifier.next()
+ }
+
+ public findStatementNodeById(id: string): AbstractStatementNode | undefined {
+ const nodes = this._statementNodes();
+ for (const node of nodes) {
+ if (node.statement.id === id) {
+ return node;
+ }
+ const found = this.findNodeInSubtree(node, id);
+ if (found) {
+ return found;
+ }
+ }
+ return undefined;
+ }
+
+ private findNodeInSubtree(
+ node: AbstractStatementNode,
+ id: string,
+ ): AbstractStatementNode | undefined {
+ for (const child of node.children) {
+ if (child) {
+ if (child.statement.id === id) {
+ return child;
+ }
+ const found = this.findNodeInSubtree(child, id);
+ if (found) {
+ return found;
+ }
+ }
+ }
+ return undefined;
+ }
+
+ public collectSubtreeNodes(
+ node: AbstractStatementNode,
+ ): AbstractStatementNode[] {
+ const nodes: AbstractStatementNode[] = [];
+ for (const child of node.children) {
+ if (child) {
+ nodes.push(...this.collectSubtreeNodes(child));
+ }
+ }
+ return nodes;
+ }
+
+ public collectAncestorNodes(
+ node: AbstractStatementNode,
+ ): AbstractStatementNode[] {
+ const ancestors: AbstractStatementNode[] = [];
+ let currentNode: AbstractStatementNode | undefined = node.parent;
+ while (currentNode) {
+ ancestors.push(currentNode);
+ currentNode = currentNode.parent;
+ }
+ return ancestors;
+ }
+
+ public markSubtreeUnverified(node: AbstractStatementNode): void {
+ const subtreeNodes = this.collectSubtreeNodes(node);
+ const ancestorNodes = this.collectAncestorNodes(node);
+ subtreeNodes.forEach((subtreeNode) => {
+ subtreeNode.statement.isProven = false;
+ subtreeNode.statement.nodeState = 'unverified'
+ });
+ ancestorNodes.forEach((ancestorNode) => {
+ ancestorNode.statement.isProven = false;
+ ancestorNode.statement.nodeState = 'unverified';
+ })
+ node.statement.isProven = false;
+ node.statement.nodeState = 'unverified';
+
+ if (this.rootFormula) {
+ this.rootFormula.isProven = false;
+ }
+ this.refreshNodes();
+ }
+
+ public markWholeTreeUnverified(): void {
+ if (!this.rootStatementNode) {
+ return;
+ }
+ this.markSubtreeUnverified(this.rootStatementNode);
+ }
+
+ public createTempFormulaFromNode(
+ node: AbstractStatementNode,
+ ): LocalCBCFormula {
+ node.finalize();
+
+ let rootStatement: IRootStatement;
+
+ if (node.statement.type === "ROOT") {
+ rootStatement = node.statement as IRootStatement;
+ } else {
+ rootStatement = new RootStatement(
+ node.statement.name || "temp",
+ node.statement.preCondition,
+ node.statement.postCondition,
+ node.statement,
+ );
+ }
+
+ const tempFormula = new LocalCBCFormula(
+ node.statement.name || "temp",
+ rootStatement,
+ this.rootFormula?.javaVariables || [],
+ this.rootFormula?.globalConditions || [],
+ this.rootFormula?.renamings || null,
+ false,
+ );
+
+ return tempFormula;
+ }
+
+ public dump() {
+ return {
+ rootStatementNode: JSON.stringify(
+ this.rootStatementNode,
+ (key, value) => {
+ if (key == "parent") {
+ return undefined;
+ }
+ return value;
+ },
+ ),
+ rootFormula: this.rootFormula,
+ statementNodes: JSON.stringify(this._statementNodes(), (key, value) => {
+ if (key == "parent") {
+ return undefined;
+ }
+ return value;
+ }),
+ variables: this._variables,
+ globalConditions: this._globalConditions,
+ renames: this._renames,
+ };
+ }
}
diff --git a/frontend/src/app/types/statements/nodes/selection-statement-node.ts b/frontend/src/app/types/statements/nodes/selection-statement-node.ts
index 1cc3bb8c..adbe7d89 100644
--- a/frontend/src/app/types/statements/nodes/selection-statement-node.ts
+++ b/frontend/src/app/types/statements/nodes/selection-statement-node.ts
@@ -188,16 +188,15 @@ export class SelectionStatementNode extends AbstractStatementNode {
return statementNode;
}
- removeSelection() {
- const index = this.guards.length - 1;
+ removeSelectionAtIndex(index: number) {
if (this.childSubscriptions[index]) {
this.childSubscriptions[index].unsubscribe();
- this.childSubscriptions.pop();
+ this.childSubscriptions.splice(index, 1);
}
- this.guards.pop();
- this.children.pop();
- this.statement.guards.pop();
- this.statement.commands.pop();
+ this.guards.splice(index, 1);
+ this.children.splice(index, 1);
+ this.statement.guards.splice(index, 1);
+ this.statement.commands.splice(index, 1);
}
override addChild(statement: AbstractStatementNode, index: number) {