示例#1
0
 /// <summary>
 /// Promotes types of arguments to match signature if possible.
 /// </summary>
 /// <param name="signature">The signature to match the types to.</param>
 /// <param name="argumentNodes">The types to promote.</param>
 internal static void TypePromoteArguments(FunctionSignature signature, List<QueryNode> argumentNodes)
 {
     // Convert all argument nodes to the best signature argument type
     Debug.Assert(signature.ArgumentTypes.Length == argumentNodes.Count, "The best signature match doesn't have the same number of arguments.");
     for (int i = 0; i < argumentNodes.Count; i++)
     {
         Debug.Assert(argumentNodes[i] is SingleValueNode, "We should have already verified that all arguments are single values.");
         SingleValueNode argumentNode = (SingleValueNode)argumentNodes[i];
         IEdmTypeReference signatureArgumentType = signature.ArgumentTypes[i];
         Debug.Assert(signatureArgumentType.IsODataPrimitiveTypeKind(), "Only primitive types should be able to get here.");
         argumentNodes[i] = MetadataBindingUtils.ConvertToTypeIfNeeded(argumentNode, signatureArgumentType);
     }
 }
示例#2
0
 public void FinalizeGeneration()
 {
     TypeBuilder.CreateType();
     FunctionSignature main = new FunctionSignature();
     main.Ident = "Main";
     main.ParamList = new List<VariableNode>();
     main.ReturnType = "Void";
     if (!FunctionTable.Keys.Contains(main))
     {
         ErrorHandler.RaiseError(new Error(0, "No Main function found."));
         return;
     }
     Console.WriteLine("Code generation successful; finalizing types..");
     AsmBuilder.SetEntryPoint(FunctionTable[main]);
     AsmBuilder.Save(path);
     Console.WriteLine("Compilation successful! Program can be found at {0}", path);
 }
示例#3
0
        public void ValidateFunctionBindingArguments_ReturnBinding_Succeeds()
        {
            Collection <FunctionParameter> parameters = new Collection <FunctionParameter>()
            {
                new FunctionParameter("input", "String", false, RefKind.None)
            };
            FunctionSignature signature = new FunctionSignature("Test", "Test", ImmutableArray.CreateRange <FunctionParameter>(parameters), "Test", false);

            var host = new HostBuilder().ConfigureDefaultTestWebScriptHost(b =>
            {
                b.AddAzureStorage();
            }).Build();

            Collection <FunctionBinding> inputBindings = new Collection <FunctionBinding>()
            {
                TestHelpers.CreateBindingFromHost(host, new JObject
                {
                    { "type", "blobTrigger" },
                    { "name", "input" },
                    { "direction", "in" },
                    { "path", "test" }
                })
            };

            Collection <FunctionBinding> outputBindings = new Collection <FunctionBinding>()
            {
                TestHelpers.CreateBindingFromHost(host, new JObject
                {
                    { "type", "blob" },
                    { "name", ScriptConstants.SystemReturnParameterBindingName },
                    { "direction", "out" },
                    { "path", "test/test" }
                })
            };

            var diagnostics = DotNetFunctionInvoker.ValidateFunctionBindingArguments(signature, "input", inputBindings, outputBindings);

            Assert.Equal(0, diagnostics.Count());
        }
示例#4
0
        private static Node GetRegisterServer(string typeName)
        {
            var logParamName = "log";

            var func = FunctionSignature.Generate(null, "RegisterServer", new[]
            {
                new FuncParamSig(logParamName, TypeModifier.ByReference, "log.Logger")
            }, null);
            var funcBody = new OpenDelimiter(BinaryDelimiterType.Brace);

            funcBody.AddChild(BinaryOpSequence.Generate(BinaryOperatorType.Assignment, new Identifier(LoggerVarName), new Identifier(logParamName)));
            funcBody.AddChild(new Terminal());

            funcBody.AddChild(FunctionCall.Generate("rpc.Register", new[]
            {
                new FuncCallParam(StructLiteral.Generate(typeName, null), TypeModifier.ByReference)
            }));

            funcBody.AddClosingDelimiter();
            func.AddChild(funcBody);

            return(func);
        }
示例#5
0
        public void FunctionSignatureKnowsHowToParseRetardedSignatures()
        {
            //function retarded_func(b: strings = "thing","", c: integer) :: string
            var ctx = ParseContext.FromCode(
                "function retarded_func(b: strings = \"thing\",\"\", c: integer) :: string");
            var signature = FunctionSignature.TryParse(ctx);

            Assert.NotNull(signature);
            Assert.Equal(2, signature.Parameters.Count);

            var firstParam = signature.Parameters[0];

            Assert.Equal("b", firstParam.Name);
            Assert.Equal("strings", firstParam.Type.FinalTypeName);
            Assert.Equal("thing", firstParam.DefaultValue.GetExplicitValue <string>(0).GenericValue);
            Assert.Equal(string.Empty, firstParam.DefaultValue.GetExplicitValue <string>(1).GenericValue);


            var secondParam = signature.Parameters[1];

            Assert.Equal("c", secondParam.Name);
            Assert.Equal("integer", secondParam.Type.FinalTypeName);
        }
示例#6
0
        /// <inheritdoc/>
        public IEnumerable <FunctionSignature> CreateOverloads(FunctionSignature function)
        {
            var arrayParameter     = function.Parameters.Last();
            var arrayParameterType = arrayParameter.Type;

            var newName       = function.Name.Singularize(false);
            var newParameters = SkipLastExtension.SkipLast(new List <ParameterSignature>(function.Parameters), 2).ToList();

            var newArrayParameterType = new TypeSignatureBuilder(arrayParameterType)
                                        .WithArrayDimensions(0)
                                        .WithIndirectionLevel(0)
                                        .Build();

            var newArrayParameter = new ParameterSignatureBuilder(arrayParameter)
                                    .WithType(newArrayParameterType)
                                    .Build();

            newParameters.Add(newArrayParameter);

            yield return(new FunctionSignatureBuilder(function)
                         .WithName(newName)
                         .WithParameters(newParameters)
                         .Build());
        }
        public FunctionSignature GetEntryPointSignature(IFunctionEntryPointResolver entryPointResolver)
        {
            EnsureAssemblyOption();

            // Scrape the compiled assembly for entry points
            IList<MethodReference<MethodInfo>> methods =
                            _assemblyOption.Value.GetTypes().SelectMany(t =>
                                t.GetMethods().Select(m =>
                                    new MethodReference<MethodInfo>(m.Name, m.IsPublic, m))).ToList();

            MethodInfo entryPointReference = entryPointResolver.GetFunctionEntryPoint(methods).Value;

            // For F#, this currently creates a malformed signautre with fewer parameter symbols than parameter names.
            // For validation we only need the parameter names. The implementation of DotNetFunctionSignature copes with the 
            // lists having different lengths.
            var parameters = entryPointReference.GetParameters().Select(x => new FunctionParameter(x.Name, x.ParameterType.FullName, x.IsOptional, GetParameterRefKind(x)));
            // For F#, we always set this to true for now.
            bool hasLocalTypeReference = true;

            var signature = new FunctionSignature(entryPointReference.DeclaringType.Name, entryPointReference.Name,
                parameters.ToImmutableArray(), entryPointReference.ReturnType.Name, hasLocalTypeReference);

            return signature;
        }
示例#8
0
        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}");
        }
示例#9
0
 /// <inheritdoc/>
 public bool IsApplicable(FunctionSignature function)
 {
     return(function.ReturnType.IsVoidPointer());
 }
示例#10
0
 public FunctionSignatureStartState(Variable functionName)
 {
     _functionSignature = new FunctionSignature(functionName);
 }
示例#11
0
        private void WriteDocumentation([NotNull] SourceWriter sw, [NotNull] FunctionSignature function)
        {
            if (!_documentation.TryGetDocumentation(function, out var documentation))
            {
                Debug.WriteLine
                (
                    $"The function \"{function.Name}\" lacks documentation. Consider adding a documentation file for " +
                    $"the function."
                );

                WritePlaceholderDocumentation(sw, function);
                return;
            }

            sw.WriteLine("/// <summary>");
            var summaryLines = documentation.Purpose.TrimEnd().Split('\n');

            foreach (var summaryLine in summaryLines)
            {
                sw.WriteLine($"/// {summaryLine}");
            }

            sw.WriteLine("/// </summary>");

            for (int i = 0; i < function.Parameters.Count; ++i)
            {
                var parameter = function.Parameters[i];
                var parameterDocumentation = documentation.Parameters.FirstOrDefault(dp => dp.Name == parameter.Name);
                if (parameterDocumentation is null)
                {
                    sw.WriteLine($"/// <param name=\"{parameter.Name}\">This parameter lacks documentation.</param>");
                    continue;
                }

                // XML documentation doesn't require keyword escaping.
                if (parameter.Name.TrimStart('@') != parameterDocumentation.Name)
                {
                    Debug.WriteLine
                    (
                        $"Parameter {parameter.Name} in function {function.Name} has incorrect documentation name " +
                        $"{parameterDocumentation.Name}."
                    );
                }

                sw.WriteLine($"/// <param name=\"{parameterDocumentation.Name}\">");
                if (!(parameter.Count is null))
                {
                    if (parameter.Count.IsStatic)
                    {
                        sw.WriteLine($"/// This parameter contains {parameter.Count.Count} elements.");
                        sw.WriteLine("///");
                    }

                    if (parameter.Count.IsComputed)
                    {
                        var parameterList = parameter.Count.ComputedFrom.Select(cf => cf.Name).Humanize();
                        sw.WriteLine($"/// This parameter's element count is computed from {parameterList}.");
                        sw.WriteLine("///");
                    }

                    if (parameter.Count.IsReference)
                    {
                        // ReSharper disable once PossibleNullReferenceException
                        sw.WriteLine($"/// This parameter's element count is taken from {parameter.Count.ValueReference.Name}.");
                        sw.WriteLine("///");
                    }
                }

                var descriptionLines = parameterDocumentation.Description.TrimEnd().Split('\n');
                foreach (var descriptionLine in descriptionLines)
                {
                    sw.WriteLine($"/// {descriptionLine}");
                }

                sw.WriteLine("/// </param>");
            }

            foreach (var genericTypeParameter in function.GenericTypeParameters)
            {
                var referencingParameter = function.Parameters.First(f => f.Type.Name == genericTypeParameter.Name);
                sw.WriteLine
                (
                    $"/// <typeparam name=\"{genericTypeParameter.Name}\">The generic type of " +
                    $"{referencingParameter.Name}.</typeparam>"
                );
            }

            if (!function.ReturnType.Name.Equals(typeof(void).Name, StringComparison.OrdinalIgnoreCase))
            {
                sw.WriteLine("/// <returns>See online documentation.</returns>");
            }
        }
示例#12
0
        public override void ExitFunctionDecl(GolangParser.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.function()?.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, "");
            }

            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(CheckForBodyCommentsRight(context));
        }
        private static (FunctionSignature, StringBuilder) ToPointer(FunctionSignature function, FunctionSignature old)
        {
            var sb = new StringBuilder();

            if (function.ReturnType.ToString() != "void")
            {
                sb.Append("return ");
            }

            sb.Append(function.Name + "(");
            var list = new List <string>();

            foreach (var param in old.Parameters)
            {
                var nm = Utilities.CSharpKeywords.Contains(param.Name) ? "@" + param.Name : param.Name;
                if (param.Type.IsVoidPointer())
                {
                    list.Add(nm + ".ToPointer()");
                }
                else
                {
                    list.Add(nm);
                }
            }

            sb.Append(string.Join(", ", list));
            sb.AppendLine(");");
            return(function, sb);
        }
        internal static ImmutableArray<Diagnostic> ValidateFunctionBindingArguments(FunctionSignature functionSignature, string triggerInputName,
            Collection<FunctionBinding> inputBindings, Collection<FunctionBinding> outputBindings,
            ImmutableArray<Diagnostic>.Builder builder = null, bool throwIfFailed = false)
        {
            var resultBuilder = builder ?? ImmutableArray<Diagnostic>.Empty.ToBuilder();

            if (!functionSignature.Parameters.Any(p => string.Compare(p.Name, triggerInputName, StringComparison.Ordinal) == 0))
            {
                string message = string.Format(CultureInfo.InvariantCulture, "Missing a trigger argument named '{0}'.", triggerInputName);
                var descriptor = new DiagnosticDescriptor(DotNetConstants.MissingTriggerArgumentCompilationCode,
                    "Missing trigger argument", message, "AzureFunctions", DiagnosticSeverity.Error, true);

                resultBuilder.Add(Diagnostic.Create(descriptor, Location.None));
            }

            var bindings = inputBindings.Where(b => !b.Metadata.IsTrigger).Union(outputBindings);

            foreach (var binding in bindings)
            {
                if (string.Compare("http", binding.Metadata.Type, StringComparison.OrdinalIgnoreCase) == 0)
                {
                    continue;
                }

                if (binding.Metadata.IsReturn)
                {
                    continue;
                }

                if (!functionSignature.Parameters.Any(p => string.Compare(p.Name, binding.Metadata.Name, StringComparison.Ordinal) == 0))
                {
                    string message = string.Format(CultureInfo.InvariantCulture,
                        "Missing binding argument named '{0}'. Mismatched binding argument names may lead to function indexing errors.", binding.Metadata.Name);

                    var descriptor = new DiagnosticDescriptor(DotNetConstants.MissingBindingArgumentCompilationCode,
                        "Missing binding argument", message, "AzureFunctions", DiagnosticSeverity.Warning, true);

                    resultBuilder.Add(Diagnostic.Create(descriptor, Location.None));
                }
            }

            ImmutableArray<Diagnostic> result = resultBuilder.ToImmutable();

            if (throwIfFailed && result.Any(d => d.Severity == DiagnosticSeverity.Error))
            {
                throw new CompilationErrorException("Function compilation failed.", result);
            }

            return resultBuilder.ToImmutable();
        }
示例#15
0
 public FunctionOpBinding(Func <Op> builder, FunctionSignature signature) : base(builder)
 {
     Signature = signature;
 }
示例#16
0
 /// <summary>
 /// Determines whether or not the given function has any generic enum parameters, including the return
 /// parameter.
 /// </summary>
 /// <param name="f">The function.</param>
 /// <returns>true if the function has generic enum parameters; otherwise, false.</returns>
 private bool HasGenericEnumParameters([NotNull] FunctionSignature f)
 {
     return(f.Parameters.Any(p => p.Type.Name == "GLenum") || f.ReturnType.Name == "GLenum");
 }
示例#17
0
 public FunctionSignatureEndState(FunctionSignature functionSignature)
 {
     _functionSignature = functionSignature;
 }
示例#18
0
        internal FunctionEmitter(IR.Function function, MethodFactory methodFactory, FunctionLookup functionLookup)
        {
            Contract.Requires(function != null);
            Contract.Requires(methodFactory != null);
            Contract.Requires(functionLookup != null);

            this.declaration    = function;
            this.functionLookup = functionLookup;
            var signature = new FunctionSignature(function.Inputs.Select(i => i.StaticRepr), function.Outputs.Select(o => o.StaticRepr));

            // Determine the method signature
            var parameterDescriptors = new List <ParameterDescriptor>();

            foreach (var input in function.Inputs)
            {
                locals.Add(input, VariableLocation.Parameter(parameterDescriptors.Count));
                parameterDescriptors.Add(new ParameterDescriptor(input.StaticCliType, ParameterAttributes.None, input.Name));
            }

            Type returnType = typeof(void);

            if (function.Outputs.Length == 1)
            {
                returnType = function.Outputs[0].StaticCliType;                 // 1 output, use return value
            }
            else if (function.Outputs.Length >= 2)
            {
                // 2 or more outputs, use 'out' parameters
                foreach (var output in function.Outputs)
                {
                    string name = output.Name;
                    if (locals.ContainsKey(output))
                    {
                        // inout parameter, rename not to clash with input
                        name += "$out";
                    }
                    else
                    {
                        locals.Add(output, VariableLocation.Parameter(parameterDescriptors.Count));
                    }

                    var parameterType = output.StaticCliType.MakeByRefType();
                    parameterDescriptors.Add(new ParameterDescriptor(parameterType, ParameterAttributes.Out, name));
                }
            }

            // Create the method and get its IL generator
            ILGenerator ilGenerator;
            var         methodInfo = methodFactory(function.Name, parameterDescriptors, returnType, out ilGenerator);

            this.method = new FunctionMethod(methodInfo, signature);

            cil = new ILGeneratorMethodBodyWriter(ilGenerator);
            cil = new MethodBodyVerifier(new MethodBodyVerificationContext
            {
                Method         = methodInfo,
                ParameterTypes = parameterDescriptors.Select(p => p.Type).ToArray(),
                ReturnType     = returnType,
                HasInitLocals  = true,
                MaxStackSize   = ushort.MaxValue
            }, cil);

            temporaryPool = new TemporaryLocalPool(cil, "$temp");

            if (function.Outputs.Length == 1)
            {
                // Declare a local variable for the return value
                var output     = function.Outputs[0];
                var localIndex = cil.DeclareLocal(output.StaticCliType, output.Name);
                if (!function.Inputs.Contains(output))
                {
                    locals.Add(output, VariableLocation.Local(localIndex));
                }
            }
        }
 public IntermediateConverter(WasmModule wasmModule, FunctionBody function, FunctionSignature signature)
 {
     this.wasmModule = wasmModule;
     this.function   = function;
     this.signature  = signature;
 }
 public FunctionArgumentReadingState(FunctionSignature functionSignature, Symbol symbol)
 {
     _functionSignature = functionSignature;
     _bracketsBalance   = 1;
     _argumentBuilder   = new LexemeBuilder(symbol);
 }
 public FunctionDocumentation GetDocumentation([NotNull] FunctionSignature function)
 {
     return(_documentedFunctions[function.NativeEntrypoint]);
 }
示例#22
0
 public Call(FunctionSignature signature)
 {
     Signature = signature;
 }
 /// <summary>
 /// Determines whether or not a given function is documented.
 /// </summary>
 /// <param name="function">The function.</param>
 /// <returns>true if the function has documentation; otherwise, false.</returns>
 public bool HasDocumentation([NotNull] FunctionSignature function)
 {
     return(_documentedFunctions.ContainsKey(function.NativeEntrypoint));
 }
示例#24
0
        public override void ExitMethodDecl(GolangParser.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.function()?.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));
        }
        private async Task<MethodInfo> CreateFunctionTarget(CancellationToken cancellationToken)
        {
            try
            {
                await VerifyPackageReferencesAsync();

                string eventName = string.Format(MetricEventNames.FunctionCompileLatencyByLanguageFormat, _compilationService.Language);
                using (_metricsLogger.LatencyEvent(eventName))
                {
                    ICompilation compilation = _compilationService.GetFunctionCompilation(Metadata);

                    Assembly assembly = compilation.EmitAndLoad(cancellationToken);
                    _assemblyLoader.CreateOrUpdateContext(Metadata, assembly, _metadataResolver, TraceWriter);

                    FunctionSignature functionSignature = compilation.GetEntryPointSignature(_functionEntryPointResolver);

                    ImmutableArray<Diagnostic> bindingDiagnostics = ValidateFunctionBindingArguments(functionSignature, _triggerInputName, _inputBindings, _outputBindings, throwIfFailed: true);
                    TraceCompilationDiagnostics(bindingDiagnostics);

                    // Set our function entry point signature
                    _functionSignature = functionSignature;
                    System.Reflection.TypeInfo scriptType = assembly.DefinedTypes
                        .FirstOrDefault(t => string.Compare(t.Name, functionSignature.ParentTypeName, StringComparison.Ordinal) == 0);

                    return _functionEntryPointResolver.GetFunctionEntryPoint(scriptType.DeclaredMethods.ToList());
                }
            }
            catch (CompilationErrorException exc)
            {
                ImmutableArray<Diagnostic> diagnostics = AddFunctionDiagnostics(exc.Diagnostics);

                // Here we only need to trace to system logs
                TraceCompilationDiagnostics(diagnostics, LogTargets.System);

                throw new CompilationErrorException(exc.Message, diagnostics);
            }
        }
示例#26
0
 public FunctionInfo(FunctionSignature signature, SprakType returnType)
 {
     Signature  = signature;
     ReturnType = returnType;
 }
 public FunctionDefinition(FunctionExec exec, FunctionSignature signature)
 {
     Exec      = exec;
     Signature = signature;
 }
示例#28
0
 /// <summary>
 /// Determines whether or not a given function signature has an applicable stage.
 /// </summary>
 /// <param name="signature">The signature.</param>
 /// <returns>True if the function has an applicable stage; otherwise, false.</returns>
 public bool HasApplicableStage(FunctionSignature signature)
 {
     return(_pipeline.Any(s => s.IsApplicable(signature)));
 }
示例#29
0
        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));
        }
示例#30
0
 public InterfaceMethod(InterfaceTypeDefinition typeDef, FunctionSignature sig)
 {
     _def = new InterfaceMethodDefinition(typeDef, sig.FunctionName, sig, sig.ReturnDataType);
 }
 public FunctionSignature MakeBindingFor(FunctionDefinitionSyntax syntax, FunctionSignature value)
 {
     FunctionSignaturesBindings[syntax] = value;
     return(value);
 }
示例#32
0
 public ItemWrapper(int location, FunctionSignature signature)
 {
     Location  = location.ToString();
     Signature = signature.ToString();
 }
        /// <inheritdoc/>
        public IEnumerable <(FunctionSignature, StringBuilder)> CreateOverloads(FunctionSignature function)
        {
            if (!function.Parameters.Any(p => p.Type.IsVoidPointer()))
            {
                yield break;
            }

            var baseParameters = function.Parameters;

            var newIntPtrParameters         = new List <ParameterSignature>(baseParameters);
            var newGenericArray1DParameters = new List <ParameterSignature>(baseParameters);
            var newGenericArray2DParameters = new List <ParameterSignature>(baseParameters);
            var newGenericArray3DParameters = new List <ParameterSignature>(baseParameters);

            var newGenericTypeParameters = new List <GenericTypeParameterSignature>();

            for (var i = 0; i < baseParameters.Count; ++i)
            {
                var parameter = baseParameters[i];
                if (!parameter.Type.IsVoidPointer())
                {
                    continue;
                }

                var genericTypeParameterName = baseParameters.Count(p => p.Type.IsVoidPointer()) > 1
                    ? $"T{newGenericTypeParameters.Count + 1}" : "T";

                var genericTypeParameter = new GenericTypeParameterSignature(
                    genericTypeParameterName,
                    new[] { "unmanaged" });

                newGenericTypeParameters.Add(genericTypeParameter);

                var newIntPtrParameterType = new TypeSignatureBuilder(parameter.Type)
                                             .WithIndirectionLevel(0)
                                             .WithName(nameof(IntPtr))
                                             .Build();

                // TODO: Simplify and generalize this
                var newGenericArray1DParameterType = new TypeSignatureBuilder(parameter.Type)
                                                     .WithIndirectionLevel(0)
                                                     .WithArrayDimensions(1)
                                                     .WithName(genericTypeParameterName)
                                                     .Build();

                var newGenericArray2DParameterType = new TypeSignatureBuilder(parameter.Type)
                                                     .WithIndirectionLevel(0)
                                                     .WithArrayDimensions(2)
                                                     .WithName(genericTypeParameterName)
                                                     .Build();

                var newGenericArray3DParameterType = new TypeSignatureBuilder(parameter.Type)
                                                     .WithIndirectionLevel(0)
                                                     .WithArrayDimensions(3)
                                                     .WithName(genericTypeParameterName)
                                                     .Build();

                newIntPtrParameters[i] = new ParameterSignatureBuilder(parameter)
                                         .WithType(newIntPtrParameterType)
                                         .Build();

                newGenericArray1DParameters[i] = new ParameterSignatureBuilder(parameter)
                                                 .WithType(newGenericArray1DParameterType)
                                                 .Build();

                newGenericArray2DParameters[i] = new ParameterSignatureBuilder(parameter)
                                                 .WithType(newGenericArray2DParameterType)
                                                 .Build();

                newGenericArray3DParameters[i] = new ParameterSignatureBuilder(parameter)
                                                 .WithType(newGenericArray3DParameterType)
                                                 .Build();
            }

            yield return(ToPointer
                         (
                             new FunctionSignatureBuilder(function)
                             .WithParameters(newIntPtrParameters)
                             .Build(),
                             function
                         ));

            yield return(Fixed
                         (
                             new FunctionSignatureBuilder(function)
                             .WithParameters(newGenericArray1DParameters)
                             .WithGenericTypeParameters(newGenericTypeParameters)
                             .Build()
                         ));

            yield return(Fixed
                         (
                             new FunctionSignatureBuilder(function)
                             .WithParameters(newGenericArray2DParameters)
                             .WithGenericTypeParameters(newGenericTypeParameters)
                             .Build()
                         ));

            yield return(Fixed
                         (
                             new FunctionSignatureBuilder(function)
                             .WithParameters(newGenericArray3DParameters)
                             .WithGenericTypeParameters(newGenericTypeParameters)
                             .Build()
                         ));
        }
示例#34
0
        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);
        }
示例#35
0
 public ReturnInstruction(FunctionSignature signature)
 {
     this.signature = signature;
 }
        public void ValidateFunctionBindingArguments_ReturnBinding_Succeeds()
        {
            Collection<FunctionParameter> parameters = new Collection<FunctionParameter>()
            {
                new FunctionParameter("input", "String", false, RefKind.None)
            };
            FunctionSignature signature = new FunctionSignature("Test", "Test", ImmutableArray.CreateRange<FunctionParameter>(parameters), "Test", false);

            Collection<FunctionBinding> inputBindings = new Collection<FunctionBinding>()
            {
                TestHelpers.CreateTestBinding(new JObject
                {
                    { "type", "blobTrigger" },
                    { "name", "input" },
                    { "direction", "in" },
                    { "path", "test" }
                })
            };
            Collection<FunctionBinding> outputBindings = new Collection<FunctionBinding>()
            {
                TestHelpers.CreateTestBinding(new JObject
                {
                    { "type", "blob" },
                    { "name", ScriptConstants.SystemReturnParameterBindingName },
                    { "direction", "out" },
                    { "path", "test/test" }
                })
            };
            var diagnostics = DotNetFunctionInvoker.ValidateFunctionBindingArguments(signature, "input", inputBindings, outputBindings);
            Assert.Equal(0, diagnostics.Count());
        }