Search in sources :

Example 1 with TaskManager

use of com.laytonsmith.core.taskmanager.TaskManager in project CommandHelper by EngineHub.

the class CommandHelperInterpreterListener method execute.

public void execute(String script, final MCPlayer p) throws ConfigCompileException, ConfigCompileGroupException {
    TokenStream stream = MethodScriptCompiler.lex(script, new File("Interpreter"), true);
    ParseTree tree = MethodScriptCompiler.compile(stream);
    interpreterMode.remove(p.getName());
    GlobalEnv gEnv = new GlobalEnv(plugin.executionQueue, plugin.profiler, plugin.persistenceNetwork, CommandHelperFileLocations.getDefault().getConfigDirectory(), plugin.profiles, new TaskManager());
    gEnv.SetDynamicScriptingMode(true);
    CommandHelperEnvironment cEnv = new CommandHelperEnvironment();
    cEnv.SetPlayer(p);
    Environment env = Environment.createEnvironment(gEnv, cEnv);
    try {
        MethodScriptCompiler.registerAutoIncludes(env, null);
        MethodScriptCompiler.execute(tree, env, new MethodScriptComplete() {

            @Override
            public void done(String output) {
                output = output.trim();
                if (output.isEmpty()) {
                    Static.SendMessage(p, ":");
                } else {
                    if (output.startsWith("/")) {
                        // Run the command
                        Static.SendMessage(p, ":" + MCChatColor.YELLOW + output);
                        p.chat(output);
                    } else {
                        // output the results
                        Static.SendMessage(p, ":" + MCChatColor.GREEN + output);
                    }
                }
                interpreterMode.add(p.getName());
            }
        }, null);
    } catch (CancelCommandException e) {
        interpreterMode.add(p.getName());
    } catch (ConfigRuntimeException e) {
        ConfigRuntimeException.HandleUncaughtException(e, env);
        Static.SendMessage(p, MCChatColor.RED + e.toString());
        interpreterMode.add(p.getName());
    } catch (Exception e) {
        Static.SendMessage(p, MCChatColor.RED + e.toString());
        Logger.getLogger(CommandHelperInterpreterListener.class.getName()).log(Level.SEVERE, null, e);
        interpreterMode.add(p.getName());
    }
}
Also used : TokenStream(com.laytonsmith.core.compiler.TokenStream) ConfigRuntimeException(com.laytonsmith.core.exceptions.ConfigRuntimeException) CancelCommandException(com.laytonsmith.core.exceptions.CancelCommandException) ConfigCompileException(com.laytonsmith.core.exceptions.ConfigCompileException) ConfigRuntimeException(com.laytonsmith.core.exceptions.ConfigRuntimeException) ConfigCompileGroupException(com.laytonsmith.core.exceptions.ConfigCompileGroupException) MethodScriptComplete(com.laytonsmith.core.MethodScriptComplete) TaskManager(com.laytonsmith.core.taskmanager.TaskManager) CancelCommandException(com.laytonsmith.core.exceptions.CancelCommandException) CommandHelperEnvironment(com.laytonsmith.core.environments.CommandHelperEnvironment) Environment(com.laytonsmith.core.environments.Environment) CommandHelperEnvironment(com.laytonsmith.core.environments.CommandHelperEnvironment) GlobalEnv(com.laytonsmith.core.environments.GlobalEnv) File(java.io.File) ParseTree(com.laytonsmith.core.ParseTree)

Example 2 with TaskManager

use of com.laytonsmith.core.taskmanager.TaskManager in project CommandHelper by EngineHub.

the class AliasCore method alias.

/**
 * This is the workhorse function. It takes a given command, then converts it into the actual command(s). If the
 * command maps to a defined alias, it will run the specified alias. It will search through the global list of
 * aliases, as well as the aliases defined for that specific player. This function doesn't handle the /alias command
 * however.
 *
 * @param command
 * @return
 */
public boolean alias(String command, final MCCommandSender player) {
    if (scripts == null) {
        throw ConfigRuntimeException.CreateUncatchableException("Cannot run alias commands, no config file is loaded", Target.UNKNOWN);
    }
    boolean match = false;
    try {
        // actually add the player to the array.
        if (player != null && player instanceof MCPlayer && echoCommand.contains(((MCPlayer) player).getName())) {
            // we are running one of the expanded commands, so exit with false
            return false;
        }
        for (Script s : scripts) {
            try {
                if (s.match(command)) {
                    this.addPlayerReference(player);
                    if (Prefs.ConsoleLogCommands() && s.doLog()) {
                        StringBuilder b = new StringBuilder("CH: Running original command ");
                        if (player instanceof MCPlayer) {
                            b.append("on player ").append(((MCPlayer) player).getName());
                        } else {
                            b.append("from a MCCommandSender");
                        }
                        b.append(" ----> ").append(command);
                        Static.getLogger().log(Level.INFO, b.toString());
                    }
                    GlobalEnv gEnv = new GlobalEnv(parent.executionQueue, parent.profiler, parent.persistenceNetwork, MethodScriptFileLocations.getDefault().getConfigDirectory(), parent.profiles, new TaskManager());
                    CommandHelperEnvironment cEnv = new CommandHelperEnvironment();
                    cEnv.SetCommandSender(player);
                    Environment env = Environment.createEnvironment(gEnv, cEnv);
                    try {
                        env.getEnv(CommandHelperEnvironment.class).SetCommand(command);
                        ProfilePoint alias = env.getEnv(GlobalEnv.class).GetProfiler().start("Global Alias - \"" + command + "\"", LogLevel.ERROR);
                        try {
                            s.run(s.getVariables(command), env, new MethodScriptComplete() {

                                @Override
                                public void done(String output) {
                                    try {
                                        if (output != null) {
                                            if (!output.trim().isEmpty() && output.trim().startsWith("/")) {
                                                if (Prefs.DebugMode()) {
                                                    if (player instanceof MCPlayer) {
                                                        Static.getLogger().log(Level.INFO, "[CommandHelper]: Executing command on " + ((MCPlayer) player).getName() + ": " + output.trim());
                                                    } else {
                                                        Static.getLogger().log(Level.INFO, "[CommandHelper]: Executing command from console equivalent: " + output.trim());
                                                    }
                                                }
                                                if (player instanceof MCPlayer) {
                                                    ((MCPlayer) player).chat(output.trim());
                                                } else {
                                                    Static.getServer().dispatchCommand(player, output.trim().substring(1));
                                                }
                                            }
                                        }
                                    } catch (Throwable e) {
                                        StreamUtils.GetSystemErr().println(e.getMessage());
                                        player.sendMessage(MCChatColor.RED + e.getMessage());
                                    } finally {
                                        Static.getAliasCore().removePlayerReference(player);
                                    }
                                }
                            });
                        } finally {
                            alias.stop();
                        }
                    } catch (ConfigRuntimeException ex) {
                        ex.setEnv(env);
                        ConfigRuntimeException.HandleUncaughtException(ex, env);
                    } catch (Throwable e) {
                        // This is not a simple user script error, this is a deeper problem, so we always handle this.
                        StreamUtils.GetSystemErr().println("An unexpected exception occured: " + e.getClass().getSimpleName());
                        player.sendMessage("An unexpected exception occured: " + MCChatColor.RED + e.getClass().getSimpleName());
                        e.printStackTrace();
                    } finally {
                        Static.getAliasCore().removePlayerReference(player);
                    }
                    match = true;
                    break;
                }
            } catch (Exception e) {
                StreamUtils.GetSystemErr().println("An unexpected exception occured inside the command " + s.toString());
                e.printStackTrace();
            }
        }
    } catch (Throwable e) {
        // Not only did an error happen, an error happened in our error handler
        throw new InternalException(TermColors.RED + "An unexpected error occured in the CommandHelper plugin. " + "Further, this is likely an error with the error handler, so it may be caused by your script, " + "however, there is no more information at this point. Check your script, but also report this " + "as a bug in CommandHelper. Also, it's possible that some commands will no longer work. As a temporary " + "workaround, restart the server, and avoid doing whatever it is you did to make this happen.\nThe error is as follows: " + e.toString() + "\n" + TermColors.reset() + "Stack Trace:\n" + StringUtils.Join(Arrays.asList(e.getStackTrace()), "\n"));
    }
    return match;
}
Also used : MCPlayer(com.laytonsmith.abstraction.MCPlayer) ConfigRuntimeException(com.laytonsmith.core.exceptions.ConfigRuntimeException) ProgramFlowManipulationException(com.laytonsmith.core.exceptions.ProgramFlowManipulationException) CancelCommandException(com.laytonsmith.core.exceptions.CancelCommandException) ConfigCompileException(com.laytonsmith.core.exceptions.ConfigCompileException) ZipException(java.util.zip.ZipException) IOException(java.io.IOException) ConfigRuntimeException(com.laytonsmith.core.exceptions.ConfigRuntimeException) ConfigCompileGroupException(com.laytonsmith.core.exceptions.ConfigCompileGroupException) ProfilePoint(com.laytonsmith.core.profiler.ProfilePoint) TaskManager(com.laytonsmith.core.taskmanager.TaskManager) CommandHelperEnvironment(com.laytonsmith.core.environments.CommandHelperEnvironment) CommandHelperEnvironment(com.laytonsmith.core.environments.CommandHelperEnvironment) Environment(com.laytonsmith.core.environments.Environment) GlobalEnv(com.laytonsmith.core.environments.GlobalEnv)

Example 3 with TaskManager

use of com.laytonsmith.core.taskmanager.TaskManager in project CommandHelper by EngineHub.

the class Manager method start.

@SuppressWarnings("ResultOfObjectAllocationIgnored")
public static void start() throws IOException, DataSourceException, URISyntaxException, Profiles.InvalidProfileException {
    Implementation.useAbstractEnumThread(false);
    Implementation.forceServerType(Implementation.Type.BUKKIT);
    ConnectionMixinFactory.ConnectionMixinOptions options = new ConnectionMixinFactory.ConnectionMixinOptions();
    options.setWorkingDirectory(chDirectory);
    persistenceNetwork = new PersistenceNetwork(CommandHelperFileLocations.getDefault().getPersistenceConfig(), CommandHelperFileLocations.getDefault().getDefaultPersistenceDBFile().toURI(), options);
    Installer.Install(chDirectory);
    CHLog.initialize(chDirectory);
    profiler = new Profiler(CommandHelperFileLocations.getDefault().getProfilerConfigFile());
    gEnv = new GlobalEnv(new MethodScriptExecutionQueue("Manager", "default"), profiler, persistenceNetwork, chDirectory, new Profiles(MethodScriptFileLocations.getDefault().getProfilesFile()), new TaskManager());
    cls();
    pl("\n" + Static.Logo() + "\n\n" + Static.DataManagerLogo());
    pl("Starting the Data Manager...");
    try {
        Environment env = Environment.createEnvironment(gEnv, new CommandHelperEnvironment());
        MethodScriptCompiler.execute(MethodScriptCompiler.compile(MethodScriptCompiler.lex("player()", null, true)), env, null, null);
    } catch (ConfigCompileException | ConfigCompileGroupException ex) {
    }
    pl(GREEN + "Welcome to the CommandHelper " + CYAN + "Data Manager!");
    pl(BLINKON + RED + "Warning!" + BLINKOFF + YELLOW + " Be sure your server is not running before using this tool to make changes to your database!");
    pl("------------------------");
    boolean finished = false;
    do {
        pl(YELLOW + "What function would you like to run? Type \"help\" for a full list of options.");
        String input = prompt();
        pl();
        if (input.toLowerCase().startsWith("help")) {
            help(input.replaceFirst("help ?", "").toLowerCase().split(" "));
        } else if (input.equalsIgnoreCase("refactor")) {
            refactor();
        } else if (input.toLowerCase().startsWith("print")) {
            print(input.replaceFirst("print ?", "").toLowerCase().split(" "));
        } else if (input.equalsIgnoreCase("cleardb")) {
            cleardb();
        } else if (input.equalsIgnoreCase("edit")) {
            edit();
        } else if (input.equalsIgnoreCase("merge")) {
            merge();
        } else if (input.equalsIgnoreCase("interpreter")) {
            new Interpreter(null, System.getProperty("user.dir"));
        } else if (input.equalsIgnoreCase("hidden-keys")) {
            hiddenKeys();
        } else if (input.equalsIgnoreCase("exit")) {
            pl("Thanks for using the " + CYAN + BOLD + "Data Manager!" + reset());
            finished = true;
        } else {
            pl("I'm sorry, that's not a valid command. Here's the help:");
            help(new String[] {});
        }
    } while (finished == false);
    StreamUtils.GetSystemOut().println(TermColors.reset());
}
Also used : PersistenceNetwork(com.laytonsmith.persistence.PersistenceNetwork) ConfigCompileException(com.laytonsmith.core.exceptions.ConfigCompileException) TaskManager(com.laytonsmith.core.taskmanager.TaskManager) Profiler(com.laytonsmith.core.profiler.Profiler) Profiles(com.laytonsmith.core.Profiles) ConnectionMixinFactory(com.laytonsmith.persistence.io.ConnectionMixinFactory) MethodScriptExecutionQueue(com.laytonsmith.core.MethodScriptExecutionQueue) CommandHelperEnvironment(com.laytonsmith.core.environments.CommandHelperEnvironment) Environment(com.laytonsmith.core.environments.Environment) CommandHelperEnvironment(com.laytonsmith.core.environments.CommandHelperEnvironment) GlobalEnv(com.laytonsmith.core.environments.GlobalEnv) ConfigCompileGroupException(com.laytonsmith.core.exceptions.ConfigCompileGroupException)

Example 4 with TaskManager

use of com.laytonsmith.core.taskmanager.TaskManager in project CommandHelper by EngineHub.

the class AliasCore method reload.

/**
 * Loads the global alias file in from the file system. If a player is running the command, send a reference to
 * them, and they will see compile errors, otherwise, null.
 *
 * @param player
 * @param settings The argument list for the settings.
 * @param firstLoad Indicates that CH is loading
 */
public final void reload(MCPlayer player, String[] settings, boolean firstLoad) {
    ReloadOptions options;
    try {
        options = new ReloadOptions(settings);
    } catch (Exception ex) {
        if (player != null) {
            player.sendMessage(ex.getMessage());
        } else {
            StreamUtils.GetSystemOut().println(ex.getMessage());
        }
        return;
    }
    try {
        if (Prefs.AllowDynamicShell()) {
            CHLog.GetLogger().Log(CHLog.Tags.GENERAL, LogLevel.WARNING, "allow-dynamic-shell is set to true in " + CommandHelperFileLocations.getDefault().getProfilerConfigFile().getName() + " you should set this to false, except during development.", Target.UNKNOWN);
        }
        if (parent.profiler == null || options.reloadProfiler()) {
            parent.profiler = new Profiler(MethodScriptFileLocations.getDefault().getProfilerConfigFile());
        }
        ProfilePoint extensionPreReload = parent.profiler.start("Extension PreReloadAliases call", LogLevel.VERBOSE);
        try {
            // Allow new-style extensions know we are about to reload aliases.
            ExtensionManager.PreReloadAliases(options);
        } finally {
            extensionPreReload.stop();
        }
        ProfilePoint shutdownHooks = parent.profiler.start("Shutdown hooks call", LogLevel.VERBOSE);
        try {
            StaticLayer.GetConvertor().runShutdownHooks();
        } finally {
            shutdownHooks.stop();
        }
        if (!firstLoad && options.reloadExtensions()) {
            ProfilePoint extensionManagerShutdown = parent.profiler.start("Extension manager shutdown", LogLevel.VERBOSE);
            try {
                ExtensionManager.Shutdown();
            } finally {
                extensionManagerShutdown.stop();
            }
        }
        CHLog.initialize(MethodScriptFileLocations.getDefault().getConfigDirectory());
        // Clear out the data source cache
        DataSourceFactory.DisconnectAll();
        // PacketJumper.startup(); we're not using this yet
        if (options.reloadExtensions()) {
            ProfilePoint extensionManagerStartup = parent.profiler.start("Extension manager startup", LogLevel.VERBOSE);
            try {
                ExtensionManager.Startup();
            } finally {
                extensionManagerStartup.stop();
            }
        }
        CHLog.GetLogger().Log(CHLog.Tags.GENERAL, LogLevel.VERBOSE, "Scripts reloading...", Target.UNKNOWN);
        if (parent.persistenceNetwork == null || options.reloadPersistenceConfig()) {
            ProfilePoint persistenceConfigReload = parent.profiler.start("Reloading persistence configuration", LogLevel.VERBOSE);
            try {
                MemoryDataSource.ClearDatabases();
                ConnectionMixinFactory.ConnectionMixinOptions mixinOptions = new ConnectionMixinFactory.ConnectionMixinOptions();
                mixinOptions.setWorkingDirectory(MethodScriptFileLocations.getDefault().getConfigDirectory());
                parent.persistenceNetwork = new PersistenceNetwork(MethodScriptFileLocations.getDefault().getPersistenceConfig(), new URI("sqlite:/" + MethodScriptFileLocations.getDefault().getDefaultPersistenceDBFile().getCanonicalFile().toURI().getRawSchemeSpecificPart().replace('\\', '/')), mixinOptions);
            } finally {
                persistenceConfigReload.stop();
            }
        }
        try {
            parent.profiles = new Profiles(MethodScriptFileLocations.getDefault().getProfilesFile());
        } catch (IOException | Profiles.InvalidProfileException ex) {
            CHLog.GetLogger().e(CHLog.Tags.GENERAL, ex.getMessage(), Target.UNKNOWN);
            return;
        }
        GlobalEnv gEnv = new GlobalEnv(parent.executionQueue, parent.profiler, parent.persistenceNetwork, MethodScriptFileLocations.getDefault().getConfigDirectory(), parent.profiles, new TaskManager());
        gEnv.SetLabel(Static.GLOBAL_PERMISSION);
        if (options.reloadExecutionQueue()) {
            ProfilePoint stoppingExecutionQueue = parent.profiler.start("Stopping execution queues", LogLevel.VERBOSE);
            try {
                parent.executionQueue.stopAllNow();
            } finally {
                stoppingExecutionQueue.stop();
            }
        }
        CommandHelperEnvironment cEnv = new CommandHelperEnvironment();
        Environment env = Environment.createEnvironment(gEnv, cEnv);
        if (options.reloadGlobals()) {
            ProfilePoint clearingGlobals = parent.profiler.start("Clearing globals", LogLevel.VERBOSE);
            try {
                Globals.clear();
            } finally {
                clearingGlobals.stop();
            }
        }
        if (options.reloadTimeouts()) {
            ProfilePoint clearingTimeouts = parent.profiler.start("Clearing timeouts/intervals", LogLevel.VERBOSE);
            try {
                Scheduling.ClearScheduledRunners();
            } finally {
                clearingTimeouts.stop();
            }
        }
        if (!aliasConfig.exists()) {
            aliasConfig.getParentFile().mkdirs();
            aliasConfig.createNewFile();
            try {
                String samp_aliases = getStringResource(AliasCore.class.getResourceAsStream("/samp_aliases.txt"));
                // Because the sample config may have been written an a machine that isn't this type, replace all
                // line endings
                samp_aliases = samp_aliases.replaceAll("\n|\r\n", System.getProperty("line.separator"));
                file_put_contents(aliasConfig, samp_aliases, "o");
            } catch (Exception e) {
                logger.log(Level.WARNING, "CommandHelper: Could not write sample config file");
            }
        }
        if (!mainFile.exists()) {
            mainFile.getParentFile().mkdirs();
            mainFile.createNewFile();
            try {
                String samp_main = getStringResource(AliasCore.class.getResourceAsStream("/samp_main.txt"));
                samp_main = samp_main.replaceAll("\n|\r\n", System.getProperty("line.separator"));
                file_put_contents(mainFile, samp_main, "o");
            } catch (Exception e) {
                logger.log(Level.WARNING, "CommandHelper: Could not write sample main file");
            }
        }
        if (!Prefs.isInitialized()) {
            Prefs.init(prefFile);
        }
        if (options.reloadScripts()) {
            ProfilePoint unregisteringEvents = parent.profiler.start("Unregistering events", LogLevel.VERBOSE);
            try {
                EventUtils.UnregisterAll();
            } finally {
                unregisteringEvents.stop();
            }
            ProfilePoint runningExtensionHooks = parent.profiler.start("Running event hooks", LogLevel.VERBOSE);
            try {
                ExtensionManager.RunHooks();
            } finally {
                runningExtensionHooks.stop();
            }
            // Clear the include cache, so it re-pulls files
            IncludeCache.clearCache();
            // Close all channel messager channels registered by CH.
            Static.getServer().getMessenger().closeAllChannels();
            scripts = new ArrayList<Script>();
            LocalPackage localPackages = new LocalPackage();
            // Run the main file once
            String main = file_get_contents(mainFile.getAbsolutePath());
            localPackages.appendMS(main, mainFile);
            // get the file again
            String alias_config = file_get_contents(aliasConfig.getAbsolutePath());
            localPackages.appendMSA(alias_config, aliasConfig);
            File auto_include = new File(env.getEnv(GlobalEnv.class).GetRootFolder(), "auto_include.ms");
            if (auto_include.exists()) {
                localPackages.addAutoInclude(auto_include);
            }
            // Now that we've included the default files, search the local_packages directory
            GetAuxAliases(auxAliases, localPackages);
            autoIncludes = localPackages.getAutoIncludes();
            ProfilePoint compilerMS = parent.profiler.start("Compilation of MS files in Local Packages", LogLevel.VERBOSE);
            try {
                env.getEnv(CommandHelperEnvironment.class).SetCommandSender(Static.getServer().getConsole());
                MethodScriptCompiler.registerAutoIncludes(env, null);
                localPackages.compileMS(player, env);
            } finally {
                env.getEnv(CommandHelperEnvironment.class).SetCommandSender(null);
                compilerMS.stop();
            }
            ProfilePoint compilerMSA = parent.profiler.start("Compilation of MSA files in Local Packages", LogLevel.VERBOSE);
            try {
                localPackages.compileMSA(scripts, player);
            } finally {
                compilerMSA.stop();
            }
        }
    } catch (IOException ex) {
        logger.log(Level.SEVERE, "[CommandHelper]: Path to config file is not correct/accessable. Please" + " check the location and try loading the plugin again.");
    } catch (Throwable t) {
        t.printStackTrace();
    }
    ProfilePoint postReloadAliases = parent.profiler.start("Extension manager post reload aliases", LogLevel.VERBOSE);
    try {
        ExtensionManager.PostReloadAliases();
    } finally {
        postReloadAliases.stop();
    }
}
Also used : PersistenceNetwork(com.laytonsmith.persistence.PersistenceNetwork) IOException(java.io.IOException) URI(java.net.URI) ProgramFlowManipulationException(com.laytonsmith.core.exceptions.ProgramFlowManipulationException) CancelCommandException(com.laytonsmith.core.exceptions.CancelCommandException) ConfigCompileException(com.laytonsmith.core.exceptions.ConfigCompileException) ZipException(java.util.zip.ZipException) IOException(java.io.IOException) ConfigRuntimeException(com.laytonsmith.core.exceptions.ConfigRuntimeException) ConfigCompileGroupException(com.laytonsmith.core.exceptions.ConfigCompileGroupException) ProfilePoint(com.laytonsmith.core.profiler.ProfilePoint) TaskManager(com.laytonsmith.core.taskmanager.TaskManager) Profiler(com.laytonsmith.core.profiler.Profiler) ConnectionMixinFactory(com.laytonsmith.persistence.io.ConnectionMixinFactory) CommandHelperEnvironment(com.laytonsmith.core.environments.CommandHelperEnvironment) CommandHelperEnvironment(com.laytonsmith.core.environments.CommandHelperEnvironment) Environment(com.laytonsmith.core.environments.Environment) GlobalEnv(com.laytonsmith.core.environments.GlobalEnv) ZipFile(java.util.zip.ZipFile) File(java.io.File)

Example 5 with TaskManager

use of com.laytonsmith.core.taskmanager.TaskManager in project CommandHelper by EngineHub.

the class MethodScriptCompiler method optimize.

/**
 * Recurses down into the tree, attempting to optimize where possible. A few things have strong coupling, for
 * information on these items, see the documentation included in the source.
 *
 * @param tree
 * @return
 */
private static void optimize(ParseTree tree, Stack<List<Procedure>> procs, Set<ConfigCompileException> compilerErrors) {
    if (tree.isOptimized()) {
        // Don't need to re-run this
        return;
    }
    // }
    if (!(tree.getData() instanceof CFunction)) {
        // There's no way to optimize something that's not a function
        return;
    }
    // If it is a proc definition, we need to go ahead and see if we can add it to the const proc stack
    if (tree.getData().val().equals("proc")) {
        procs.push(new ArrayList<Procedure>());
    }
    CFunction cFunction = (CFunction) tree.getData();
    Function func;
    try {
        func = (Function) FunctionList.getFunction(cFunction);
    } catch (ConfigCompileException e) {
        func = null;
    }
    if (func != null) {
        if (func.getClass().getAnnotation(nolinking.class) != null) {
            // It's an unlinking function, so we need to stop at this point
            return;
        }
    }
    if (cFunction instanceof CIdentifier) {
        // Add the child to the identifier
        ParseTree c = ((CIdentifier) cFunction).contained();
        tree.addChild(c);
        c.getData().setWasIdentifier(true);
    }
    List<ParseTree> children = tree.getChildren();
    if (func instanceof Optimizable && ((Optimizable) func).optimizationOptions().contains(OptimizationOption.PRIORITY_OPTIMIZATION)) {
        // would cause an error, even though the user did in fact provide code in that section.
        try {
            ((Optimizable) func).optimizeDynamic(tree.getTarget(), children, tree.getFileOptions());
        } catch (ConfigCompileException ex) {
            // If an error occurs, we will skip the rest of this element
            compilerErrors.add(ex);
            return;
        } catch (ConfigRuntimeException ex) {
            compilerErrors.add(new ConfigCompileException(ex));
            return;
        }
    }
    for (int i = 0; i < children.size(); i++) {
        ParseTree t = children.get(i);
        if (t.getData() instanceof CFunction) {
            if (t.getData().val().startsWith("_") || (func != null && func.useSpecialExec())) {
                continue;
            }
            Function f;
            try {
                f = (Function) FunctionList.getFunction(t.getData());
            } catch (ConfigCompileException ex) {
                compilerErrors.add(ex);
                return;
            }
            Set<OptimizationOption> options = NO_OPTIMIZATIONS;
            if (f instanceof Optimizable) {
                options = ((Optimizable) f).optimizationOptions();
            }
            if (options.contains(OptimizationOption.TERMINAL)) {
                if (children.size() > i + 1) {
                    // First, a compiler warning
                    CHLog.GetLogger().Log(CHLog.Tags.COMPILER, LogLevel.WARNING, "Unreachable code. Consider removing this code.", children.get(i + 1).getTarget());
                    // Now, truncate the children
                    for (int j = children.size() - 1; j > i; j--) {
                        children.remove(j);
                    }
                    break;
                }
            }
        }
    }
    boolean fullyStatic = true;
    boolean hasIVars = false;
    for (ParseTree node : children) {
        if (node.getData() instanceof CFunction) {
            optimize(node, procs, compilerErrors);
        }
        if (node.getData().isDynamic() && !(node.getData() instanceof IVariable)) {
            fullyStatic = false;
        }
        if (node.getData() instanceof IVariable) {
            hasIVars = true;
        }
    }
    // In all cases, at this point, we are either unable to optimize, or we will
    // optimize, so set our optimized variable at this point.
    tree.setOptimized(true);
    if (func == null) {
        // It's a proc call. Let's see if we can optimize it
        Procedure p = null;
        loop: for (List<Procedure> proc : procs) {
            for (Procedure pp : proc) {
                if (pp.getName().equals(cFunction.val())) {
                    p = pp;
                    break loop;
                }
            }
        }
        if (p != null) {
            try {
                Construct c = DataHandling.proc.optimizeProcedure(p.getTarget(), p, children);
                if (c != null) {
                    tree.setData(c);
                    tree.removeChildren();
                    return;
                }
            // else Nope, couldn't optimize.
            } catch (ConfigRuntimeException ex) {
                // Cool. Caught a runtime error at compile time :D
                compilerErrors.add(new ConfigCompileException(ex));
            }
        }
        // so we can't for sure say, but we do know we can't optimize this
        return;
    }
    if (tree.getData().val().equals("proc")) {
        // Check for too few arguments
        if (children.size() < 2) {
            compilerErrors.add(new ConfigCompileException("Incorrect number of arguments passed to proc", tree.getData().getTarget()));
            return;
        }
        // We just went out of scope, so we need to pop the layer of Procedures that
        // are internal to us
        procs.pop();
        // Let's see.
        try {
            ParseTree root = new ParseTree(new CFunction(__autoconcat__, Target.UNKNOWN), tree.getFileOptions());
            Script fakeScript = Script.GenerateScript(root, "*");
            Environment env = null;
            try {
                if (Implementation.GetServerType().equals(Implementation.Type.BUKKIT)) {
                    CommandHelperPlugin plugin = CommandHelperPlugin.self;
                    GlobalEnv gEnv = new GlobalEnv(plugin.executionQueue, plugin.profiler, plugin.persistenceNetwork, MethodScriptFileLocations.getDefault().getConfigDirectory(), plugin.profiles, new TaskManager());
                    env = Environment.createEnvironment(gEnv, new CommandHelperEnvironment());
                } else {
                    env = Static.GenerateStandaloneEnvironment(false);
                }
            } catch (IOException | DataSourceException | URISyntaxException | Profiles.InvalidProfileException e) {
            // 
            }
            Procedure myProc = DataHandling.proc.getProcedure(tree.getTarget(), env, fakeScript, children.toArray(new ParseTree[children.size()]));
            // Yep. So, we can move on with our lives now, and if it's used later, it could possibly be static.
            procs.peek().add(myProc);
        } catch (ConfigRuntimeException e) {
            // Well, they have an error in there somewhere
            compilerErrors.add(new ConfigCompileException(e));
        } catch (NullPointerException e) {
            // Nope, can't optimize.
            return;
        }
    }
    // the compiler trick functions know how to deal with it specially, even if everything isn't
    // static, so do this first.
    String oldFunctionName = func.getName();
    Set<OptimizationOption> options = NO_OPTIMIZATIONS;
    if (func instanceof Optimizable) {
        options = ((Optimizable) func).optimizationOptions();
    }
    if (options.contains(OptimizationOption.OPTIMIZE_DYNAMIC)) {
        try {
            ParseTree tempNode;
            try {
                tempNode = ((Optimizable) func).optimizeDynamic(tree.getData().getTarget(), tree.getChildren(), tree.getFileOptions());
            } catch (ConfigRuntimeException e) {
                // Turn it into a compile exception, then rethrow
                throw new ConfigCompileException(e);
            }
            if (tempNode == Optimizable.PULL_ME_UP) {
                if (tree.hasChildren()) {
                    tempNode = tree.getChildAt(0);
                } else {
                    tempNode = null;
                }
            }
            if (tempNode == Optimizable.REMOVE_ME) {
                tree.setData(new CFunction("p", Target.UNKNOWN));
                tree.removeChildren();
            } else if (tempNode != null) {
                tree.setData(tempNode.getData());
                tree.setOptimized(tempNode.isOptimized());
                tree.setChildren(tempNode.getChildren());
                tree.getData().setWasIdentifier(tempNode.getData().wasIdentifier());
                optimize(tree, procs, compilerErrors);
                tree.setOptimized(true);
                // array, so if they have reversed this, make note of that now
                if (tempNode.hasBeenMadeStatic()) {
                    fullyStatic = true;
                }
            }
        // else it wasn't an optimization, but a compile check
        } catch (ConfigCompileException ex) {
            compilerErrors.add(ex);
        }
    }
    if (!fullyStatic) {
        return;
    }
    // specially from here forward
    if (func.preResolveVariables() && hasIVars) {
        // Well, this function isn't equipped to deal with IVariables.
        return;
    }
    // don't want to run this now
    if (tree.getData().getValue().equals(oldFunctionName) && (options.contains(OptimizationOption.OPTIMIZE_CONSTANT) || options.contains(OptimizationOption.CONSTANT_OFFLINE))) {
        Construct[] constructs = new Construct[tree.getChildren().size()];
        for (int i = 0; i < tree.getChildren().size(); i++) {
            constructs[i] = tree.getChildAt(i).getData();
        }
        try {
            try {
                Construct result;
                if (options.contains(OptimizationOption.CONSTANT_OFFLINE)) {
                    List<Integer> numArgsList = Arrays.asList(func.numArgs());
                    if (!numArgsList.contains(Integer.MAX_VALUE) && !numArgsList.contains(tree.getChildren().size())) {
                        compilerErrors.add(new ConfigCompileException("Incorrect number of arguments passed to " + tree.getData().val(), tree.getData().getTarget()));
                        result = null;
                    } else {
                        result = func.exec(tree.getData().getTarget(), null, constructs);
                    }
                } else {
                    result = ((Optimizable) func).optimize(tree.getData().getTarget(), constructs);
                }
                // If the result is null, it was just a check, it can't optimize further.
                if (result != null) {
                    result.setWasIdentifier(tree.getData().wasIdentifier());
                    tree.setData(result);
                    tree.removeChildren();
                }
            } catch (ConfigRuntimeException e) {
                // Turn this into a ConfigCompileException, then rethrow
                throw new ConfigCompileException(e);
            }
        } catch (ConfigCompileException ex) {
            compilerErrors.add(ex);
        }
    }
// It doesn't know how to optimize. Oh well.
}
Also used : CommandHelperPlugin(com.laytonsmith.commandhelper.CommandHelperPlugin) IVariable(com.laytonsmith.core.constructs.IVariable) ConfigRuntimeException(com.laytonsmith.core.exceptions.ConfigRuntimeException) URISyntaxException(java.net.URISyntaxException) CString(com.laytonsmith.core.constructs.CString) ConfigCompileException(com.laytonsmith.core.exceptions.ConfigCompileException) Function(com.laytonsmith.core.functions.Function) CFunction(com.laytonsmith.core.constructs.CFunction) CommandHelperEnvironment(com.laytonsmith.core.environments.CommandHelperEnvironment) KeywordList(com.laytonsmith.core.compiler.KeywordList) FunctionList(com.laytonsmith.core.functions.FunctionList) List(java.util.List) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) com.laytonsmith.annotations.nolinking(com.laytonsmith.annotations.nolinking) OptimizationOption(com.laytonsmith.core.Optimizable.OptimizationOption) CFunction(com.laytonsmith.core.constructs.CFunction) IOException(java.io.IOException) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) TaskManager(com.laytonsmith.core.taskmanager.TaskManager) DataSourceException(com.laytonsmith.persistence.DataSourceException) CIdentifier(com.laytonsmith.core.constructs.CIdentifier) Construct(com.laytonsmith.core.constructs.Construct) CommandHelperEnvironment(com.laytonsmith.core.environments.CommandHelperEnvironment) Environment(com.laytonsmith.core.environments.Environment) GlobalEnv(com.laytonsmith.core.environments.GlobalEnv)

Aggregations

CommandHelperEnvironment (com.laytonsmith.core.environments.CommandHelperEnvironment)6 GlobalEnv (com.laytonsmith.core.environments.GlobalEnv)6 TaskManager (com.laytonsmith.core.taskmanager.TaskManager)6 Environment (com.laytonsmith.core.environments.Environment)5 ConfigCompileException (com.laytonsmith.core.exceptions.ConfigCompileException)5 ConfigCompileGroupException (com.laytonsmith.core.exceptions.ConfigCompileGroupException)4 ConfigRuntimeException (com.laytonsmith.core.exceptions.ConfigRuntimeException)4 CancelCommandException (com.laytonsmith.core.exceptions.CancelCommandException)3 Profiler (com.laytonsmith.core.profiler.Profiler)3 PersistenceNetwork (com.laytonsmith.persistence.PersistenceNetwork)3 ConnectionMixinFactory (com.laytonsmith.persistence.io.ConnectionMixinFactory)3 File (java.io.File)3 IOException (java.io.IOException)3 ProgramFlowManipulationException (com.laytonsmith.core.exceptions.ProgramFlowManipulationException)2 ProfilePoint (com.laytonsmith.core.profiler.ProfilePoint)2 URI (java.net.URI)2 ZipException (java.util.zip.ZipException)2 MCPlayer (com.laytonsmith.abstraction.MCPlayer)1 com.laytonsmith.annotations.nolinking (com.laytonsmith.annotations.nolinking)1 CommandHelperPlugin (com.laytonsmith.commandhelper.CommandHelperPlugin)1