<commit_before>#include "clay.hpp"

static void initializePatterns(OverloadPtr x)
{
    if (x->patternsInitializedState == 1)
        return;
    if (x->patternsInitializedState == -1)
        error("unholy recursion detected");
    assert(x->patternsInitializedState == 0);
    x->patternsInitializedState = -1;

    CodePtr code = x->code;
    const vector<PatternVar> &pvars = code->patternVars;
    x->patternEnv = new Env(x->env);
    for (unsigned i = 0; i < pvars.size(); ++i) {
        if (pvars[i].isMulti) {
            MultiPatternCellPtr multiCell = new MultiPatternCell(NULL);
            x->multiCells.push_back(multiCell);
            x->cells.push_back(NULL);
            addLocal(x->patternEnv, pvars[i].name, multiCell.ptr());
        }
        else {
            PatternCellPtr cell = new PatternCell(NULL);
            x->cells.push_back(cell);
            x->multiCells.push_back(NULL);
            addLocal(x->patternEnv, pvars[i].name, cell.ptr());
        }
    }

    assert(x->target.ptr());
    x->callablePattern = evaluateOnePattern(x->target, x->patternEnv);

    const vector<FormalArgPtr> &formalArgs = code->formalArgs;
    for (unsigned i = 0; i < formalArgs.size(); ++i) {
        FormalArgPtr y = formalArgs[i];
        PatternPtr pattern;
        if (y->type.ptr())
            pattern = evaluateOnePattern(y->type, x->patternEnv);
        x->argPatterns.push_back(pattern);
    }

    if (code->formalVarArg.ptr() && code->formalVarArg->type.ptr()) {
        ExprPtr unpack = new Unpack(code->formalVarArg->type.ptr());
        unpack->location = code->formalVarArg->type->location;
        x->varArgPattern = evaluateMultiPattern(new ExprList(unpack),
                                                x->patternEnv);
    }

    x->patternsInitializedState = 1;
}

static void resetPatterns(OverloadPtr x)
{
    assert(x->cells.size() == x->multiCells.size());
    for (unsigned i = 0; i < x->cells.size(); ++i) {
        if (x->cells[i].ptr()) {
            x->cells[i]->obj = NULL;
            assert(!x->multiCells[i]);
        }
        else {
            assert(x->multiCells[i].ptr());
            x->multiCells[i]->data = NULL;
        }
    }
}

struct PatternReseter {
    OverloadPtr x;
    PatternReseter(OverloadPtr x)
        : x(x) {}
    ~PatternReseter() {
        reset();
    }
    void reset() {
        if (!x)
            return;
        resetPatterns(x);
        x = NULL;
    }
};

MatchResultPtr matchInvoke(OverloadPtr overload,
                           ObjectPtr callable,
                           const vector<TypePtr> &argsKey)
{
    initializePatterns(overload);

    PatternReseter reseter(overload);

    if (!unifyPatternObj(overload->callablePattern, callable))
        return new MatchCallableError(overload->target, callable);

    CodePtr code = overload->code;
    if (code->formalVarArg.ptr()) {
        if (argsKey.size() < code->formalArgs.size())
            return new MatchArityError(argsKey.size(), code->formalArgs.size(), true);
    }
    else {
        if (code->formalArgs.size() != argsKey.size())
            return new MatchArityError(argsKey.size(), code->formalArgs.size(), false);
    }

    const vector<FormalArgPtr> &formalArgs = code->formalArgs;
    for (unsigned i = 0; i < formalArgs.size(); ++i) {
        FormalArgPtr x = formalArgs[i];
        if (x->type.ptr()) {
            PatternPtr pattern = overload->argPatterns[i];
            if (!unifyPatternObj(pattern, argsKey[i].ptr()))
                return new MatchArgumentError(i, argsKey[i], x);<commit_msg>show expected/actual arg counts in right order<commit_after>#include "clay.hpp"

static void initializePatterns(OverloadPtr x)
{
    if (x->patternsInitializedState == 1)
        return;
    if (x->patternsInitializedState == -1)
        error("unholy recursion detected");
    assert(x->patternsInitializedState == 0);
    x->patternsInitializedState = -1;

    CodePtr code = x->code;
    const vector<PatternVar> &pvars = code->patternVars;
    x->patternEnv = new Env(x->env);
    for (unsigned i = 0; i < pvars.size(); ++i) {
        if (pvars[i].isMulti) {
            MultiPatternCellPtr multiCell = new MultiPatternCell(NULL);
            x->multiCells.push_back(multiCell);
            x->cells.push_back(NULL);
            addLocal(x->patternEnv, pvars[i].name, multiCell.ptr());
        }
        else {
            PatternCellPtr cell = new PatternCell(NULL);
            x->cells.push_back(cell);
            x->multiCells.push_back(NULL);
            addLocal(x->patternEnv, pvars[i].name, cell.ptr());
        }
    }

    assert(x->target.ptr());
    x->callablePattern = evaluateOnePattern(x->target, x->patternEnv);

    const vector<FormalArgPtr> &formalArgs = code->formalArgs;
    for (unsigned i = 0; i < formalArgs.size(); ++i) {
        FormalArgPtr y = formalArgs[i];
        PatternPtr pattern;
        if (y->type.ptr())
            pattern = evaluateOnePattern(y->type, x->patternEnv);
        x->argPatterns.push_back(pattern);
    }

    if (code->formalVarArg.ptr() && code->formalVarArg->type.ptr()) {
        ExprPtr unpack = new Unpack(code->formalVarArg->type.ptr());
        unpack->location = code->formalVarArg->type->location;
        x->varArgPattern = evaluateMultiPattern(new ExprList(unpack),
                                                x->patternEnv);
    }

    x->patternsInitializedState = 1;
}

static void resetPatterns(OverloadPtr x)
{
    assert(x->cells.size() == x->multiCells.size());
    for (unsigned i = 0; i < x->cells.size(); ++i) {
        if (x->cells[i].ptr()) {
            x->cells[i]->obj = NULL;
            assert(!x->multiCells[i]);
        }
        else {
            assert(x->multiCells[i].ptr());
            x->multiCells[i]->data = NULL;
        }
    }
}

struct PatternReseter {
    OverloadPtr x;
    PatternReseter(OverloadPtr x)
        : x(x) {}
    ~PatternReseter() {
        reset();
    }
    void reset() {
        if (!x)
            return;
        resetPatterns(x);
        x = NULL;
    }
};

MatchResultPtr matchInvoke(OverloadPtr overload,
                           ObjectPtr callable,
                           const vector<TypePtr> &argsKey)
{
    initializePatterns(overload);

    PatternReseter reseter(overload);

    if (!unifyPatternObj(overload->callablePattern, callable))
        return new MatchCallableError(overload->target, callable);

    CodePtr code = overload->code;
    if (code->formalVarArg.ptr()) {
        if (argsKey.size() < code->formalArgs.size())
            return new MatchArityError(code->formalArgs.size(), argsKey.size(), true);
    }
    else {
        if (code->formalArgs.size() != argsKey.size())
            return new MatchArityError(code->formalArgs.size(), argsKey.size(), false);
    }

    const vector<FormalArgPtr> &formalArgs = code->formalArgs;
    for (unsigned i = 0; i < formalArgs.size(); ++i) {
        FormalArgPtr x = formalArgs[i];
        if (x->type.ptr()) {
            PatternPtr pattern = overload->argPatterns[i];
            if (!unifyPatternObj(pattern, argsKey[i].ptr()))
                return new MatchArgumentError(i, argsKey[i], x);
{'fraction_non_alphanumeric': 0.14556873691556177, 'fraction_numerical': 0.002512212142358688, 'mean_word_length': 2.320667284522706, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 123, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7631448', 'n_tokens_mistral': 2253, 'n_tokens_neox': 2168, 'n_words': 415}