<commit_before>// Copyright 2009 <NAME>

#include "circa.h"

namespace circa {

Term* create_term(Branch* branch, Term* function, RefList const& inputs)
{
    assert_good_pointer(function);

    if (!is_function(function))
        throw std::runtime_error("in create_term, 2nd arg to create_term must be a function");

    Term* term = new Term();

    if (branch != NULL)
        branch->append(term);

    term->function = function;
    term->needsUpdate = true;

    Function& functionData = as_function(function);

    // Initialize inputs
    for (unsigned int i=0; i < inputs.count(); i++)
        set_input(term, i, inputs[i]);

    Term* outputType = functionData.outputType;

    // Check if this function has a specializeType function
    // Side note: maybe we should do this step later. Doing it here means that we can only
    // specialize on inputs, but it might be cool to specialize on state too.
    if (functionData.specializeType != NULL) {
        outputType = functionData.specializeType(term);
        if (outputType == NULL)
            throw std::runtime_error("result of specializeType is NULL");
    }

    if (outputType == NULL)
        throw std::runtime_error("outputType is NULL");
        
    if (!is_type(outputType))
        throw std::runtime_error(outputType->name + " is not a type");

    change_type(term, outputType);

    // Create state (if a state type is defined)
    Term* stateType = functionData.stateType;
    if (stateType != NULL) {
        if (!is_type(stateType))
            throw std::runtime_error(stateType->name + " is not a type");
        term->state = create_value(NULL, stateType);
    }

    return term;
}
    
void set_input(Term* term, int index, Term* input)
{
    assert_good_pointer(term);

    term->inputs.setAt(index, input);
}

Term* create_duplicate(Branch* branch, Term* source, bool copyBranches)
{
    Term* term = create_term(branch, source->function, source->inputs);

    term->name = source->name;

    if (copyBranches)
        assign_value(source, term);
    else
        assign_value_but_dont_copy_inner_branch(source,term);

    duplicate_branch(source->properties, term->properties);

    if (source->state != NULL) {
        if (copyBranches && !has_inner_branch(source))
            assign_value(source->state, term->state);
    }
        
    return term;
}

Term* apply(Branch* branch, Term* function, RefList const& _inputs, std::string const& name)
{
    // Make a local copy of _inputs
    RefList inputs = _inputs;

    // Evaluate this function if needed
    if (function->needsUpdate)
        evaluate_term(function);

    // Check if 'function' is actually a type
    if (is_type(function))
    {<commit_msg>Fix a bug inside create_duplicate<commit_after>// Copyright 2009 <NAME>

#include "circa.h"

namespace circa {

Term* create_term(Branch* branch, Term* function, RefList const& inputs)
{
    assert_good_pointer(function);

    if (!is_function(function))
        throw std::runtime_error("in create_term, 2nd arg to create_term must be a function");

    Term* term = new Term();

    if (branch != NULL)
        branch->append(term);

    term->function = function;
    term->needsUpdate = true;

    Function& functionData = as_function(function);

    // Initialize inputs
    for (unsigned int i=0; i < inputs.count(); i++)
        set_input(term, i, inputs[i]);

    Term* outputType = functionData.outputType;

    // Check if this function has a specializeType function
    // Side note: maybe we should do this step later. Doing it here means that we can only
    // specialize on inputs, but it might be cool to specialize on state too.
    if (functionData.specializeType != NULL) {
        outputType = functionData.specializeType(term);
        if (outputType == NULL)
            throw std::runtime_error("result of specializeType is NULL");
    }

    if (outputType == NULL)
        throw std::runtime_error("outputType is NULL");
        
    if (!is_type(outputType))
        throw std::runtime_error(outputType->name + " is not a type");

    change_type(term, outputType);

    // Create state (if a state type is defined)
    Term* stateType = functionData.stateType;
    if (stateType != NULL) {
        if (!is_type(stateType))
            throw std::runtime_error(stateType->name + " is not a type");
        term->state = create_value(NULL, stateType);
    }

    return term;
}
    
void set_input(Term* term, int index, Term* input)
{
    assert_good_pointer(term);

    term->inputs.setAt(index, input);
}

Term* create_duplicate(Branch* branch, Term* source, bool copyBranches)
{
    Term* term = create_term(branch, source->function, source->inputs);

    term->name = source->name;

    if (copyBranches)
        assign_value(source, term);
    else
        assign_value_but_dont_copy_inner_branch(source,term);

    duplicate_branch(source->properties, term->properties);

    if (source->state != NULL) {
        if (copyBranches || !has_inner_branch(source))
            assign_value(source->state, term->state);
    }
        
    return term;
}

Term* apply(Branch* branch, Term* function, RefList const& _inputs, std::string const& name)
{
    // Make a local copy of _inputs
    RefList inputs = _inputs;

    // Evaluate this function if needed
    if (function->needsUpdate)
        evaluate_term(function);

    // Check if 'function' is actually a type
    if (is_type(function))
    {
{'fraction_non_alphanumeric': 0.11413843888070692, 'fraction_numerical': 0.0022091310751104565, 'mean_word_length': 3.0334075723830733, 'pattern_counts': {'":': 0, '<': 7, '<?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': '5127697', 'n_tokens_mistral': 1632, 'n_tokens_neox': 1587, 'n_words': 474}