diff --git a/ObjectAlgebraExecutionGraphs/Algebras/CSharpTranslatableGraphAlgebra.cs b/ObjectAlgebraExecutionGraphs/Algebras/CSharpTranslatableGraphAlgebra.cs index 4a1a6db..6de3b61 100644 --- a/ObjectAlgebraExecutionGraphs/Algebras/CSharpTranslatableGraphAlgebra.cs +++ b/ObjectAlgebraExecutionGraphs/Algebras/CSharpTranslatableGraphAlgebra.cs @@ -3,95 +3,26 @@ using ObjectAlgebraExecutionGraphs.Variants; using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; -using System.Reflection; using System.Text; namespace ObjectAlgebraExecutionGraphs.Algebras { - public class CSharpTranslatableGraphAlgebra : IExecutionGraphAlgebra, ICSharpTranslatableOutputDataPin>, ICSharpTranslatableInputExecPin, ICSharpTranslatableOutputExecPin, ICSharpTranslatableInputDataPin, ICSharpTranslatableOutputDataPin> + public class CSharpTranslatableGraphAlgebra : IDataGraphAlgebra, IExecutionGraphAlgebra { - public ICSharpTranslatableNode, ICSharpTranslatableOutputDataPin> CreateLiteralNode(Type type, object value) - => new LiteralNode(type, value); - - public ICSharpTranslatableNode, ICSharpTranslatableOutputDataPin> CreateConcatenateNode(ICSharpTranslatableOutputDataPin aFrom, ICSharpTranslatableOutputDataPin bFrom, ICSharpTranslatableInputExecPin execTo) - => new ConcatenateNode(aFrom, bFrom, execTo); - - public ICSharpTranslatableNode, ICSharpTranslatableOutputDataPin> CreateReverseStringNode(ICSharpTranslatableOutputDataPin aFrom) - => new ReverseStringNode(aFrom); + public ICSharpTranslatableNode CreateConcatenateNode() => new ConcatenateNode(); + public ICSharpTranslatableNode CreateLiteralNode(Type type, object value) => new LiteralNode(type, value); + public ICSharpTranslatableNode CreateReverseStringNode() => new ReverseStringNode(); public Type TypeFromString(string typeString) => Type.GetType(typeString); - private class InputExecPin : ICSharpTranslatableInputExecPin - { - public string Label { get; } = RandomGenerator.GetRandomLowerLetters(16); - } - - private class OutputExecPin : ICSharpTranslatableOutputExecPin - { - - } - - private class InputDataPin : ICSharpTranslatableInputDataPin - { - public string VariableName { get; } = RandomGenerator.GetRandomLowerLetters(16); - public Type Type { get; } - - private readonly ICSharpTranslatableOutputDataPin incomingPin; - - public InputDataPin(Type type, ICSharpTranslatableOutputDataPin incomingPin) - { - Type = type; - this.incomingPin = incomingPin; - } - - public IEnumerable TranslateCallPureFunction() - { - if (incomingPin?.IsPure == true) - { - return incomingPin.TranslateCallPureFunction(); - } - - return new string[0]; - } - } - - private class OutputDataPin : ICSharpTranslatableOutputDataPin - { - public string VariableName { get; } = RandomGenerator.GetRandomLowerLetters(16); - public bool IsPure => node.IsPure; - public Type Type { get; } - - private readonly ICSharpTranslatableNode, ICSharpTranslatableOutputDataPin> node; - - public OutputDataPin(ICSharpTranslatableNode, ICSharpTranslatableOutputDataPin> node, Type type) - { - this.node = node; - Type = type; - } - - public IEnumerable TranslateCallPureFunction() - { - if (!IsPure) - { - throw new Exception(); - } - - return node.TranslateCallPureFunction(); - } - } - - private abstract class BaseCSharpTranslatableNode : ICSharpTranslatableNode, ICSharpTranslatableOutputDataPin> + private abstract class BaseCSharpTranslatableNode : ICSharpTranslatableNode { - public IEnumerable InputExecPins => ixps; - public IEnumerable OutputExecPins => oxps; - public IEnumerable> InputDataPins => idps; - public IEnumerable> OutputDataPins => odps; - - protected readonly IList> idps = new List>(); - protected readonly IList> odps = new List>(); - protected readonly IList ixps = new List(); - protected readonly IList oxps = new List(); + public IImmutableList<(Type type, string variableName)> Inputs { get; private set; } = ImmutableList<(Type, string)>.Empty; + public IImmutableList<(Type type, string variableName)> Outputs { get; private set; } = ImmutableList<(Type, string)>.Empty; + public IImmutableList ExecInputs { get; private set; } = ImmutableList.Empty; + public int ExecOutputCount { get; private set; } public virtual bool IsPure { get; } public string PureFunctionName { get; } @@ -102,72 +33,41 @@ public BaseCSharpTranslatableNode() PureFunctionName = $"{GetType().Name}_{nodeCounter++}"; } - public virtual string TranslateVariables() - { - return ""; - } - - public virtual string TranslatePureFunctions() - { - return ""; - } + public virtual string TranslateVariables() => string.Concat(Inputs.Concat(Outputs).Select(x => $"{x.type} {x.variableName} = default({x.type});\n")); - public virtual string TranslateStates() - { - return ""; - } - - public IEnumerable TranslateCallPureFunction() - { - var pureCalls = idps.SelectMany(idp => idp.TranslateCallPureFunction()); + public virtual string TranslatePureFunctions() => ""; - if (IsPure) - { - pureCalls = pureCalls.Concat(new[] { $"{PureFunctionName}();" }); - } + public virtual string TranslateStates(IImmutableList outputExecLabels, string pureCalls) => ""; - return pureCalls.Distinct(); - } + protected void AddInput(Type type) => Inputs = Inputs.Add((type, RandomGenerator.GetRandomLowerLetters(8))); + protected void AddOutput(Type type) => Outputs = Outputs.Add((type, RandomGenerator.GetRandomLowerLetters(8))); + protected void AddExecInput() => ExecInputs = ExecInputs.Add(RandomGenerator.GetRandomLowerLetters(8)); + protected void AddExecOutput() => ExecOutputCount++; } private class ConcatenateNode : BaseCSharpTranslatableNode { - private readonly ICSharpTranslatableInputExecPin execTo; - - public ConcatenateNode(ICSharpTranslatableOutputDataPin aFrom, ICSharpTranslatableOutputDataPin bFrom, ICSharpTranslatableInputExecPin execTo) + public ConcatenateNode() { - ixps.Add(new InputExecPin()); - idps.Add(new InputDataPin(typeof(string), aFrom)); - idps.Add(new InputDataPin(typeof(string), bFrom)); - odps.Add(new OutputDataPin(this, typeof(string))); - oxps.Add(new OutputExecPin()); - - this.execTo = execTo; + AddInput(typeof(string)); + AddInput(typeof(string)); + AddOutput(typeof(string)); + AddExecInput(); + AddExecOutput(); } - public override string TranslateVariables() - { - return $"var {odps.Single().VariableName} = default(string);\n"; - } - - public override string TranslateStates() + public override string TranslateStates(IImmutableList outputExecLabels, string pureCalls) { StringBuilder builder = new StringBuilder(); - // Translate label - builder.Append($"{ixps[0].Label}:\n"); - - // Translate pure calls - builder.Append(string.Join("\n", TranslateCallPureFunction())); - builder.Append("\n"); + builder.Append($"{ExecInputs[0]}:\n"); + builder.Append(pureCalls); + builder.Append($"{Outputs.Single().variableName} = {Inputs[0].variableName} + \" \" + {Inputs[1].variableName};\n"); - // Translate actual logic and result assignment - builder.Append($"{odps.Single().VariableName} = {idps[0].VariableName} + \" \" + {idps[1].VariableName};\n"); - - // Translate goto next - if (execTo != null) + var outputLabel = outputExecLabels.Single(); + if (outputLabel != null) { - builder.Append($"goto {execTo.Label};\n"); + builder.Append($"goto {outputLabel};\n"); } else { @@ -187,26 +87,13 @@ private class LiteralNode : BaseCSharpTranslatableNode public LiteralNode(Type type, object value) { this.value = value; - odps.Add(new OutputDataPin(this, type)); + AddOutput(type); } public override string TranslateVariables() { - var odp = OutputDataPins.Single(); - - return $"const {odp.Type.FullName} {odp.VariableName} = {value};\n"; - } - - public override string TranslatePureFunctions() - { - StringBuilder builder = new StringBuilder(); - - builder.Append($"void {PureFunctionName}()\n"); - builder.Append("{\n"); - //builder.Append($"{OutputDataPins.Single().VariableName} = {value};\n"); - builder.Append("}\n"); - - return builder.ToString(); + var output = Outputs.Single(); + return $"const {output.type.FullName} {output.variableName} = {value};\n"; } } @@ -214,27 +101,15 @@ private class ReverseStringNode : BaseCSharpTranslatableNode { public override bool IsPure => true; - public ReverseStringNode(ICSharpTranslatableOutputDataPin aFrom) - { - idps.Add(new InputDataPin(typeof(string), aFrom)); - odps.Add(new OutputDataPin(this, typeof(string))); - } - - public override string TranslateVariables() + public ReverseStringNode() { - return $"var {OutputDataPins.Single().VariableName} = default(string);\n"; + AddInput(typeof(string)); + AddOutput(typeof(string)); } public override string TranslatePureFunctions() { - StringBuilder builder = new StringBuilder(); - - builder.Append($"void {PureFunctionName}()\n"); - builder.Append("{\n"); - builder.Append($"{OutputDataPins.Single().VariableName} = string.Concat({idps.Single().VariableName}.Reverse());\n"); - builder.Append("}\n"); - - return builder.ToString(); + return $"{Outputs.Single().variableName} = string.Concat({Inputs.Single().variableName}.Reverse());\n"; } } } diff --git a/ObjectAlgebraExecutionGraphs/Algebras/DotExecutionGraphAlgebra.cs b/ObjectAlgebraExecutionGraphs/Algebras/DotExecutionGraphAlgebra.cs index 1dc1f75..e0c69c2 100644 --- a/ObjectAlgebraExecutionGraphs/Algebras/DotExecutionGraphAlgebra.cs +++ b/ObjectAlgebraExecutionGraphs/Algebras/DotExecutionGraphAlgebra.cs @@ -1,173 +1,29 @@ -using ObjectAlgebraExecutionGraphs.Behaviors.DataGraph; -using ObjectAlgebraExecutionGraphs.Behaviors.DotGraph; -using ObjectAlgebraExecutionGraphs.Behaviors.ExecutionGraph; +using ObjectAlgebraExecutionGraphs.Behaviors.DotGraph; +using ObjectAlgebraExecutionGraphs.Utility; using ObjectAlgebraExecutionGraphs.Variants; using System.Collections.Generic; -using System.Text; +using System.Linq; namespace ObjectAlgebraExecutionGraphs.Algebras { - public class DotExecutionGraphAlgebra : IExecutionGraphAlgebra, IDotOutputDataPin>, IInputExecPin, IDotOutputExecPin, IInputDataPin, IDotOutputDataPin> + public class DotExecutionGraphAlgebra : IDataGraphAlgebra, IExecutionGraphAlgebra { - public IDotNode, IDotOutputDataPin> CreateLiteralNode(string type, object value) - => new LiteralNode(type, value); + private int nodeCounter; + private string MakeNodeName(string prefix) => $"{prefix}{nodeCounter++}"; - public IDotNode, IDotOutputDataPin> CreateConcatenateNode(IDotOutputDataPin aFrom, IDotOutputDataPin bFrom, IInputExecPin execTo) - => new ConcatenateNode(aFrom, bFrom, execTo); - - public IDotNode, IDotOutputDataPin> CreateReverseStringNode(IDotOutputDataPin aFrom) - => new ReverseStringNode(aFrom); + public IDotNode CreateConcatenateNode() => new DotNode(MakeNodeName("Concatenate")); + public IDotNode CreateLiteralNode(string type, object value) => new DotNode(MakeNodeName("Literal")); + public IDotNode CreateReverseStringNode() => new DotNode(MakeNodeName("ReverseString")); public string TypeFromString(string typeString) => typeString; - private class InputExecPin : IInputExecPin - { - } - - private class OutputExecPin : IDotOutputExecPin - { - private IDotNode, IDotOutputDataPin> node; - - public OutputExecPin(IDotNode, IDotOutputDataPin> node) - { - this.node = node; - } - - public string GenerateDotGraph(string toName) => node.GenerateDotGraph(toName); - } - - private class InputDataPin : IInputDataPin - { - public string Type { get; } - - public InputDataPin(string type) - { - Type = type; - } - } - - private class OutputDataPin : IDotOutputDataPin - { - private IDotNode, IDotOutputDataPin> node; - - public OutputDataPin(IDotNode, IDotOutputDataPin> node, string type) - { - this.node = node; - Type = Type; - } - - public string Type { get; } - - public string GenerateDotGraph(string toName) => node.GenerateDotGraph(toName); - } - - private abstract class BaseNode : IDotNode, IDotOutputDataPin> - { - public string DotName => $"{GetType().Name}_{nodeId}"; - - private static int nodeCounter = 0; - private readonly int nodeId = nodeCounter++; - - public string GenerateDotGraph(string toName) - { - StringBuilder builder = new StringBuilder(); - - if (toName != null) - { - builder.AppendLine($"{DotName} -> {toName};"); - } - - builder.Append(GenerateIncomingDotGraph()); - - return builder.ToString(); - } - - protected abstract string GenerateIncomingDotGraph(); - - public IEnumerable InputExecPins => ixps; - public IEnumerable OutputExecPins => oxps; - public IEnumerable> InputDataPins => idps; - public IEnumerable> OutputDataPins => odps; - - protected readonly IList> idps = new List>(); - protected readonly IList> odps = new List>(); - protected readonly IList ixps = new List(); - protected readonly IList oxps = new List(); - } - - private class LiteralNode : BaseNode + private class DotNode : IDotNode { - private object value; + public string DotName { get; } - public LiteralNode(string type, object value) + public DotNode(string name) { - this.value = value; - odps.Add(new OutputDataPin(this, type)); - } - - protected override string GenerateIncomingDotGraph() - { - return ""; - } - } - - private class ConcatenateNode : BaseNode - { - private readonly IDotOutputDataPin aFrom; - private readonly IDotOutputDataPin bFrom; - private readonly IInputExecPin execTo; - - public ConcatenateNode(IDotOutputDataPin aFrom, IDotOutputDataPin bFrom, IInputExecPin execTo) - { - ixps.Add(new InputExecPin()); - odps.Add(new OutputDataPin(this, typeof(string).AssemblyQualifiedName)); - oxps.Add(new OutputExecPin(this)); - - this.aFrom = aFrom; - this.bFrom = bFrom; - this.execTo = execTo; - } - - protected override string GenerateIncomingDotGraph() - { - StringBuilder builder = new StringBuilder(); - - if (aFrom != null) - { - builder.Append(aFrom.GenerateDotGraph(DotName)); - } - - if (bFrom != null && aFrom != bFrom) - { - builder.Append(bFrom.GenerateDotGraph(DotName)); - } - - return builder.ToString(); - } - } - - private class ReverseStringNode : BaseNode - { - private IDotOutputDataPin aFrom; - - public ReverseStringNode(IDotOutputDataPin aFrom) - { - this.aFrom = aFrom; - - idps.Add(new InputDataPin(typeof(string).AssemblyQualifiedName)); - odps.Add(new OutputDataPin(this, typeof(string).AssemblyQualifiedName)); - } - - protected override string GenerateIncomingDotGraph() - { - StringBuilder builder = new StringBuilder(); - - if (aFrom != null) - { - builder.Append(aFrom.GenerateDotGraph(DotName)); - } - - return builder.ToString(); + DotName = name; } } } diff --git a/ObjectAlgebraExecutionGraphs/Algebras/EvaluableGraphAlgebra.cs b/ObjectAlgebraExecutionGraphs/Algebras/EvaluableGraphAlgebra.cs index 1d8bcce..8d4a900 100644 --- a/ObjectAlgebraExecutionGraphs/Algebras/EvaluableGraphAlgebra.cs +++ b/ObjectAlgebraExecutionGraphs/Algebras/EvaluableGraphAlgebra.cs @@ -2,97 +2,44 @@ using ObjectAlgebraExecutionGraphs.Variants; using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; -using System.Reflection; namespace ObjectAlgebraExecutionGraphs.Algebras { - public class EvaluableGraphAlgebra : IDataGraphAlgebra, IEvaluableInputDataPin, IEvaluableOutputDataPin> + public class EvaluableGraphAlgebra : IDataGraphAlgebra { - public IEvaluableNode CreateLiteralNode(Type type, object value) - => new LiteralNode(type, value); + public IEvaluableNode CreateLiteralNode(Type type, object value) => new LiteralNode(type, value); - public IEvaluableNode CreateReverseStringNode(IEvaluableOutputDataPin aFrom) - => new ReverseStringNode(aFrom); + public IEvaluableNode CreateReverseStringNode() => new ReverseStringNode(); public Type TypeFromString(string typeString) => Type.GetType(typeString); - private class InputDataPin : IEvaluableInputDataPin + private class LiteralNode : IEvaluableNode { - public Type Type { get; } - - private readonly IEvaluableOutputDataPin incomingOdp; - - public InputDataPin(Type type, IEvaluableOutputDataPin incomingOdp) - { - this.incomingOdp = incomingOdp; - Type = type; - } - - public object Evaluate() - { - return incomingOdp.Evaluate(); - } - } - - private class OutputDataPin : IEvaluableOutputDataPin - { - public Type Type { get; } - - private readonly IEvaluableNode node; - - public OutputDataPin(Type type, IEvaluableNode node) - { - this.node = node; - Type = type; - } - - public object Evaluate() - { - return node.Evaluate()[this]; - } - } - - private abstract class BaseNode : IEvaluableNode - { - public IEnumerable InputDataPins => idps; - public IEnumerable OutputDataPins => odps; - - protected readonly IList idps = new List(); - protected readonly IList odps = new List(); - - public abstract IReadOnlyDictionary Evaluate(); - } - - private class LiteralNode : BaseNode - { - private readonly Type type; private readonly object value; public LiteralNode(Type type, object value) { - this.type = type; this.value = value; - odps.Add(new OutputDataPin(type, this)); } - public override IReadOnlyDictionary Evaluate() + public IImmutableList Evaluate(IImmutableList inputs) { - return new Dictionary { [odps.Single()] = value }; + if (inputs.Count != 0) + { + throw new Exception(); + } + + return ImmutableArray.Create(value); } } - private class ReverseStringNode : BaseNode + private class ReverseStringNode : IEvaluableNode { - public ReverseStringNode(IEvaluableOutputDataPin aFrom) - { - idps.Add(new InputDataPin(typeof(string), aFrom)); - odps.Add(new OutputDataPin(typeof(string), this)); - } - - public override IReadOnlyDictionary Evaluate() + public IImmutableList Evaluate(IImmutableList inputs) { - return new Dictionary() { [odps.Single()] = string.Concat(((string)idps.Single().Evaluate()).Reverse()) }; + return ImmutableArray.Create(string.Concat(inputs.Cast().Single().Reverse())); } } } diff --git a/ObjectAlgebraExecutionGraphs/Algebras/TupleDataAlgebra.cs b/ObjectAlgebraExecutionGraphs/Algebras/TupleDataAlgebra.cs new file mode 100644 index 0000000..8f06c21 --- /dev/null +++ b/ObjectAlgebraExecutionGraphs/Algebras/TupleDataAlgebra.cs @@ -0,0 +1,25 @@ +using ObjectAlgebraExecutionGraphs.Variants; + +namespace ObjectAlgebraExecutionGraphs.Algebras +{ + public class TupleDataAlgebra : IDataGraphAlgebra<(TType1, TType2), (TNode1, TNode2)> + { + private readonly IDataGraphAlgebra alg1; + private readonly IDataGraphAlgebra alg2; + + public TupleDataAlgebra(IDataGraphAlgebra algebra1, IDataGraphAlgebra algebra2) + { + alg1 = algebra1; + alg2 = algebra2; + } + + public (TNode1, TNode2) CreateLiteralNode((TType1, TType2) type, object value) + => (alg1.CreateLiteralNode(type.Item1, value), alg2.CreateLiteralNode(type.Item2, value)); + + public (TNode1, TNode2) CreateReverseStringNode() + => (alg1.CreateReverseStringNode(), alg2.CreateReverseStringNode()); + + public (TType1, TType2) TypeFromString(string typeString) + => (alg1.TypeFromString(typeString), alg2.TypeFromString(typeString)); + } +} diff --git a/ObjectAlgebraExecutionGraphs/Behaviors/CSharpTranslatableGraph/ICSharpTranslatableInputDataPin.cs b/ObjectAlgebraExecutionGraphs/Behaviors/CSharpTranslatableGraph/ICSharpTranslatableInputDataPin.cs deleted file mode 100644 index 8a3847d..0000000 --- a/ObjectAlgebraExecutionGraphs/Behaviors/CSharpTranslatableGraph/ICSharpTranslatableInputDataPin.cs +++ /dev/null @@ -1,15 +0,0 @@ -using ObjectAlgebraExecutionGraphs.Behaviors.DataGraph; -using System.Collections.Generic; - -namespace ObjectAlgebraExecutionGraphs.Behaviors.CSharpTranslatableGraph -{ - public interface ICSharpTranslatableInputDataPin : IInputDataPin - { - /// - /// Name of the pin's variable in code. - /// - string VariableName { get; } - - IEnumerable TranslateCallPureFunction(); - } -} diff --git a/ObjectAlgebraExecutionGraphs/Behaviors/CSharpTranslatableGraph/ICSharpTranslatableInputExecPin.cs b/ObjectAlgebraExecutionGraphs/Behaviors/CSharpTranslatableGraph/ICSharpTranslatableInputExecPin.cs deleted file mode 100644 index dabf39d..0000000 --- a/ObjectAlgebraExecutionGraphs/Behaviors/CSharpTranslatableGraph/ICSharpTranslatableInputExecPin.cs +++ /dev/null @@ -1,12 +0,0 @@ -using ObjectAlgebraExecutionGraphs.Behaviors.ExecutionGraph; - -namespace ObjectAlgebraExecutionGraphs.Behaviors.CSharpTranslatableGraph -{ - public interface ICSharpTranslatableInputExecPin : IInputExecPin - { - /// - /// Goto label of the input execution pin in code. - /// - string Label { get; } - } -} diff --git a/ObjectAlgebraExecutionGraphs/Behaviors/CSharpTranslatableGraph/ICSharpTranslatableNode.cs b/ObjectAlgebraExecutionGraphs/Behaviors/CSharpTranslatableGraph/ICSharpTranslatableNode.cs index 13cf9e4..0910dd1 100644 --- a/ObjectAlgebraExecutionGraphs/Behaviors/CSharpTranslatableGraph/ICSharpTranslatableNode.cs +++ b/ObjectAlgebraExecutionGraphs/Behaviors/CSharpTranslatableGraph/ICSharpTranslatableNode.cs @@ -1,17 +1,19 @@ -using ObjectAlgebraExecutionGraphs.Behaviors.ExecutionGraph; +using System; using System.Collections.Generic; +using System.Collections.Immutable; namespace ObjectAlgebraExecutionGraphs.Behaviors.CSharpTranslatableGraph { /// /// Node that is translatable to C#. /// - /// Input execution pin type - /// Output execution pin type - /// Input data pin type - /// Output data pin type - public interface ICSharpTranslatableNode : IExecutionNode + public interface ICSharpTranslatableNode { + public IImmutableList<(Type type, string variableName)> Inputs { get; } + public IImmutableList<(Type type, string variableName)> Outputs { get; } + public IImmutableList ExecInputs { get; } + public int ExecOutputCount { get; } + /// /// Translate all variables of this node to code. /// @@ -28,7 +30,7 @@ public interface ICSharpTranslatableNode : IExecutionNod /// Translate this node's stateful operations (ie. node with execution pins) into code. /// /// Code for the stateful operations of this node. - public string TranslateStates(); + public string TranslateStates(IImmutableList outputExecLabels, string pureCalls); /// /// Whether this node is pure (ie. has no execution pins of its own but is executed @@ -40,11 +42,5 @@ public interface ICSharpTranslatableNode : IExecutionNod /// Name of this node's local function if it is pure. /// public string PureFunctionName { get; } - - /// - /// Translates to code that calls this node's local function. - /// - /// Code for calling this node's local function. - public IEnumerable TranslateCallPureFunction(); } } diff --git a/ObjectAlgebraExecutionGraphs/Behaviors/CSharpTranslatableGraph/ICSharpTranslatableOutputDataPin.cs b/ObjectAlgebraExecutionGraphs/Behaviors/CSharpTranslatableGraph/ICSharpTranslatableOutputDataPin.cs deleted file mode 100644 index 1dacb1b..0000000 --- a/ObjectAlgebraExecutionGraphs/Behaviors/CSharpTranslatableGraph/ICSharpTranslatableOutputDataPin.cs +++ /dev/null @@ -1,24 +0,0 @@ -using ObjectAlgebraExecutionGraphs.Behaviors.DataGraph; -using System.Collections.Generic; - -namespace ObjectAlgebraExecutionGraphs.Behaviors.CSharpTranslatableGraph -{ - public interface ICSharpTranslatableOutputDataPin : IOutputDataPin - { - /// - /// Name for the variable of this pin in code. - /// - string VariableName { get; } - - /// - /// Whether the node this pin is on is pure. - /// - bool IsPure { get; } - - /// - /// Proxy for translating to code for calling this pin's node's call to its local function. - /// - /// Code for calling this pin's node's call to its local function - IEnumerable TranslateCallPureFunction(); - } -} diff --git a/ObjectAlgebraExecutionGraphs/Behaviors/CSharpTranslatableGraph/ICSharpTranslatableOutputExecPin.cs b/ObjectAlgebraExecutionGraphs/Behaviors/CSharpTranslatableGraph/ICSharpTranslatableOutputExecPin.cs deleted file mode 100644 index 7627a94..0000000 --- a/ObjectAlgebraExecutionGraphs/Behaviors/CSharpTranslatableGraph/ICSharpTranslatableOutputExecPin.cs +++ /dev/null @@ -1,9 +0,0 @@ -using ObjectAlgebraExecutionGraphs.Behaviors.ExecutionGraph; - -namespace ObjectAlgebraExecutionGraphs.Behaviors.CSharpTranslatableGraph -{ - public interface ICSharpTranslatableOutputExecPin : IOutputExecPin - { - - } -} diff --git a/ObjectAlgebraExecutionGraphs/Behaviors/DataGraph/IDataNode.cs b/ObjectAlgebraExecutionGraphs/Behaviors/DataGraph/IDataNode.cs deleted file mode 100644 index c5d797f..0000000 --- a/ObjectAlgebraExecutionGraphs/Behaviors/DataGraph/IDataNode.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Collections.Generic; - -namespace ObjectAlgebraExecutionGraphs.Behaviors.DataGraph -{ - /// - /// A graph node holding a collection of pins. - /// - /// Input data pin type - /// Output data pin type - public interface IDataNode - { - /// - /// Input data pins of this node that can receive data. - /// - public IEnumerable InputDataPins { get; } - - /// - /// Output data pins of this node that can pass on data. - /// - public IEnumerable OutputDataPins { get; } - } -} diff --git a/ObjectAlgebraExecutionGraphs/Behaviors/DataGraph/IInputDataPin.cs b/ObjectAlgebraExecutionGraphs/Behaviors/DataGraph/IInputDataPin.cs deleted file mode 100644 index bdf7db4..0000000 --- a/ObjectAlgebraExecutionGraphs/Behaviors/DataGraph/IInputDataPin.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace ObjectAlgebraExecutionGraphs.Behaviors.DataGraph -{ - public interface IInputDataPin - { - TType Type { get; } - } -} diff --git a/ObjectAlgebraExecutionGraphs/Behaviors/DataGraph/IOutputDataPin.cs b/ObjectAlgebraExecutionGraphs/Behaviors/DataGraph/IOutputDataPin.cs deleted file mode 100644 index edcca5a..0000000 --- a/ObjectAlgebraExecutionGraphs/Behaviors/DataGraph/IOutputDataPin.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace ObjectAlgebraExecutionGraphs.Behaviors.DataGraph -{ - public interface IOutputDataPin - { - TType Type { get; } - } -} diff --git a/ObjectAlgebraExecutionGraphs/Behaviors/DotGraph/IDotNode.cs b/ObjectAlgebraExecutionGraphs/Behaviors/DotGraph/IDotNode.cs index 152ce4c..67e9db9 100644 --- a/ObjectAlgebraExecutionGraphs/Behaviors/DotGraph/IDotNode.cs +++ b/ObjectAlgebraExecutionGraphs/Behaviors/DotGraph/IDotNode.cs @@ -1,22 +1,7 @@ -using ObjectAlgebraExecutionGraphs.Behaviors.ExecutionGraph; - -namespace ObjectAlgebraExecutionGraphs.Behaviors.DotGraph +namespace ObjectAlgebraExecutionGraphs.Behaviors.DotGraph { - /// - /// A graph node holding a collection of pins. Can create dot graphs for visualization. - /// - /// Input execution pin type - /// Output execution pin type - /// Input data pin type - /// Output data pin type - public interface IDotNode : IExecutionNode + public interface IDotNode { - /// - /// Generates a DOT graph for this node and its incoming nodes recursively. - /// - /// DOT graph for this node and its incoming nodes. - public string GenerateDotGraph(string toName); - /// /// Name of the node in the DOT graph. /// diff --git a/ObjectAlgebraExecutionGraphs/Behaviors/DotGraph/IDotOutputDataPin.cs b/ObjectAlgebraExecutionGraphs/Behaviors/DotGraph/IDotOutputDataPin.cs deleted file mode 100644 index 7c87da9..0000000 --- a/ObjectAlgebraExecutionGraphs/Behaviors/DotGraph/IDotOutputDataPin.cs +++ /dev/null @@ -1,13 +0,0 @@ -using ObjectAlgebraExecutionGraphs.Behaviors.DataGraph; - -namespace ObjectAlgebraExecutionGraphs.Behaviors.DotGraph -{ - public interface IDotOutputDataPin : IOutputDataPin - { - /// - /// Generates a DOT graph for this pin's node and its incoming nodes recursively. - /// - /// DOT graph for this pin's node and its incoming nodes. - public string GenerateDotGraph(string toName); - } -} diff --git a/ObjectAlgebraExecutionGraphs/Behaviors/DotGraph/IDotOutputExecPin.cs b/ObjectAlgebraExecutionGraphs/Behaviors/DotGraph/IDotOutputExecPin.cs deleted file mode 100644 index 9bf7de9..0000000 --- a/ObjectAlgebraExecutionGraphs/Behaviors/DotGraph/IDotOutputExecPin.cs +++ /dev/null @@ -1,13 +0,0 @@ -using ObjectAlgebraExecutionGraphs.Behaviors.ExecutionGraph; - -namespace ObjectAlgebraExecutionGraphs.Behaviors.DotGraph -{ - public interface IDotOutputExecPin : IOutputExecPin - { - /// - /// Generates a DOT graph for this pin's node and its incoming nodes recursively. - /// - /// DOT graph for this pin's node and its incoming nodes. - public string GenerateDotGraph(string toName); - } -} diff --git a/ObjectAlgebraExecutionGraphs/Behaviors/EvaluableGraph/IEvaluableInputDataPin.cs b/ObjectAlgebraExecutionGraphs/Behaviors/EvaluableGraph/IEvaluableInputDataPin.cs deleted file mode 100644 index 996e764..0000000 --- a/ObjectAlgebraExecutionGraphs/Behaviors/EvaluableGraph/IEvaluableInputDataPin.cs +++ /dev/null @@ -1,10 +0,0 @@ -using ObjectAlgebraExecutionGraphs.Behaviors.DataGraph; -using System; - -namespace ObjectAlgebraExecutionGraphs.Behaviors.EvaluableGraph -{ - public interface IEvaluableInputDataPin : IInputDataPin - { - object Evaluate(); - } -} diff --git a/ObjectAlgebraExecutionGraphs/Behaviors/EvaluableGraph/IEvaluableNode.cs b/ObjectAlgebraExecutionGraphs/Behaviors/EvaluableGraph/IEvaluableNode.cs index fe328d5..cdaf98f 100644 --- a/ObjectAlgebraExecutionGraphs/Behaviors/EvaluableGraph/IEvaluableNode.cs +++ b/ObjectAlgebraExecutionGraphs/Behaviors/EvaluableGraph/IEvaluableNode.cs @@ -1,15 +1,10 @@ -using ObjectAlgebraExecutionGraphs.Behaviors.DataGraph; -using System.Collections.Generic; +using System.Collections.Generic; +using System.Collections.Immutable; namespace ObjectAlgebraExecutionGraphs.Behaviors.EvaluableGraph { - /// - /// An evaluable graph node holding a collection of pins. - /// - /// Input data pin type - /// Output data pin type - public interface IEvaluableNode : IDataNode + public interface IEvaluableNode { - public IReadOnlyDictionary Evaluate(); + public IImmutableList Evaluate(IImmutableList inputs); } } diff --git a/ObjectAlgebraExecutionGraphs/Behaviors/EvaluableGraph/IEvaluableOutputDataPin.cs b/ObjectAlgebraExecutionGraphs/Behaviors/EvaluableGraph/IEvaluableOutputDataPin.cs deleted file mode 100644 index 1742443..0000000 --- a/ObjectAlgebraExecutionGraphs/Behaviors/EvaluableGraph/IEvaluableOutputDataPin.cs +++ /dev/null @@ -1,10 +0,0 @@ -using ObjectAlgebraExecutionGraphs.Behaviors.DataGraph; -using System; - -namespace ObjectAlgebraExecutionGraphs.Behaviors.EvaluableGraph -{ - public interface IEvaluableOutputDataPin : IOutputDataPin - { - object Evaluate(); - } -} diff --git a/ObjectAlgebraExecutionGraphs/Behaviors/ExecutionGraph/IExecutionNode.cs b/ObjectAlgebraExecutionGraphs/Behaviors/ExecutionGraph/IExecutionNode.cs deleted file mode 100644 index 4d356d7..0000000 --- a/ObjectAlgebraExecutionGraphs/Behaviors/ExecutionGraph/IExecutionNode.cs +++ /dev/null @@ -1,25 +0,0 @@ -using ObjectAlgebraExecutionGraphs.Behaviors.DataGraph; -using System.Collections.Generic; - -namespace ObjectAlgebraExecutionGraphs.Behaviors.ExecutionGraph -{ - /// - /// A graph node holding a collection of pins. - /// - /// Input execution pin type - /// Output execution pin type - /// Input data pin type - /// Output data pin type - public interface IExecutionNode : IDataNode - { - /// - /// Input execution pins of this node that can receive execution. - /// - public IEnumerable InputExecPins { get; } - - /// - /// Output execution pins of this node that can pass on execution. - /// - public IEnumerable OutputExecPins { get; } - } -} diff --git a/ObjectAlgebraExecutionGraphs/Behaviors/ExecutionGraph/IInputExecPin.cs b/ObjectAlgebraExecutionGraphs/Behaviors/ExecutionGraph/IInputExecPin.cs deleted file mode 100644 index 3c2f96e..0000000 --- a/ObjectAlgebraExecutionGraphs/Behaviors/ExecutionGraph/IInputExecPin.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace ObjectAlgebraExecutionGraphs.Behaviors.ExecutionGraph -{ - public interface IInputExecPin - { - } -} diff --git a/ObjectAlgebraExecutionGraphs/Behaviors/ExecutionGraph/IOutputExecPin.cs b/ObjectAlgebraExecutionGraphs/Behaviors/ExecutionGraph/IOutputExecPin.cs deleted file mode 100644 index a2b400c..0000000 --- a/ObjectAlgebraExecutionGraphs/Behaviors/ExecutionGraph/IOutputExecPin.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace ObjectAlgebraExecutionGraphs.Behaviors.ExecutionGraph -{ - public interface IOutputExecPin - { - } -} diff --git a/ObjectAlgebraExecutionGraphs/Program.cs b/ObjectAlgebraExecutionGraphs/Program.cs index cb10a66..c83f6f8 100644 --- a/ObjectAlgebraExecutionGraphs/Program.cs +++ b/ObjectAlgebraExecutionGraphs/Program.cs @@ -1,112 +1,95 @@ using ObjectAlgebraExecutionGraphs.Algebras; -using ObjectAlgebraExecutionGraphs.Behaviors.DataGraph; -using ObjectAlgebraExecutionGraphs.Behaviors.ExecutionGraph; +using ObjectAlgebraExecutionGraphs.Behaviors.CSharpTranslatableGraph; +using ObjectAlgebraExecutionGraphs.Behaviors.DotGraph; +using ObjectAlgebraExecutionGraphs.Behaviors.EvaluableGraph; +using ObjectAlgebraExecutionGraphs.Utility; using ObjectAlgebraExecutionGraphs.Variants; using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; +using System.Text; namespace ObjectAlgebraExecutionGraphs { internal static class Program { - private static IEnumerable CreateDataGraph(IDataGraphAlgebra factory) - where TNode : IDataNode + private static (IImmutableList nodes, IImmutableList> dataConnections) CreateDataGraph(TFactory factory) + where TFactory : IDataGraphAlgebra { var literalType = factory.TypeFromString(typeof(string).AssemblyQualifiedName); var literalNode = factory.CreateLiteralNode(literalType, "\"hello\""); - var reverseStringNode = factory.CreateReverseStringNode(literalNode.OutputDataPins.Single()); - var reverseStringNode2 = factory.CreateReverseStringNode(reverseStringNode.OutputDataPins.Single()); + var reverseStringNode = factory.CreateReverseStringNode(); + var reverseStringNode2 = factory.CreateReverseStringNode(); - return new[] { literalNode, reverseStringNode, reverseStringNode2 }; + var literalToReverse = new NodeConnection(literalNode, 0, reverseStringNode, 0); + var reverseToReverse2 = new NodeConnection(reverseStringNode, 0, reverseStringNode2, 0); + + return (ImmutableArray.Create(literalNode, reverseStringNode, reverseStringNode2), ImmutableArray.Create(literalToReverse, reverseToReverse2)); } - private static IEnumerable CreateExecutionGraph(TIXP next, IExecutionGraphAlgebra factory) - where TNode : IExecutionNode + private static (IImmutableList nodes, IImmutableList> dataConnections, IImmutableList> execConnections) CreateExecutionGraph(TFactory factory) + where TFactory : IDataGraphAlgebra, IExecutionGraphAlgebra { var literalType = factory.TypeFromString(typeof(string).AssemblyQualifiedName); var literalNode = factory.CreateLiteralNode(literalType, "\"hello\""); - var reverseStringNode = factory.CreateReverseStringNode(literalNode.OutputDataPins.Single()); - var concatenateNode = factory.CreateConcatenateNode(literalNode.OutputDataPins.Single(), reverseStringNode.OutputDataPins.Single(), next); + var reverseStringNode = factory.CreateReverseStringNode(); + var concatenateNode = factory.CreateConcatenateNode(); + + var literalToReverse = new NodeConnection(literalNode, 0, reverseStringNode, 0); + var literalToConcatenate = new NodeConnection(literalNode, 0, concatenateNode, 0); + var reverseToConcatenate = new NodeConnection(reverseStringNode, 0, concatenateNode, 1); - return new[] { literalNode, reverseStringNode, concatenateNode }; + return (ImmutableArray.Create(literalNode, reverseStringNode, concatenateNode), ImmutableArray.Create(literalToReverse, literalToConcatenate, reverseToConcatenate), ImmutableArray>.Empty); } private static void RunExecutionGraphExamples() { // Generate a DOT graph from the an execution graph's last node var dotFactory = new DotExecutionGraphAlgebra(); - var dotExecutionGraph = CreateExecutionGraph(null, dotFactory); + var dotExecutionGraph = CreateExecutionGraph(dotFactory); Console.WriteLine("--- DOT graph ---"); - Console.WriteLine("digraph dotGraph {"); - Console.Write(dotExecutionGraph.Last().GenerateDotGraph(null)); - Console.WriteLine("}"); + Console.WriteLine(TranslateToDotGraph(dotExecutionGraph.nodes, dotExecutionGraph.dataConnections, dotExecutionGraph.execConnections)); Console.WriteLine(); // Create the same execution graph, but now with elements translatable to C# var csharpTranslatableFactory = new CSharpTranslatableGraphAlgebra(); - var csharpTranslatableGraph = CreateExecutionGraph(null, csharpTranslatableFactory); + var csharpTranslatableGraph = CreateExecutionGraph(csharpTranslatableFactory); Console.WriteLine("--- C# translated graph ---"); - Console.WriteLine("void Func()"); - Console.WriteLine("{"); - foreach (var node in csharpTranslatableGraph) - { - Console.Write(node.TranslateVariables()); - } - foreach (var node in csharpTranslatableGraph) - { - Console.Write(node.TranslatePureFunctions()); - } - foreach (var node in csharpTranslatableGraph) - { - Console.Write(node.TranslateStates()); - } - Console.WriteLine("}"); + Console.WriteLine(TranslateToCSharp(csharpTranslatableGraph.nodes, csharpTranslatableGraph.dataConnections, csharpTranslatableGraph.execConnections)); } private static void RunDataGraphExamples() { // Create an evaluable data graph and evaluate it var evaluableFactory = new EvaluableGraphAlgebra(); - var evaluableDataGraph = CreateDataGraph(evaluableFactory); + (var evaluableNodes, var evaluableConnections) = CreateDataGraph(evaluableFactory); Console.Write("--- Evaluable graph ---"); Console.WriteLine("Last node outputs:"); - foreach ((var odp, var value) in evaluableDataGraph.Last().Evaluate()) + /*foreach ((var odp, var value) in evaluableNodes.Last().Evaluate() { Console.WriteLine(value); - } + }*/ // Generate a DOT graph from the same data graph's last node var dotFactory = new DotExecutionGraphAlgebra(); - var dotExecutionGraph = CreateDataGraph(dotFactory); + (var dotNodes, var dotConnections) = CreateDataGraph(dotFactory); Console.WriteLine("--- DOT graph ---"); - Console.WriteLine("digraph dotGraph {"); - Console.Write(dotExecutionGraph.Last().GenerateDotGraph(null)); - Console.WriteLine("}"); + Console.WriteLine(TranslateToDotGraph(dotNodes, dotConnections, ImmutableArray>.Empty)); Console.WriteLine(); // Create the same data graph, but now with elements translatable to C# var csharpTranslatableFactory = new CSharpTranslatableGraphAlgebra(); - var csharpTranslatableGraph = CreateDataGraph(csharpTranslatableFactory); + (var csharpNodes, var csharpConnections) = CreateDataGraph(csharpTranslatableFactory); Console.WriteLine("--- C# translated graph ---"); - Console.WriteLine("void Func()"); - Console.WriteLine("{"); - foreach (var node in csharpTranslatableGraph) - { - Console.Write(node.TranslateVariables()); - } - foreach (var node in csharpTranslatableGraph) - { - Console.Write(node.TranslatePureFunctions()); - } + Console.WriteLine(TranslateToCSharp(csharpNodes, csharpConnections, ImmutableArray>.Empty)); - // Since we don't have any states, translate a call to the last pure node instead. - Console.WriteLine(string.Join("\n", csharpTranslatableGraph.Last().TranslateCallPureFunction().Distinct())); - - Console.WriteLine("}"); + // We can also combine two algebras + var tupleFactory = new TupleDataAlgebra(dotFactory, csharpTranslatableFactory); + var tupleGraph = CreateDataGraph<(string, Type), (IDotNode, ICSharpTranslatableNode), TupleDataAlgebra>(tupleFactory); } private static void Main() @@ -117,5 +100,75 @@ private static void Main() Console.WriteLine("### Execution graph examples ###"); RunExecutionGraphExamples(); } + + private static string TranslateToDotGraph(IImmutableList nodes, IImmutableList> dataConnections, IImmutableList> execConnections) + => $"digraph graph {{\n{string.Join("\n", dataConnections.Concat(execConnections).Distinct().Select(conn => $"{conn.FromNode.DotName} -> {conn.ToNode.DotName}"))}\n}}"; + + private static IEnumerable CallPureDependents(ICSharpTranslatableNode node, IImmutableList> dataConnections) + { + for (int toIndex = 0; toIndex < node.Inputs.Count; toIndex++) + { + var conns = dataConnections.Where(conn => conn.ToNode == node && conn.ToPinIndex == toIndex).ToArray(); + if (conns.Length > 1) + { + throw new Exception(); + } + + if (conns.Length == 1) + { + var conn = conns[0]; + if (conn.FromNode.IsPure) + { + foreach (var call in CallPureDependents(conn.FromNode, dataConnections)) + { + yield return call; + } + } + + yield return $"{conn.FromNode.PureFunctionName}();\n"; + } + } + } + + private static string TranslateToCSharp(IImmutableList nodes, IImmutableList> dataConnections, IImmutableList> execConnections) + { + StringBuilder builder = new StringBuilder(); + + foreach (var node in nodes) + { + builder.Append(node.TranslateVariables()); + } + + foreach (var pureNode in nodes.Where(node => node.IsPure)) + { + builder.Append($"void {pureNode.PureFunctionName}()\n"); + builder.Append("{\n"); + builder.Append(pureNode.TranslatePureFunctions()); + builder.Append("}\n"); + } + + foreach (var stateNode in nodes.Where(node => !node.IsPure)) + { + IImmutableList pureCalls = CallPureDependents(stateNode, dataConnections).ToImmutableArray(); + + if (!stateNode.IsPure) + { + var outputConnectedLabels = new string[stateNode.ExecOutputCount]; + + var nodeExecConnections = execConnections + .Where(conn => conn.FromNode == stateNode) + .ToArray(); + + foreach (var execConn in nodeExecConnections) + { + outputConnectedLabels[execConn.FromPinIndex] = execConn.ToNode.ExecInputs[execConn.ToPinIndex]; + } + + builder.Append(stateNode.TranslateStates(outputConnectedLabels.ToImmutableArray(), string.Concat(pureCalls.Distinct()))); + } + } + + return builder.ToString(); + } } } diff --git a/ObjectAlgebraExecutionGraphs/Utility/NodeConnection.cs b/ObjectAlgebraExecutionGraphs/Utility/NodeConnection.cs new file mode 100644 index 0000000..a7ee2e2 --- /dev/null +++ b/ObjectAlgebraExecutionGraphs/Utility/NodeConnection.cs @@ -0,0 +1,18 @@ +namespace ObjectAlgebraExecutionGraphs.Utility +{ + public struct NodeConnection + { + public TNode FromNode { get; } + public TNode ToNode { get; } + public int FromPinIndex { get; } + public int ToPinIndex { get; } + + public NodeConnection(TNode fromNode, int fromPinIndex, TNode toNode, int toPinIndex) + { + FromNode = fromNode; + FromPinIndex = fromPinIndex; + ToNode = toNode; + ToPinIndex = toPinIndex; + } + } +} diff --git a/ObjectAlgebraExecutionGraphs/Variants/IDataGraphAlgebra.cs b/ObjectAlgebraExecutionGraphs/Variants/IDataGraphAlgebra.cs index 5984654..03b474a 100644 --- a/ObjectAlgebraExecutionGraphs/Variants/IDataGraphAlgebra.cs +++ b/ObjectAlgebraExecutionGraphs/Variants/IDataGraphAlgebra.cs @@ -1,12 +1,9 @@ -using ObjectAlgebraExecutionGraphs.Behaviors.DataGraph; - -namespace ObjectAlgebraExecutionGraphs.Variants +namespace ObjectAlgebraExecutionGraphs.Variants { - public interface IDataGraphAlgebra - where TNode : IDataNode + public interface IDataGraphAlgebra { public TNode CreateLiteralNode(TType type, object value); - public TNode CreateReverseStringNode(TODP aFrom); + public TNode CreateReverseStringNode(); public TType TypeFromString(string typeString); } } diff --git a/ObjectAlgebraExecutionGraphs/Variants/IExecutionGraphAlgebra.cs b/ObjectAlgebraExecutionGraphs/Variants/IExecutionGraphAlgebra.cs index 4d78fc0..73984f2 100644 --- a/ObjectAlgebraExecutionGraphs/Variants/IExecutionGraphAlgebra.cs +++ b/ObjectAlgebraExecutionGraphs/Variants/IExecutionGraphAlgebra.cs @@ -1,10 +1,10 @@ -using ObjectAlgebraExecutionGraphs.Behaviors.ExecutionGraph; +using ObjectAlgebraExecutionGraphs.Utility; +using System.Collections.Generic; namespace ObjectAlgebraExecutionGraphs.Variants { - public interface IExecutionGraphAlgebra : IDataGraphAlgebra - where TNode : IExecutionNode + public interface IExecutionGraphAlgebra { - public TNode CreateConcatenateNode(TODP aFrom, TODP bFrom, TIXP execTo); + public TNode CreateConcatenateNode(); } }