Esempio n. 1
0
        //When a library is defined.
        public override object VisitStat_library([NotNull] algoParser.Stat_libraryContext context)
        {
            //Check if a library with this name already exists.
            if (Scopes.LibraryExists(context.IDENTIFIER().GetText()))
            {
                Error.Warning(context, "A library with the name '" + context.IDENTIFIER().GetText() + "' has already been loaded, so loading was ignored.");
            }

            //Switch the current scope out for a new "library" scope.
            AlgoScopeCollection oldScope = Scopes;

            Scopes = new AlgoScopeCollection();

            //Evaluate the contents of the library.
            foreach (var statement in context.statement())
            {
                VisitStatement(statement);
            }

            //Save the new scope, and switch back to the old one.
            AlgoScopeCollection libScope = Scopes;

            Scopes = oldScope;

            //Add the library scope to the library list.
            Scopes.AddLibrary(context.IDENTIFIER().GetText(), libScope);
            return(null);
        }
Esempio n. 2
0
        //Add a library.
        public void AddLibrary(string name, AlgoScopeCollection library)
        {
            //Checking if library is a dupe.
            if (Libraries.ContainsKey(name))
            {
                Error.FatalNoContext("A library with the name '" + name + "' already exists in this scope, can't define it again.");
                return;
            }

            //Not a dupe, add it.
            Libraries.Add(name, library);
        }
Esempio n. 3
0
        //Runs an Algo script, given a file path.
        public void RunAlgoScript(string path, string newScopeName = "")
        {
            //Read the entire text file into a lexer and tokens.
            string input  = File.ReadAllText(path);
            var    chars  = new AntlrInputStream(input);
            var    lexer  = new algoLexer(chars);
            var    tokens = new CommonTokenStream(lexer);

            //Parse the file.
            var parser = new algoParser(tokens);

            parser.BuildParseTree = true;
            var tree = parser.compileUnit();

            //Set the currently loaded file.
            FileInfo fi      = new FileInfo(path);
            string   oldFile = AlgoRuntimeInformation.FileLoaded;

            AlgoRuntimeInformation.FileLoaded = fi.Name;

            //If this is being placed in a separate scope, switch out now.
            AlgoScopeCollection oldScope = null;

            if (newScopeName != "")
            {
                oldScope = Scopes;
                Scopes   = new AlgoScopeCollection();
            }

            //Visit this tree, and fully execute.
            VisitCompileUnit(tree);

            //Set the currently loaded file back.
            AlgoRuntimeInformation.FileLoaded = oldFile;

            //If it was executed in a separate scope, save as a library with this name.
            if (newScopeName != "")
            {
                AlgoScopeCollection importScope = Scopes;
                Scopes = oldScope;
                Scopes.AddLibrary(newScopeName, importScope);
            }
        }
Esempio n. 4
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);
            }
        }
Esempio n. 5
0
 /// <summary>
 /// Deletes the scopes to evaluate function arguments for particles (uses current instead).
 /// </summary>
 public static void ResetFunctionArgumentScopes()
 {
     funcArgumentScopes = null;
 }
Esempio n. 6
0
 /// <summary>
 /// Sets the scopes to evaluate function arguments for particles.
 /// </summary>
 public static void SetFunctionArgumentScopes(AlgoScopeCollection scopes)
 {
     funcArgumentScopes = scopes;
 }
Esempio n. 7
0
        /// <summary>
        /// Evaluates a given particle, and returns the result.
        /// </summary>
        public override object VisitParticle([NotNull] algoParser.ParticleContext context)
        {
            //Get the last result of the particle before this.
            AlgoValue current = Particles.GetParticleResult();

            if (current == null)
            {
                Error.Internal("Particle chain started without setting an initial value.");
                return(null);
            }

            //Prepare an "old" scope for swapping.
            AlgoScopeCollection oldScope = null;

            //What type of particle is it?

            //CHILD VARIABLE
            if (context.IDENTIFIER() != null)
            {
                //Sub-variable. Attempt to get from the object.
                if (current.Type != AlgoValueType.Object)
                {
                    Error.Fatal(context, "Cannot access children when given variable is not an object, and has no children to access.");
                    return(null);
                }

                //Does the sub-variable exist?
                AlgoObject curObj = (AlgoObject)current.Value;
                AlgoValue  newObj = curObj.ObjectScopes.GetVariable(context.IDENTIFIER().GetText());
                if (newObj == null)
                {
                    Error.Fatal(context, "No child of the given object exists with name '" + context.IDENTIFIER().GetText() + "'.");
                    return(null);
                }

                //Yes, set result and return.
                Particles.SetParticleInput(newObj);
                return(null);
            }

            //ARRAY ACCESS
            else if (context.array_access_particle() != null)
            {
                var aap = context.array_access_particle();

                //Indexing.
                //For each index, iterate over.
                AlgoValue currentLV = current;
                foreach (var index in aap.literal_params().expr())
                {
                    //Is the current list value a list?
                    if (currentLV.Type != AlgoValueType.List)
                    {
                        Error.Fatal(context, "Cannot index into variable that is not a list or indexable object.");
                        return(null);
                    }

                    //Need to switch scopes for evaluating indexes?
                    if (Particles.funcArgumentScopes != null)
                    {
                        oldScope = Scopes;
                        Scopes   = Particles.funcArgumentScopes;
                    }

                    //Evaluate the expression.
                    AlgoValue indexVal = (AlgoValue)VisitExpr(index);

                    //Back to normal.
                    if (Particles.funcArgumentScopes != null)
                    {
                        Scopes = oldScope;
                    }

                    //Valid?
                    if (indexVal.Type != AlgoValueType.Integer)
                    {
                        Error.Fatal(context, "Index value provided is not an integer. Indexes must be whole integer values.");
                        return(null);
                    }

                    //Is the index outside of the bounds of the array?
                    if (((List <AlgoValue>)currentLV.Value).Count <= (BigInteger)indexVal.Value)
                    {
                        Error.Fatal(context, "Index provided is outside the bounds of the array.");
                        return(null);
                    }

                    //Index into it, set the current value.
                    currentLV = ((List <AlgoValue>)currentLV.Value)[(int)((BigInteger)indexVal.Value)];
                }

                //Set result.
                Particles.SetParticleInput(currentLV);
                return(null);
            }

            //CHILD FUNCTION
            else if (context.functionCall_particle() != null)
            {
                //Function call.
                if (current.Type != AlgoValueType.Object)
                {
                    Error.Fatal(context, "Cannot call a child function on a value with no children (given value was not an object).");
                    return(null);
                }

                //Get the child, see if it's a function.
                AlgoObject thisObj   = current.Value as AlgoObject;
                string     funcName  = context.functionCall_particle().IDENTIFIER().GetText();
                AlgoValue  childFunc = thisObj.ObjectScopes.GetVariable(funcName);
                if (childFunc == null || (childFunc.Type != AlgoValueType.Function && childFunc.Type != AlgoValueType.EmulatedFunction))
                {
                    Error.Fatal(context, "No child function exists with name '" + funcName + "'.");
                    return(null);
                }

                //Set the particle result as the function value, call the function call particle.
                Particles.SetParticleInput(childFunc);
                var result = VisitFunctionCall_particle(context.functionCall_particle());
                if (result == null)
                {
                    Particles.ResetParticleInput(); //Returned no result.
                }
                else
                {
                    //A result came back, set input for the next particle.
                    Particles.SetParticleInput((AlgoValue)result);
                }

                return(null);
            }
            else
            {
                //Unrecognized!
                Error.Internal("Unrecognized particle type to parse, implementation either unfinished or incorrect.");
                return(null);
            }
        }
Esempio n. 8
0
        /// <summary>
        /// Evaluates a single function call particle, and returns the result as a value (NOT using particle manager).
        /// </summary>
        public override object VisitFunctionCall_particle([NotNull] algoParser.FunctionCall_particleContext context)
        {
            //Set up an old scope.
            AlgoScopeCollection oldScope = null;

            //Get the previous particle output.
            var current = Particles.GetParticleResult();

            //Right length of parameters?
            var paramCtx       = context.literal_params();
            int givenNumParams = 0;

            if (paramCtx != null)
            {
                givenNumParams = paramCtx.expr().Length;
            }

            else if (current.Type == AlgoValueType.EmulatedFunction)
            {
                var func     = ((AlgoPluginFunction)current.Value);
                int paramNum = func.ParameterCount;
                if (givenNumParams != paramNum)
                {
                    Error.Fatal(context, "Invalid number of parameters for function '" + func.Name + "' (Expected " + func.ParameterCount + ", got " + givenNumParams + ").");
                    return(null);
                }
            }
            else if (current.Type == AlgoValueType.Function)
            {
                var func     = ((AlgoFunction)current.Value);
                int paramNum = func.Parameters.Count;
                if (givenNumParams != paramNum)
                {
                    Error.Fatal(context, "Invalid number of parameters for function '" + func.Name + "' (Expected " + func.Parameters.Count + ", got " + givenNumParams + ").");
                    return(null);
                }
            }

            //Evaluate all the parameters, in the paramScope if necessary.
            if (Particles.funcArgumentScopes != null)
            {
                oldScope = Scopes;
                Scopes   = Particles.funcArgumentScopes;
            }

            List <AlgoValue> params_ = new List <AlgoValue>();

            if (paramCtx != null)
            {
                foreach (var paramToEval in paramCtx.expr())
                {
                    params_.Add((AlgoValue)VisitExpr(paramToEval));
                }
            }

            //Switch back scopes.
            if (Particles.funcArgumentScopes != null)
            {
                Scopes = oldScope;
            }

            //Depending on the type of function, execute.
            if (current.Type == AlgoValueType.Function)
            {
                //STANDARD FUNCTION
                var func = (AlgoFunction)current.Value;

                //Create a new scope, add the parameters to it.
                Scopes.AddScope();
                for (int i = 0; i < params_.Count; i++)
                {
                    Scopes.AddVariable(func.Parameters[i], params_[i], context);
                }

                //Running the function's body.
                foreach (var statement in func.Body)
                {
                    AlgoValue returned = (AlgoValue)VisitStatement(statement);
                    if (returned != null)
                    {
                        //Normal function, remove scope and return.
                        Scopes.RemoveScope();

                        return(returned);
                    }
                }

                //Remove the scope.
                Scopes.RemoveScope();

                //Return nothing, no result.
                return(null);
            }
            else if (current.Type == AlgoValueType.EmulatedFunction)
            {
                //EMULATED FUNCTION
                var func = (AlgoPluginFunction)current.Value;

                //Attempt to evaluate, and return result.
                AlgoValue returned = null;
                try
                {
                    returned = func.Function(context, params_.ToArray());
                }
                catch (Exception e)
                {
                    Error.Fatal(context, "External function returned an error, " + e.Message);
                    return(null);
                }

                return(returned);
            }
            else
            {
                //Unsupported uncaught function type.
                Error.Internal("Unsupported uncaught function type detected (" + current.Type.ToString() + "), cannot execute.");
                return(null);
            }
        }