<commit_before>//=======================================================================
// Copyright <NAME> 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "FunctionChecker.hpp"

#include "ast/Program.hpp"
#include "FunctionTable.hpp"

#include "SemanticalException.hpp"
#include "ASTVisitor.hpp"
#include "VisitorUtils.hpp"

#include "mangling.hpp"

using namespace eddic;

class FunctionInserterVisitor : public boost::static_visitor<> {
    private:
        FunctionTable& functionTable;

    public:
        FunctionInserterVisitor(FunctionTable& table) : functionTable(table) {}

        AUTO_RECURSE_PROGRAM()
         
        void operator()(ASTFunctionDeclaration& declaration){
            auto signature = std::make_shared<Function>();

            signature->name = declaration.Content->functionName;

            for(auto& param : declaration.Content->parameters){
                auto parameter = std::make_shared<ParameterType>();
                parameter->name = param.parameterName;
                parameter->paramType = stringToType(param.parameterType);

                signature->parameters.push_back(parameter);
            }
            
            declaration.Content->mangledName = signature->mangledName = mangle(declaration.Content->functionName, signature->parameters);

            //TODO Verifiy that the function has not been previously defined

            functionTable.addFunction(signature);

            //Stop recursion here
        }

        void operator()(GlobalVariableDeclaration&){
            //Stop recursion here
        }
};

class FunctionCheckerVisitor : public boost::static_visitor<> {
    private:
        FunctionTable& functionTable;

    public:
        FunctionCheckerVisitor(FunctionTable& table) : functionTable(table) {}

        AUTO_RECURSE_PROGRAM()
        AUTO_RECURSE_FUNCTION_DECLARATION() 
        AUTO_RECURSE_GLOBAL_DECLARATION() 
        AUTO_RECURSE_SIMPLE_LOOPS()
        AUTO_RECURSE_FOREACH()
        AUTO_RECURSE_BRANCHES()
        AUTO_RECURSE_BINARY_CONDITION()
        AUTO_RECURSE_COMPOSED_VALUES()
        AUTO_RECURSE_VARIABLE_OPERATIONS()

        void operator()(ASTFunctionCall& functionCall){
            std::string name = functionCall.Content->functionName;
            
            if(name == "println" || name == "print"){
                return;
            }

            std::string mangled = mangle(name, functionCall.Content->values);

            if(!functionTable.exists(mangled)){
                throw SemanticalException("The function \"" + functionCall.Content->functionName + "()\" does not exists");
            }
        }
        
        void operator()(ASTVariable&){
            //No function calls there
        }

        void operator()(ASTSwap&){
            //No function calls there
        }
        
        void operator()(TerminalNode&){
            //No function calls there
        }
};

void FunctionChecker::check(ASTProgram& program, FunctionTable& functionTable){
    //First phase : Collect functions
    FunctionInserterVisitor inserterVisitor(functionTable);
    inserterVisitor(program);

    //Second phase : Verify calls
    FunctionCheckerVisitor checkerVisitor(functionTable);
    checkerVisitor(program);
}<commit_msg>Warn the user if a function is not used<commit_after>//=======================================================================
// Copyright <NAME> 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "FunctionChecker.hpp"

#include "ast/Program.hpp"
#include "FunctionTable.hpp"

#include "SemanticalException.hpp"
#include "ASTVisitor.hpp"
#include "VisitorUtils.hpp"

#include "mangling.hpp"

#include "Options.hpp"
#include "Compiler.hpp"

using namespace eddic;

class FunctionInserterVisitor : public boost::static_visitor<> {
    private:
        FunctionTable& functionTable;

    public:
        FunctionInserterVisitor(FunctionTable& table) : functionTable(table) {}

        AUTO_RECURSE_PROGRAM()
         
        void operator()(ASTFunctionDeclaration& declaration){
            auto signature = std::make_shared<Function>();

            signature->name = declaration.Content->functionName;

            for(auto& param : declaration.Content->parameters){
                auto parameter = std::make_shared<ParameterType>();
                parameter->name = param.parameterName;
                parameter->paramType = stringToType(param.parameterType);

                signature->parameters.push_back(parameter);
            }
            
            declaration.Content->mangledName = signature->mangledName = mangle(declaration.Content->functionName, signature->parameters);

            //TODO Verifiy that the function has not been previously defined

            functionTable.addFunction(signature);

            //Stop recursion here
        }

        void operator()(GlobalVariableDeclaration&){
            //Stop recursion here
        }
};

class FunctionCheckerVisitor : public boost::static_visitor<> {
    private:
        FunctionTable& functionTable;

    public:
        FunctionCheckerVisitor(FunctionTable& table) : functionTable(table) {}

        AUTO_RECURSE_PROGRAM()
        AUTO_RECURSE_FUNCTION_DECLARATION() 
        AUTO_RECURSE_GLOBAL_DECLARATION() 
        AUTO_RECURSE_SIMPLE_LOOPS()
        AUTO_RECURSE_FOREACH()
        AUTO_RECURSE_BRANCHES()
        AUTO_RECURSE_BINARY_CONDITION()
        AUTO_RECURSE_COMPOSED_VALUES()
        AUTO_RECURSE_VARIABLE_OPERATIONS()

        void operator()(ASTFunctionCall& functionCall){
            std::string name = functionCall.Content->functionName;
            
            if(name == "println" || name == "print"){
                return;
            }

            std::string mangled = mangle(name, functionCall.Content->values);

            if(!functionTable.exists(mangled)){
                throw SemanticalException("The function \"" + functionCall.Content->functionName + "()\" does not exists");
            } else {
                functionTable.addReference(mangled);
            }
        }
        
        void operator()(ASTVariable&){
            //No function calls there
        }

        void operator()(ASTSwap&){
            //No function calls there
        }
        
        void operator()(TerminalNode&){
            //No function calls there
        }
};

class FunctionInspector : public boost::static_visitor<> {
    private:
        FunctionTable& functionTable;

    public:
        FunctionInspector(FunctionTable& table) : functionTable(table) {}

        void operator()(ASTProgram& program){
            visit_each(*this, program.Content->blocks);
        }

        void operator()(ASTFunctionDeclaration& declaration){
            int references = functionTable.referenceCount(declaration.Content->mangledName);

            if(declaration.Content->functionName != "main" && references == 0){
                warn("unused function '" + declaration.Content->functionName + "'");
            }
        }

        void operator()(GlobalVariableDeclaration&){
            //Nothing to warn about there
        }
};

void FunctionChecker::check(ASTProgram& program, FunctionTable& functionTable){
    //First phase : Collect functions
    FunctionInserterVisitor inserterVisitor(functionTable);
    inserterVisitor(program);

    //Second phase : Verify calls
    FunctionCheckerVisitor checkerVisitor(functionTable);
    checkerVisitor(program);

    if(WarningUnused){
        //Third phase, warnings
        FunctionInspector inspector(functionTable);
        inspector(program);
    }
}
{'fraction_non_alphanumeric': 0.13297338021094926, 'fraction_numerical': 0.002636865896534405, 'mean_word_length': 2.677285318559557, 'pattern_counts': {'":': 0, '<': 14, '<?xml version=': 0, '>': 44, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7185689', 'n_tokens_mistral': 2089, 'n_tokens_neox': 1996, 'n_words': 399}