<commit_before>
#include <iosfwd>
#include <string>
#include <fstream>
#include <sexpr_parsing/SExpr.h>
#include <sexpr_parsing/SExprParser.h>
#include <iostream>
#include <map>
#include <list>
#include <boost/filesystem.hpp>

using namespace wasm_module;
using namespace wasm_module::sexpr;


class UnknownAssertValue : public std::exception {};
class NoModuleWithExport : public std::exception {};

class ModuleWrapper {
public:
    SExpr moduleExpr_;
    std::map<std::string, std::string> exports;

    SExpr positiveExpr_;
    std::vector<SExpr> negativeExprs_;

    ModuleWrapper(const SExpr& moduleExpr) {
        moduleExpr_ = moduleExpr;

        std::list<std::size_t> positionsToRemove;
        for (std::size_t i = 0; i < moduleExpr_.children().size(); i++) {
            if (moduleExpr[i].hasChildren() && moduleExpr_[i][0].value() == "export") {
                positionsToRemove.push_back(i);
                exports[moduleExpr[i][1].value()] = moduleExpr[i][2].value();
            }
        }
        while (!positionsToRemove.empty()) {
            moduleExpr_.removeChild(positionsToRemove.back());
            positionsToRemove.pop_back();
        }
    }

    bool hasPositiveChecks() {
        return positiveExpr_.hasChildren();
    }

    void addPositiveCheck(const SExpr& expr) {
        positiveExpr_.addChild(expr);
    }

    void addNegativeCheck(const SExpr& expr) {
        negativeExprs_.push_back(expr);
    }

    void addMain(SExpr& module, const SExpr& mainContent) {
        SExpr mainExpr;
        mainExpr.addChild("func");
        mainExpr.addChild("main");
        mainExpr.addChild(mainContent);
        module.addChild(mainExpr);
    }

    SExpr getPositiveTestSource() {
        SExpr result = moduleExpr_;

        addMain(result, positiveExpr_);

        return result;
    }

    std::vector<SExpr> getNegativeSources() {
        std::vector<SExpr> result;
        result.reserve(negativeExprs_.size());

        for (const SExpr& expr : negativeExprs_) {
            SExpr output = moduleExpr_;
            addMain(output, expr);
            result.push_back(output);
        }

        return result;
    }


    bool hasExport(std::string expo) {
        return exports.find(expo) != exports.end();
    }

    std::string getExport(std::string expo) {
        return exports.find(expo)->second;
    }
};

class WastTestTransformer {
    std::string baseName;
    std::vector<ModuleWrapper> modules;
    sexpr::SExpr mainExpr;

    void writeSExpr(std::string directoryPath, const SExpr& sexpr, std::string fileName) {

        boost::filesystem::path directory(directoryPath);
        boost::filesystem::create_directories(directory);

        boost::filesystem::path absolutePath = directory / (fileName + ".wasm");

        std::ofstream out(absolutePath.string());

        out << sexpr.toString();
        out.close();
    }

public:
    WastTestTransformer(const std::string& wastPath) {
        boost::filesystem::path p(wastPath);

        baseName = p.stem().string();

        std::ifstream moduleFile(wastPath);
        std::string moduleData((std::istreambuf_iterator<char>(moduleFile)),
                               std::istreambuf_iterator<char>());
        sexpr::CharacterStream stream(moduleData);

        mainExpr = sexpr::SExprParser(stream).parse(true);

        for (const SExpr& expr : mainExpr.children()) {
            if (expr.hasChildren()) {
                if (expr[0].value() == "module") {
                    modules.push_back(ModuleWrapper(expr));
                }
            }
        }
    }

    ModuleWrapper& getModule(std::string exportName) {
        for(ModuleWrapper& moduleWrapper : modules) {
            if (moduleWrapper.hasExport(exportName)) {
                return moduleWrapper;
            }
        }
        std::cerr << exportName << std::endl;
        throw NoModuleWithExport();
    }

    ModuleWrapper& invokeToCall(SExpr&invoke) {
        ModuleWrapper& wrapper = getModule(invoke[1].value());

        std::string functionName = wrapper.getExport(invoke[1].value());

        invoke[0] = SExpr("call");
        invoke[1] = SExpr(functionName);

        return wrapper;
    }

    void generateOutput() {
        int testNumber = 1;
        for (SExpr expr : mainExpr.children()) {
            if (!expr.hasChildren())
                continue;
            if (expr[0].value() == "invoke") {
                ModuleWrapper& wrapper = invokeToCall(expr);
                wrapper.addPositiveCheck(expr);
            } else if (expr[0].value() == "assert_return") {
                SExpr invokeExpr = expr[1];

                ModuleWrapper& wrapper = invokeToCall(invokeExpr);

                SExpr ifExpr;
                ifExpr.addChild("if_else");

                std::string dataType;

                if (expr.children().size() <= 2) {
                    std::cout << "warning - can't handle this assert_return: " << expr.toString() << std::endl;
                } else {
                    if (expr[2][0].value() == "i32.const") {
                        dataType = "i32";
                    } else if (expr[2][0].value() == "i64.const") {
                        dataType = "i64";
                    } else if (expr[2][0].value() == "f32.const") {
                        dataType = "f32";
                    } else if (expr[2][0].value() == "f64.const") {
                        dataType = "f64";
                    } else {
                        std::cerr << expr[2][0].value() << std::endl;
                        throw UnknownAssertValue();
                    }

                    SExpr eqExpr;
                    eqExpr.addChild(dataType + ".eq");
                    eqExpr.addChild(invokeExpr);
                    eqExpr.addChild(expr[2]);

                    ifExpr.addChild(eqExpr);
                    ifExpr.addChild();
                    ifExpr.addChild(SExprParser::parseString("(unreachable)"));

                    wrapper.addPositiveCheck(ifExpr);
                }

            } else if (expr[0].value() == "assert_return_nan") {
                // TODO<commit_msg>No longer use float/double equal in assert_return<commit_after>
#include <iosfwd>
#include <string>
#include <fstream>
#include <sexpr_parsing/SExpr.h>
#include <sexpr_parsing/SExprParser.h>
#include <iostream>
#include <map>
#include <list>
#include <boost/filesystem.hpp>

using namespace wasm_module;
using namespace wasm_module::sexpr;


class UnknownAssertValue : public std::exception {};
class NoModuleWithExport : public std::exception {};

class ModuleWrapper {
public:
    SExpr moduleExpr_;
    std::map<std::string, std::string> exports;

    SExpr positiveExpr_;
    std::vector<SExpr> negativeExprs_;

    ModuleWrapper(const SExpr& moduleExpr) {
        moduleExpr_ = moduleExpr;

        std::list<std::size_t> positionsToRemove;
        for (std::size_t i = 0; i < moduleExpr_.children().size(); i++) {
            if (moduleExpr[i].hasChildren() && moduleExpr_[i][0].value() == "export") {
                positionsToRemove.push_back(i);
                exports[moduleExpr[i][1].value()] = moduleExpr[i][2].value();
            }
        }
        while (!positionsToRemove.empty()) {
            moduleExpr_.removeChild(positionsToRemove.back());
            positionsToRemove.pop_back();
        }
    }

    bool hasPositiveChecks() {
        return positiveExpr_.hasChildren();
    }

    void addPositiveCheck(const SExpr& expr) {
        positiveExpr_.addChild(expr);
    }

    void addNegativeCheck(const SExpr& expr) {
        negativeExprs_.push_back(expr);
    }

    void addMain(SExpr& module, const SExpr& mainContent) {
        SExpr mainExpr;
        mainExpr.addChild("func");
        mainExpr.addChild("main");
        mainExpr.addChild(mainContent);
        module.addChild(mainExpr);
    }

    SExpr getPositiveTestSource() {
        SExpr result = moduleExpr_;

        addMain(result, positiveExpr_);

        return result;
    }

    std::vector<SExpr> getNegativeSources() {
        std::vector<SExpr> result;
        result.reserve(negativeExprs_.size());

        for (const SExpr& expr : negativeExprs_) {
            SExpr output = moduleExpr_;
            addMain(output, expr);
            result.push_back(output);
        }

        return result;
    }


    bool hasExport(std::string expo) {
        return exports.find(expo) != exports.end();
    }

    std::string getExport(std::string expo) {
        return exports.find(expo)->second;
    }
};

class WastTestTransformer {
    std::string baseName;
    std::vector<ModuleWrapper> modules;
    sexpr::SExpr mainExpr;

    void writeSExpr(std::string directoryPath, const SExpr& sexpr, std::string fileName) {

        boost::filesystem::path directory(directoryPath);
        boost::filesystem::create_directories(directory);

        boost::filesystem::path absolutePath = directory / (fileName + ".wasm");

        std::ofstream out(absolutePath.string());

        out << sexpr.toString();
        out.close();
    }

public:
    WastTestTransformer(const std::string& wastPath) {
        boost::filesystem::path p(wastPath);

        baseName = p.stem().string();

        std::ifstream moduleFile(wastPath);
        std::string moduleData((std::istreambuf_iterator<char>(moduleFile)),
                               std::istreambuf_iterator<char>());
        sexpr::CharacterStream stream(moduleData);

        mainExpr = sexpr::SExprParser(stream).parse(true);

        for (const SExpr& expr : mainExpr.children()) {
            if (expr.hasChildren()) {
                if (expr[0].value() == "module") {
                    modules.push_back(ModuleWrapper(expr));
                }
            }
        }
    }

    ModuleWrapper& getModule(std::string exportName) {
        for(ModuleWrapper& moduleWrapper : modules) {
            if (moduleWrapper.hasExport(exportName)) {
                return moduleWrapper;
            }
        }
        std::cerr << exportName << std::endl;
        throw NoModuleWithExport();
    }

    ModuleWrapper& invokeToCall(SExpr&invoke) {
        ModuleWrapper& wrapper = getModule(invoke[1].value());

        std::string functionName = wrapper.getExport(invoke[1].value());

        invoke[0] = SExpr("call");
        invoke[1] = SExpr(functionName);

        return wrapper;
    }

    void generateOutput() {
        int testNumber = 1;
        for (SExpr expr : mainExpr.children()) {
            if (!expr.hasChildren())
                continue;
            if (expr[0].value() == "invoke") {
                ModuleWrapper& wrapper = invokeToCall(expr);
                wrapper.addPositiveCheck(expr);
            } else if (expr[0].value() == "assert_return") {
                SExpr invokeExpr = expr[1];

                ModuleWrapper& wrapper = invokeToCall(invokeExpr);


                std::string dataType;

                if (expr.children().size() <= 2) {
                    std::cout << "warning - can't handle this assert_return: " << expr.toString() << std::endl;
                } else {
                    if (expr[2][0].value() == "i32.const") {
                        dataType = "i32";
                    } else if (expr[2][0].value() == "i64.const") {
                        dataType = "i64";
                    } else if (expr[2][0].value() == "f32.const") {
                        dataType = "f32";
                    } else if (expr[2][0].value() == "f64.const") {
                        dataType = "f64";
                    } else {
                        std::cerr << expr[2][0].value() << std::endl;
                        throw UnknownAssertValue();
                    }

                    if (dataType[0] == 'i') {
                        SExpr ifExpr;
                        ifExpr.addChild("if_else");

                        SExpr eqExpr;
                        eqExpr.addChild(dataType + ".eq");
                        eqExpr.addChild(invokeExpr);
                        eqExpr.addChild(expr[2]);

                        ifExpr.addChild(eqExpr);
                        ifExpr.addChild();
                        ifExpr.addChild(SExprParser::parseString("(unreachable)"));
                        wrapper.addPositiveCheck(ifExpr);
                    } else {
                        if (dataType == "f32") {
                            SExpr ifExpr = SExprParser::parseString("(if_else (i32.eq (i32.reinterpret/f32) (i32.reinterpret/f32)) () (unreachable) )");
                            ifExpr[0][1][1].addChild(invokeExpr);
                            ifExpr[0][1][2].addChild(expr[2]);
                            wrapper.addPositiveCheck(ifExpr);
                        } else if (dataType == "f64") {
                            SExpr ifExpr = SExprParser::parseString("(if_else (i64.eq (i64.reinterpret/f64) (i64.reinterpret/f64)) () (unreachable) )");
                            ifExpr[0][1][1].addChild(invokeExpr);
                            ifExpr[0][1][2].addChild(expr[2]);
                            wrapper.addPositiveCheck(ifExpr);
                        } else {
                            assert(false);
                        }
                    }

                }

            } else if (expr[0].value() == "assert_return_nan") {
                // TODO
{'fraction_non_alphanumeric': 0.1309211020193679, 'fraction_numerical': 0.00923354102544854, 'mean_word_length': 1.9017643214985842, 'pattern_counts': {'":': 0, '<': 73, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '4796555', 'n_tokens_mistral': 3844, 'n_tokens_neox': 3625, 'n_words': 658}