public Task <dynamic> Execute()
        {
            lock (this)
            {
                if (currentState != ScriptUnitState.Ready)
                {
                    Reset();
                }

                if (currentState != ScriptUnitState.Ready)
                {
                    throw new InvalidScriptUnitStateException();
                }

                return(Task.Run <dynamic>(() =>
                {
                    try
                    {
                        lastLine = -1;
                        lastError = null;
                        currentState = ScriptUnitState.Running;
                        PublishEvent(new ScriptUnitStateEvent(this, currentState));

                        if (isDebugEnabled)
                        {
                            engine.SetTrace(traceDelegate); //set again trace at beginning
                        }
                        foreach (var g in globals)
                        {
                            builtinModule.SetVariable(g.Key, g.Value);
                        }

                        var result = compiled.Execute(scope);

                        currentState = ScriptUnitState.Done;
                        PublishEvent(new ScriptUnitStateEvent(this, currentState));

                        return result;
                    }
                    catch (PythonScriptUnitAbortException ex)
                    {
                        //script was aborted through the abort exception
                        currentState = ScriptUnitState.Aborted;
                        lastError = null;

                        throw ex;
                    }
                    catch (Exception ex)
                    {
                        currentState = ScriptUnitState.Error;
                        lastError = ex;
                        PublishEvent(new ScriptUnitStateEvent(this, currentState, ex));

                        throw ex;
                    }
                }));
            }
        }
        public PythonScriptUnit(PythonScript sourceScript, bool enableDebug = true, ScriptScope scriptScope = null)
        {
            this.name   = sourceScript.Name;
            this.script = sourceScript;

            Dictionary <string, object> options = new Dictionary <string, object>();

            isDebugEnabled   = enableDebug;
            options["Debug"] = enableDebug;
            engine           = Python.CreateEngine(options);
            //setup trace delegate
            traceDelegate = new IronPython.Runtime.Exceptions.TracebackDelegate(TraceCallback);
            if (enableDebug)
            {
                engine.SetTrace(traceDelegate);
            }

            if (scriptScope == null)
            {
                scope = engine.CreateScope();
            }
            else
            {
                scope = scriptScope;
            }

            builtinModule = engine.GetBuiltinModule();
            builtinModule.SetVariable("WaitAll", new Action <Task[]>((tasks) => Task.WaitAll(tasks)));
            builtinModule.SetVariable("TaskSleep", new Func <double, Task>((secs) => TaskSleep(secs)));
            builtinModule.SetVariable("StartLambda", new Func <Func <dynamic>, Task>((action) => Task.Run(action)));
            builtinModule.SetVariable("AllowBreak", new Action(() => AllowBreak()));
            builtinModule.SetVariable("Break", new Action(() => Break()));
            builtinModule.SetVariable("WaitBreak", new Action(() => { })); //empty method so the break will happen there

            source = engine.CreateScriptSourceFromString(script.Content, SourceCodeKind.File);

            try
            {
                compiled = source.Compile();

                currentState = ScriptUnitState.Ready;
                PublishEvent(new ScriptUnitStateEvent(this, currentState));
            }
            catch (SyntaxErrorException ex)
            {
                currentState = ScriptUnitState.Error;
                PublishEvent(new ScriptUnitStateEvent(this, currentState));
                throw ex;
            }
        }
 public void Reset()
 {
     lock (this)
     {
         if (IsBusy)
         {
             throw new InvalidScriptUnitStateException();
         }
         if (compiled != null && script != null)
         {
             currentState = ScriptUnitState.Ready;
         }
         else
         {
             currentState = ScriptUnitState.Idle;
         }
         breakEvent.Reset();
         requestBreakEvent.Reset();
         PublishEvent(new ScriptUnitStateEvent(this, currentState));
     }
 }
        protected IronPython.Runtime.Exceptions.TracebackDelegate TraceCallback(IronPython.Runtime.Exceptions.TraceBackFrame frame, string eventName, object payload)
        {
            bool abort = false;

            abort = abortEvent.WaitOne(0); //test abort signal

            int currentFrameLine = (int)frame.f_lineno;

            if (currentFrameLine != lastLine)
            {
                lastLine = currentFrameLine;
                PublishEvent(new ScriptUnitProgressEvent(this, source != null ? source.MapLine(currentFrameLine) : currentFrameLine));
            }


            if (!abort)
            {
                bool breaking = breakEvent.WaitOne(0); //test if a break was requested
                if (!breaking)
                {
                    int currentLine = source != null?source.MapLine(currentFrameLine) : currentFrameLine;

                    lock (breakpoints)
                    {
                        breaking |= breakpoints.Contains(currentLine);
                    }
                }

                if (breaking)
                {
                    currentState = ScriptUnitState.Breaking;
                    PublishEvent(new ScriptUnitStateEvent(this, currentState));

                    //break!
                    //wait for resume event (or abort as we could want to abort while debugging)
                    int eventIndex = AutoResetEvent.WaitAny(new WaitHandle[] { resumeEvent, abortEvent });


                    if (eventIndex == 1)
                    {
                        abort = true;
                    }
                    else if (eventIndex == 0)
                    {
                        breaking     = false;
                        currentState = ScriptUnitState.Running;

                        PublishEvent(new ScriptUnitStateEvent(this, currentState));
                    }
                }
            }

            if (abort)
            {
                breakEvent.Reset();
                requestBreakEvent.Reset();
                currentState = ScriptUnitState.Aborting;
                PublishEvent(new ScriptUnitStateEvent(this, currentState));
                throw new PythonScriptUnitAbortException();
            }

            return(traceDelegate);
        }
 public ScriptUnitStateEvent(IScriptUnit unit, ScriptUnitState state, Exception error = null)
 {
     this.unit  = unit;
     this.state = state;
     this.error = error;
 }