Beispiel #1
0
        private string GetPriorityComparisonBody()
        {
            var    priorityComparison = new SolidityIfElse();
            string ifCondition        = string.Empty;

            //Make function of cycles comparing priorities
            foreach (var outputVarable in Decision.DecisionTable.Outputs.Select((value, i) => new { i, value }))
            {
                ifCondition += $"priorities[i].{outputVarable.value.Name} == currentOutput.{outputVarable.value.Name}";
                if (outputVarable.i + 1 < Decision.DecisionTable.Outputs.Count)
                {
                    ifCondition += " && ";
                }
            }
            priorityComparison.AddConditionBlock(ifCondition, new SolidityStatement("return currentOutput", true));
            string elseCondition = string.Empty;

            foreach (var outputVarable in Decision.DecisionTable.Outputs.Select((value, i) => new { i, value }))
            {
                elseCondition += $"priorities[i].{outputVarable.value.Name} == newOutput.{outputVarable.value.Name}";
                if (outputVarable.i + 1 < Decision.DecisionTable.Outputs.Count)
                {
                    elseCondition += " && ";
                }
            }
            priorityComparison.AddConditionBlock(elseCondition, new SolidityStatement("return newOutput", true));
            return(priorityComparison.ToString());
        }
Beispiel #2
0
        //Returns output for section representing situation if there is the match or not
        private string GetMatchOrNotBody(int ruleIndex)
        {
            //Assign maximum/minimum if this is the first met condition
            var    noMatchCheck     = new SolidityIfElse();
            string noMatchCheckBody = string.Empty;

            foreach (var outputEntry in Decision.DecisionTable.Rules[ruleIndex].OutputEntries.Select((value, i) => new { i, value }))
            {
                var dataType       = Decision.DecisionTable.Outputs[outputEntry.i].TypeRef;
                var convertedValue = ConvertToSolidityValue(outputEntry.value.Text, dataType);
                noMatchCheckBody += $"output.{Decision.DecisionTable.Outputs[outputEntry.i].Name.Replace(".", "__")} = {convertedValue};";
                if (outputEntry.i + 1 < Decision.DecisionTable.Rules[ruleIndex].OutputEntries.Count())
                {
                    noMatchCheckBody += "\n";
                }
            }
            noMatchCheck.AddConditionBlock("!matchedRule", new SolidityStatement(noMatchCheckBody, false));

            //Assign maximum/minimum if the values are greater/lesser
            string matchCheckBody = string.Empty;

            foreach (var outputEntry in Decision.DecisionTable.Rules[ruleIndex].OutputEntries.Select((value, i) => new { i, value }))
            {
                var    outputsCheck          = new SolidityIfElse();
                var    dataType              = Decision.DecisionTable.Outputs[outputEntry.i].TypeRef;
                var    convertedValue        = ConvertToSolidityValue(outputEntry.value.Text, dataType);
                string outputsCheckCondition = $"output.{Decision.DecisionTable.Outputs[outputEntry.i].Name} {Sign} {convertedValue}";
                string outputsCheckBody      = $"output.{Decision.DecisionTable.Outputs[outputEntry.i].Name.Replace(".", "__")} = {convertedValue};";
                outputsCheck.AddConditionBlock(outputsCheckCondition, new SolidityStatement(outputsCheckBody, false));
                matchCheckBody += outputsCheck.ToString();
            }
            noMatchCheck.AddConditionBlock(string.Empty, new SolidityStatement(matchCheckBody, false));
            return(noMatchCheck.ToString());
        }
        private SolidityIfElse GetConditionCheck(int ruleIndex)
        {
            var conditionCheck = new SolidityIfElse();
            //Assign output if there is already the match
            string matchBody = GetMatchBody(ruleIndex);

            conditionCheck.AddConditionBlock("!matchedRule", new SolidityStatement(matchBody, false));
            //Assign output if there is no match yet
            conditionCheck.AddConditionBlock("", new SolidityStatement("revert('Undefined output')", true));

            return(conditionCheck);
        }
Beispiel #4
0
        //Returns output for section representing situation if there is the match or not
        private string GetPriorityCheckBody(int ruleIndex)
        {
            var priorityCheck = new SolidityIfElse();
            //Assign output if there is already match
            string matchBody = GetMatchBody(ruleIndex);

            priorityCheck.AddConditionBlock("!matchedRule", new SolidityStatement(matchBody, false));

            //Assign output if there is no match yet
            string noMatchBody = GetNoMatchBody(ruleIndex);

            priorityCheck.AddConditionBlock("", new SolidityStatement(noMatchBody, true));
            return(priorityCheck.ToString());
        }
Beispiel #5
0
        public override SolidityFunction CreateDecisionFunction()
        {
            //Define function's header
            FunctionName = Regex.Replace(Decision.Id, @" ", "").ToLowerCamelCase();
            SolidityFunction function = new SolidityFunction(FunctionName, SolidityVisibility.Internal, $"{OutputStructName} memory", true);

            //Add declaration of helper varaibles
            function.AddToBody(new SolidityStatement($"{OutputStructName} memory output", true));
            function.AddToBody(new SolidityStatement($"bool matchedRule = false", true));

            //For each row representing rule create condition for if statement
            var rules = GetAllConditions();

            foreach (var rule in rules.Select((value, i) => new { i, value }))
            {
                //Add to sum if the conditions are met
                string conditionBody = string.Empty;
                foreach (var outputEntry in Decision.DecisionTable.Rules[rule.i].OutputEntries.Select((value, i) => new { i, value }))
                {
                    conditionBody += $"output.{Decision.DecisionTable.Outputs[outputEntry.i].Name.Replace(".", "__")} += {outputEntry.value.Text};\n";
                }
                conditionBody += "matchedRule = true;";

                //If the row is empty then do not put the logic into conditional statement
                function.AddToBody(AddBodyBasedOnRule(rule.value, conditionBody));
            }

            //Add the rest of the function
            var undefinedOutputCheck = new SolidityIfElse();

            undefinedOutputCheck.AddConditionBlock("!matchedRule", new SolidityStatement("revert('Undefined output')", true));
            function.AddToBody(undefinedOutputCheck);
            function.AddToBody(new SolidityStatement("return output", true));
            return(function);
        }
        SolidityModifier CreateAddressGuard()
        {
            //Initialize the modifier using the generated name
            SolidityModifier addressGuard = new SolidityModifier(ConversionTemplates.AddressGuardModifierName(GetElementCallName()));

            addressGuard.AddParameters(processConverter.GetIdentifiersAsParameters());
            //Address is force assigned
            if (userTaskElement.Assignee.Address != null)
            {
                SolidityStatement requireStatement = new SolidityStatement($"require(msg.sender=={GetAssigneeAddress()})");
                addressGuard.AddToBody(requireStatement);
            }
            //Address is not force assigned, it will be assigned to the first caller of the first task method containing this assignee
            else if (userTaskElement.Assignee.Name != null)
            {
                var addressPosition = $"{ConverterConfig.ADDRESS_MAPPING_VAR_NAME}[\"{userTaskElement.Assignee.Name}\"]";

                var ifElseBlock = new SolidityIfElse();
                //Assigns the address, if address has not been been yet assigned to the assignee
                ifElseBlock.AddConditionBlock($"{addressPosition} == address(0x0)", new SolidityStatement($"{addressPosition} = msg.sender"));
                //Checks whether the sender has the required address
                SolidityStatement requireStatement = new SolidityStatement($"require(msg.sender=={addressPosition})");
                addressGuard.AddToBody(ifElseBlock);
                addressGuard.AddToBody(requireStatement);
            }
            return(addressGuard);
        }
Beispiel #7
0
        public override SolidityFunction CreateDecisionFunction()
        {
            FunctionName = Regex.Replace(Decision.Id, @" ", "").ToLowerCamelCase();
            SolidityFunction function = new SolidityFunction(FunctionName, SolidityVisibility.Internal, $"{OutputStructName} memory", true);
            //Add declaration of helper varaibles
            var prioritiesFormatted = GetPriorities(Decision);
            var noUniqueOutputs     = Regex.Matches(prioritiesFormatted, $"{OutputStructName}").Count;

            function.AddToBody(new SolidityStatement($"{OutputStructName}[{noUniqueOutputs}] memory priorities = {prioritiesFormatted}", true));
            function.AddToBody(new SolidityStatement($"{OutputStructName} memory output", true));
            function.AddToBody(new SolidityStatement($"bool matchedRule = false", true));

            var rules = GetAllConditions();

            foreach (var rule in rules.Skip(PriorityOffset).Select((value, i) => new { i, value }))
            {
                string priorityCheck = GetPriorityCheckBody(rule.i + PriorityOffset);
                function.AddToBody(AddBodyBasedOnRule(rule.value, priorityCheck));
            }
            //Add the rest of the function
            var undefinedOutputCheck = new SolidityIfElse();

            undefinedOutputCheck.AddConditionBlock("!matchedRule", new SolidityStatement("revert('Undefined output')", true));
            function.AddToBody(undefinedOutputCheck);
            function.AddToBody(new SolidityStatement("return output", true));
            return(function);
        }
Beispiel #8
0
        SolidityFunction CreateMainFunction()
        {
            var logicFunction = new SolidityFunction($"{GetElementCallName()}", SolidityVisibility.Internal);
            var body          = CreateCallsToOutgoing();

            logicFunction.AddParameters(processConverter.GetIdentifiersAsParameters());

            if (gatewayElement.Incoming.Count == 1)
            {
                logicFunction.AddToBody(body);
            }
            else
            {
                //Increment the incoming variable
                logicFunction.AddToBody(new SolidityStatement($"{incrementVariableName} += 1"));

                var    ifElseBlock     = new SolidityIfElse();
                string ifElseCondition = $"{incrementVariableName}=={gatewayElement.Incoming.Count}";
                //reset the incoming flow count
                body.Add(incrementVariableName + " = 0");
                ifElseBlock.AddConditionBlock(ifElseCondition, body);
                logicFunction.AddToBody(ifElseBlock);
            }

            return(logicFunction);
        }
Beispiel #9
0
        public override IList <SolidityComponent> GetElementCode(List <ElementConverter> nextElements, IList <SequenceFlow> outgoingSeqFlows, IList <SolidityStruct> dataModel = null)
        {
            var logicFunction = new SolidityFunction(gateway.Id + "Logic", SolidityVisibility.Internal);
            var body          = CreateParallelism(nextElements);

            if (gateway.Incoming.Count == 1)
            {
                logicFunction.AddToBody(body);
                return(new List <SolidityComponent> {
                    logicFunction
                });
            }
            else
            {
                var    incomingFlowsVar = new SolidityStatement("int " + incVaribaleName + " = 0");
                var    ifElseBlock      = new SolidityIfElse();
                string ifElseCondition  = incVaribaleName + "==" + gateway.Incoming.Count.ToString();
                body.Add(incVaribaleName + " = 0");
                ifElseBlock.AddConditionBlock(ifElseCondition, body);
                logicFunction.AddToBody(ifElseBlock);
                return(new List <SolidityComponent> {
                    incomingFlowsVar, logicFunction
                });
            }
        }
Beispiel #10
0
        public override SolidityFunction CreateDecisionFunction()
        {
            //Define function's header
            FunctionName = Regex.Replace(Decision.Id, @" ", "").ToLowerCamelCase();
            SolidityFunction function = new SolidityFunction(FunctionName, SolidityVisibility.Internal, $"{OutputStructName} memory", true);

            //Add declaration of helper varaibles
            function.AddToBody(new SolidityStatement($"{OutputStructName} memory output", true));
            function.AddToBody(new SolidityStatement($"bool matchedRule = false", true));

            //For each row representing rule create condition for if statement
            var rules = GetAllConditions();

            foreach (var rule in rules.Select((value, i) => new { i, value }))
            {
                var    noMatchCheck  = GetMatchOrNotBody(rule.i);
                string conditionBody = noMatchCheck;
                conditionBody += "matchedRule = true;";
                function.AddToBody(AddBodyBasedOnRule(rule.value, conditionBody));
            }

            //Add the rest of the function
            var undefinedOutputCheck = new SolidityIfElse();

            undefinedOutputCheck.AddConditionBlock("!matchedRule", new SolidityStatement("revert('Undefined output')", true));
            function.AddToBody(undefinedOutputCheck);
            function.AddToBody(new SolidityStatement("return output", true));
            return(function);
        }
        public override SolidityFunction CreateDecisionFunction()
        {
            FunctionName = Regex.Replace(Decision.Id, @" ", "").ToLowerCamelCase();
            SolidityFunction function = new SolidityFunction(FunctionName, SolidityVisibility.Internal, $"{OutputStructName} memory", true);

            //Add declaration of helper varaibles
            function.AddToBody(new SolidityStatement($"{OutputStructName} memory output", true));
            function.AddToBody(new SolidityStatement($"bool matchedRule = false", true));

            //Add checks of conditions for matches and their bodies
            var rules = GetAllConditions();

            foreach (var rule in rules.Select((value, i) => new { i, value }))
            {
                var conditionCheck = GetConditionCheck(rule.i);
                function.AddToBody(AddBodyBasedOnRule(rule.value, conditionCheck.ToString()));
            }

            //Add the rest of the function
            var undefinedOutputCheck = new SolidityIfElse();

            undefinedOutputCheck.AddConditionBlock("!matchedRule", new SolidityStatement("revert('Undefined output')", true));
            function.AddToBody(undefinedOutputCheck);
            function.AddToBody(new SolidityStatement("return output", true));
            return(function);
        }
        SolidityIfElse CreateIfElseBlock(IList <SequenceFlow> outgoingSequenceFlows)
        {
            var ifElseBlock = new SolidityIfElse();

            foreach (var sequenceFlow in outgoingSequenceFlows)
            {
                var targetConverter = processConverter.GetConverterOfElement(sequenceFlow.TargetId);
                ifElseBlock.AddConditionBlock(sequenceFlow.Condition, targetConverter.GetStatementForPrevious(gatewayElement));
            }
            return(ifElseBlock);
        }
        public void ThreeConditionsTest()
        {
            SolidityIfElse ifelse = new SolidityIfElse();

            ifelse.AddConditionBlock("a == 2", new SolidityStatement("a = 0"));
            ifelse.AddConditionBlock("b == 2", new SolidityStatement("b = 0"));
            ifelse.AddConditionBlock("c == 2", new SolidityStatement("c = 0"));


            string expected = "if(a == 2){\n" +
                              "\ta = 0;\n" +
                              "}\n" +
                              "else if(b == 2){\n" +
                              "\tb = 0;\n" +
                              "}\n" +
                              "else if(c == 2){\n" +
                              "\tc = 0;\n" +
                              "}\n";

            Assert.Equal(expected, ifelse.ToString());
        }
Beispiel #14
0
        SolidityFunction CreateProcessReturnFunction()
        {
            var function = new SolidityFunction(ConversionTemplates.CallActivityReturnFunctionName(GetElementCallName()), SolidityVisibility.Internal);

            function.AddParameters(processConverter.GetIdentifiersAsParameters());

            var nextElementStatement      = CreateNextElementStatement();
            var incrementStatement        = new SolidityStatement($"{ConversionTemplates.CallActivityCounter(GetElementCallName())}++");
            var checkConditionBlock       = new SolidityIfElse();
            var calledStartEventConverter = processConverter.ContractConverter.GetStartEventConverter(callActivity);
            var callSubprocessStatement   = calledStartEventConverter.GetStatementForPrevious(callActivity);

            checkConditionBlock.AddConditionBlock($"{ConversionTemplates.CallActivityCounter(GetElementCallName())} >= {GetCountTarget(callActivity)}",
                                                  nextElementStatement);

            switch (callActivity.InstanceType)
            {
            case InstanceType.Single:
                function.AddToBody(nextElementStatement);
                break;

            case InstanceType.Sequential:
                //increment the counter, check if counter reached limit.
                //If counter reached limit, then call the next element. If not, call the subprocess again.
                function.AddToBody(incrementStatement);

                checkConditionBlock.AddConditionBlock("", callSubprocessStatement);
                function.AddToBody(checkConditionBlock);

                break;

            case InstanceType.Parallel:
                //increment the counter, check if counter reached limit.
                //If counter reached limit, then call the next element. If not, do nothing.
                function.AddToBody(incrementStatement);
                function.AddToBody(checkConditionBlock);
                break;
            }
            return(function);
        }
Beispiel #15
0
        SolidityFunction CreateTouchFunction(TaskConverter attachedToConverter)
        {
            var function = new SolidityFunction($"touch{GetElementCallName()}", SolidityVisibility.Public, "bool");

            function.AddParameters(processConverter.GetIdentifiersAsParameters());
            function.AddModifier($"{ConversionTemplates.StateGuardModifierName(attachedToConverter.GetElementCallName())}({processConverter.GetIdentifierNames()})");

            var solidityCondition = new SolidityIfElse();

            solidityCondition.AddConditionBlock($"now > {GetTimerCondition()}", CreateTouchFunctionLogic(attachedToConverter));
            function.AddToBody(solidityCondition);
            function.AddToBody(new SolidityStatement("return true"));
            return(function);
        }
 //Adds either if-else statement or a general statement
 protected SolidityComponent AddBodyBasedOnRule(string ruleValue, string body)
 {
     //If the row is empty then do not put the logic into conditional statement
     if (string.IsNullOrEmpty(ruleValue))
     {
         return(new SolidityStatement(body, false));
     }
     else
     {
         var condition = new SolidityIfElse();
         condition.AddConditionBlock(ruleValue, new SolidityStatement(body, false));
         return(condition);
     }
 }
        List <SolidityComponent> CreateCallNextBody()
        {
            var components        = new List <SolidityComponent>();
            var callNextStatement = GetChangeActiveStateStatement(false);

            callNextStatement.Add(processConverter.GetStatementOfNextElement(userTaskElement));

            if (userTaskElement.InstanceType != InstanceType.Single)
            {
                //The tasks will run until it gets interrupted by some boundary event
                if (userTaskElement.LoopCardinality == -1 || (userTaskElement.LoopCardinality == 0 && userTaskElement.LoopCollection == null))
                {
                    return(components);
                }

                var ifStatement         = new SolidityIfElse();
                var counterVariableName = ConversionTemplates.MultiInstanceCounterVariable(GetElementCallName());

                components.Add(new SolidityStatement($"{counterVariableName}++"));
                counterVariablePresent = true;
                if (userTaskElement.LoopCardinality > 0)
                {
                    ifStatement.AddConditionBlock($"{counterVariableName} >= {userTaskElement.LoopCardinality}", callNextStatement);
                }
                else if (userTaskElement.LoopCollection != null)
                {
                    ifStatement.AddConditionBlock($"{counterVariableName} >= {GetCountTarget(userTaskElement)}", callNextStatement);
                }
                components.Add(ifStatement);
            }
            else
            {
                components.Add(callNextStatement);
            }

            return(components);
        }
Beispiel #18
0
        SolidityIfElse CreateIfElseBlock(List <ElementConverter> nextElements, IList <SequenceFlow> outgoingSeqFlows)
        {
            var ifElseBlock = new SolidityIfElse();

            foreach (var seqFlow in outgoingSeqFlows)
            {
                foreach (var nextElement in nextElements)
                {
                    if (seqFlow.TargetId == nextElement.GetElementId())
                    {
                        ifElseBlock.AddConditionBlock(seqFlow.Condition, nextElement.GetStatementForPrevious(gateway));
                    }
                }
            }
            return(ifElseBlock);
        }
Beispiel #19
0
        //Returns string representation of section checking existence of matched output in the priority list
        private string GetPirorityListCheck(int ruleIndex)
        {
            var    priorityListCheck     = new SolidityIfElse();
            string priorityListCheckBody = "existsInOutput[i] = true;\n" +
                                           "outputSize++;\n" +
                                           "matchedRule = true;\n" +
                                           "break;";
            string priorityListCheckCond = "!existsInOutput[i]";

            foreach (var outputEntry in Decision.DecisionTable.Rules[ruleIndex].OutputEntries.Select((value, i) => new { i, value }))
            {
                var comparisonVar   = $"priorities[i].{Decision.DecisionTable.Outputs[outputEntry.i].Name}";
                var comparisonType  = Decision.DecisionTable.Outputs[outputEntry.i].TypeRef;
                var comparisonEntry = outputEntry.value.Text;
                var comparison      = ConvertExpressionToCondition(comparisonVar, comparisonType, comparisonEntry, true);
                priorityListCheckCond += $" && {comparison}";
            }
            priorityListCheck.AddConditionBlock(priorityListCheckCond, new SolidityStatement(priorityListCheckBody, false));
            return(priorityListCheck.ToString());
        }
Beispiel #20
0
        SolidityModifier CreateAddressGuard()
        {
            SolidityModifier addressGuard = new SolidityModifier("is" + GetTaskName() + "Authorized");

            if (userTask.Assignee.Address != null)
            {
                SolidityStatement requireStatement = new SolidityStatement("require(msg.sender==" + GetAssigneeAddress() + ")");
                addressGuard.AddToBody(requireStatement);
            }
            else if (userTask.Assignee.Name != null)
            {
                var addressPosition = Helpers.ADDRESS_MAPPING_VAR_NAME + "[\"" + userTask.Assignee.Name + "\"]";
                var ifElseBlock     = new SolidityIfElse();
                ifElseBlock.AddConditionBlock(addressPosition + " == address(0x0)", new SolidityStatement(addressPosition + " = msg.sender"));
                SolidityStatement requireStatement = new SolidityStatement("require(msg.sender==" + addressPosition + ")");
                addressGuard.AddToBody(ifElseBlock);
                addressGuard.AddToBody(requireStatement);
            }
            return(addressGuard);
        }
Beispiel #21
0
        //Retruns for loop component initializing the output
        private SolidityFor GetInitializationForLoop(int noUniqueOutputs)
        {
            var initForLoop = new SolidityFor("i", $"{noUniqueOutputs}");
            //Add only outputs that meet the conditions
            var    initCheck     = new SolidityIfElse();
            string initCheckBody = $"output[j] = {OutputStructName}(";

            foreach (var output in Decision.DecisionTable.Outputs.Select((value, i) => new { i, value }))
            {
                initCheckBody += $"priorities[i].{output.value.Name}";
                if (output.i + 1 < Decision.DecisionTable.Outputs.Count)
                {
                    initCheckBody += ", ";
                }
            }
            initCheckBody += ");\n";
            initCheckBody += "j++;";
            initCheck.AddConditionBlock("existsInOutput[i]", new SolidityStatement(initCheckBody, false));
            initForLoop.AddToBody(new SolidityStatement(initCheck.ToString(), false));
            return(initForLoop);
        }
Beispiel #22
0
        public override SolidityFunction CreateDecisionFunction()
        {
            FunctionName = Regex.Replace(Decision.Id, @" ", "").ToLowerCamelCase();
            SolidityFunction function = new SolidityFunction(FunctionName, SolidityVisibility.Internal, $"{OutputStructName} memory", true);

            //Add declaration of helper varaibles
            function.AddToBody(new SolidityStatement($"{OutputStructName} memory output", true));
            var emptyRule = false;

            //Add checks of conditions for matches and their bodies
            var rules = GetAllConditions();

            foreach (var rule in rules.Select((value, i) => new { i, value }))
            {
                //Assign output if there is already the match
                string conditionBody = GetConditionBody(rule.i);

                //If the row is empty then do not put the logic into conditional statement
                if (string.IsNullOrEmpty(rule.value))
                {
                    var condition = new SolidityStatement(conditionBody, false);
                    function.AddToBody(condition);
                    emptyRule = true;
                    break;
                }
                else
                {
                    var condition = new SolidityIfElse();
                    condition.AddConditionBlock(rule.value, new SolidityStatement(conditionBody, false));
                    function.AddToBody(condition);
                }
            }

            //Add the rest of the function
            if (!emptyRule)
            {
                function.AddToBody(new SolidityStatement("revert('Undefined output')", true));
            }
            return(function);
        }
Beispiel #23
0
        public override SolidityFunction CreateDecisionFunction()
        {
            //Define function's header
            FunctionName = Regex.Replace(Decision.Id, @" ", "").ToLowerCamelCase();
            SolidityFunction function = new SolidityFunction(FunctionName, SolidityVisibility.Internal, $"{OutputStructName}[] memory", true);
            //Add declaration of helper varaibles
            var prioritiesFormatted = GetPriorities();
            var noUniqueOutputs     = Regex.Matches(prioritiesFormatted, $"{OutputStructName}").Count;

            function.AddToBody(new SolidityStatement($"{OutputStructName}[{noUniqueOutputs}] memory priorities = {prioritiesFormatted}", true));
            function.AddToBody(new SolidityStatement($"bool[{noUniqueOutputs}] memory existsInOutput", true));
            function.AddToBody(new SolidityStatement($"uint outputSize = 0", true));
            function.AddToBody(new SolidityStatement($"bool matchedRule = false", true));

            var rules = GetAllConditions();

            foreach (var rule in rules.Skip(PriorityOffset).Select((value, i) => new { i, value }))
            {
                string priorityListCheck = GetPirorityListCheck(rule.i + PriorityOffset);
                var    priorityCheckLoop = new SolidityFor("i", $"{noUniqueOutputs}");
                priorityCheckLoop.AddToBody(new SolidityStatement(priorityListCheck, false));

                function.AddToBody(AddBodyBasedOnRule(rule.value, priorityCheckLoop.ToString()));
            }

            //Initialization of output list
            function.AddToBody(new SolidityStatement("uint j = 0", true));
            function.AddToBody(new SolidityStatement($"{OutputStructName}[] memory output = new {OutputStructName}[](outputSize)", true));
            var initForLoop = GetInitializationForLoop(noUniqueOutputs);

            function.AddToBody(initForLoop);

            //Add the rest of the function
            var undefinedOutputCheck = new SolidityIfElse();

            undefinedOutputCheck.AddConditionBlock("!matchedRule", new SolidityStatement("revert('Undefined output')", true));
            function.AddToBody(undefinedOutputCheck);
            function.AddToBody(new SolidityStatement("return output", true));
            return(function);
        }