<commit_before>var lexer = require('./lexer'),
    typeparser = require('./typeparser').parser,
    nodes = require('./nodes').nodes,
    _ = require('underscore');

var resolveNodeModule = function(moduleName, filename) {
    var path = require('path');

    // node.js uses a few prefixes to decide where to load from:
    // http://nodejs.org/docs/latest/api/all.html#loading_from_node_modules_Folders
    var relative = _.any(['/', './', '../'], function(e) {
        return moduleName.indexOf(e) == 0;
    });

    if(relative) {
        return path.resolve(path.dirname(filename), moduleName);
    } else {
        var resolved = require.resolve(moduleName);
        return path.join(path.dirname(resolved), path.basename(resolved, '.js'));
    }
};

exports.loadModule = function(moduleName, mode, argument) {
    var source;
    switch(mode) {
    case "require":
        source = require('fs').readFileSync(resolveNodeModule(moduleName, argument) + '.roym', 'utf8');
        break;
    case "amd":
        throw new Error("TODO: Implement AMD support");
        break;
    case "browser":
    default:
        source = argument[moduleName];
        break;
    }

    var tokens = lexer.tokenise(source);
    var moduleTypes = typeparser.parse(tokens);
    return moduleTypes;
};

exports.exportType = function(arg, env, exported, nodejs) {
    var name = arg.value;
    exported[name] = env[name];
    var scope = nodejs ? "exports" : "this";
    return new nodes.Assignment(new nodes.Access(new nodes.Identifier(scope), new nodes.String(JSON.stringify(name))), arg);
};<commit_msg>Only allow explicit exporting of tag constructors<commit_after>var lexer = require('./lexer'),
    typeparser = require('./typeparser').parser,
    nodes = require('./nodes').nodes,
    types = require('./types'),
    _ = require('underscore');

var resolveNodeModule = function(moduleName, filename) {
    var path = require('path');

    // node.js uses a few prefixes to decide where to load from:
    // http://nodejs.org/docs/latest/api/all.html#loading_from_node_modules_Folders
    var relative = _.any(['/', './', '../'], function(e) {
        return moduleName.indexOf(e) == 0;
    });

    if(relative) {
        return path.resolve(path.dirname(filename), moduleName);
    } else {
        var resolved = require.resolve(moduleName);
        return path.join(path.dirname(resolved), path.basename(resolved, '.js'));
    }
};

exports.loadModule = function(moduleName, mode, argument) {
    var source;
    switch(mode) {
    case "require":
        source = require('fs').readFileSync(resolveNodeModule(moduleName, argument) + '.roym', 'utf8');
        break;
    case "amd":
        throw new Error("TODO: Implement AMD support");
        break;
    case "browser":
    default:
        source = argument[moduleName];
        break;
    }

    var tokens = lexer.tokenise(source);
    var moduleTypes = typeparser.parse(tokens);
    return moduleTypes;
};

exports.exportType = function(arg, env, exported, nodejs) {
    var name = arg.value;
    if(env[name] instanceof types.TagType) {
        throw new Error("Can't export " + JSON.stringify(name) + " (it's a type) - can only export constructors");
    }
    exported[name] = env[name];
    var scope = nodejs ? "exports" : "this";
    return new nodes.Assignment(new nodes.Access(new nodes.Identifier(scope), new nodes.String(JSON.stringify(name))), arg);
};
{'fraction_non_alphanumeric': 0.15105386416861827, 'fraction_numerical': 0.00117096018735363, 'mean_word_length': 3.182374541003672, 'pattern_counts': {'":': 6, '<': 3, '<?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': '5061840', 'n_tokens_mistral': 1019, 'n_tokens_neox': 1004, 'n_words': 237}