public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is MethodSpecifier methodSpecifier)
            {
                string name;

                // Check if the method is an operator
                if (OperatorUtil.TryGetOperatorInfo(methodSpecifier, out OperatorInfo operatorInfo))
                {
                    name = $"Operator {operatorInfo.DisplayName}";
                }
                else
                {
                    name = methodSpecifier.Name;
                }

                string paramTypeNames = string.Join(", ", methodSpecifier.Parameters);
                string s = $"{methodSpecifier.DeclaringType} {name} ({paramTypeNames})";

                if (methodSpecifier.ReturnTypes.Count > 0)
                {
                    s += $" : {string.Join(", ", methodSpecifier.ReturnTypes)}";
                }

                return(s);
            }

            return(value.ToString());
        }
Example #2
0
        public void TranslateCallMethodNode(CallMethodNode node)
        {
            // Wrap in try / catch
            if (node.HandlesExceptions)
            {
                builder.AppendLine("try");
                builder.AppendLine("{");
            }

            string temporaryReturnName = null;

            if (!node.IsPure)
            {
                // Translate all the pure nodes this node depends on in
                // the correct order
                TranslateDependentPureNodes(node);
            }

            // Write assignment of return values
            if (node.ReturnValuePins.Count == 1)
            {
                string returnName = GetOrCreatePinName(node.ReturnValuePins[0]);

                builder.Append($"{returnName} = ");
            }
            else if (node.OutputDataPins.Count > 1)
            {
                temporaryReturnName = TranslatorUtil.GetTemporaryVariableName(random);

                var returnTypeNames = string.Join(", ", node.OutputDataPins.Select(pin => pin.PinType.Value.FullCodeName));

                builder.Append($"{typeof(Tuple).FullName}<{returnTypeNames}> {temporaryReturnName} = ");
            }

            // Get arguments for method call
            var argumentNames = GetPinIncomingValues(node.ArgumentPins);

            // Check whether the method is an operator and we need to translate its name
            // into operator symbols. Otherwise just call the method normally.
            if (OperatorUtil.TryGetOperatorInfo(node.MethodSpecifier, out OperatorInfo operatorInfo))
            {
                if (operatorInfo.Unary)
                {
                    if (argumentNames.Count() != 1)
                    {
                        throw new Exception($"Unary operator was found but did not have one argument: {node.MethodName}");
                    }

                    if (operatorInfo.UnaryRightPosition)
                    {
                        builder.AppendLine($"{argumentNames.ElementAt(0)}{operatorInfo.Symbol};");
                    }
                    else
                    {
                        builder.AppendLine($"{operatorInfo.Symbol}{argumentNames.ElementAt(0)};");
                    }
                }
                else
                {
                    if (argumentNames.Count() != 2)
                    {
                        throw new Exception($"Binary operator was found but did not have two arguments: {node.MethodName}");
                    }

                    builder.AppendLine($"{argumentNames.ElementAt(0)}{operatorInfo.Symbol}{argumentNames.ElementAt(1)};");
                }
            }
            else
            {
                // Static: Write class name / target, default to own class name
                // Instance: Write target, default to this

                if (node.IsStatic)
                {
                    builder.Append($"{node.DeclaringType.FullCodeName}.");
                }
                else
                {
                    if (node.TargetPin.IncomingPin != null)
                    {
                        string targetName = GetOrCreatePinName(node.TargetPin.IncomingPin);
                        builder.Append($"{targetName}.");
                    }
                    else
                    {
                        // Default to this
                        builder.Append("this.");
                    }
                }

                // Prefix with "out" / "ref" / "in"
                string[] argNameArray = argumentNames.ToArray();
                Debug.Assert(argNameArray.Length == node.MethodSpecifier.Parameters.Count);

                for (int i = 0; i < node.MethodSpecifier.Parameters.Count; i++)
                {
                    MethodParameterPassType passType = node.MethodSpecifier.Parameters[i].PassType;
                    switch (passType)
                    {
                    case MethodParameterPassType.Out:
                        argNameArray[i] = "out " + argNameArray[i];
                        break;

                    case MethodParameterPassType.Reference:
                        argNameArray[i] = "ref " + argNameArray[i];
                        break;

                    case MethodParameterPassType.In:
                        // Don't pass with in as it could break implicit casts.
                        // argNameArray[i] = "in " + argNameArray[i];
                        break;

                    default:
                        break;
                    }
                }

                // Write the method call
                builder.AppendLine($"{node.BoundMethodName}({string.Join(", ", argNameArray)});");
            }

            // Assign the real variables from the temporary tuple
            if (node.ReturnValuePins.Count > 1)
            {
                var returnNames = GetOrCreatePinNames(node.ReturnValuePins);
                for (int i = 0; i < returnNames.Count(); i++)
                {
                    builder.AppendLine($"{returnNames.ElementAt(i)} = {temporaryReturnName}.Item{i+1};");
                }
            }

            // Set the exception to null on success if catch pin is connected
            if (node.HandlesExceptions)
            {
                builder.AppendLine($"{GetOrCreatePinName(node.ExceptionPin)} = null;");
            }

            // Go to the next state
            if (!node.IsPure)
            {
                WriteGotoOutputPinIfNecessary(node.OutputExecPins[0], node.InputExecPins[0]);
            }

            // Catch exceptions if catch pin is connected
            if (node.HandlesExceptions)
            {
                string exceptionVarName = TranslatorUtil.GetTemporaryVariableName(random);
                builder.AppendLine("}");
                builder.AppendLine($"catch (System.Exception {exceptionVarName})");
                builder.AppendLine("{");
                builder.AppendLine($"{GetOrCreatePinName(node.ExceptionPin)} = {exceptionVarName};");

                // Set all return values to default on exception
                foreach (var returnValuePin in node.ReturnValuePins)
                {
                    string returnName = GetOrCreatePinName(returnValuePin);
                    builder.AppendLine($"{returnName} = default({returnValuePin.PinType.Value.FullCodeName});");
                }

                if (!node.IsPure)
                {
                    WriteGotoOutputPinIfNecessary(node.CatchPin, node.InputExecPins[0]);
                }

                builder.AppendLine("}");
            }
        }
Example #3
0
        public void TranslateCallMethodNode(CallMethodNode node)
        {
            // Wrap in try/catch if we have a catch handler
            if (node.CatchPin.OutgoingPin != null)
            {
                builder.AppendLine("try");
                builder.AppendLine("{");
            }

            string temporaryReturnName = null;

            // Translate all the pure nodes this node depends on in
            // the correct order
            TranslateDependentPureNodes(node);

            // Write assignment of return values
            if (node.ReturnValuePins.Count == 1)
            {
                string returnName = GetOrCreatePinName(node.ReturnValuePins[0]);

                builder.Append($"{returnName} = ");
            }
            else if (node.OutputDataPins.Count > 1)
            {
                temporaryReturnName = TranslatorUtil.GetTemporaryVariableName();

                var returnTypeNames = string.Join(", ", node.OutputDataPins.Select(pin => pin.PinType));

                builder.Append($"{typeof(Tuple).FullName}<{returnTypeNames}> {temporaryReturnName} = ");
            }

            // Get arguments for method call
            var argumentNames = GetPinIncomingValues(node.ArgumentPins);

            // Check whether the method is an operator and we need to translate its name
            // into operator symbols. Otherwise just call the method normally.
            if (OperatorUtil.TryGetOperatorInfo(node.MethodSpecifier, out OperatorInfo operatorInfo))
            {
                if (operatorInfo.Unary)
                {
                    if (argumentNames.Count() != 1)
                    {
                        throw new Exception($"Unary operator was found but did not have one argument: {node.MethodName}");
                    }

                    if (operatorInfo.UnaryRightPosition)
                    {
                        builder.AppendLine($"{argumentNames.ElementAt(0)}{operatorInfo.Symbol};");
                    }
                    else
                    {
                        builder.AppendLine($"{operatorInfo.Symbol}{argumentNames.ElementAt(0)};");
                    }
                }
                else
                {
                    if (argumentNames.Count() != 2)
                    {
                        throw new Exception($"Binary operator was found but did not have two arguments: {node.MethodName}");
                    }

                    builder.AppendLine($"{argumentNames.ElementAt(0)}{operatorInfo.Symbol}{argumentNames.ElementAt(1)};");
                }
            }
            else
            {
                // Static: Write class name / target, default to own class name
                // Instance: Write target, default to this

                if (node.IsStatic)
                {
                    builder.Append($"{node.DeclaringType.FullCodeName}.");
                }
                else
                {
                    if (node.TargetPin.IncomingPin != null)
                    {
                        string targetName = GetOrCreatePinName(node.TargetPin.IncomingPin);
                        builder.Append($"{targetName}.");
                    }
                    else
                    {
                        // Default to this
                        builder.Append("this.");
                    }
                }

                // Write the method call
                builder.AppendLine($"{node.MethodName}({string.Join(", ", argumentNames)});");
            }

            // Assign the real variables from the temporary tuple
            if (node.ReturnValuePins.Count > 1)
            {
                var returnNames = GetOrCreatePinNames(node.ReturnValuePins);
                for (int i = 0; i < returnNames.Count(); i++)
                {
                    builder.AppendLine($"{returnNames.ElementAt(i)} = {temporaryReturnName}.Item{i+1};");
                }
            }

            // Go to the next state
            WriteGotoOutputPin(node.OutputExecPins[0]);

            // Catch exceptions and execute catch pin
            if (node.CatchPin.OutgoingPin != null)
            {
                string exceptionVarName = TranslatorUtil.GetTemporaryVariableName();
                builder.AppendLine("}");
                builder.AppendLine($"catch (System.Exception {exceptionVarName})");
                builder.AppendLine("{");
                builder.AppendLine($"{GetOrCreatePinName(node.ExceptionPin)} = {exceptionVarName};");
                WriteGotoOutputPin(node.CatchPin);
                builder.AppendLine("}");
            }
        }