Пример #1
0
        // ****************************************************************
        // *** Test Functions
        // ****************************************************************

        // Returns true if the script executes successfully and returns expectedValue.
        // If expectedValue is null, then the return value is ignored and simply returns
        // true if there are no other errors.
        public bool RunTest(string script, object expectedValue, bool verbose = false)
        {
            if (verbose)
            {
                Log("-> " + script);
            }

            List <ParseErrorInst> errors = new List <ParseErrorInst>();
            IExpr expr = _Parse(_GetScriptNameFromScript(script), script, ref errors, verbose, false);

            if (errors.Count > 0)
            {
                if (!verbose)
                {
                    Log("-> " + script);
                }
                if (verbose)
                {
                    if (null == expr)
                    {
                        LogError("Parse failed.");
                    }
                    else
                    {
                        LogError("Parse = " + expr.MyToString(""));
                    }
                }
                return(false);
            }

            object actualValue = null;

            if (null != expr)
            {
                ScriptResult result;
                try {
                    result = _EvaluateExpression(expr, false);
                } catch (Exception e) {
                    if (!verbose)
                    {
                        Log("-> " + script);
                    }
                    LogError(script + "\n Unhandled exception evaluating script: " + e.ToString());
                    LogError("Parse = " + expr.MyToString(""));
                    return(false);
                }

                if (!result.success)
                {
                    LogError("Parse = " + expr.MyToString(""));
                    return(false);
                }

                actualValue = result.value;
            }

            if (expectedValue is int)
            {
                expectedValue = Convert.ToDouble(expectedValue);
            }

            if (actualValue == null)
            {
                if (expectedValue == null)
                {
                    return(true);
                }

                if (!verbose)
                {
                    Log("-> " + script);
                }
                LogError("Parse = " + (null == expr ? "null" : expr.MyToString("")));
                LogError("Test result is null.");
                return(false);
            }
            else if (actualValue is Exception)
            {
                if (!verbose)
                {
                    Log("-> " + script);
                }
                LogError("Parse = " + expr.MyToString(""));
                LogError("Test return exception: " + actualValue.ToString());
                return(false);
            }

            if (expectedValue == null)
            {
                return(true);
            }

            if (expectedValue is double)
            {
                if (!(actualValue is double))
                {
                    if (!verbose)
                    {
                        Log("-> " + script);
                    }
                    LogError("Parse = " + expr.MyToString(""));
                    LogError("Test result type (" + actualValue.GetType() + ") is not the expected double.");
                    return(false);
                }
                else if ((double)expectedValue != (double)actualValue)
                {
                    if (!verbose)
                    {
                        Log("-> " + script);
                    }
                    LogError("Parse = " + expr.MyToString(""));
                    LogError("Test result number (" + (double)actualValue + ") doesn't match expected result (" + (double)expectedValue + ").");
                    return(false);
                }
            }
            else if (expectedValue is string)
            {
                if ((string)expectedValue != (string)actualValue)
                {
                    if (!verbose)
                    {
                        Log("-> " + script);
                    }
                    LogError("Parse = " + expr.MyToString(""));
                    LogError("Test result string (" + (string)actualValue + ") doesn't match expected result (" + (string)expectedValue + ").");
                    return(false);
                }
            }
            else if (expectedValue is bool)
            {
                if ((bool)expectedValue != (bool)actualValue)
                {
                    if (!verbose)
                    {
                        Log("-> " + script);
                    }
                    LogError("Parse = " + expr.MyToString(""));
                    LogError("Test result bool (" + (bool)actualValue + ") doesn't match expected result (" + (bool)expectedValue + ").");
                    return(false);
                }
            }
            else
            {
                if (!verbose)
                {
                    Log("-> " + script);
                }
                LogError("Parse = " + expr.MyToString(""));
                LogError("Test result returned unrecognized value type (" + expectedValue.GetType().ToString() + ")");
                return(false);
            }

            return(true);
        }
Пример #2
0
        private IExpr _Parse(string scriptName, string s, ref List <ParseErrorInst> errors, bool verbose = false, bool createTempScope = true, bool hardTerminal = false)
        {
            errors.Clear();
            // Save this for LogCompileErrors.
            _parseErrors = errors;

            Buffer  buffer  = new SimpleBuffer(s);
            Scanner scanner = new Scanner(buffer);
            Parser  parser  = new Parser(scanner);

            parser.context    = defaultContext;
            parser.scriptName = scriptName;
            parser.Parse();

            if (parser.errors.count > 0)
            {
                if (logCompileErrors)
                {
                    for (int ii = 0; ii < parser.errors.errors.Count; ++ii)
                    {
                        LogError(parser.errors.errors[ii].ToString());
                    }
                }

                errors.AddRange(parser.errors.errors);
                _parseErrors = null;
                return(null);
            }

            IExpr expr = parser._headExpr;

            if (null == expr)
            {
                // This can happen if, for example, you try to parse ";".
                // Upon reflection I don't think this should be an error. Maybe someone is
                // compiling a commented out file.
                //LogCompileError(ParseErrorType.NullExpression, "Script parses to no expression.");
                //_parseErrors = null;
                return(null);
            }

            defaultContext.BeginCompile();

            bool error = false;

            if (createTempScope)
            {
                if (!defaultContext.stack.PushTerminalScope("<Parse>", defaultContext, hardTerminal))
                {
                    LogCompileError(ParseErrorType.StackOverflow, "_Parse: stack overflow");
                    error = true;
                }
            }

            // This is the first pass through the tree. It is where class expressions can add themselves to the type library.
            // Because it happens earlier than TypeCheck, it allows for code higher in a file than the class declaration to
            // use the class.
            // Note that it is a VERY incomplete pass because the only Expr that calls this function on it's child Exprs is Expr_List.
            // This is because class declarations can ONLY by at the top level, or within Expr_Lists at the top level.
            // For example, there's no need for Expr_If to call RegisterType on it's true/false blocks because those (currently)
            // can never contain Expr_Class'es.
            if (!error)
            {
                expr.RegisterTypes(defaultContext, ref error);
            }

            // This is the second pass through the tree. It does virtually all the work.
            if (!error)
            {
                expr.TypeCheck(defaultContext, ref error);
            }

            if (verbose && !error)
            {
                Log(expr.MyToString(""));
            }

            // Restore state always. Parsing should never permanently affect the stack.
            defaultContext.FinishCompile(error);

            if (error)
            {
                _parseErrors = null;
                return(null);
            }

            _parseErrors = null;
            return(expr);
        }