// Path: src/main/java/com/pidanic/saral/domain/Statement.java
// public interface Statement {
//     void accept(StatementGenerator generator);
// }
// 
// Path: src/main/java/com/pidanic/saral/domain/block/WhileStatement.java
// public class WhileStatement extends BlockStatementImpl {
// 
//     private List<Statement> block;
//     private Expression expression;
// 
//     public WhileStatement(Scope scope, Expression expression, List<Statement> block) {
//         super(scope);
//         this.expression = expression;
//         if(block != null) {
//             this.block = Collections.unmodifiableList(block);
//         } else {
//             this.block = Collections.emptyList();
//         }
//     }
// 
//     @Override
//     public void accept(StatementGenerator generator) {
//         ((BlockStatementGenerator) generator).generate(this);
//     }
// 
//     public Expression getExpression() {
//         return expression;
//     }
// 
//     public List<Statement> getBlock() {
//         return block;
//     }
// }
// 
// Path: src/main/java/com/pidanic/saral/domain/expression/Expression.java
// public abstract class Expression {
//     private Type type;
// 
//     public Expression(Type type) {
//         this.type = type;
//     }
// 
//     public Type type() {
//         return type;
//     }
// 
//     public abstract void accept(ExpressionGenerator generator);
// }
// 
// Path: src/main/java/com/pidanic/saral/exception/EmptyWhileStatementBlock.java
// public class EmptyWhileStatementBlock extends RuntimeException {
//     public EmptyWhileStatementBlock(Scope scope) {
//             super("You defined empty while loop");
//     }
// }
// 
// Path: src/main/java/com/pidanic/saral/scope/Scope.java
// public class Scope {
// 
//     private static final LocalVariable EMPTY = new LocalVariable("empty", BuiltInType.BOOLEAN, true);
// 
//     private List<LocalVariable> localVariables;
//     private List<Function> functions;
//     private String className;
// 
//     public Scope(String className) {
//         localVariables = new ArrayList<>();
//         functions = new ArrayList<>();
//         this.className = className;
//     }
// 
//     public Scope(Scope scope) {
//         localVariables = new ArrayList<>(scope.localVariables);
//         functions = new ArrayList<>(scope.functions);
//         className = scope.className;
//     }
// 
//     public List<LocalVariable> getLocalVariables() {
//         return Collections.unmodifiableList(localVariables);
//     }
// 
//     public void addLocalVariable(LocalVariable localVariable) {
//         localVariables.add(localVariable);
//         if(localVariable.type() == BuiltInType.LONG || localVariable.type() == BuiltInType.DOUBLE) {
//             localVariables.add(EMPTY);
//         }
//     }
// 
//     public boolean existsLocalVariable(String variableName) {
//         return localVariables.stream().anyMatch(variable -> variable.name().equals(variableName));
//     }
// 
//     public Optional<LocalVariable> getLocalVariable(String varName) {
//         return localVariables.stream()
//                 .filter(variable -> variable.name().equals(varName))
//                 .findFirst();
//     }
// 
//     public int getLocalVariableIndex(String varName) {
//         return localVariables.stream().map(LocalVariable::name).collect(Collectors.toList()).indexOf(varName);
//     }
// 
//     public Optional<Function> getFunction(String functionName) {
//         return functions.stream().filter(proc -> proc.getName().equals(functionName))
//                 .findFirst();
//     }
// 
//     public String getClassName() {
//         return className;
//     }
// 
//     public void addFunction(Function function) {
//         this.functions.add(function);
//     }
// 
//     public LocalVariable initializeLocalVariableAtIndex(int index) {
//         LocalVariable localVariable = this.localVariables.get(index);
//         LocalVariable initializedLocalVar = localVariable.initialize();
//         this.localVariables.set(index, initializedLocalVar);
//         return initializedLocalVar;
//     }
// 
//     public LocalVariable initializeLocalVariable(String name) {
//         LocalVariable localVariable = getLocalVariable(name).get();
//         int index = getLocalVariableIndex(name);
//         LocalVariable initializedLocalVar = localVariable.initialize();
//         this.localVariables.set(index, initializedLocalVar);
//         return initializedLocalVar;
//     }
// 
//     public int localVariablesCount() {
//         return localVariables.size();
//     }
// }
// 
// Path: src/main/java/com/pidanic/saral/util/StatementsHelper.java
// public final class StatementsHelper {
//     public static List<Statement> parseStatements(SaralParser.StatementsContext statementsContext, Scope scope) {
//         List<Statement> allStatements = statementsContext.statement().stream().map(stmtCtx -> {
//             SaralParser.Block_statementContext block = stmtCtx.block_statement();
//             SaralParser.Simple_statementContext simpleStmt = stmtCtx.simple_statement();
//             Statement val;
//             if(block != null) {
//                 val = block.accept(new BlockStatementVisitor(scope));
//             } else {
//                 val = simpleStmt.accept(new SimpleStatementVisitor(scope));
//             }
//             return val;
//         }).collect(Collectors.toList());
// 
//         return allStatements;
//     }
// }


import com.pidanic.saral.domain.Statement;
import com.pidanic.saral.domain.block.WhileStatement;
import com.pidanic.saral.domain.expression.Expression;
import com.pidanic.saral.exception.EmptyWhileStatementBlock;
import com.pidanic.saral.grammar.SaralBaseVisitor;
import com.pidanic.saral.grammar.SaralParser;
import com.pidanic.saral.scope.Scope;
import com.pidanic.saral.util.StatementsHelper;
import java.util.List;
package com.pidanic.saral.visitor;



public class WhileStatementVisitor extends SaralBaseVisitor<WhileStatement> {
    private Scope scope;

    public WhileStatementVisitor(Scope scope) {
        this.scope = new Scope(scope);
    }

    @Override
    public WhileStatement visitWhile_statement(SaralParser.While_statementContext ctx) {
        ExpressionVisitor expressionVisitor = new ExpressionVisitor(scope);
        Expression expression = ctx.expression().accept(expressionVisitor);
// Path: src/main/java/com/pidanic/saral/domain/Statement.java
// public interface Statement {
//     void accept(StatementGenerator generator);
// }
// 
// Path: src/main/java/com/pidanic/saral/domain/block/WhileStatement.java
// public class WhileStatement extends BlockStatementImpl {
// 
//     private List<Statement> block;
//     private Expression expression;
// 
//     public WhileStatement(Scope scope, Expression expression, List<Statement> block) {
//         super(scope);
//         this.expression = expression;
//         if(block != null) {
//             this.block = Collections.unmodifiableList(block);
//         } else {
//             this.block = Collections.emptyList();
//         }
//     }
// 
//     @Override
//     public void accept(StatementGenerator generator) {
//         ((BlockStatementGenerator) generator).generate(this);
//     }
// 
//     public Expression getExpression() {
//         return expression;
//     }
// 
//     public List<Statement> getBlock() {
//         return block;
//     }
// }
// 
// Path: src/main/java/com/pidanic/saral/domain/expression/Expression.java
// public abstract class Expression {
//     private Type type;
// 
//     public Expression(Type type) {
//         this.type = type;
//     }
// 
//     public Type type() {
//         return type;
//     }
// 
//     public abstract void accept(ExpressionGenerator generator);
// }
// 
// Path: src/main/java/com/pidanic/saral/exception/EmptyWhileStatementBlock.java
// public class EmptyWhileStatementBlock extends RuntimeException {
//     public EmptyWhileStatementBlock(Scope scope) {
//             super("You defined empty while loop");
//     }
// }
// 
// Path: src/main/java/com/pidanic/saral/scope/Scope.java
// public class Scope {
// 
//     private static final LocalVariable EMPTY = new LocalVariable("empty", BuiltInType.BOOLEAN, true);
// 
//     private List<LocalVariable> localVariables;
//     private List<Function> functions;
//     private String className;
// 
//     public Scope(String className) {
//         localVariables = new ArrayList<>();
//         functions = new ArrayList<>();
//         this.className = className;
//     }
// 
//     public Scope(Scope scope) {
//         localVariables = new ArrayList<>(scope.localVariables);
//         functions = new ArrayList<>(scope.functions);
//         className = scope.className;
//     }
// 
//     public List<LocalVariable> getLocalVariables() {
//         return Collections.unmodifiableList(localVariables);
//     }
// 
//     public void addLocalVariable(LocalVariable localVariable) {
//         localVariables.add(localVariable);
//         if(localVariable.type() == BuiltInType.LONG || localVariable.type() == BuiltInType.DOUBLE) {
//             localVariables.add(EMPTY);
//         }
//     }
// 
//     public boolean existsLocalVariable(String variableName) {
//         return localVariables.stream().anyMatch(variable -> variable.name().equals(variableName));
//     }
// 
//     public Optional<LocalVariable> getLocalVariable(String varName) {
//         return localVariables.stream()
//                 .filter(variable -> variable.name().equals(varName))
//                 .findFirst();
//     }
// 
//     public int getLocalVariableIndex(String varName) {
//         return localVariables.stream().map(LocalVariable::name).collect(Collectors.toList()).indexOf(varName);
//     }
// 
//     public Optional<Function> getFunction(String functionName) {
//         return functions.stream().filter(proc -> proc.getName().equals(functionName))
//                 .findFirst();
//     }
// 
//     public String getClassName() {
//         return className;
//     }
// 
//     public void addFunction(Function function) {
//         this.functions.add(function);
//     }
// 
//     public LocalVariable initializeLocalVariableAtIndex(int index) {
//         LocalVariable localVariable = this.localVariables.get(index);
//         LocalVariable initializedLocalVar = localVariable.initialize();
//         this.localVariables.set(index, initializedLocalVar);
//         return initializedLocalVar;
//     }
// 
//     public LocalVariable initializeLocalVariable(String name) {
//         LocalVariable localVariable = getLocalVariable(name).get();
//         int index = getLocalVariableIndex(name);
//         LocalVariable initializedLocalVar = localVariable.initialize();
//         this.localVariables.set(index, initializedLocalVar);
//         return initializedLocalVar;
//     }
// 
//     public int localVariablesCount() {
//         return localVariables.size();
//     }
// }
// 
// Path: src/main/java/com/pidanic/saral/util/StatementsHelper.java
// public final class StatementsHelper {
//     public static List<Statement> parseStatements(SaralParser.StatementsContext statementsContext, Scope scope) {
//         List<Statement> allStatements = statementsContext.statement().stream().map(stmtCtx -> {
//             SaralParser.Block_statementContext block = stmtCtx.block_statement();
//             SaralParser.Simple_statementContext simpleStmt = stmtCtx.simple_statement();
//             Statement val;
//             if(block != null) {
//                 val = block.accept(new BlockStatementVisitor(scope));
//             } else {
//                 val = simpleStmt.accept(new SimpleStatementVisitor(scope));
//             }
//             return val;
//         }).collect(Collectors.toList());
// 
//         return allStatements;
//     }
// }


// Path: src/main/java/com/pidanic/saral/visitor/WhileStatementVisitor.java
import com.pidanic.saral.domain.Statement;
import com.pidanic.saral.domain.block.WhileStatement;
import com.pidanic.saral.domain.expression.Expression;
import com.pidanic.saral.exception.EmptyWhileStatementBlock;
import com.pidanic.saral.grammar.SaralBaseVisitor;
import com.pidanic.saral.grammar.SaralParser;
import com.pidanic.saral.scope.Scope;
import com.pidanic.saral.util.StatementsHelper;
import java.util.List;

package com.pidanic.saral.visitor;



public class WhileStatementVisitor extends SaralBaseVisitor<WhileStatement> {
    private Scope scope;

    public WhileStatementVisitor(Scope scope) {
        this.scope = new Scope(scope);
    }

    @Override
    public WhileStatement visitWhile_statement(SaralParser.While_statementContext ctx) {
        ExpressionVisitor expressionVisitor = new ExpressionVisitor(scope);
        Expression expression = ctx.expression().accept(expressionVisitor);
        List<Statement> block = StatementsHelper.parseStatements(ctx.block().statements(), scope);