mirror of https://github.com/wagesj45/cs-mic.git
338 lines
12 KiB
C#
338 lines
12 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.IO;
|
|
using System.Threading;
|
|
using csmic.Scripting;
|
|
using System.Runtime.Remoting.Messaging;
|
|
|
|
namespace csmic
|
|
{
|
|
/// <summary>
|
|
/// A builder object that executes macro scripts.
|
|
/// </summary>
|
|
public class MacroBuilder
|
|
{
|
|
#region Members
|
|
|
|
/// <summary>
|
|
/// The input inputInterpreter.
|
|
/// </summary>
|
|
private InputInterpreter interpreter;
|
|
/// <summary> The script to run as a macro. </summary>
|
|
private string script;
|
|
/// <summary>
|
|
/// The output as a list of strings.
|
|
/// </summary>
|
|
private List<string> output;
|
|
/// <summary>
|
|
/// The time for execution.
|
|
/// </summary>
|
|
private TimeSpan executionTime;
|
|
/// <summary>
|
|
/// The root macro operation.
|
|
/// </summary>
|
|
private MacroOperation rootOperation;
|
|
|
|
#endregion
|
|
|
|
#region Constructor
|
|
|
|
/// <summary>
|
|
/// Creates a new builder object that executes a given macro script.
|
|
/// </summary>
|
|
/// <param name="script">A list of strings representing the macro.</param>
|
|
/// <param name="inputInterpreter">The InputInterpreter to be used.</param>
|
|
public MacroBuilder(string script, InputInterpreter inputInterpreter)
|
|
{
|
|
this.output = new List<string>();
|
|
this.executionTime = new TimeSpan();
|
|
|
|
this.script = script;
|
|
this.interpreter = inputInterpreter;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a new builder object that executes a given macro script.
|
|
/// </summary>
|
|
/// <param name="script">A list of strings representing the macro.</param>
|
|
/// <param name="inputInterpreter">The InputInterpreter to be used.</param>
|
|
internal MacroBuilder(MacroOperation script, InputInterpreter inputInterpreter)
|
|
{
|
|
this.output = new List<string>();
|
|
this.executionTime = new TimeSpan();
|
|
DateTime timeStart = DateTime.Now;
|
|
|
|
this.interpreter = inputInterpreter;
|
|
|
|
this.rootOperation = script;
|
|
|
|
ExecuteOperation(this.rootOperation);
|
|
|
|
DateTime timeEnd = DateTime.Now;
|
|
this.executionTime = timeEnd - timeStart;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Properties
|
|
|
|
/// <summary>
|
|
/// Gets a list of strings representing the output.
|
|
/// </summary>
|
|
public List<string> Output
|
|
{
|
|
get
|
|
{
|
|
return this.output;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the execution time of the last script computation.
|
|
/// </summary>
|
|
public TimeSpan LastExecutionTime
|
|
{
|
|
get
|
|
{
|
|
return this.executionTime;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the decimal value last computed by the macrobuilder.
|
|
/// </summary>
|
|
public string FinalOutput
|
|
{
|
|
get
|
|
{
|
|
return this.interpreter.Output;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Public Methods
|
|
|
|
/// <summary> Runs this macro. </summary>
|
|
public void Run()
|
|
{
|
|
DateTime timeStart = DateTime.Now;
|
|
|
|
ASCIIEncoding encoder = new ASCIIEncoding();
|
|
Parser p = new Parser(new Scanner(new MemoryStream(encoder.GetBytes(this.script))));
|
|
p.Parse();
|
|
|
|
this.rootOperation = p.Root;
|
|
|
|
ExecuteOperation(p.Root);
|
|
|
|
DateTime timeEnd = DateTime.Now;
|
|
this.executionTime = timeEnd - timeStart;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Private Methods
|
|
|
|
private void ExecuteOperation(MacroOperation operation)
|
|
{
|
|
switch (operation.OperationType)
|
|
{
|
|
case OperationType.If:
|
|
if (operation.Input.Count == 1)
|
|
{
|
|
this.interpreter.Interpret(operation.Input[0]);
|
|
if (this.interpreter.Decimal == 1)
|
|
{
|
|
foreach (MacroOperation op in operation.Children)
|
|
{
|
|
ExecuteOperation(op);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case OperationType.Else:
|
|
foreach (MacroOperation op in operation.Children)
|
|
{
|
|
ExecuteOperation(op);
|
|
}
|
|
break;
|
|
case OperationType.IfElse:
|
|
if (operation.Children.Count == 2 && operation.Children[0].Input.Count == 1)
|
|
{
|
|
MacroOperation ifOp = operation.Children[0];
|
|
MacroOperation elseOp = operation.Children[1];
|
|
this.interpreter.Interpret(ifOp.Input[0]);
|
|
if (this.interpreter.Decimal == 1)
|
|
{
|
|
foreach (MacroOperation op in ifOp.Children)
|
|
{
|
|
ExecuteOperation(op);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
foreach (MacroOperation op in elseOp.Children)
|
|
{
|
|
ExecuteOperation(op);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case OperationType.While:
|
|
if (operation.Input.Count == 1)
|
|
{
|
|
this.interpreter.Interpret(operation.Input[0]);
|
|
while (this.interpreter.Decimal == 1)
|
|
{
|
|
foreach (MacroOperation op in operation.Children)
|
|
{
|
|
ExecuteOperation(op);
|
|
}
|
|
this.interpreter.Interpret(operation.Input[0]);
|
|
}
|
|
}
|
|
break;
|
|
case OperationType.For:
|
|
if (operation.Input.Count == 3)
|
|
{
|
|
this.interpreter.Interpret(operation.Input[0]);
|
|
this.interpreter.Interpret(operation.Input[1]);
|
|
int loopCount = this.interpreter.Int;
|
|
while (this.interpreter.Int == 1)
|
|
{
|
|
foreach (MacroOperation op in operation.Children)
|
|
{
|
|
ExecuteOperation(op);
|
|
}
|
|
this.interpreter.Interpret(operation.Input[2]);
|
|
this.interpreter.Interpret(operation.Input[1]);
|
|
}
|
|
}
|
|
break;
|
|
case OperationType.FunctionDeclaration:
|
|
if (operation.Input.Count > 1)
|
|
{
|
|
string name = operation.Input[0];
|
|
operation.Input.RemoveAt(0);
|
|
StringBuilder builder = new StringBuilder();
|
|
operation.OperationType = OperationType.Unknown;
|
|
InterpretedFunction function = new InterpretedFunction(name, operation, operation.Input.ToArray());
|
|
if (this.interpreter.InterpretedFunctions.Contains(function))
|
|
{
|
|
this.interpreter.InterpretedFunctions[this.interpreter.InterpretedFunctions.IndexOf(function)] = function;
|
|
}
|
|
else
|
|
{
|
|
this.interpreter.InterpretedFunctions.Add(function);
|
|
}
|
|
}
|
|
break;
|
|
case OperationType.Echo:
|
|
if (operation.Children.Count == 1)
|
|
{
|
|
MacroOperation op = operation.Children[0];
|
|
if (op.OperationType == OperationType.Statement)
|
|
{
|
|
this.interpreter.Interpret(op.Input[0]);
|
|
this.output.Add(this.interpreter.Output);
|
|
}
|
|
}
|
|
break;
|
|
case OperationType.Say:
|
|
if (operation.Input.Count == 1)
|
|
{
|
|
this.output.Add(operation.Input[0]);
|
|
}
|
|
break;
|
|
case OperationType.Display:
|
|
StringBuilder sb = new StringBuilder();
|
|
foreach (MacroOperation op in operation.Children)
|
|
{
|
|
if (op.OperationType == OperationType.Statement)
|
|
{
|
|
if (op.Input.Count == 1)
|
|
{
|
|
this.interpreter.Interpret(op.Input[0]);
|
|
sb.Append(this.interpreter.Output);
|
|
}
|
|
}
|
|
else if (op.OperationType == OperationType.String)
|
|
{
|
|
if (op.Input.Count == 1)
|
|
{
|
|
sb.Append(op.Input[0]);
|
|
}
|
|
}
|
|
}
|
|
this.output.Add(sb.ToString());
|
|
break;
|
|
case OperationType.Statement:
|
|
if (operation.Input.Count == 1)
|
|
{
|
|
this.interpreter.Interpret(operation.Input[0]);
|
|
}
|
|
break;
|
|
case OperationType.String:
|
|
//Should not reach this state.
|
|
break;
|
|
case OperationType.Unknown:
|
|
if (operation.Children.Count > 0)
|
|
{
|
|
foreach (MacroOperation op in operation.Children)
|
|
{
|
|
ExecuteOperation(op);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
//CRAP.
|
|
break;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Asynchronous
|
|
|
|
/// <summary> Executes the asynchronous operation. </summary>
|
|
/// <param name="input"> The input. </param>
|
|
/// <param name="callback"> The callback. </param>
|
|
public void RunAsync(string input, Action<MacroBuilder> callback)
|
|
{
|
|
MacroAsyncDelegate del = new MacroAsyncDelegate(RunAsyncThreadingWork);
|
|
del.BeginInvoke(input, (result) =>
|
|
{
|
|
AsyncResult returned = result as AsyncResult;
|
|
if (returned != null)
|
|
{
|
|
MacroAsyncDelegate end = returned.AsyncDelegate as MacroAsyncDelegate;
|
|
if (end != null)
|
|
{
|
|
MacroBuilder returnValue = end.EndInvoke(result);
|
|
callback(returnValue);
|
|
}
|
|
}
|
|
}, null);
|
|
}
|
|
|
|
/// <summary> Executes the asynchronous threading work operation. </summary>
|
|
/// <param name="input"> The input. </param>
|
|
/// <returns> . </returns>
|
|
private MacroBuilder RunAsyncThreadingWork(string input)
|
|
{
|
|
Run();
|
|
return this;
|
|
}
|
|
|
|
/// <summary> Macro asynchronous delegate. </summary>
|
|
/// <param name="input"> The input. </param>
|
|
/// <returns> . </returns>
|
|
private delegate MacroBuilder MacroAsyncDelegate(string input);
|
|
|
|
#endregion
|
|
}
|
|
}
|