<commit_before>#include <iostream>
#include <map>
#include <vector>
#include <sstream>
#include <assert.h>
#include "ast.h"

void test()
{
    extern void lex_test();
    extern void ast_test();
    lex_test();
    ast_test();
}

int main()
{
    test();

    const char* const program = R"(
        2 * x = 8
        )";
    source::file src{"<example>", program};
    ast::parser p{src};
    std::vector<std::unique_ptr<ast::expression>> exprs;
    while (!p.eof()) {
        exprs.emplace_back(p.parse_expression());
    }
    for (const auto& ep : exprs) {
        if (auto bin_op = dynamic_cast<const ast::binary_operation*>(ep.get())) {
            if (bin_op->op() == '=') {
                std::cout << "Handle bind of " << bin_op->lhs().repr() << " and " << bin_op->rhs().repr() << "\n";
                continue;
            }
        }
        std::cout << "Unexpected top level expression:\n" << ep->repr() << std::endl;
        assert(false);
    }
}<commit_msg>Attempt at visitor using templates<commit_after>#include <iostream>
#include <map>
#include <vector>
#include <sstream>
#include <assert.h>
#include "ast.h"

void test()
{
    extern void lex_test();
    extern void ast_test();
    lex_test();
    ast_test();
}

template<typename Derived>
struct ast_visitor {
protected:
    template<typename Arg>
    bool try_visit(const ast::expression& arg, void (Derived::* f)(const Arg&)) {
        if (auto a = dynamic_cast<const Arg*>(&arg)) {
            (static_cast<Derived&>(*this).*f)(*a);
            return true;
        }
        return false;
    }
};

struct visitor : public ast_visitor<visitor> {

    void do_it(const ast::expression& e) {
        try_visit(e, &visitor::visit_bin_op);
        std::cout << "In " << __func__ << " e: " << e.repr() << std::endl;
        assert(false);
    }

    void visit_bin_op(const ast::binary_operation& e) {
        if (e.op() == '=') {
            std::cout << "Handle bind of " << e.lhs().repr() << " and " << e.rhs().repr() << "\n";
        }
    }
};

int main()
{
    test();

    const char* const program = R"(
        2 * x = 8
        )";
    source::file src{"<example>", program};
    ast::parser p{src};
    std::vector<std::unique_ptr<ast::expression>> exprs;
    while (!p.eof()) {
        exprs.emplace_back(p.parse_expression());
    }
    visitor v;
    for (const auto& ep : exprs) {
        v.do_it(*ep);
    }
}
{'fraction_non_alphanumeric': 0.18458333333333332, 'fraction_numerical': 0.0016666666666666668, 'mean_word_length': 2.5412979351032448, 'pattern_counts': {'":': 0, '<': 61, '<?xml version=': 0, '>': 29, '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': '3970796', 'n_tokens_mistral': 836, 'n_tokens_neox': 820, 'n_words': 183}