<commit_before>// Copyright 2008 <NAME>

#include "common_headers.h"

#include "ast.h"
#include "branch.h"
#include "builtins.h"
#include "compilation.h"
#include "cpp_interface.h"
#include "function.h"
#include "parser.h"
#include "runtime.h"
#include "term.h"
#include "token_stream.h"
#include "type.h"
#include "wrappers.h"
#include "values.h"

namespace circa {
namespace ast {

Infix::~Infix()
{
    delete left;
    delete right;
}

std::string
Infix::toString() const
{
    if (left == NULL) return "<error, left is NULL>";
    if (right == NULL) return "<error, right is NULL>";
    return this->left->toString() + this->preOperatorWhitespace
        + this->operatorStr
        + this->postOperatorWhitespace
        + this->right->toString();
}

Term*
Infix::createTerm(CompilationContext &context)
{
    // special case for dot operator. Try to find a member function.
    // If not found, apply right term as a function
    if (this->operatorStr == ".") {
        Term* leftTerm = this->left->createTerm(context);

        // Figure out the function name. Right expression might be
        // an identifier or a function call
        std::string functionName;

        if (right->typeName() == "Identifier")
            functionName = dynamic_cast<Identifier*>(right)->text;
        else if (right->typeName() == "FunctionCall")
            functionName = dynamic_cast<FunctionCall*>(right)->functionName;
        else
            parser::syntax_error(right->typeName() + " on right side of infix dot");

        Type &leftType = as_type(leftTerm->type);

        // Try to find the function. Check the type's member function first.
        Term* function = NULL;

        bool memberFunctionCall = false;

        if (leftType.memberFunctions.contains(functionName)) {
            function = leftType.memberFunctions[functionName];
            memberFunctionCall = true;

        } else {
            function = context.findNamed(functionName);
        }

        if (function == NULL)
            parser::syntax_error(functionName + " function not found.");

        // Assemble input list
        ReferenceList inputs(leftTerm);

        if (right->typeName() == "FunctionCall") {
            FunctionCall* functionCall = dynamic_cast<FunctionCall*>(right);

            for (unsigned int i=0; i < functionCall->arguments.size(); i++) {
                FunctionCall::Argument *arg = functionCall->arguments[i];
                Term *term = arg->expression->createTerm(context);
                inputs.append(term);
            }
        }

        Term* result = apply_function(context.topBranch(), function, inputs);

        if (memberFunctionCall
                && (left->typeName() == "Identifier")
                && (right->typeName() == "FunctionCall")) {

            // Rebind this identifier
            std::string id = dynamic_cast<Identifier*>(left)->text;

            context.topBranch().bindName(result, id);
        }

        return result;
    }

    // special case for right arrow. Apply the right term as a function
    if (this->operatorStr == "->") {
        Term* leftTerm = this->left->createTerm(context);

        Identifier *rightIdent = dynamic_cast<Identifier*>(this->right);

        if (rightIdent == NULL) {
            parser::syntax_error("Right side of -> must be an identifier");
        }

        return find_and_apply_function(context, rightIdent->text, ReferenceList(leftTerm));
    }

    // another special case: :=
    if (this->operatorStr == ":=") {

        Term* leftTerm = this->left->createTerm(context);
        Term* rightTerm = this->right->createTerm(context);

        return apply_function(context.topBranch(), APPLY_FEEDBACK, ReferenceList(leftTerm, rightTerm));
    }

    std::string functionName = getInfixFunctionName(this->operatorStr);

    Term* function = context.findNamed(functionName);

    if (function == NULL) {
        parser::syntax_error(std::string("couldn't find function: ") + functionName);
        return NULL; // unreachable
    }

    Term* leftTerm = this->left->createTerm(context);
    Term* rightTerm = this->right->createTerm(context);
    
    return apply_function(context.topBranch(), function, ReferenceList(leftTerm, rightTerm));
}

void
Infix::walk(ExpressionWalker& walker)
{
    walker.visit(this);
    left->walk(walker);
    right->walk(walker);
}

FunctionCall::~FunctionCall()
{
    ArgumentList::iterator it;
    for (it = this->arguments.begin(); it != this->arguments.end(); ++it) {
        delete (*it);
    }
}

void
FunctionCall::addArgument(Expression* expr, std::string const& preWhitespace,
            std::string const& postWhitespace)
{
    Argument *arg = new Argument();
    arg->expression = expr;
    arg->preWhitespace = preWhitespace;
    arg->postWhitespace = postWhitespace;
    this->arguments.push_back(arg);
}

std::string
FunctionCall::toString() const
{
    std::stringstream output;
    output << this->functionName << "(";

    bool firstArg = true;
    ArgumentList::const_iterator it;
    for (it = arguments.begin(); it != arguments.end(); ++it) {
        if (!firstArg)
            output << ",";
        output << (*it)->preWhitespace << (*it)->expression->toString()
            << (*it)->postWhitespace;
        firstArg = false;
    }
    output << ")";
    return output.str();
}

Term*
FunctionCall::createTerm(CompilationContext &context)
{
    ReferenceList inputs;

    for (unsigned int i=0; i < arguments.size(); i++) {
        Argument* arg = arguments[i];
        Term* term = arg->expression->createTerm(context);
        assert(term != NULL);
        inputs.append(term);
    }

    Term* result = find_and_apply_function(context, this->functionName, inputs);
    assert(result != NULL);
    return result;
}

void
FunctionCall::walk(ExpressionWalker& walker)
{
    walker.visit(this);
    ArgumentList::iterator it;
    for (it = arguments.begin(); it != arguments.end(); ++it) {
        if (*it == NULL)
            throw std::runtime_error("argument is null");
        Expression* expr = (*it)->expression;
        if (expr == NULL)
            throw std::runtime_error("expression is null");
        expr->walk(walker);
    }
}

std::string
LiteralString::toString() const
{
    return "\"" + this->text + "\"";
}

Term*
LiteralString::createTerm(CompilationContext &context)
{
    return string_value(context.topBranch(), this->text);
}

Term*
LiteralFloat::createTerm(CompilationContext &context)
{
    float value = atof(this->text.c_str());
    Term* term = float_value(context.topBranch(), value);
    float mutability = hasQuestionMark ? 1.0 : 0.0;
    term->addProperty("mutability", FLOAT_TYPE)->asFloat() = mutability;
    return term;
}

Term*
LiteralInteger::createTerm(CompilationContext &context)
{
    int value = atoi(this->text.c_str());
    return int_value(context.topBranch(), value);
}

std::string
Identifier::toString() const
{
    std::string rebindSymbol = "";
    if (hasRebindOperator)
        rebindSymbol = "@";
    return rebindSymbol + text;
}

Term*
Identifier::createTerm(CompilationContext &context)
{
    Term* result = context.findNamed(this->text);

    if (result == NULL) {
        parser::syntax_error(std::string("Couldn't find identifier: ") + this->text);
    }

    assert(result != NULL);
    return result;
}

std::string
ExpressionStatement::toString() const
{
    std::string output;

    if (nameBinding != "") {
        output = nameBinding + preEqualsWhitepace + "=" + postEqualsWhitespace;
    }

    output += expression->toString();
    
    return output;
}

Term*
ExpressionStatement::createTerm(CompilationContext &context)
{
    Term* term = this->expression->createTerm(context);
    
    if (this->nameBinding != "")
        context.topBranch().bindName(term, this->nameBinding);

    return term;
}

StatementList::~StatementList()
{
    Statement::List::iterator it;
    for (it = statements.begin(); it != statements.end(); ++it) {
        delete (*it);
    }<commit_msg>Temporarily disallow a statement of "name = identifier"<commit_after>// Copyright 2008 <NAME>

#include "common_headers.h"

#include "ast.h"
#include "branch.h"
#include "builtins.h"
#include "compilation.h"
#include "cpp_interface.h"
#include "function.h"
#include "parser.h"
#include "runtime.h"
#include "term.h"
#include "token_stream.h"
#include "type.h"
#include "wrappers.h"
#include "values.h"

namespace circa {
namespace ast {

Infix::~Infix()
{
    delete left;
    delete right;
}

std::string
Infix::toString() const
{
    if (left == NULL) return "<error, left is NULL>";
    if (right == NULL) return "<error, right is NULL>";
    return this->left->toString() + this->preOperatorWhitespace
        + this->operatorStr
        + this->postOperatorWhitespace
        + this->right->toString();
}

Term*
Infix::createTerm(CompilationContext &context)
{
    // special case for dot operator. Try to find a member function.
    // If not found, apply right term as a function
    if (this->operatorStr == ".") {
        Term* leftTerm = this->left->createTerm(context);

        // Figure out the function name. Right expression might be
        // an identifier or a function call
        std::string functionName;

        if (right->typeName() == "Identifier")
            functionName = dynamic_cast<Identifier*>(right)->text;
        else if (right->typeName() == "FunctionCall")
            functionName = dynamic_cast<FunctionCall*>(right)->functionName;
        else
            parser::syntax_error(right->typeName() + " on right side of infix dot");

        Type &leftType = as_type(leftTerm->type);

        // Try to find the function. Check the type's member function first.
        Term* function = NULL;

        bool memberFunctionCall = false;

        if (leftType.memberFunctions.contains(functionName)) {
            function = leftType.memberFunctions[functionName];
            memberFunctionCall = true;

        } else {
            function = context.findNamed(functionName);
        }

        if (function == NULL)
            parser::syntax_error(functionName + " function not found.");

        // Assemble input list
        ReferenceList inputs(leftTerm);

        if (right->typeName() == "FunctionCall") {
            FunctionCall* functionCall = dynamic_cast<FunctionCall*>(right);

            for (unsigned int i=0; i < functionCall->arguments.size(); i++) {
                FunctionCall::Argument *arg = functionCall->arguments[i];
                Term *term = arg->expression->createTerm(context);
                inputs.append(term);
            }
        }

        Term* result = apply_function(context.topBranch(), function, inputs);

        if (memberFunctionCall
                && (left->typeName() == "Identifier")
                && (right->typeName() == "FunctionCall")) {

            // Rebind this identifier
            std::string id = dynamic_cast<Identifier*>(left)->text;

            context.topBranch().bindName(result, id);
        }

        return result;
    }

    // special case for right arrow. Apply the right term as a function
    if (this->operatorStr == "->") {
        Term* leftTerm = this->left->createTerm(context);

        Identifier *rightIdent = dynamic_cast<Identifier*>(this->right);

        if (rightIdent == NULL) {
            parser::syntax_error("Right side of -> must be an identifier");
        }

        return find_and_apply_function(context, rightIdent->text, ReferenceList(leftTerm));
    }

    // another special case: :=
    if (this->operatorStr == ":=") {

        Term* leftTerm = this->left->createTerm(context);
        Term* rightTerm = this->right->createTerm(context);

        return apply_function(context.topBranch(), APPLY_FEEDBACK, ReferenceList(leftTerm, rightTerm));
    }

    std::string functionName = getInfixFunctionName(this->operatorStr);

    Term* function = context.findNamed(functionName);

    if (function == NULL) {
        parser::syntax_error(std::string("couldn't find function: ") + functionName);
        return NULL; // unreachable
    }

    Term* leftTerm = this->left->createTerm(context);
    Term* rightTerm = this->right->createTerm(context);
    
    return apply_function(context.topBranch(), function, ReferenceList(leftTerm, rightTerm));
}

void
Infix::walk(ExpressionWalker& walker)
{
    walker.visit(this);
    left->walk(walker);
    right->walk(walker);
}

FunctionCall::~FunctionCall()
{
    ArgumentList::iterator it;
    for (it = this->arguments.begin(); it != this->arguments.end(); ++it) {
        delete (*it);
    }
}

void
FunctionCall::addArgument(Expression* expr, std::string const& preWhitespace,
            std::string const& postWhitespace)
{
    Argument *arg = new Argument();
    arg->expression = expr;
    arg->preWhitespace = preWhitespace;
    arg->postWhitespace = postWhitespace;
    this->arguments.push_back(arg);
}

std::string
FunctionCall::toString() const
{
    std::stringstream output;
    output << this->functionName << "(";

    bool firstArg = true;
    ArgumentList::const_iterator it;
    for (it = arguments.begin(); it != arguments.end(); ++it) {
        if (!firstArg)
            output << ",";
        output << (*it)->preWhitespace << (*it)->expression->toString()
            << (*it)->postWhitespace;
        firstArg = false;
    }
    output << ")";
    return output.str();
}

Term*
FunctionCall::createTerm(CompilationContext &context)
{
    ReferenceList inputs;

    for (unsigned int i=0; i < arguments.size(); i++) {
        Argument* arg = arguments[i];
        Term* term = arg->expression->createTerm(context);
        assert(term != NULL);
        inputs.append(term);
    }

    Term* result = find_and_apply_function(context, this->functionName, inputs);
    assert(result != NULL);
    return result;
}

void
FunctionCall::walk(ExpressionWalker& walker)
{
    walker.visit(this);
    ArgumentList::iterator it;
    for (it = arguments.begin(); it != arguments.end(); ++it) {
        if (*it == NULL)
            throw std::runtime_error("argument is null");
        Expression* expr = (*it)->expression;
        if (expr == NULL)
            throw std::runtime_error("expression is null");
        expr->walk(walker);
    }
}

std::string
LiteralString::toString() const
{
    return "\"" + this->text + "\"";
}

Term*
LiteralString::createTerm(CompilationContext &context)
{
    return string_value(context.topBranch(), this->text);
}

Term*
LiteralFloat::createTerm(CompilationContext &context)
{
    float value = atof(this->text.c_str());
    Term* term = float_value(context.topBranch(), value);
    float mutability = hasQuestionMark ? 1.0 : 0.0;
    term->addProperty("mutability", FLOAT_TYPE)->asFloat() = mutability;
    return term;
}

Term*
LiteralInteger::createTerm(CompilationContext &context)
{
    int value = atoi(this->text.c_str());
    return int_value(context.topBranch(), value);
}

std::string
Identifier::toString() const
{
    std::string rebindSymbol = "";
    if (hasRebindOperator)
        rebindSymbol = "@";
    return rebindSymbol + text;
}

Term*
Identifier::createTerm(CompilationContext &context)
{
    Term* result = context.findNamed(this->text);

    if (result == NULL) {
        parser::syntax_error(std::string("Couldn't find identifier: ") + this->text);
    }

    assert(result != NULL);
    return result;
}

std::string
ExpressionStatement::toString() const
{
    std::string output;

    if (nameBinding != "") {
        output = nameBinding + preEqualsWhitepace + "=" + postEqualsWhitespace;
    }

    output += expression->toString();
    
    return output;
}

Term*
ExpressionStatement::createTerm(CompilationContext &context)
{
    // Make sure our expression is not just an identifier.
    if (expression->typeName() == "Identifier" && nameBinding != "") {
        parser::syntax_error("Renaming an identifier is not currently supported");
    }

    Term* term = this->expression->createTerm(context);
    
    if (this->nameBinding != "")
        context.topBranch().bindName(term, this->nameBinding);

    return term;
}

StatementList::~StatementList()
{
    Statement::List::iterator it;
    for (it = statements.begin(); it != statements.end(); ++it) {
        delete (*it);
    }
{'fraction_non_alphanumeric': 0.1434809348093481, 'fraction_numerical': 0.0012300123001230013, 'mean_word_length': 3.019031141868512, 'pattern_counts': {'":': 2, '<': 51, '<?xml version=': 0, '>': 164, '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': '5232015', 'n_tokens_mistral': 4708, 'n_tokens_neox': 4609, 'n_words': 1070}