<commit_before>var traverse = require('traverse'),
    esprima = require('esprima'),
    escodegen = require('escodegen'),
    tcoLabel = {
        type: 'Identifier',
        name: 'tco'
    };

function returnValue(r) {
    this.update({
        type: 'BlockStatement',
        body: [{
            type: 'ExpressionStatement',
            expression: {
                type: 'AssignmentExpression',
                operator: '=',
                left: {
                    type: 'Identifier',
                    name: 'result'
                },
                right: r.argument
            }
        }, {
            type: 'BreakStatement',
            label: tcoLabel
        }]
    });
}

function tailCall(f, r) {
    var functionExpression = {
            type: 'FunctionExpression',
            params: [],
            body: {
                type: 'BlockStatement',
                body: []
            }
        },
        i,
        identifier;

    for(i = 0; i < f.params.length; i++) {
        identifier = {
            type: 'Identifier',
            name: '_' + f.params[i].name
        };
        functionExpression.params.push(identifier);
        functionExpression.body.body.push({
            type: 'ExpressionStatement',
            expression: {
                type: 'AssignmentExpression',
                operator: '=',
                left: f.params[i],
                right: identifier
            }
        });
    }

    this.update({
        type: 'BlockStatement',
        body: [{
            type: 'ExpressionStatement',
            expression: {
                type: 'CallExpression',
                callee: functionExpression,
                arguments: r.argument.arguments
            }
        }, {
            type: 'ContinueStatement',
            label: tcoLabel
        }]
    });
}

function optimizeFunction(f) {
    var name = f.id.name,
        block = f.body;

    traverse(block.body).forEach(function(n) {
        if(!n || n.type != 'ReturnStatement')
            return;

        if(n.argument.type == 'CallExpression' && n.argument.callee.name == name) {
            tailCall.call(this, f, n);
        } else {
            returnValue.call(this, n);
        }
    });

    block.body = [{
        type: 'VariableDeclaration',
        declarations: [{
            type: 'VariableDeclarator',
            id: {
                type: 'Identifier',
                name: 'result',
            },
            init: null
        }],
        kind: 'var'
    }, {
        type: 'LabeledStatement',
        label: tcoLabel,
        body: {
            type: 'WhileStatement',
            test: {
                type: 'Literal',
                value: true
            },
            body: {
                type: 'BlockStatement',
                body: block.body
            }
        }
    }, {
        type: 'ReturnStatement',
        argument: {
            type: 'Identifier',
            name: 'result'
        }
    }];
}

function hasOnlyTailCalls(f) {
    var name = f.id.name,
        result = traverse(f).reduce(function(accum, n) {
            if(!accum.all || !n || n.type != 'CallExpression' || n.callee.name != name)<commit_msg>Change from 'result' identifier to '__tcor'<commit_after>var traverse = require('traverse'),
    esprima = require('esprima'),
    escodegen = require('escodegen'),
    tcoLabel = {
        type: 'Identifier',
        name: 'tco'
    },
    resultIdentifier = {
        type: 'Identifier',
        name: '__tcor'
    };

function returnValue(r) {
    this.update({
        type: 'BlockStatement',
        body: [{
            type: 'ExpressionStatement',
            expression: {
                type: 'AssignmentExpression',
                operator: '=',
                left: resultIdentifier,
                right: r.argument
            }
        }, {
            type: 'BreakStatement',
            label: tcoLabel
        }]
    });
}

function tailCall(f, r) {
    var functionExpression = {
            type: 'FunctionExpression',
            params: [],
            body: {
                type: 'BlockStatement',
                body: []
            }
        },
        i,
        identifier;

    for(i = 0; i < f.params.length; i++) {
        identifier = {
            type: 'Identifier',
            name: '_' + f.params[i].name
        };
        functionExpression.params.push(identifier);
        functionExpression.body.body.push({
            type: 'ExpressionStatement',
            expression: {
                type: 'AssignmentExpression',
                operator: '=',
                left: f.params[i],
                right: identifier
            }
        });
    }

    this.update({
        type: 'BlockStatement',
        body: [{
            type: 'ExpressionStatement',
            expression: {
                type: 'CallExpression',
                callee: functionExpression,
                arguments: r.argument.arguments
            }
        }, {
            type: 'ContinueStatement',
            label: tcoLabel
        }]
    });
}

function optimizeFunction(f) {
    var name = f.id.name,
        block = f.body;

    traverse(block.body).forEach(function(n) {
        if(!n || n.type != 'ReturnStatement')
            return;

        if(n.argument.type == 'CallExpression' && n.argument.callee.name == name) {
            tailCall.call(this, f, n);
        } else {
            returnValue.call(this, n);
        }
    });

    block.body = [{
        type: 'VariableDeclaration',
        declarations: [{
            type: 'VariableDeclarator',
            id: resultIdentifier,
            init: null
        }],
        kind: 'var'
    }, {
        type: 'LabeledStatement',
        label: tcoLabel,
        body: {
            type: 'WhileStatement',
            test: {
                type: 'Literal',
                value: true
            },
            body: {
                type: 'BlockStatement',
                body: block.body
            }
        }
    }, {
        type: 'ReturnStatement',
        argument: resultIdentifier
    }];
}

function hasOnlyTailCalls(f) {
    var name = f.id.name,
        result = traverse(f).reduce(function(accum, n) {
            if(!accum.all || !n || n.type != 'CallExpression' || n.callee.name != name)
{'fraction_non_alphanumeric': 0.126744923857868, 'fraction_numerical': 0.00031725888324873094, 'mean_word_length': 1.3053016453382085, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, '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': '1899875', 'n_tokens_mistral': 1722, 'n_tokens_neox': 1665, 'n_words': 326}