/// <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); } }
/// <summary> /// Get a result from this particle block (null if none). /// </summary> public static AlgoValue ParseParticleBlock(algoVisitor visitor, ParserRuleContext ctx, ITerminalNode firstIdentifier, algoParser.ParticleContext[] particleContext) { //Is it a user created variable? if (algoVisitor.Scopes.VariableExists(firstIdentifier.GetText())) { //Yes, get the value and evaluate the particles. var value = algoVisitor.Scopes.GetVariable(firstIdentifier.GetText()); if (particleContext != null) { //Set particle input as the current value. SetParticleInput(value); foreach (var particle in particleContext) { //Evaluate all the particles, get the final result. visitor.VisitParticle(particle); } value = GetParticleResult(); } //Return the value. return(value); } //Is it a library? else if (algoVisitor.Scopes.LibraryExists(firstIdentifier.GetText())) { //If it's a library, you've got to have a particle access. if (particleContext == null || particleContext.Length == 0) { Error.Fatal(ctx, "Cannot use a library directly as a value."); return(null); } //It's a library, prepare for a scope switch. var scopes_local = algoVisitor.Scopes.GetLibrary(firstIdentifier.GetText()); AlgoScopeCollection oldScope = algoVisitor.Scopes; //First, get the first particle to set as the particle input. var toEval = particleContext[0]; AlgoValue particleVal = null; //Is the first particle an identifier? if (toEval.IDENTIFIER() != null) { particleVal = scopes_local.GetVariable(toEval.IDENTIFIER().GetText()); if (particleVal == null) { Error.Fatal(toEval, "No variable exists in library '" + firstIdentifier.GetText() + "' named '" + toEval.IDENTIFIER().GetText() + "'."); return(null); } } else if (toEval.functionCall_particle() != null) { //Not an identifier, a function. Attempt to call with the correct scopes. SetFunctionArgumentScopes(algoVisitor.Scopes); algoVisitor.Scopes = scopes_local; var funcParticle = toEval.functionCall_particle(); //Attempt to get the function from the library. if (!scopes_local.VariableExists(funcParticle.IDENTIFIER().GetText())) { Error.Fatal(funcParticle, "No function exists named '" + funcParticle.IDENTIFIER().GetText() + " in library '" + firstIdentifier.GetText() + "'."); return(null); } //Is it a valid function? var funcVal = scopes_local.GetVariable(funcParticle.IDENTIFIER().GetText()); if (funcVal.Type != AlgoValueType.EmulatedFunction && funcVal.Type != AlgoValueType.Function) { Error.Fatal(funcParticle, "Cannot call a value that is not a function ('" + funcParticle.IDENTIFIER().GetText() + " in library '" + firstIdentifier.GetText() + "')."); return(null); } SetParticleInput(funcVal); var returned = visitor.VisitFunctionCall_particle(toEval.functionCall_particle()); if (returned != null) { particleVal = (AlgoValue)returned; } else { particleVal = null; } //Reset scopes. algoVisitor.Scopes = oldScope; ResetFunctionArgumentScopes(); ResetParticleInput(); } else { //Not a function call or child. Error.Fatal(toEval, "Cannot index directly into a library."); return(null); } //Do more particle values need to be gathered? if (particleContext.Length > 1) { //If particle value is null, throw an error. if (particleVal == null) { Error.Fatal(toEval, "No value returned to perform further operations on."); return(null); } //Swap out the scopes, set the argument evaluation scope. SetFunctionArgumentScopes(algoVisitor.Scopes); SetParticleInput(particleVal); algoVisitor.Scopes = scopes_local; //Execute all the particles past the first one. for (int i = 1; i < particleContext.Length; i++) { visitor.VisitParticle(particleContext[i]); particleVal = GetParticleResult(); } //Switch back to the original scope, reset the arg eval scope. ResetFunctionArgumentScopes(); ResetParticleInput(); algoVisitor.Scopes = oldScope; } return(particleVal); } else { Error.Fatal(ctx, "No variable or library exists with name '" + firstIdentifier.GetText() + "'."); return(null); } }