public override void ExitMethodDecl(GoParser.MethodDeclContext context) { CurrentFunction = null; CurrentFunctionName = null; OriginalFunctionName = null; InFunction = false; }
public override void EnterMethodDecl(GoParser.MethodDeclContext context) { InFunction = true; OriginalFunctionName = context.IDENTIFIER()?.GetText() ?? "_"; CurrentFunctionName = SanitizedIdentifier(OriginalFunctionName); GoParser.ParameterDeclContext[] receiverParameters = context.receiver().parameters().parameterDecl(); string receiverTypeName; if (receiverParameters.Length > 0) { receiverTypeName = receiverParameters[0].type_().GetText(); // Receiver does not need to handle pointer-to-pointer look ups if (receiverTypeName.StartsWith("*")) { receiverTypeName = $"ptr<{receiverTypeName.Substring(1)}>"; } } else { receiverTypeName = "object"; } string functionSignature = FunctionSignature.Generate(OriginalFunctionName, new[] { receiverTypeName }); FunctionInfo currentFunction = null; Metadata?.Functions.TryGetValue(functionSignature, out currentFunction); CurrentFunction = currentFunction; }
public override void ExitMethodDecl(GoParser.MethodDeclContext context) { FunctionInfo functionInfo = ExitMethod(context); if (Parameters.TryGetValue(context.receiver().parameters(), out List <ParameterInfo> parameters)) { functionInfo.Signature = new MethodSignature(functionInfo.Signature) { ReceiverParameters = parameters.ToArray() }; } m_functions.Add(GetUniqueIdentifier(m_functions, functionInfo.Signature.Generate()), functionInfo); }
public override void EnterMethodDecl(GoParser.MethodDeclContext context) { m_inFunction = true; // May need to scope certain objects, like consts, to current function m_originalFunctionName = context.IDENTIFIER().GetText(); m_currentFunctionName = SanitizedIdentifier(m_originalFunctionName); // Function signature containing result type and parameters have not been visited yet, // so we mark their desired positions and replace once the visit has occurred m_functionResultTypeMarker = string.Format(FunctionResultTypeMarker, m_currentFunctionName); m_functionParametersMarker = string.Format(FunctionParametersMarker, m_currentFunctionName); m_functionExecContextMarker = string.Format(FunctionExecContextMarker, m_currentFunctionName); m_targetFile.AppendLine($"{Spacing()}{m_functionResultTypeMarker} {m_currentFunctionName}{m_functionParametersMarker}{m_functionExecContextMarker}"); }
public override void EnterMethodDecl(GoParser.MethodDeclContext context) { base.EnterMethodDecl(context); m_variableIdentifiers.Clear(); m_variableTypes.Clear(); if (CurrentFunction is null) { throw new InvalidOperationException($"Failed to find metadata for method function \"{CurrentFunctionName}\"."); } // Function signature containing result type and parameters have not been visited yet, // so we mark their desired positions and replace once the visit has occurred m_functionResultTypeMarker = string.Format(FunctionResultTypeMarker, CurrentFunctionName); m_functionParametersMarker = string.Format(FunctionParametersMarker, CurrentFunctionName); m_functionExecContextMarker = string.Format(FunctionExecContextMarker, CurrentFunctionName); PushInnerBlockPrefix(string.Format(FunctionBlockPrefixMarker, CurrentFunctionName)); m_targetFile.AppendLine($"{Spacing()}{m_functionResultTypeMarker} {CurrentFunctionName}{m_functionParametersMarker}{m_functionExecContextMarker}"); }
public override void EnterMethodDecl(GoParser.MethodDeclContext context) { m_inFunction = true; // May need to scope certain objects, like consts, to current function m_originalFunctionName = context.IDENTIFIER().GetText(); m_currentFunctionName = SanitizedIdentifier(m_originalFunctionName); m_variableIdentifiers.Clear(); m_variableTypes.Clear(); string receiverTypeName = context.receiver().parameters().parameterDecl()[0].type_().GetText().Replace("*", "ref "); string functionSignature = FunctionSignature.Generate(m_originalFunctionName, new[] { receiverTypeName }); if (!Metadata.Functions.TryGetValue(functionSignature, out m_currentFunction)) { throw new InvalidOperationException($"Failed to find metadata for method function \"{functionSignature}\"."); } // Function signature containing result type and parameters have not been visited yet, // so we mark their desired positions and replace once the visit has occurred m_functionResultTypeMarker = string.Format(FunctionResultTypeMarker, m_currentFunctionName); m_functionParametersMarker = string.Format(FunctionParametersMarker, m_currentFunctionName); m_functionExecContextMarker = string.Format(FunctionExecContextMarker, m_currentFunctionName); m_targetFile.AppendLine($"{Spacing()}{m_functionResultTypeMarker} {m_currentFunctionName}{m_functionParametersMarker}{m_functionExecContextMarker}"); }
public override void ExitMethodDecl(GoParser.MethodDeclContext context) { if (!(m_currentFunction.Signature is MethodSignature method)) { throw new InvalidOperationException($"Failed to find signature metadata for method function \"{m_currentFunctionName}\"."); } bool hasDefer = m_currentFunction.HasDefer; bool hasPanic = m_currentFunction.HasPanic; bool hasRecover = m_currentFunction.HasRecover; bool useFuncExecutionContext = hasDefer || hasPanic || hasRecover; Signature signature = method.Signature; string receiverParametersSignature = method.GenerateReceiverParametersSignature(useFuncExecutionContext); string parametersSignature = signature.GenerateParametersSignature(useFuncExecutionContext); string resultSignature = signature.GenerateResultSignature(); if (signature.Parameters.Length == 0) { parametersSignature = $"({receiverParametersSignature})"; } else { parametersSignature = $"({receiverParametersSignature}, {parametersSignature})"; } // Scope of an extension function is based on scope of the receiver type string scope = char.IsUpper(method.ReceiverParameters[0].Type.TypeName[0]) ? "public" : "private"; resultSignature = $"{scope} static {resultSignature}"; // Replace function markers m_targetFile.Replace(m_functionResultTypeMarker, resultSignature); m_targetFile.Replace(m_functionParametersMarker, parametersSignature); if (useFuncExecutionContext) { List <string> funcExecContextByRefParams = new List <string>(method.GetByRefReceiverParameters(false)); Stack <string> unusedNames = new Stack <string>(new[] { "__", "_" }); funcExecContextByRefParams.AddRange(signature.GetByRefParameters(false)); if (funcExecContextByRefParams.Count > 0) { List <string> lambdaByRefParameters = new List <string>(method.GetByRefReceiverParameters(true)); lambdaByRefParameters.AddRange(signature.GetByRefParameters(true)); m_targetFile.Replace(m_functionExecContextMarker, $" => func({string.Join(", ", funcExecContextByRefParams)}, ({string.Join(", ", lambdaByRefParameters)}, Defer {(hasDefer ? "defer" : unusedNames.Pop())}, Panic {(hasPanic ? "panic" : unusedNames.Pop())}, Recover {(hasRecover ? "recover" : unusedNames.Pop())}) =>"); } else { m_targetFile.Replace(m_functionExecContextMarker, $" => func(({(hasDefer ? "defer" : unusedNames.Pop())}, {(hasPanic ? "panic" : unusedNames.Pop())}, {(hasRecover ? "recover" : unusedNames.Pop())}) =>"); } } else { m_targetFile.Replace(m_functionExecContextMarker, ""); } m_currentFunction = null; m_currentFunctionName = null; m_originalFunctionName = null; m_inFunction = false; if (useFuncExecutionContext) { m_targetFile.Append(");"); } m_targetFile.Append(CheckForCommentsRight(context)); }
public override void EnterMethodDecl(GoParser.MethodDeclContext context) { EnterMethod(); }
public override void ExitMethodDecl(GoParser.MethodDeclContext context) { if (!(CurrentFunction.Signature is MethodSignature method)) { throw new InvalidOperationException($"Failed to find signature metadata for method function \"{CurrentFunctionName}\"."); } bool hasDefer = CurrentFunction.HasDefer; bool hasPanic = CurrentFunction.HasPanic; bool hasRecover = CurrentFunction.HasRecover; bool useFuncExecutionContext = hasDefer || hasPanic || hasRecover; Signature signature = method.Signature; string receiverParametersSignature = method.GenerateReceiverParametersSignature(); string parametersSignature = signature.GenerateParametersSignature(); string resultSignature = signature.GenerateResultSignature(); ParameterInfo[] receiverParameters = method.ReceiverParameters ?? Array.Empty <ParameterInfo>(); if (signature.Parameters.Length == 0) { parametersSignature = $"({receiverParametersSignature})"; } else { parametersSignature = $"({receiverParametersSignature}, {parametersSignature})"; } // Scope of an extension function is based on scope of the receiver type string receiverType = receiverParameters.Length > 0 ? receiverParameters[0].Type.TypeName : "object"; string scope = char.IsUpper(receiverType[0]) ? "public" : "private"; resultSignature = $"{scope} static {resultSignature}"; string blockPrefix = ""; StringBuilder resultParameters = new StringBuilder(); StringBuilder arrayClones = new StringBuilder(); StringBuilder implicitPointers = new StringBuilder(); foreach (ParameterInfo parameter in signature.Result) { if (!string.IsNullOrEmpty(parameter.Name)) { resultParameters.AppendLine($"{Spacing(1)}{parameter.Type.TypeName} {parameter.Name} = default{(parameter.Type is PointerTypeInfo || parameter.Type.TypeClass == TypeClass.Interface ? "!" : "")};"); } } foreach (ParameterInfo parameter in receiverParameters.Concat(signature.Parameters)) { // For any array parameters, Go copies the array by value if (parameter.Type.TypeClass == TypeClass.Array) { arrayClones.AppendLine($"{Spacing(1)}{parameter.Name} = {parameter.Name}.Clone();"); } // All pointers in Go can be implicitly dereferenced, so setup a "local ref" instance to each if (parameter.Type is PointerTypeInfo pointer) { implicitPointers.AppendLine($"{Spacing(1)}ref {pointer.TargetTypeInfo.TypeName} {parameter.Name} = ref {AddressPrefix}{parameter.Name}.val;"); } } if (resultParameters.Length > 0) { resultParameters.Insert(0, Environment.NewLine); blockPrefix += resultParameters.ToString(); } if (arrayClones.Length > 0) { if (blockPrefix.Length == 0) { arrayClones.Insert(0, Environment.NewLine); } blockPrefix += arrayClones.ToString(); } if (implicitPointers.Length > 0) { if (blockPrefix.Length == 0) { implicitPointers.Insert(0, Environment.NewLine); } blockPrefix += implicitPointers.ToString(); StringBuilder updatedSignature = new StringBuilder(); bool initialParam = true; foreach (ParameterInfo parameter in receiverParameters.Concat(signature.Parameters)) { if (initialParam) { updatedSignature.Append("this "); } else { updatedSignature.Append(", "); } initialParam = false; updatedSignature.Append($"{(parameter.IsVariadic ? "params " : "")}{parameter.Type.TypeName} "); if (parameter.Type is PointerTypeInfo) { updatedSignature.Append(AddressPrefix); } updatedSignature.Append(parameter.Name); } parametersSignature = $"({updatedSignature})"; } // Replace function markers m_targetFile.Replace(m_functionResultTypeMarker, resultSignature); m_targetFile.Replace(m_functionParametersMarker, parametersSignature); if (useFuncExecutionContext) { Stack <string> unusedNames = new Stack <string>(new[] { "__", "_" }); m_targetFile.Replace(m_functionExecContextMarker, $" => func(({(hasDefer ? "defer" : unusedNames.Pop())}, {(hasPanic ? "panic" : unusedNames.Pop())}, {(hasRecover ? "recover" : unusedNames.Pop())}) =>"); } else { m_targetFile.Replace(m_functionExecContextMarker, ""); } m_targetFile.Replace(string.Format(FunctionBlockPrefixMarker, CurrentFunctionName), blockPrefix); if (useFuncExecutionContext) { m_targetFile.Append(");"); } m_targetFile.Append(CheckForCommentsRight(context)); base.ExitMethodDecl(context); }
public override void ExitMethodDecl(GoParser.MethodDeclContext context) { bool signatureOnly = false; if (!Parameters.TryGetValue(context.receiver()?.parameters(), out List <ParameterInfo> receiverParameters) || (object)receiverParameters == null) { receiverParameters = new List <ParameterInfo>(); } if (Parameters.TryGetValue(context.signature()?.parameters(), out List <ParameterInfo> functionParameters) && (object)functionParameters != null) { signatureOnly = true; } else if (!Parameters.TryGetValue(context.signature()?.parameters(), out functionParameters) || (object)functionParameters == null) { functionParameters = new List <ParameterInfo>(); } IEnumerable <ParameterInfo> parameters = receiverParameters.Concat(functionParameters); string functionSignature = FunctionSignature.Generate(m_originalFunctionName, parameters); if (!Metadata.Functions.TryGetValue(functionSignature, out m_currentFunction)) { throw new InvalidOperationException($"Failed to find metadata for method function \"{functionSignature}\"."); } MethodSignature method = m_currentFunction.Signature as MethodSignature; if ((object)method == null) { throw new InvalidOperationException($"Failed to find signature metadata for method function \"{m_currentFunctionName}\"."); } bool hasDefer = m_currentFunction.HasDefer; bool hasPanic = m_currentFunction.HasPanic; bool hasRecover = m_currentFunction.HasRecover; bool useFuncExecutionContext = hasDefer || hasPanic || hasRecover; Signature signature = method.Signature; string receiverParametersSignature = method.GenerateReceiverParametersSignature(useFuncExecutionContext); string parametersSignature = signature.GenerateParametersSignature(useFuncExecutionContext); string resultSignature = signature.GenerateResultSignature(); if (signature.Parameters.Length == 0) { parametersSignature = $"({receiverParametersSignature})"; } else { parametersSignature = $"({receiverParametersSignature}, {parametersSignature})"; } // Scope of an extension function is based on scope of the receiver type string scope = char.IsUpper(method.ReceiverParameters[0].Type.TypeName[0]) ? "public" : "private"; resultSignature = $"{scope} static {resultSignature}"; // Replace function markers m_targetFile.Replace(m_functionResultTypeMarker, resultSignature); m_targetFile.Replace(m_functionParametersMarker, parametersSignature); if (useFuncExecutionContext) { List <string> funcExecContextByRefParams = new List <string>(method.GetByRefReceiverParameters(false)); funcExecContextByRefParams.AddRange(signature.GetByRefParameters(false)); if (funcExecContextByRefParams.Count > 0) { List <string> lambdaByRefParameters = new List <string>(method.GetByRefReceiverParameters(true)); lambdaByRefParameters.AddRange(signature.GetByRefParameters(true)); m_targetFile.Replace(m_functionExecContextMarker, $" => func({string.Join(", ", funcExecContextByRefParams)}, ({string.Join(", ", lambdaByRefParameters)}, Defer {(hasDefer ? "defer" : "_")}, Panic {(hasPanic ? "panic" : "_")}, Recover {(hasRecover ? "recover" : "_")}) =>"); } else { m_targetFile.Replace(m_functionExecContextMarker, $" => func(({(hasDefer ? "defer" : "_")}, {(hasPanic ? "panic" : "_")}, {(hasRecover ? "recover" : "_")}) =>"); } } else { m_targetFile.Replace(m_functionExecContextMarker, ""); } m_currentFunction = null; m_currentFunctionName = null; m_originalFunctionName = null; m_inFunction = false; if (useFuncExecutionContext) { m_targetFile.Append(");"); } else if (signatureOnly) { m_targetFile.Append(";"); } m_targetFile.Append(CheckForCommentsRight(context)); }