<commit_before>#include <cassert>
#include <set>
#include <string>
#include <queue>
#include <iostream>
#include "CallGraph.h"
#include "CodeGen_Bash.h"
#include "Parser.h"
#include "IRVisitor.h"

const std::string BISH_VERSION = "0.1";
const std::string BISH_URL = "https://github.com/tdenniston/bish";
const std::string STDLIB_PATH = "src/StdLib.bish";

class FindFunctionCalls : public Bish::IRVisitor {
public:
    FindFunctionCalls(const std::set<std::string> &n) {
        to_find.insert(n.begin(), n.end());
    }

    std::set<std::string> names() { return names_; }

    virtual void visit(Bish::FunctionCall *call) {
        for (std::vector<Bish::IRNode *>::const_iterator I = call->args.begin(),
                 E = call->args.end(); I != E; ++I) {
            (*I)->accept(this);
        }
        if (to_find.count(call->function->name)) {
            names_.insert(call->function->name);
        }
    }
private:
    std::set<std::string> to_find;
    std::set<std::string> names_;
};

// Add necessary stdlib functions to the given module.
void link_stdlib(Bish::Module *m) {
    Bish::Parser p;
    Bish::Module *stdlib = p.parse(STDLIB_PATH);
    std::set<std::string> stdlib_functions;
    for (std::vector<Bish::Function *>::iterator I = stdlib->functions.begin(),
             E = stdlib->functions.end(); I != E; ++I) {
        Bish::Function *f = *I;
        if (f->name.compare("main") == 0) continue;
        stdlib_functions.insert(f->name);
    }
    FindFunctionCalls find(stdlib_functions);
    m->accept(&find);
    Bish::CallGraphBuilder cgb;
    Bish::CallGraph cg = cgb.build(stdlib);
    
    std::set<std::string> to_link = find.names();
    for (std::set<std::string>::iterator I = to_link.begin(), E = to_link.end(); I != E; ++I) {
        Bish::Function *f = stdlib->get_function(*I);
        assert(f);
        if (f->name.compare("main") == 0) continue;
        m->add_function(f);
        std::vector<Bish::Function *> calls = cg.transitive_calls(f);
        for (std::vector<Bish::Function *>::iterator II = calls.begin(), EE = calls.end(); II != EE; ++II) {
            m->add_function(stdlib->get_function((*II)->name));
        }
    }
}

void compile_to_bash(std::ostream &os, Bish::Module *m) {
    link_stdlib(m);
    os << "#!/bin/bash\n";
    os << "# Autogenerated script, compiled from the Bish language.\n";
    os << "# Bish version " << BISH_VERSION << "\n";
    os << "# Please see " << BISH_URL << " for more information about Bish.\n\n";
    Bish::CodeGen_Bash compile(os);
    m->accept(&compile);
}

int main(int argc, char **argv) {
    if (argc < 2) {
        std::cerr << "USAGE: " << argv[0] << " <INPUT>\n";
        std::cerr << "  Compiles Bish file <INPUT> to bash.\n";
        return 1;
    }

    std::string path(argv[1]);
    Bish::Parser p;
    Bish::Module *m = p.parse(path);

    compile_to_bash(std::cout, m);

    return 0;
}<commit_msg>Use /usr/bin/env to find the path of bash.<commit_after>#include <cassert>
#include <set>
#include <string>
#include <queue>
#include <iostream>
#include "CallGraph.h"
#include "CodeGen_Bash.h"
#include "Parser.h"
#include "IRVisitor.h"

const std::string BISH_VERSION = "0.1";
const std::string BISH_URL = "https://github.com/tdenniston/bish";
const std::string STDLIB_PATH = "src/StdLib.bish";

class FindFunctionCalls : public Bish::IRVisitor {
public:
    FindFunctionCalls(const std::set<std::string> &n) {
        to_find.insert(n.begin(), n.end());
    }

    std::set<std::string> names() { return names_; }

    virtual void visit(Bish::FunctionCall *call) {
        for (std::vector<Bish::IRNode *>::const_iterator I = call->args.begin(),
                 E = call->args.end(); I != E; ++I) {
            (*I)->accept(this);
        }
        if (to_find.count(call->function->name)) {
            names_.insert(call->function->name);
        }
    }
private:
    std::set<std::string> to_find;
    std::set<std::string> names_;
};

// Add necessary stdlib functions to the given module.
void link_stdlib(Bish::Module *m) {
    Bish::Parser p;
    Bish::Module *stdlib = p.parse(STDLIB_PATH);
    std::set<std::string> stdlib_functions;
    for (std::vector<Bish::Function *>::iterator I = stdlib->functions.begin(),
             E = stdlib->functions.end(); I != E; ++I) {
        Bish::Function *f = *I;
        if (f->name.compare("main") == 0) continue;
        stdlib_functions.insert(f->name);
    }
    FindFunctionCalls find(stdlib_functions);
    m->accept(&find);
    Bish::CallGraphBuilder cgb;
    Bish::CallGraph cg = cgb.build(stdlib);
    
    std::set<std::string> to_link = find.names();
    for (std::set<std::string>::iterator I = to_link.begin(), E = to_link.end(); I != E; ++I) {
        Bish::Function *f = stdlib->get_function(*I);
        assert(f);
        if (f->name.compare("main") == 0) continue;
        m->add_function(f);
        std::vector<Bish::Function *> calls = cg.transitive_calls(f);
        for (std::vector<Bish::Function *>::iterator II = calls.begin(), EE = calls.end(); II != EE; ++II) {
            m->add_function(stdlib->get_function((*II)->name));
        }
    }
}

void compile_to_bash(std::ostream &os, Bish::Module *m) {
    link_stdlib(m);
    os << "#!/usr/bin/env bash\n";
    os << "# Autogenerated script, compiled from the Bish language.\n";
    os << "# Bish version " << BISH_VERSION << "\n";
    os << "# Please see " << BISH_URL << " for more information about Bish.\n\n";
    Bish::CodeGen_Bash compile(os);
    m->accept(&compile);
}

int main(int argc, char **argv) {
    if (argc < 2) {
        std::cerr << "USAGE: " << argv[0] << " <INPUT>\n";
        std::cerr << "  Compiles Bish file <INPUT> to bash.\n";
        return 1;
    }

    std::string path(argv[1]);
    Bish::Parser p;
    Bish::Module *m = p.parse(path);

    compile_to_bash(std::cout, m);

    return 0;
}
{'fraction_non_alphanumeric': 0.1873189023350946, 'fraction_numerical': 0.0030680074995738877, 'mean_word_length': 3.092050209205021, 'pattern_counts': {'":': 0, '<': 89, '<?xml version=': 0, '>': 77, 'https://': 2, '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': '5644215', 'n_tokens_mistral': 2085, 'n_tokens_neox': 2028, 'n_words': 430}