Ejemplo n.º 1
0
        protected void runProgram(string program, Dictionary <string, object> variablesIn, int expectedIterations, out FrameContext context)
        {
            var inputStream = new AntlrInputStream(program);
            var lexer       = new CloacaLexer(inputStream);
            CommonTokenStream commonTokenStream = new CommonTokenStream(lexer);
            var errorListener = new ParseErrorListener();
            var parser        = new CloacaParser(commonTokenStream);

            parser.AddErrorListener(errorListener);

            var antlrVisitorContext = parser.file_input();

            Assert.That(errorListener.Errors.Count, Is.Zero, "There were parse errors:\n" + errorListener.Report());

            var visitor = new CloacaBytecodeVisitor(variablesIn);

            visitor.Visit(antlrVisitorContext);

            // We'll do a disassembly here but won't assert against it. We just want to make sure it doesn't crash.
            CodeObject compiledProgram = visitor.RootProgram.Build();

            Dis.dis(compiledProgram);

            // TODO: This dependency association is kind of gross. It's almost circular and is broken by assigning
            // the interpreter reference to the schedular after its initial constructor.
            var scheduler   = new Scheduler();
            var interpreter = new Interpreter(scheduler);

            // Create native resource manager which will handle builtins that provide access to 'native' resources such as files.
            var nativeResourceManager = new NativeResourceManager();

            nativeResourceManager.RegisterProvider <INativeFileProvider>(new DefaultFileProvider());
            nativeResourceManager.RegisterBuiltins(interpreter);

            interpreter.DumpState = true;
            scheduler.SetInterpreter(interpreter);

            var receipt = scheduler.Schedule(compiledProgram);

            context = receipt.Frame;
            foreach (string varName in variablesIn.Keys)
            {
                context.SetVariable(varName, variablesIn[varName]);
            }

            // Waiting on the task makes sure we get punched in the face by any exceptions it throws.
            // But they'll come rolling in as AggregateExceptions so we'll have to unpack them.
            var scheduler_task = scheduler.RunUntilDone();

            scheduler_task.Wait();
            Assert.That(receipt.Completed);
            if (receipt.EscapedExceptionInfo != null)
            {
                receipt.EscapedExceptionInfo.Throw();
            }

            Assert.That(scheduler.TickCount, Is.EqualTo(expectedIterations));
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Evaluates the given input and will trigger WhenReplCommandDone when it has finished. The data passed to that
        /// event will include the result of evaluating the input--whether it was successful or unsuccessful.
        ///
        /// Look at InterpretAsync if you'd like to receive the text output directly and block until evaluation has
        /// completely finished.
        /// </summary>
        /// <param name="input">The code to interpret. Note that REPL code should have a trailing newline.</param>
        public void Interpret(string input)
        {
            CaughtError = false;

            var inputStream = new AntlrInputStream(input);
            var lexer       = new CloacaLexer(inputStream);
            CommonTokenStream commonTokenStream = new CommonTokenStream(lexer);

            errorListener.Clear();
            var parser = new CloacaParser(commonTokenStream);

            parser.AddErrorListener(errorListener);

            var antlrVisitorContext = parser.single_input();

            if (errorListener.Errors.Count > 0)
            {
                CaughtError = true;
                StringBuilder errorBuilder = new StringBuilder("There were errors trying to compile the script. We cannot run it:" + Environment.NewLine);
                foreach (var error in errorListener.Errors)
                {
                    errorBuilder.Append(error);
                    errorBuilder.Append(Environment.NewLine);
                }
                WhenReplCommandDone(this, errorBuilder.ToString());
                return;
            }
            else if (errorListener.ExpectedMoreText)
            {
                WhenReplCommandDone(this, "...");
                return;
            }

            if (ContextVariables == null)
            {
                ContextVariables = new Dictionary <string, object>();
            }

            var visitor = new CloacaBytecodeVisitor(ContextVariables);

            visitor.Visit(antlrVisitorContext);

            CodeObject compiledProgram = visitor.RootProgram.Build();

            var scheduledTaskRecord = Scheduler.Schedule(compiledProgram);

            activeContext = scheduledTaskRecord.Frame;
            scheduledTaskRecord.WhenTaskCompleted        += WhenReplTaskCompleted;
            scheduledTaskRecord.WhenTaskExceptionEscaped += WhenReplTaskExceptionEscaped;
            foreach (string varName in ContextVariables.Keys)
            {
                activeContext.SetVariable(varName, ContextVariables[varName]);
            }

            Run();
        }
Ejemplo n.º 3
0
        protected void runProgram(string program, Dictionary <string, object> variablesIn, List <ISpecFinder> moduleSpecFinders, int expectedIterations, out FrameContext context)
        {
            CodeObject compiledProgram = null;

            try
            {
                compiledProgram = ByteCodeCompiler.Compile(program, variablesIn);
            }
            catch (CloacaParseException parseFailed)
            {
                Assert.Fail(parseFailed.Message);
            }

            Dis.dis(compiledProgram);

            // TODO: This dependency association is kind of gross. It's almost circular and is broken by assigning
            // the interpreter reference to the schedular after its initial constructor.
            var scheduler   = new Scheduler();
            var interpreter = new Interpreter(scheduler);

            interpreter.DumpState = true;
            foreach (var finder in moduleSpecFinders)
            {
                interpreter.AddModuleFinder(finder);
            }
            scheduler.SetInterpreter(interpreter);

            var receipt = scheduler.Schedule(compiledProgram);

            context = receipt.Frame;
            foreach (string varName in variablesIn.Keys)
            {
                context.SetVariable(varName, variablesIn[varName]);
            }

            // Waiting on the task makes sure we get punched in the face by any exceptions it throws.
            // But they'll come rolling in as AggregateExceptions so we'll have to unpack them.
            var scheduler_task = scheduler.RunUntilDone();

            scheduler_task.Wait();
            Assert.That(receipt.Completed);
            if (receipt.EscapedExceptionInfo != null)
            {
                receipt.EscapedExceptionInfo.Throw();
            }

            Assert.That(scheduler.TickCount, Is.EqualTo(expectedIterations));
        }
Ejemplo n.º 4
0
        protected async Task <FrameContext> runProgram(string program, Dictionary <string, object> variablesIn, List <ISpecFinder> moduleSpecFinders, int expectedIterations, bool checkExceptions = true)
        {
            // TODO: This dependency association is kind of gross. It's almost circular and is broken by assigning
            // the interpreter reference to the schedular after its initial constructor.
            var scheduler   = new Scheduler();
            var interpreter = new Interpreter(scheduler);

            interpreter.DumpState = true;
            foreach (var finder in moduleSpecFinders)
            {
                interpreter.AddModuleFinder(finder);
            }
            scheduler.SetInterpreter(interpreter);
            scheduler.OnTaskScheduled += whenTaskScheduled;

            escapedExceptions = new List <ExceptionDispatchInfo>();
            CodeObject        compiledProgram = null;
            Task <CodeObject> compiledTask    = null;

            try
            {
                // This is awaitable now but relies on the scheduler. We'll tick the scheduler
                // awhile until this resolves.
                compiledTask = ByteCodeCompiler.Compile(program, variablesIn, scheduler);
            }
            catch (CloacaParseException parseFailed)
            {
                Assert.Fail(parseFailed.Message);
            }

            for (int tries = 1; tries < 1000 && !compiledTask.IsCompleted && escapedExceptions.Count == 0; ++tries)
            {
                await scheduler.Tick();
            }

            if (!compiledTask.IsCompleted)
            {
                Assert.Fail("Compilation did not finish with interpreter after 1,000 scheduler ticks");
            }
            else if (escapedExceptions.Count > 0)
            {
                escapedExceptions[0].Throw();
            }
            compiledProgram = await compiledTask;
            Dis.dis(compiledProgram);

            receipt = scheduler.Schedule(compiledProgram);
            FrameContext context = receipt.Frame;

            foreach (string varName in variablesIn.Keys)
            {
                context.SetVariable(varName, variablesIn[varName]);
            }

            // Waiting on the task makes sure we get punched in the face by any exceptions it throws.
            // But they'll come rolling in as AggregateExceptions so we'll have to unpack them.
            var scheduler_task = scheduler.RunUntilDone();

            scheduler_task.Wait();
            Assert.That(receipt.Completed);

            if (checkExceptions)
            {
                AssertNoExceptions();
            }

            Assert.That(scheduler.TickCount, Is.EqualTo(expectedIterations));
            return(context);
        }