public override void EnterFunctionDecl(GoParser.FunctionDeclContext 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); string scope = char.IsUpper(m_originalFunctionName[0]) ? "public" : "private"; // Handle Go "main" function as a special case, in C# this should be capitalized "Main" if (m_currentFunctionName.Equals("main")) { m_currentFunctionName = "Main"; // Track file names that contain main function in main package if (Package.Equals("main")) { s_mainPackageFiles.Add(TargetFileName); } } // 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); PushInnerBlockPrefix(string.Format(FunctionBlockPrefixMarker, m_currentFunctionName)); m_targetFile.AppendLine($"{Spacing()}{scope} static {m_functionResultTypeMarker} {m_currentFunctionName}{m_functionParametersMarker}{m_functionExecContextMarker}"); }
public override void ExitFunctionDecl(GoParser.FunctionDeclContext context) { CurrentFunction = null; CurrentFunctionName = null; OriginalFunctionName = null; InFunction = false; }
public override void EnterFunctionDecl(GoParser.FunctionDeclContext context) { InFunction = true; OriginalFunctionName = context.IDENTIFIER()?.GetText() ?? "_"; CurrentFunctionName = SanitizedIdentifier(OriginalFunctionName); string functionSignature = FunctionSignature.Generate(OriginalFunctionName); FunctionInfo currentFunction = null; Metadata?.Functions.TryGetValue(functionSignature, out currentFunction); CurrentFunction = currentFunction; }
public override void ExitFunctionDecl(GoParser.FunctionDeclContext context) { FunctionInfo functionInfo = ExitMethod(context); if (functionInfo is null) { return; } m_functions.Add(GetUniqueIdentifier(m_functions, functionInfo.Signature.GenerateLookup()), functionInfo); base.ExitFunctionDecl(context); }
public override void EnterFunctionDecl(GoParser.FunctionDeclContext 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 functionSignature = FunctionSignature.Generate(m_originalFunctionName); if (!Metadata.Functions.TryGetValue(functionSignature, out m_currentFunction)) { throw new InvalidOperationException($"Failed to find metadata for method function \"{functionSignature}\"."); } FunctionSignature function = m_currentFunction.Signature; if (function is null) { throw new InvalidOperationException($"Failed to find signature metadata for function \"{m_currentFunctionName}\"."); } string scope = char.IsUpper(m_originalFunctionName[0]) ? "public" : "private"; // Handle Go "main" function as a special case, in C# this should be capitalized "Main" if (m_currentFunctionName.Equals("main")) { m_currentFunctionName = "Main"; // Track file names that contain main function in main package if (Package.Equals("main")) { s_mainPackageFiles.Add(TargetFileName); } } // 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); PushInnerBlockPrefix(string.Format(FunctionBlockPrefixMarker, m_currentFunctionName)); m_targetFile.AppendLine($"{Spacing()}{scope} static {m_functionResultTypeMarker} {m_currentFunctionName}{m_functionParametersMarker}{m_functionExecContextMarker}"); }
public override void EnterFunctionDecl(GoParser.FunctionDeclContext context) { base.EnterFunctionDecl(context); m_variableIdentifiers.Clear(); m_variableTypes.Clear(); if (CurrentFunction is null) { throw new InvalidOperationException($"Failed to find metadata for function \"{CurrentFunctionName}\"."); } FunctionSignature function = CurrentFunction.Signature; if (function is null) { throw new InvalidOperationException($"Failed to find signature metadata for function \"{CurrentFunctionName}\"."); } string scope = char.IsUpper(OriginalFunctionName[0]) ? "public" : "private"; // Handle Go "main" function as a special case, in C# this should be capitalized "Main" if (CurrentFunctionName.Equals("main")) { CurrentFunctionName = "Main"; // Track file names that contain main function in main package if (Package.Equals("main")) { s_mainPackageFiles.Add(TargetFileName); } } // 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()}{scope} static {m_functionResultTypeMarker} {CurrentFunctionName}{m_functionParametersMarker}{m_functionExecContextMarker}"); }
public override void ExitFunctionDecl(GoParser.FunctionDeclContext context) { bool signatureOnly = false; if (Parameters.TryGetValue(context.signature()?.parameters(), out List <ParameterInfo> parameters) && (object)parameters != null) { signatureOnly = true; } else if (!Parameters.TryGetValue(context.signature()?.parameters(), out parameters) || (object)parameters == null) { parameters = new List <ParameterInfo>(); } 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}\"."); } FunctionSignature function = m_currentFunction.Signature; if ((object)function == null) { throw new InvalidOperationException($"Failed to find signature metadata for 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 = function.Signature; string parametersSignature = $"({signature.GenerateParametersSignature(useFuncExecutionContext)})"; string resultSignature = signature.GenerateResultSignature(); // Replace function markers m_targetFile.Replace(m_functionResultTypeMarker, resultSignature); m_targetFile.Replace(m_functionParametersMarker, parametersSignature); if (useFuncExecutionContext) { string[] funcExecContextByRefParams = signature.GetByRefParameters(false).ToArray(); if (funcExecContextByRefParams.Length > 0) { string[] lambdaByRefParameters = signature.GetByRefParameters(true).ToArray(); 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, ""); } string blockPrefix = ""; if (!signatureOnly) { // For any array parameters, Go copies the array by value StringBuilder arrayClones = new StringBuilder(); foreach (ParameterInfo parameter in signature.Parameters) { if (parameter.Type.TypeClass == TypeClass.Array) { arrayClones.AppendLine($"{Spacing(1)}{parameter.Name} = {parameter.Name}.Clone();"); } } if (arrayClones.Length > 0) { arrayClones.Insert(0, Environment.NewLine); blockPrefix = arrayClones.ToString(); } } m_targetFile.Replace(string.Format(FunctionBlockPrefixMarker, m_currentFunctionName), blockPrefix); 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)); }
public override void ExitFunctionDecl(GoParser.FunctionDeclContext context) { FunctionInfo functionInfo = ExitMethod(context); m_functions.Add(GetUniqueIdentifier(m_functions, functionInfo.Signature.Generate()), functionInfo); }
public override void EnterFunctionDecl(GoParser.FunctionDeclContext context) { EnterMethod(); }
public override void ExitFunctionDecl(GoParser.FunctionDeclContext context) { bool signatureOnly = context.block() is null; FunctionSignature function = CurrentFunction.Signature; bool hasDefer = CurrentFunction.HasDefer; bool hasPanic = CurrentFunction.HasPanic; bool hasRecover = CurrentFunction.HasRecover; bool useFuncExecutionContext = hasDefer || hasPanic || hasRecover; Signature signature = function.Signature; string parametersSignature = $"({signature.GenerateParametersSignature()})"; string resultSignature = signature.GenerateResultSignature(); string blockPrefix = ""; if (!signatureOnly) { 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 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 signature.Parameters) { if (!initialParam) { 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(");"); } else if (signatureOnly) { m_targetFile.Append(";"); } m_targetFile.Append(CheckForCommentsRight(context)); base.ExitFunctionDecl(context); }
public override void ExitFunctionDecl(GoParser.FunctionDeclContext context) { bool signatureOnly = context.block() is null; FunctionSignature function = m_currentFunction.Signature; bool hasDefer = m_currentFunction.HasDefer; bool hasPanic = m_currentFunction.HasPanic; bool hasRecover = m_currentFunction.HasRecover; bool useFuncExecutionContext = hasDefer || hasPanic || hasRecover; Signature signature = function.Signature; string parametersSignature = $"({signature.GenerateParametersSignature(useFuncExecutionContext)})"; string resultSignature = signature.GenerateResultSignature(); // Replace function markers m_targetFile.Replace(m_functionResultTypeMarker, resultSignature); m_targetFile.Replace(m_functionParametersMarker, parametersSignature); if (useFuncExecutionContext) { string[] funcExecContextByRefParams = signature.GetByRefParameters(false).ToArray(); Stack <string> unusedNames = new Stack <string>(new[] { "__", "_" }); if (funcExecContextByRefParams.Length > 0) { string[] lambdaByRefParameters = signature.GetByRefParameters(true).ToArray(); 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, ""); } string blockPrefix = ""; if (!signatureOnly) { // TODO: Double check if any other types need clone-type copy operations // For any array parameters, Go copies the array by value StringBuilder arrayClones = new StringBuilder(); foreach (ParameterInfo parameter in signature.Parameters) { if (parameter.Type.TypeClass == TypeClass.Array) { arrayClones.AppendLine($"{Spacing(1)}{parameter.Name} = {parameter.Name}.Clone();"); } } if (arrayClones.Length > 0) { arrayClones.Insert(0, Environment.NewLine); blockPrefix = arrayClones.ToString(); } } m_targetFile.Replace(string.Format(FunctionBlockPrefixMarker, m_currentFunctionName), blockPrefix); 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)); }