示例#1
0
        //Loads the "core.ag" standard library.
        public void LoadCoreLibrary()
        {
            //Check the file exists.
            var dirParts = DefaultDirectories.StandardLibDirectory.Concat(new string[] { "core.ag" }).ToArray();
            var corePath = CPFilePath.GetPlatformFilePath(dirParts);

            if (!File.Exists(corePath))
            {
                Error.FatalNoContext("Failed loading the core library from '" + corePath + "'. No core functions could be loaded, Algo cannot run. Please reinstall Algo, or redownload the 'core.ag' standard library.");
                return;
            }

            //Load it.
            RunAlgoScript(corePath);
        }
示例#2
0
        //When a file is imported.
        public override object VisitStat_import([NotNull] algoParser.Stat_importContext context)
        {
            //The following are checked for the parent library, in order:
            //1. Executing directory of the script + whatever referenced folder path.
            //2. Packages directory for Algo.
            //3. Standard libraries.

            //Make sure they're not trying to import multiple as a single identifier.
            if (context.literal_params().expr().Length > 1 && context.AS_SYM() != null)
            {
                Error.Warning(context, "Failed to import scripts, cannot import multiple scripts as a single identifier.");
                return(null);
            }

            //Import each.
            foreach (var item in context.literal_params().expr())
            {
                //Getting directory tree text.
                string importLoc = "";

                //Evaluating the statement to get dir text.
                AlgoValue locVal = (AlgoValue)VisitExpr(item);
                if (locVal.Type != AlgoValueType.String)
                {
                    Error.Fatal(context, "Given file path to import was not a string.");
                    return(null);
                }
                importLoc = (string)locVal.Value;

                List <string> fileParts = importLoc.Split('/').ToList();

                //Append the extension to the end (imports don't require an extension).
                if (!fileParts[fileParts.Count - 1].EndsWith(".ag"))
                {
                    fileParts[fileParts.Count - 1] = fileParts.Last() + ".ag";
                }

                //Is the import being placed into a different scope?
                string importScope = "";
                if (context.AS_SYM() != null)
                {
                    //Yes, get the name of the scope.
                    importScope = context.IDENTIFIER().GetText();
                }

                //Test 1: Executing directory of the script.
                string[] dirParts = new string[] { Environment.CurrentDirectory }.Concat(fileParts).ToArray();
                string   dirToCheck = CPFilePath.GetPlatformFilePath(dirParts);

                //Is it there?
                if (File.Exists(dirToCheck))
                {
                    //Yes! Run the load function.
                    RunAlgoScript(dirToCheck, importScope);
                    continue;
                }

                //Nope.
                //Test 2: Packages directory for Algo.
                dirParts   = DefaultDirectories.PackagesDirectory.Concat(fileParts).ToArray();
                dirToCheck = CPFilePath.GetPlatformFilePath(dirParts);

                //Is it there?
                if (File.Exists(dirToCheck))
                {
                    //Yep, load it.
                    RunAlgoScript(dirToCheck, importScope);
                    continue;
                }

                //Nope.
                //Test 3: Standard libraries.
                dirParts   = DefaultDirectories.StandardLibDirectory.Concat(fileParts).ToArray();
                dirToCheck = CPFilePath.GetPlatformFilePath(dirParts);

                //Is it there?
                if (File.Exists(dirToCheck))
                {
                    //Yep, load it.
                    RunAlgoScript(dirToCheck, importScope);
                    continue;
                }

                //No, nowhere else to check from, so throw a linking warning.
                Error.Warning(context, "Failed to link the Algo script '" + importLoc + "'. It has not been loaded.");
            }

            return(null);
        }
示例#3
0
        /// <summary>
        /// Runs Algo in "inline" mode (no package manager, etc). Returns an exit code.
        /// </summary>
        private static int RunAlgoInline(InlineCLIOptions opts, string[] originalArgs)
        {
            //Set developer mode on if necessary.
            if (opts.DeveloperMode)
            {
                AlgoRuntimeInformation.DeveloperMode = true;
            }
            if (opts.TestMode)
            {
                AlgoRuntimeInformation.UnitTestMode = true;
            }

            //Displaying any generic info and then shutting off?
            if (opts.ShowVersionOnly)
            {
                PrintVersionInfo(); return(0);
            }

            //Compiling a file?
            if (opts.Compile != null)
            {
                //Attempt to compile.
                ALEC.Compile(opts.Compile);
                return(0);
            }

            //Running the script interpreter, or the live interpreter?
            if (opts.ScriptFile == null)
            {
                //Run live.
                //Print version info. If --nohead is on, then the header info for the interpreter is skipped.
                if (!opts.NoHeader)
                {
                    PrintVersionInfo();
                    Console.WriteLine("Starting interpreter...\n");
                }

                //Create a visitor.
                if (visitor == null)
                {
                    visitor = new algoVisitor();

                    //Load core library.
                    visitor.LoadCoreLibrary();
                }

                //Interactive interpreter.
                while (true)
                {
                    Console.Write(">> ");
                    string line = Console.ReadLine();

                    //Catch keywords and null strings.
                    if (line == "quit" || line == "exit" || line == "stop")
                    {
                        break;
                    }
                    if (line == "help")
                    {
                        PrintHelp(); continue;
                    }
                    if (line == "clear")
                    {
                        Console.Clear(); continue;
                    }
                    if (line == "")
                    {
                        continue;
                    }

                    //Parse line.
                    var s_chars  = new AntlrInputStream(line);
                    var s_lexer  = new algoLexer(s_chars);
                    var s_tokens = new CommonTokenStream(s_lexer);
                    var s_parse  = new algoParser(s_tokens);

                    //Turn on continuous mode.
                    AlgoRuntimeInformation.ContinuousMode = true;

                    //Execute.
                    s_parse.BuildParseTree = true;
                    var s_tree = s_parse.compileUnit();

                    try
                    {
                        visitor.VisitCompileUnit(s_tree);
                    }
                    catch (Exception e)
                    {
                        //Internal exception.
                        if (!AlgoRuntimeInformation.UnitTestMode)
                        {
                            Error.Internal(e.Message);
                        }
                        else
                        {
                            throw e;
                        }
                    }
                }

                return(0);
            }
            else
            {
                //Run normal script.
                //Does the given file location exist?
                string fullPath = CPFilePath.GetPlatformFilePath(new string[] { Environment.CurrentDirectory, opts.ScriptFile });
                if (!File.Exists(fullPath))
                {
                    Error.FatalNoContext("No file with the name '" + opts.ScriptFile + "' exists relative to your current directory.");
                    return(-1);
                }

                //Loading in the file arguments.
                List <string> args = originalArgs.ToList();
                args.RemoveAll(x => x.StartsWith("-"));
                algoVisitor.SetConsoleArguments(args.Skip(1).ToArray());

                //Read in the input.
                AlgoRuntimeInformation.FileLoaded = opts.ScriptFile;
                string input  = File.ReadAllText(fullPath);
                var    chars  = new AntlrInputStream(input);
                var    lexer  = new algoLexer(chars);
                var    tokens = new CommonTokenStream(lexer);

                //Debug print.
                if (AlgoRuntimeInformation.DeveloperMode)
                {
                    ANTLRDebug.PrintTokens(lexer);
                }

                //Debug print tree.
                var parser = new algoParser(tokens);
                parser.BuildParseTree = true;
                var tree = parser.compileUnit();
                if (AlgoRuntimeInformation.DeveloperMode)
                {
                    ANTLRDebug.PrintParseList(tree, parser);

                    //Add a gap.
                    Console.WriteLine(" --------------------\n | BEGIN EVALUATION |\n --------------------\n");
                }

                //Walking the tree.
                visitor = new algoVisitor();
                visitor.LoadCoreLibrary();
                visitor.VisitCompileUnit(tree);

                if (AlgoRuntimeInformation.DeveloperMode)
                {
                    Console.ForegroundColor = ConsoleColor.Gray;
                    Console.WriteLine("\n ------------------\n | END EVALUATION |\n ------------------\n");

                    //Print variables.
                    ANTLRDebug.PrintScopes();
                }

                return(0);
            }
        }
示例#4
0
        //On construct, add all the standard libraries as loaded function plugins.
        //Also, load in all plugins in the "/packages/" directory (and all subdirectories).
        public AlgoFunctionPlugins()
        {
            //Add standard libraries.
            //string.*
            Plugins.Add(new StandardLibrary.AlgoStd_String());
            //*.* (core)
            Plugins.Add(new StandardLibrary.AlgoStd_Core());
            //input.* and output.* (io)
            Plugins.Add(new StandardLibrary.AlgoStd_IO());
            //web.*
            Plugins.Add(new StandardLibrary.AlgoStd_Web());
            //json.*
            Plugins.Add(new StandardLibrary.AlgoStd_JSON());
            //*.* (reflection)
            Plugins.Add(new StandardLibrary.AlgoStd_Reflection());
            //random.* (maths)
            Plugins.Add(new StandardLibrary.AlgoStd_Maths());

            //Are there any plugin files in the /packages/ directory?
            string[] files = null;
            string[] dirs  = null;
            try
            {
                files = Directory.GetFiles(CPFilePath.GetPlatformFilePath(DefaultDirectories.PackagesDirectory));
                dirs  = Directory.GetDirectories(CPFilePath.GetPlatformFilePath(DefaultDirectories.PackagesDirectory));
            }
            catch
            {
                //Failed to load, this is likely a compiled ALEC executable. Don't bother doing any more.
                return;
            }

            List <string> dllFiles = new List <string>();

            foreach (var file in files)
            {
                if (file.Contains(".dll"))
                {
                    dllFiles.Add(file);
                }
            }

            //Also search one directory deeper.
            foreach (var dir in dirs)
            {
                DirectoryInfo d        = new DirectoryInfo(dir);
                FileInfo[]    dirFiles = d.GetFiles();
                foreach (var file in dirFiles)
                {
                    if (file.Extension == ".dll")
                    {
                        dllFiles.Add(file.FullName);
                    }
                }
            }

            //Attempt to load all the DLL files.
            foreach (var file in dllFiles)
            {
                LoadPlugin(file);
            }
        }
示例#5
0
文件: ALEC.cs 项目: c272/algo-lang
        ////////////////////////////
        /// MAIN COMPILE METHODS ///
        ////////////////////////////

        public static void Compile(string file)
        {
            //Print the compile header.
            PrintCompileHeader();

            //Note the compile start time.
            CompileStartTime = DateTime.Now;

            //Does the file that is being compiled exist?
            if (!File.Exists(file))
            {
                Error.FatalCompile("The file you wish to compile does not exist.");
                return;
            }

            //Get the FileInfo, set the name of the project.
            FileInfo fi = new FileInfo(file);

            if (fi.Name.Contains("."))
            {
                ProjectName = fi.Name.Split('.')[0];
            }
            else
            {
                ProjectName = fi.Name;
            }

            //Yes, read the file into memory and strip all the comments.
            Log("Linking base Algo file '" + file + "'.");
            string toCompile = "";

            try
            {
                toCompile = File.ReadAllText(file);
            }
            catch (Exception e)
            {
                Error.FatalCompile("Could not read from base script file, error '" + e.Message + "'.");
                return;
            }

            //Attaching the "core" library to the start.
            Log("Attaching the 'core' library to the base script.");
            MainScript = "import \"core\";" + MainScript;

            //Strip all comment lines.
            var scriptLines = toCompile.Replace("\r", "").Split('\n');

            foreach (var line in scriptLines)
            {
                if (!line.StartsWith("//"))
                {
                    MainScript += line + "\n";
                }
            }
            Log("Successfully linked main file, linking references...");

            //Get all linked import reference files.
            LinkFile(MainScript, file);
            Log("Successfully linked base and all referenced Algo scripts.", ALECEvent.Success);

            //Replacing import references with their proper scripts.
            Log("Attempting to replace abstract import links...");
            bool success = ReplaceImportReferences();

            if (!success)
            {
                Error.FatalCompile("Failed to replace import links with script references. Do you have a circular import loop?");
                return;
            }

            //Do a sanity check to make sure it compiles as normal Algo.
            Log("Sanity checking the syntax of the provided script...");
            SyntaxCheck(MainScript, MainScript.Replace("\r", "").Split('\n').Length - scriptLines.Length);

            //That's done, now convert it to a literal string.
            Log("Converting script into literal form for compilation...");
            MainScript = MainScript.Replace("\"", "\"\"");
            Log("Successfully converted into literal form.");

            //Create the compiler (with arguments).
            CSharpCodeProvider provider = new CSharpCodeProvider();
            CompilerParameters cp       = new CompilerParameters();

            cp.GenerateExecutable = true;
            cp.OutputAssembly     = ProjectName + ".exe";
            cp.GenerateInMemory   = false;

            //Reference the main Algo assembly (this one) when compiling.
            Assembly entryasm = Assembly.GetEntryAssembly();

            if (AlgoPlatformInfo.IsWindows)
            {
                cp.ReferencedAssemblies.Add(entryasm.Location);
            }
            else
            {
                cp.ReferencedAssemblies.Add(CPFilePath.GetPlatformFilePath(new string[] { DefaultDirectories.AssemblyDirectory, "Algo.exe" }));
            }
            cp.ReferencedAssemblies.Add(CPFilePath.GetPlatformFilePath(new string[] { DefaultDirectories.AssemblyDirectory, "Antlr4.Runtime.dll" }));

            //Attempt to compile.
            string          finalScript = ALECTemplates.ALECEntryPoint.Replace("[CUSTOM-CODE-HERE]", MainScript);
            CompilerResults results     = provider.CompileAssemblyFromSource(cp, finalScript);

            if (results.Errors.HasErrors)
            {
                //Uh oh, failed.
                //Collect the errors.
                string        final  = "Attempting to compile returned some errors:\n";
                List <string> errors = new List <string>();
                foreach (CompilerError error in results.Errors)
                {
                    errors.Add(error.ErrorText + " (Line " + error.Line + ", column " + error.Column + ").");
                }

                for (int i = 0; i < errors.Count; i++)
                {
                    final += "[" + (i + 1) + "] - " + errors[i] + "\n";
                }

                //Log.
                Error.FatalCompile(final);
                return;
            }

            //Successfully compiled, try to output to file.
            Log("Successfully compiled the Algo script into assembly.", ALECEvent.Success);
            Log("Output has been saved in '" + ProjectName + ".exe'.");

            //If Linux, MKBundle.
            if (AlgoPlatformInfo.IsLinux)
            {
                //Attempt to run MKBundle.
                Log("Linux detected as the operating system, attempting to create a native binary...");
                Log("MAKE SURE YOU HAVE MKBUNDLE INSTALLED, AND HAVE A MONO 'machine.config' AT /etc/mono/4.5/machine.config.");
                Process proc = new Process();
                proc.StartInfo.FileName  = "/bin/bash";
                proc.StartInfo.Arguments = "-c \" mkbundle -o " + ProjectName + " --simple " + cp.OutputAssembly + " --machine-config /etc/mono/4.5/machine.config --no-config --nodeps "
                                           + CPFilePath.GetPlatformFilePath(new string[] { DefaultDirectories.AssemblyDirectory, "*.dll" })
                                           + " "
                                           + CPFilePath.GetPlatformFilePath(new string[] { DefaultDirectories.AssemblyDirectory, "Algo.exe" })
                                           + "\"";
                proc.StartInfo.UseShellExecute        = false;
                proc.StartInfo.RedirectStandardOutput = true;
                proc.Start();

                while (!proc.StandardOutput.EndOfStream)
                {
                    Log(proc.StandardOutput.ReadLine());
                }

                Log("MKBundle has finished executing.");

                //Delete the main executable.
                Log("Attempting to clean up...");
                try
                {
                    File.Delete(ProjectName + ".exe");
                }
                catch (Exception e)
                {
                    Error.WarningCompile("Failed to clean up Windows executable, given error '" + e.Message + "'.");
                }
            }
            else if (AlgoPlatformInfo.IsWindows)
            {
                //It's Windows, use ILRepack instead.
                Log("Windows detected as the operating system, attempting to create a native binary...");
                Log("Attempting to bundle dependencies into packed executable...");
                RepackOptions opt = new RepackOptions();
                opt.OutputFile        = ProjectName + "_packed.exe";
                opt.SearchDirectories = new string[] { AppDomain.CurrentDomain.BaseDirectory, Environment.CurrentDirectory };

                //Setting input assemblies.
                string[] files = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.dll");
                opt.InputAssemblies = new string[] { ProjectName + ".exe", entryasm.Location }.Concat(files).ToArray();

                try
                {
                    //Merging.
                    ILRepack pack = new ILRepack(opt);
                    pack.Repack();
                    Log("Successfully merged all dependencies with the output executable.", ALECEvent.Success);

                    //Replacing the depending executable with the new one.
                    Log("Cleaning up build files...");
                    try
                    {
                        File.Delete(ProjectName + ".exe");
                        File.Move(ProjectName + "_packed.exe", ProjectName + ".exe");
                    }
                    catch (Exception e)
                    {
                        Error.WarningCompile("File cleanup failed with error '" + e.Message + "'.");
                        Error.WarningCompile("Failed to clean up build files, the executable to use is named '" + ProjectName + "_packed.exe' rather than '" + ProjectName + ".exe'.");
                    }
                }
                catch (Exception e)
                {
                    Error.WarningCompile("Packing the executable's dependencies failed, with error '" + e.Message + "'. You will need to include algo.exe and all it's dependencies along with the built executable for it to run.");
                }
            }
            else
            {
                Error.FatalCompile("Could not detect the operating system to compile native binary.");
                return;
            }

            //Print the compile footer.
            PrintCompileFooter();
            return;
        }
示例#6
0
文件: ALEC.cs 项目: c272/algo-lang
        //Recursively grabs all import references through linked files in scripts, strips comments.
        private static void LinkFile(string toCompile, string fileName)
        {
            //Strip all comment lines.
            List <string> lines = toCompile.Replace("\r", "").Split('\n').ToList();

            for (int i = 0; i < lines.Count; i++)
            {
                if (lines[i].StartsWith("//"))
                {
                    lines.RemoveAt(i);
                    i--;
                }
            }

            //Join it back together, split with line end instead.
            string source = string.Join("", lines);

            lines = source.Split(';').ToList();

            //Get all the import lines.
            List <string> imports = new List <string>();

            foreach (var line in lines)
            {
                if (ImportRegex.IsMatch(line))
                {
                    imports.Add(ImportRegex.Match(line).Value);
                }
            }

            //Check if there are actually any imports in this file.
            if (imports.Count == 0)
            {
                Log("No imports detected, skipping linking.");
                return;
            }
            Log("Detected " + imports.Count + " referenced external scripts.");

            //For each of those, check contain a valid import (regex).
            foreach (var line in imports)
            {
                if (!ImportRegex.IsMatch(line))
                {
                    //Uh oh, failed the link.
                    Error.FatalCompile("An invalid import statement was found in script '" + fileName + "', \"" + line.Substring(0, 30) + "...\".");
                    return;
                }

                //Matches, get the substring out.
                string symbolicName   = line.Substring("import \"".Length).TrimEnd('"');
                string referencedFile = symbolicName;
                if (!referencedFile.EndsWith(".ag"))
                {
                    referencedFile += ".ag";
                }

                //Has the file been linked already?
                if (LinkedScripts.Keys.Contains(symbolicName))
                {
                    Log("Script '" + symbolicName + "' has already been linked, skipping.");
                    continue;
                }

                //Is the file in std or packages?
                string stdPath = CPFilePath.GetPlatformFilePath(DefaultDirectories.StandardLibDirectory.Concat(referencedFile.Split('/')).ToArray());
                string pkgPath = CPFilePath.GetPlatformFilePath(DefaultDirectories.PackagesDirectory.Concat(referencedFile.Split('/')).ToArray());
                if (File.Exists(stdPath))
                {
                    Log("'" + referencedFile + "' discovered as a standard library file, attempting to read...");
                    referencedFile = stdPath;
                }
                else if (File.Exists(pkgPath))
                {
                    Log("'" + referencedFile + "' discovered as a package, attempting to read...");
                    referencedFile = pkgPath;
                }
                else
                {
                    Log("Discovered external reference to '" + referencedFile + "', attempting to read...");
                }

                //Not linked yet, trying to read the file into LinkedScripts.
                try
                {
                    //Add the symbolic name rather than the filename, easier to substitute into the file that way.
                    LinkedScripts.Add(symbolicName, File.ReadAllText(referencedFile));
                }
                catch (Exception e)
                {
                    Error.FatalCompile("Failed to read file '" + referencedFile + "', with error '" + e.Message + "'.");
                    return;
                }

                //Read in.
                Log("Successfully read and linked file '" + referencedFile + "'.", ALECEvent.Success);

                //Link files for all linked scripts (recursively).
                for (int i = 0; i < LinkedScripts.Count; i++)
                {
                    var file = LinkedScripts.ElementAt(i);
                    LinkFile(file.Value, file.Key);
                }
            }
        }