/// <summary>
        /// The method that represents the 'exit' function in the language.
        /// Exits from the current function, returning any value passed to the function.
        /// </summary>
        /// <param name="interpreter">The interpreter that the method is being called from.</param>
        /// <param name="args">The arguments being passed to the function as a TArgumentList.</param>
        /// <returns>The argument passed to the function. If no arguments were passed, it returns TNil.</returns>
        public static TType Exit(Interpreter interpreter, TArgumentList args)
        {
            // Get the argument passed (if any) to return
            TType returnValue = TNil.Instance;
            if (args.Count > 0) returnValue = args[0];

            // Pops from the function stack or kill the interpreter if the stack level is already at it's lowest
            // When this method returns, the calling method should check the stack level and exit accordingly
            if (interpreter.Stack.Level <= 1) interpreter.Kill();
            else interpreter.Stack.Pop();

            return returnValue;
        }
Пример #2
0
        /// <summary>
        /// Appends a TType to this TArgumentList. If a TArgumentList is passed, then the values contained in that
        /// TArgumentList are appended to this TArgumentList. If the values to be appended are TVariables, then the
        /// value of the TVariable will be appended instead of the TVariable itself (although if TVariable A
        /// containing TVariable B is passed, then TVariable B will be appended, as opposed to TVariable B's value).
        /// </summary>
        /// <param name="argument">The TType to append.</param>
        public void Add(TType argument)
        {
            TArgumentList argList = argument as TArgumentList;

            if (argList == null)
            {
                TVariable variable = argument as TVariable;
                if (variable == null)
                {
                    arguments.Add(argument);
                }
                else
                {
                    arguments.Add(variable.Value);
                }
            }
            else
            {
                for (int i = 0; i < argList.Count; ++i)
                {
                    arguments.Add(argList[i]);
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Calls the TFunction with the specified arguments.
        /// </summary>
        /// <param name="interpreter">The interpreter that the method is being called from.</param>
        /// <param name="value">
        /// The argument to pass to the function. When passing multiple arguments, use a TArgumentList.
        /// </param>
        /// <returns></returns>
        public TType Call(Interpreter interpreter, TType value)
        {
            // If value is already a TArgumentList, then simply copy the reference, otherwise create a new
            // TArgumentList and add the value to it. This TArgument list is to be passed to the function.
            TArgumentList argList = value as TArgumentList;

            if (argList == null)
            {
                argList = new TArgumentList();
                argList.Add(value);
            }

            // If the function takes a fixed number of arguments...
            if (ArgNames != null)
            {
                // Occupy the argument list with the default arguments. If there is no default argument in a place
                // where an argument should have been given, return a TException.
                if (argList.Count < ArgNames.Length)
                {
                    for (int i = argList.Count; i < DefaultArgs.Length; ++i)
                    {
                        if (DefaultArgs[i] == null)
                        {
                            break;
                        }
                        else
                        {
                            argList.Add(DefaultArgs[i]);
                        }
                    }
                }

                if (argList.Count != ArgNames.Length)
                {
                    return(new TException(interpreter, "Incorrect number of arguments for function '" + Name + "'",
                                          argList.Count.ToString() + " out of " + ArgNames.Length.ToString() + " given"));
                }
            }

            interpreter.Stack.Push();
            // Keep a track of the new stack level so that if a function calls 'exit()', which pops from the stack,
            // this will be able to be detected and the function call can be terminated properly
            int stackLevel = interpreter.Stack.Level;

            // Put the arguments on the current stack 'frame'
            if (ArgNames == null)
            {
                for (int i = 0; i < argList.Count; ++i)
                {
                    interpreter.Stack.AddVariable(new TVariable("arg" + i.ToString(), argList[i]));
                }
            }
            else
            {
                for (int i = 0; i < argList.Count; ++i)
                {
                    interpreter.Stack.AddVariable(new TVariable(ArgNames[i], argList[i]));
                }
            }

            TType returnValue = null;
            bool  dontPop     = false; // Set to true if the stack is popped during the call, i.e. if 'exit()' is called

            // Call the function
            if (HardCodedFunction != null)
            {
                returnValue = HardCodedFunction.Invoke(interpreter, argList);
            }
            else if (Block != null)
            {
                bool breakUsed;
                returnValue = Block.Execute(interpreter, out dontPop, out breakUsed);
            }
            else if (CustomFunction != "")
            {
                returnValue = interpreter.Interpret(CustomFunction, true);
                if (interpreter.Stack.Level < stackLevel)
                {
                    dontPop = true;
                }
            }

            // If returnValue is a TVariable, then return the value of the TVariable (e.g. we want to return 5, as
            // opposed to the variable X which contains 5)
            TVariable variable = returnValue as TVariable;

            if (variable != null)
            {
                returnValue = variable.Value;
            }

            if (!dontPop)
            {
                interpreter.Stack.Pop();
            }

            return(returnValue ?? TNil.Instance);
        }
        /// <summary>
        /// Parses the commas in the group, converting a comma separated list into a TArgumentList, and replacing the
        /// list in the group with it.
        /// </summary>
        /// <param name="group">The group to parse.</param>
        /// <returns>A TException on failure, otherwise null.</returns>
        TException ParseCommasOfGroup(Group group)
        {
            int index;
            while ((index = group.IndexOf(",")) >= 0)
            {
                if ((index - 1 < 0) || (index + 1 >= group.Count))
                    return new TException(this, "Invalid expression term ','");

                TType a = TType.Parse(this, group[index - 1]);
                if (a is TException) return a as TException;
                TType b = TType.Parse(this, group[index + 1]);
                if (b is TException) return b as TException;

                TArgumentList argList = a as TArgumentList;
                if (argList == null)
                {
                    argList = new TArgumentList();
                    argList.Add(a);
                    argList.Add(b);
                }
                else argList.Add(b);

                group[index - 1] = argList;
                group.RemoveRange(index, 2);
            }

            return null;
        }
 /// <summary>
 /// The method that represents the 'load' function in the language.
 /// Loads a script file with the specified file name (given by a TString) and runs it.
 /// </summary>
 /// <param name="interpreter">The interpreter that the method is being called from.</param>
 /// <param name="args">The arguments being passed to the function as a TArgumentList.</param>
 /// <returns>TNil</returns>
 public static TType Load(Interpreter interpreter, TArgumentList args)
 {
     TString fileName = args[0] as TString;
     if (fileName == null) return new TException(interpreter, "Name of file to load must be given as a string");
     interpreter.LoadFile(fileName.Value);
     return TNil.Instance;
 }
 /// <summary>
 /// The method that represents the 'read_string' function in the language.
 /// Reads in a string returns it as a TString.
 /// </summary>
 /// <param name="interpreter">The interpreter that the method is being called from.</param>
 /// <param name="args">The arguments being passed to the function as a TArgumentList.</param>
 /// <returns>An TString representing the string that was entered.</returns>
 public static TType ReadString(Interpreter interpreter, TArgumentList args)
 {
     return new TString(System.Console.ReadLine());
 }
 /// <summary>
 /// The method that represents the 'read' function in the language.
 /// Reads in a string and converts it into the most suitable TType.
 /// If the string cannot be converted, it just returns the string as a TString.
 /// </summary>
 /// <param name="interpreter">The interpreter that the method is being called from.</param>
 /// <param name="args">The arguments being passed to the function as a TArgumentList.</param>
 /// <returns>An TType of the type that the entered string represents best.</returns>
 public static TType Read(Interpreter interpreter, TArgumentList args)
 {
     // Read in a string and convert it to a suitable TType with TType.Parse.
     string str = System.Console.ReadLine();
     TType value = TType.Parse(interpreter, str);
     if (value is TException) value = new TString(str); // If the string can't be parsed, return it as a TString
     return value;
 }
        /// <summary>
        /// The method that represents the 'random' function in the language.
        /// Generates a random TInteger between 0 and the given value - 1.
        /// </summary>
        /// <param name="interpreter">The interpreter that the method is being called from.</param>
        /// <param name="args">The arguments being passed to the function as a TArgumentList.</param>
        /// <returns>An TInteger with a value between 0 and the given value - 1</returns>
        public static TType Random(Interpreter interpreter, TArgumentList args)
        {
            // Check if the argument passed is a number, and return a new TInteger from the random value generated
            TNumber maximum = args[0] as TNumber;
            if (maximum == null) return new TException(interpreter,
                "Arguments of type '" + args[0].TypeName + "' cannot be used by random function");

            return new TInteger(randomNumberGenerator.Next((int)maximum.TIntegerValue));
        }
        /// <summary>
        /// The method that represents the 'print' function in the language.
        /// Takes any number of values and writes their string values.
        /// </summary>
        /// <param name="interpreter">The interpreter that the method is being called from.</param>
        /// <param name="args">The arguments being passed to the function as a TArgumentList.</param>
        /// <returns>TNil</returns>
        public static TType Print(Interpreter interpreter, TArgumentList args)
        {
            // Loop through arguments, append their string values to a StringBuilder, and output the StringBuilder
            StringBuilder str = new StringBuilder();
            for (int i = 0; i < args.Count; ++i)
            {
                TString arg = args[i] as TString;
                if (arg == null) str.Append(args[i].ToCSString());
                else str.Append(arg.Value);
            }
            System.Console.WriteLine(str);

            return TNil.Instance;
        }
        /// <summary>
        /// Calls the TFunction with the specified arguments.
        /// </summary>
        /// <param name="interpreter">The interpreter that the method is being called from.</param>
        /// <param name="value">
        /// The argument to pass to the function. When passing multiple arguments, use a TArgumentList.
        /// </param>
        /// <returns></returns>
        public TType Call(Interpreter interpreter, TType value)
        {
            // If value is already a TArgumentList, then simply copy the reference, otherwise create a new
            // TArgumentList and add the value to it. This TArgument list is to be passed to the function.
            TArgumentList argList = value as TArgumentList;
            if (argList == null)
            {
                argList = new TArgumentList();
                argList.Add(value);
            }

            // If the function takes a fixed number of arguments...
            if (ArgNames != null)
            {
                // Occupy the argument list with the default arguments. If there is no default argument in a place
                // where an argument should have been given, return a TException.
                if (argList.Count < ArgNames.Length)
                {
                    for (int i = argList.Count; i < DefaultArgs.Length; ++i)
                    {
                        if (DefaultArgs[i] == null) break;
                        else argList.Add(DefaultArgs[i]);
                    }
                }

                if (argList.Count != ArgNames.Length)
                {
                    return new TException(interpreter, "Incorrect number of arguments for function '" + Name + "'",
                        argList.Count.ToString() + " out of " + ArgNames.Length.ToString() + " given");
                }
            }

            interpreter.Stack.Push();
            // Keep a track of the new stack level so that if a function calls 'exit()', which pops from the stack,
            // this will be able to be detected and the function call can be terminated properly
            int stackLevel = interpreter.Stack.Level;

            // Put the arguments on the current stack 'frame'
            if (ArgNames == null)
            {
                for (int i = 0; i < argList.Count; ++i)
                    interpreter.Stack.AddVariable(new TVariable("arg" + i.ToString(), argList[i]));
            }
            else
            {
                for (int i = 0; i < argList.Count; ++i)
                    interpreter.Stack.AddVariable(new TVariable(ArgNames[i], argList[i]));
            }

            TType returnValue = null;
            bool dontPop = false; // Set to true if the stack is popped during the call, i.e. if 'exit()' is called

            // Call the function
            if (HardCodedFunction != null) returnValue = HardCodedFunction.Invoke(interpreter, argList);
            else if (Block != null)
            {
                bool breakUsed;
                returnValue = Block.Execute(interpreter, out dontPop, out breakUsed);
            }
            else if (CustomFunction != "")
            {
                returnValue = interpreter.Interpret(CustomFunction, true);
                if (interpreter.Stack.Level < stackLevel) dontPop = true;
            }

            // If returnValue is a TVariable, then return the value of the TVariable (e.g. we want to return 5, as
            // opposed to the variable X which contains 5)
            TVariable variable = returnValue as TVariable;
            if (variable != null) returnValue = variable.Value;

            if (!dontPop) interpreter.Stack.Pop();

            return returnValue ?? TNil.Instance;
        }