diff --git a/new/AutoItInterpreter/AssemblyInfo.cs b/new/AutoItInterpreter/AssemblyInfo.cs
index bddc8f55..b7679ac7 100644
--- a/new/AutoItInterpreter/AssemblyInfo.cs
+++ b/new/AutoItInterpreter/AssemblyInfo.cs
@@ -1,15 +1,15 @@
//////////////////////////////////////////////////////////////////////////
-// Auto-generated 2020-07-26 17:04:48.009 //
+// Auto-generated 2020-07-27 01:57:30.012 //
// ANY CHANGES TO THIS DOCUMENT WILL BE LOST UPON RE-GENERATION //
//////////////////////////////////////////////////////////////////////////
using System.Reflection;
using System;
-[assembly: AssemblyVersion("0.6.1256.7328")]
-[assembly: AssemblyFileVersion("0.6.1256.7328")]
-[assembly: AssemblyInformationalVersion("cdfd24e8c9341f9fc41540bef89d37e540605174")]
+[assembly: AssemblyVersion("0.6.1257.7329")]
+[assembly: AssemblyFileVersion("0.6.1257.7329")]
+[assembly: AssemblyInformationalVersion("f3c8f7753e53011c5fac5224b49c3724c68f2759")]
[assembly: AssemblyCompany("Unknown6656")]
[assembly: AssemblyCopyright("Copyright © 2018 - 2020, Unknown6656")]
[assembly: AssemblyProduct("AutoIt3 Interpreter by Unknown6656")]
@@ -35,11 +35,11 @@ public static class __module__
///
/// The interpreter's current version.
///
- public static Version? InterpreterVersion { get; } = Version.Parse("0.6.1256.7328");
+ public static Version? InterpreterVersion { get; } = Version.Parse("0.6.1257.7329");
///
/// The Git hash associated with the current build.
///
- public const string GitHash = "cdfd24e8c9341f9fc41540bef89d37e540605174";
+ public const string GitHash = "f3c8f7753e53011c5fac5224b49c3724c68f2759";
///
/// The URL of this project's Git(Hub) repository.
///
diff --git a/new/AutoItInterpreter/MainProgram.cs b/new/AutoItInterpreter/MainProgram.cs
index a5d7b072..6819b100 100644
--- a/new/AutoItInterpreter/MainProgram.cs
+++ b/new/AutoItInterpreter/MainProgram.cs
@@ -135,7 +135,7 @@ public static int Start(string[] argv)
Console.CancelKeyPress += (_, e) =>
{
- Interpreter[] instances = Interpreter.Instances;
+ Interpreter[] instances = Interpreter.ActiveInstances;
e.Cancel = instances.Length > 0;
diff --git a/new/AutoItInterpreter/Runtime/AU3Thread.cs b/new/AutoItInterpreter/Runtime/AU3Thread.cs
index 1a67c6bd..d09a1145 100644
--- a/new/AutoItInterpreter/Runtime/AU3Thread.cs
+++ b/new/AutoItInterpreter/Runtime/AU3Thread.cs
@@ -1,24 +1,14 @@
-using System.Text.RegularExpressions;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
+using System.Collections.Concurrent;
using System.Linq;
using System;
-using Microsoft.FSharp.Collections;
-using Microsoft.FSharp.Core;
-
-using Piglet.Parser.Configuration.Generic;
-
-using Unknown6656.AutoIt3.Extensibility.Plugins.Au3Framework;
-using Unknown6656.AutoIt3.Extensibility.Plugins.Internals;
-using Unknown6656.AutoIt3.ExpressionParser;
-using Unknown6656.AutoIt3.Extensibility;
using Unknown6656.Common;
-using static Unknown6656.AutoIt3.ExpressionParser.AST;
-
namespace Unknown6656.AutoIt3.Runtime
{
+ ///
+ /// Represents an AutoIt execution thread. The thread consists of multiple call frames which in term represent function invocations.
+ ///
public sealed class AU3Thread
: IDisposable
, IEquatable
@@ -29,24 +19,51 @@ public sealed class AU3Thread
private int? _override_exitcode = null;
+ ///
+ /// The on which the current thread has been created.
+ ///
public Interpreter Interpreter { get; }
+ ///
+ /// Indicates whether the current thread is actively running.
+ ///
public bool IsRunning => _running;
+ ///
+ /// The top-most , representing the top-most function invocation of this thread.
+ ///
public CallFrame? CurrentFrame => _callstack.TryPeek(out CallFrame? lp) ? lp : null;
+ ///
+ /// The of the currently executed statement or line.
+ ///
public SourceLocation? CurrentLocation => CallStack.OfType().FirstOrDefault()?.CurrentLocation ?? SourceLocation.Unknown;
+ ///
+ /// The currently executed function.
+ ///
public ScriptFunction? CurrentFunction => CurrentFrame?.CurrentFunction;
public VariableScope CurrentVariableResolver => CurrentFrame?.VariableResolver ?? Interpreter.VariableResolver;
+ ///
+ /// The current call stack (function invocation stack) of this thread. The first item of the collection represents the top-most thread and holds the same value as .
+ ///
public CallFrame[] CallStack => CurrentFrame.Propagate(frame => (frame?.CallerFrame, frame is { })).ToArrayWhere(frame => frame is { })!;
+ ///
+ /// Indicates whether the current thread has been disposed.
+ ///
public bool IsDisposed { get; private set; }
+ ///
+ /// Indicates whether the current thread is the of the associated .
+ ///
public bool IsMainThread => ReferenceEquals(this, Interpreter.MainThread);
+ ///
+ /// The unique ID of this thread.
+ ///
public int ThreadID { get; }
@@ -59,6 +76,14 @@ internal AU3Thread(Interpreter interpreter)
MainProgram.PrintfDebugMessage("debug.au3thread.created", this);
}
+ ///
+ /// Starts the current thread by invoking the given with the given arguments.
+ ///
+ /// This function is blocking and returns only after the given function has been invoked.
+ ///
+ /// The function to be invoked.
+ /// The arguments to be passed to the function.
+ /// The functions return value or execution error.
public Union Start(ScriptFunction function, Variant[] args) =>
Interpreter.Telemetry.Measure>(TelemetryCategory.ThreadRun, delegate
{
@@ -77,6 +102,16 @@ public Union Start(ScriptFunction function, Variant[]
return result;
});
+ ///
+ /// [UNSAFE!]
+ /// Invokes the given with the given arguments. A call to this function is considered to be unsafe, as any non-concurrent call may result into undefined behavior.
+ /// Use instead.
+ ///
+ /// This function is blocking and returns only after the given function has been invoked.
+ ///
+ /// The function to be invoked.
+ /// The arguments to be passed to the function.
+ /// The functions return value or execution error.
public Union Call(ScriptFunction function, Variant[] args)
{
if (IsDisposed)
@@ -100,6 +135,9 @@ public Union Call(ScriptFunction function, Variant[]
return result;
}
+ ///
+ /// Stops the current thread execution. This will dispose the current thread.
+ ///
public void Stop()
{
_running = false;
@@ -107,6 +145,10 @@ public void Stop()
Dispose();
}
+ ///
+ /// Stops the current thread execution with the given exit code. This will dispose the current thread.
+ ///
+ /// Exit code, with which the current thread will return.
public void Stop(int exitcode)
{
Stop();
@@ -126,14 +168,19 @@ public void Stop(int exitcode)
return CurrentLocation;
}
+ ///
public override string ToString() => $"0x{ThreadID:x4}{(IsMainThread ? " (main)" : "")} @ {CurrentLocation}";
+ ///
public override int GetHashCode() => HashCode.Combine(Interpreter, ThreadID);
+ ///
public override bool Equals(object? obj) => obj is AU3Thread thread && Equals(thread);
+ ///
public bool Equals(AU3Thread? other) => Interpreter == other?.Interpreter && ThreadID == other?.ThreadID;
+ ///
public void Dispose()
{
_running = false;
@@ -151,1562 +198,4 @@ public void Dispose()
MainProgram.PrintfDebugMessage("debug.au3thread.disposed", this);
}
}
-
-#pragma warning disable CA1063
- // TODO : covariant return for 'CurrentFunction'
- public abstract class CallFrame
- : IDisposable
- {
- public AU3Thread CurrentThread { get; }
-
- public virtual ScriptFunction CurrentFunction { get; }
-
- public VariableScope VariableResolver { get; }
-
- public Variant[] PassedArguments { get; }
-
- public CallFrame? CallerFrame { get; }
-
- public Variant ReturnValue { protected set; get; } = Variant.Zero;
-
- public virtual SourceLocation CurrentLocation => CurrentThread.CurrentLocation ?? CurrentFunction.Location;
-
- public Interpreter Interpreter => CurrentThread.Interpreter;
-
-
- internal CallFrame(AU3Thread thread, CallFrame? caller, ScriptFunction function, Variant[] args)
- {
- CurrentThread = thread;
- CallerFrame = caller;
- CurrentFunction = function;
- PassedArguments = args;
-
- // TODO : the following line is wrong - it should be interpreter as parent, not the previous frame
- VariableResolver = function.IsMainFunction ? thread.CurrentVariableResolver : thread.CurrentVariableResolver.CreateChildScope(this);
- }
-
- public void Dispose() => VariableResolver.Dispose();
-
- protected abstract Union InternalExec(Variant[] args);
-
- internal Union Execute(Variant[] args)
- {
- Union result = Variant.Zero;
- ScannedScript script = CurrentFunction.Script;
-
- SetError(0, 0);
-
- Interpreter.Telemetry.Measure(TelemetryCategory.OnAutoItStart, delegate
- {
- if (CurrentFunction.IsMainFunction && script.LoadScript(this) is InterpreterError load_error)
- result = load_error;
- });
-
- (int min_argc, int max_argc) = CurrentFunction.ParameterCount;
-
- if (args.Length < min_argc)
- return InterpreterError.WellKnown(CurrentThread.CurrentLocation, "error.not_enough_args", CurrentFunction.Name, min_argc, args.Length);
- else if (args.Length > max_argc)
- return InterpreterError.WellKnown(CurrentThread.CurrentLocation, "error.too_many_args", CurrentFunction.Name, max_argc, args.Length);
- else if (result.Is())
- if (CurrentThread.IsRunning)
- {
- MainProgram.PrintfDebugMessage("debug.au3thread.executing", CurrentFunction);
-
- result = Interpreter.Telemetry.Measure(TelemetryCategory.ScriptExecution, () => InternalExec(args));
- }
-
- Interpreter.Telemetry.Measure(TelemetryCategory.OnAutoItExit, delegate
- {
- if (CurrentFunction.IsMainFunction && result.Is() && script.UnLoadScript(this) is InterpreterError unload_error)
- result = unload_error;
- });
-
- if (result.Is(out Variant @return))
- ReturnValue = @return;
-
- return result;
- }
-
- public Union Call(ScriptFunction function, Variant[] args) => CurrentThread.Call(function, args);
-
- public Variant SetError(int error, Variant? extended = null, in Variant @return = default)
- {
- Interpreter.ErrorCode = error;
-
- return SetExtended(extended, in @return);
- }
-
- public Variant SetExtended(Variant? extended, in Variant @return = default)
- {
- Interpreter.ExtendedValue = extended ?? Variant.Null;
-
- return @return;
- }
-
- public void Print(Variant value) => Interpreter.Print(this, value);
-
- public void Print(object? value) => Interpreter.Print(this, value);
-
- public override string ToString() => $"[0x{CurrentThread.ThreadID:x4}]";
-
- internal void IssueWarning(string key, params object?[] args) => MainProgram.PrintWarning(CurrentLocation, Interpreter.CurrentUILanguage[key, args]);
- }
-#pragma warning restore CA1063
-
- public sealed class NativeCallFrame
- : CallFrame
- {
- internal NativeCallFrame(AU3Thread thread, CallFrame? caller, NativeFunction function, Variant[] args)
- : base(thread, caller, function, args)
- {
- }
-
- protected override Union InternalExec(Variant[] args)
- {
- FunctionReturnValue result = Interpreter.Telemetry.Measure(TelemetryCategory.NativeScriptExecution, () => ((NativeFunction)CurrentFunction).Execute(this, args));
- Variant? extended = null;
- int error = 0;
-
- if (result.IsFatal(out InterpreterError? fatal))
- return fatal;
- else if (result.IsSuccess(out Variant variant, out extended) || result.IsError(out variant, out error, out extended))
- return SetError(error, extended, in variant);
- else
- throw new InvalidOperationException("Return value could not be processed");
- }
-
- public override string ToString() => $"{base.ToString()} native call frame";
- }
-
- public sealed class AU3CallFrame
- : CallFrame
- {
- private const RegexOptions _REGEX_OPTIONS = RegexOptions.IgnoreCase | RegexOptions.Compiled;
- private static readonly Regex REGEX_INTERNAL_LABEL = new Regex(@"^§\w+$", _REGEX_OPTIONS);
- private static readonly Regex REGEX_VARIABLE = new Regex(@"\$([^\W\d]|[^\W\d]\w*)\b", _REGEX_OPTIONS);
- private static readonly Regex REGEX_GOTO = new Regex(@"^goto\s+(?