// Path: src/main/java/com/pidanic/saral/domain/block/Function.java
// public class Function extends CallableStatement {
//     private String name;
//     private List<Argument> arguments;
//     private List<Statement> statements;
//     private ReturnStatement retStatement;
//     private Type returnType;
// 
//     public Function(Scope scope, String name, List<Argument> arguments, List<Statement> statements, Type returnType, ReturnStatement retStatement) {
//         super(scope);
//         this.name = name;
//         this.arguments = new ArrayList<>(arguments);
//         this.statements = new ArrayList<>(statements);
//         this.returnType = returnType;
//         this.retStatement = retStatement;
//     }
// 
//     Function(Scope scope, String name, List<Argument> arguments, List<Statement> statements, Type returnType) {
//         this(scope, name, arguments, statements, returnType, null);
//     }
// 
//     public String getName() {
//         return name;
//     }
// 
//     public List<Argument> getArguments() {
//         return Collections.unmodifiableList(arguments);
//     }
// 
//     public List<Statement> getStatements() {
//         return Collections.unmodifiableList(statements);
//     }
// 
//     @Override
//     public void accept(StatementGenerator generator) {
//         ((CallableStatementGenerator) generator).generate(this);
//     }
// 
//     public Type getReturnType() {
//         return returnType;
//     }
// 
//     public Optional<ReturnStatement> getReturnStatement() {
//         return Optional.ofNullable(retStatement);
//     }
// 
//     public void setStatements(List<Statement> newStatements) {
//         this.statements = newStatements;
//     }
// 
//     public void setRetStatement(ReturnStatement newStatements) {
//         this.retStatement = newStatements;
//     }
// }
// 
// Path: src/main/java/com/pidanic/saral/exception/VariableNameAlreadyExists.java
// public class VariableNameAlreadyExists extends RuntimeException {
//     public VariableNameAlreadyExists(Scope scope, String varName) {
//         super("Local variable " + varName + " already exists in scope " + scope);
//     }
// }
// 
// Path: src/main/java/com/pidanic/saral/util/BuiltInType.java
// public enum BuiltInType implements Type {
//     BOOLEAN("logický", boolean.class, "Z", TypeSpecificOpcodes.INT),
//     INT ("neskutočné numeralio int", int.class, "I", TypeSpecificOpcodes.INT),
//     CHAR ("písmeno", char.class, "C", TypeSpecificOpcodes.INT),
//     //BYTE ("neskutočné numeralio", byte.class, "B", TypeSpecificOpcodes.INT),
//     //SHORT ("neskutočné numeralio", short.class, "S", TypeSpecificOpcodes.INT),
//     LONG ("neskutočné numeralio", long.class, "J", TypeSpecificOpcodes.LONG),
//     //FLOAT ("skutočné numeralio", float.class, "F", TypeSpecificOpcodes.FLOAT),
//     DOUBLE ("skutočné numeralio", double.class, "D", TypeSpecificOpcodes.DOUBLE),
//     STRING ("slovo", String.class, "Ljava/lang/String;", TypeSpecificOpcodes.OBJECT),
//     BOOLEAN_ARR("funduš logický", boolean[].class, "[B", TypeSpecificOpcodes.BOOLEAN_ARRAY),
//     //INT_ARR ("int[]", int[].class, "[I"),
//     CHAR_ARR ("funduš písmeno", char[].class, "[C", TypeSpecificOpcodes.CHAR_ARRAY),
//     //BYTE_ARR ("byte[]", byte[].class, "[B"),
//     //SHORT_ARR ("short[]", short[].class, "[S"),
//     LONG_ARR ("funduš neskutočné numeralio", long[].class, "[J", TypeSpecificOpcodes.LONG_ARRAY),
//     //FLOAT_ARR ("float[]", float[].class, "[F"),
//     DOUBLE_ARR ("funduš skutočné numeralio", double[].class, "[D", TypeSpecificOpcodes.DOUBLE_ARRAY),
//     STRING_ARR ("funduš slovo", String[].class, "[Ljava/lang/String;", TypeSpecificOpcodes.OBJECT_ARRAY),
//     //NONE("", null,""),
//     VOID("void", void.class, "V", TypeSpecificOpcodes.VOID);
// 
//     private String name;
//     private Class<?> typeClass;
//     private String descriptor;
//     private TypeSpecificOpcodes opCode;
// 
//     BuiltInType(String name, Class<?> typeClass, String descriptor, TypeSpecificOpcodes op) {
//         this.name = name;
//         this.typeClass = typeClass;
//         this.descriptor = descriptor;
//         this.opCode = op;
//     }
// 
//     @Override
//     public String getName() {
//         return name;
//     }
// 
//     @Override
//     public Class<?> getTypeClass() {
//         return typeClass;
//     }
// 
//     @Override
//     public String getDescriptor() {
//         return descriptor;
//     }
// 
//     @Override
//     public String getInternalName() {
//         return getDescriptor();
//     }
// 
//     @Override
//     public TypeSpecificOpcodes getTypeSpecificOpcode() {
//         return opCode;
//     }
// }


import com.pidanic.saral.domain.block.Function;
import com.pidanic.saral.exception.VariableNameAlreadyExists;
import com.pidanic.saral.util.BuiltInType;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

    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);
// Path: src/main/java/com/pidanic/saral/domain/block/Function.java
// public class Function extends CallableStatement {
//     private String name;
//     private List<Argument> arguments;
//     private List<Statement> statements;
//     private ReturnStatement retStatement;
//     private Type returnType;
// 
//     public Function(Scope scope, String name, List<Argument> arguments, List<Statement> statements, Type returnType, ReturnStatement retStatement) {
//         super(scope);
//         this.name = name;
//         this.arguments = new ArrayList<>(arguments);
//         this.statements = new ArrayList<>(statements);
//         this.returnType = returnType;
//         this.retStatement = retStatement;
//     }
// 
//     Function(Scope scope, String name, List<Argument> arguments, List<Statement> statements, Type returnType) {
//         this(scope, name, arguments, statements, returnType, null);
//     }
// 
//     public String getName() {
//         return name;
//     }
// 
//     public List<Argument> getArguments() {
//         return Collections.unmodifiableList(arguments);
//     }
// 
//     public List<Statement> getStatements() {
//         return Collections.unmodifiableList(statements);
//     }
// 
//     @Override
//     public void accept(StatementGenerator generator) {
//         ((CallableStatementGenerator) generator).generate(this);
//     }
// 
//     public Type getReturnType() {
//         return returnType;
//     }
// 
//     public Optional<ReturnStatement> getReturnStatement() {
//         return Optional.ofNullable(retStatement);
//     }
// 
//     public void setStatements(List<Statement> newStatements) {
//         this.statements = newStatements;
//     }
// 
//     public void setRetStatement(ReturnStatement newStatements) {
//         this.retStatement = newStatements;
//     }
// }
// 
// Path: src/main/java/com/pidanic/saral/exception/VariableNameAlreadyExists.java
// public class VariableNameAlreadyExists extends RuntimeException {
//     public VariableNameAlreadyExists(Scope scope, String varName) {
//         super("Local variable " + varName + " already exists in scope " + scope);
//     }
// }
// 
// Path: src/main/java/com/pidanic/saral/util/BuiltInType.java
// public enum BuiltInType implements Type {
//     BOOLEAN("logický", boolean.class, "Z", TypeSpecificOpcodes.INT),
//     INT ("neskutočné numeralio int", int.class, "I", TypeSpecificOpcodes.INT),
//     CHAR ("písmeno", char.class, "C", TypeSpecificOpcodes.INT),
//     //BYTE ("neskutočné numeralio", byte.class, "B", TypeSpecificOpcodes.INT),
//     //SHORT ("neskutočné numeralio", short.class, "S", TypeSpecificOpcodes.INT),
//     LONG ("neskutočné numeralio", long.class, "J", TypeSpecificOpcodes.LONG),
//     //FLOAT ("skutočné numeralio", float.class, "F", TypeSpecificOpcodes.FLOAT),
//     DOUBLE ("skutočné numeralio", double.class, "D", TypeSpecificOpcodes.DOUBLE),
//     STRING ("slovo", String.class, "Ljava/lang/String;", TypeSpecificOpcodes.OBJECT),
//     BOOLEAN_ARR("funduš logický", boolean[].class, "[B", TypeSpecificOpcodes.BOOLEAN_ARRAY),
//     //INT_ARR ("int[]", int[].class, "[I"),
//     CHAR_ARR ("funduš písmeno", char[].class, "[C", TypeSpecificOpcodes.CHAR_ARRAY),
//     //BYTE_ARR ("byte[]", byte[].class, "[B"),
//     //SHORT_ARR ("short[]", short[].class, "[S"),
//     LONG_ARR ("funduš neskutočné numeralio", long[].class, "[J", TypeSpecificOpcodes.LONG_ARRAY),
//     //FLOAT_ARR ("float[]", float[].class, "[F"),
//     DOUBLE_ARR ("funduš skutočné numeralio", double[].class, "[D", TypeSpecificOpcodes.DOUBLE_ARRAY),
//     STRING_ARR ("funduš slovo", String[].class, "[Ljava/lang/String;", TypeSpecificOpcodes.OBJECT_ARRAY),
//     //NONE("", null,""),
//     VOID("void", void.class, "V", TypeSpecificOpcodes.VOID);
// 
//     private String name;
//     private Class<?> typeClass;
//     private String descriptor;
//     private TypeSpecificOpcodes opCode;
// 
//     BuiltInType(String name, Class<?> typeClass, String descriptor, TypeSpecificOpcodes op) {
//         this.name = name;
//         this.typeClass = typeClass;
//         this.descriptor = descriptor;
//         this.opCode = op;
//     }
// 
//     @Override
//     public String getName() {
//         return name;
//     }
// 
//     @Override
//     public Class<?> getTypeClass() {
//         return typeClass;
//     }
// 
//     @Override
//     public String getDescriptor() {
//         return descriptor;
//     }
// 
//     @Override
//     public String getInternalName() {
//         return getDescriptor();
//     }
// 
//     @Override
//     public TypeSpecificOpcodes getTypeSpecificOpcode() {
//         return opCode;
//     }
// }


// Path: src/main/java/com/pidanic/saral/scope/Scope.java
import com.pidanic.saral.domain.block.Function;
import com.pidanic.saral.exception.VariableNameAlreadyExists;
import com.pidanic.saral.util.BuiltInType;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;


    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();