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()); }
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("}"); } }
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("}"); } }