public static bool ValidateParameters(Context context, Scope scope,
                                              FunctionParameterDefinitionStatement[] schemeParameters, EvaluationStatement[] parameters,
                                              out Exception exception
                                              )
        {
            var passedCount   = parameters?.Length ?? 0;
            var expectedCount = schemeParameters?.Length ?? 0;

            if (passedCount != expectedCount)
            {
                exception = new InvalidFunctionCallParametersCompilerException(expectedCount, passedCount, null);
                return(false);
            }

            if (parameters != null && schemeParameters != null)
            {
                for (var i = 0; i < parameters.Length; i++)
                {
                    var passed = parameters[i];
                    var scheme = schemeParameters[i];

                    var passedType = passed.GetDataType(context, scope);
                    if (!StatementHelpers.IsAssignableFrom(context, scope, scheme.TypeDescriptor, passedType))
                    {
                        if (scheme.DynamicType)
                        {
                            continue;
                        }

                        exception = new TypeMismatchCompilerException(passedType, scheme.TypeDescriptor, passed.Info);
                        return(false);
                    }
                }
            }

            exception = null;
            return(true);
        }
        public override void WriteBlock(Context context, Scope scope, TextWriter writer,
                                        TextWriter metaWriter,
                                        IStatement statement)
        {
            if (!(statement is VariableDefinitionStatement varDefStt))
            {
                throw new InvalidOperationException();
            }

            if (varDefStt.IsConstant)
            {
                if (!varDefStt.HasDefaultValue)
                {
                    throw new InvalidOperationException();
                }

                var result =
                    EvaluationStatementTranspilerBase.ProcessEvaluation(context, scope, varDefStt.DefaultValue);

                if (!(result is ConstantValueStatement constantValueStatement))
                {
                    throw new InvalidOperationException(ErrorMessages.ConstantValueRequired);
                }

                if (!StatementHelpers.IsAssignableFrom(context, scope, varDefStt.TypeDescriptor,
                                                       constantValueStatement.TypeDescriptor))
                {
                    throw new TypeMismatchCompilerException(constantValueStatement.TypeDescriptor,
                                                            varDefStt.TypeDescriptor, varDefStt.Info);
                }

                scope.ReserveNewConstant(varDefStt.TypeDescriptor, varDefStt.Name, constantValueStatement.Value);
            }
            else
            {
                var skipDefinition = false;
                if (varDefStt.HasDefaultValue)
                {
                    var def        = varDefStt.DefaultValue;
                    var transpiler = context.GetEvaluationTranspilerForStatement(def);
                    if (transpiler == null)
                    {
                        throw new InvalidOperationException();
                    }

                    //it pins non-inlinable values to a helper variable:
                    //int x = 34 * myFunc();
                    //becomes:
                    //myFuncResult=myFunc()
                    //x=$((34 * myFuncResult))
                    if (varDefStt.TypeDescriptor.IsArray())
                    {
                        var p = new ExpressionBuilderParams(context, scope, metaWriter, writer,
                                                            new BlockStatement(null, varDefStt.Info));

                        scope.ReserveNewVariable(varDefStt.TypeDescriptor, varDefStt.Name);
                        skipDefinition = true;

                        var targetVar = new VariableAccessStatement(varDefStt.Name, varDefStt.Info);

                        var call = transpiler.CallApiFunction <ApiArray.Copy>(p, new[] { targetVar, def }, varDefStt,
                                                                              varDefStt.Info);

                        if (!call.IsEmptyResult)
                        {
                            WriteVariableDefinition(context, scope, writer, varDefStt.Name, call.Expression);
                        }
                    }
                    else
                    {
                        var result = transpiler.GetExpression(context, scope, metaWriter, writer, null, def);

                        WriteVariableDefinition(context, scope, writer, varDefStt.Name, result.Expression);
                    }
                }
                else
                {
                    WriteVariableDefinition(context, scope, writer, varDefStt.Name,
                                            context.Platform.GetDefaultValue(varDefStt.TypeDescriptor.DataType));
                }

                if (!skipDefinition)
                {
                    scope.ReserveNewVariable(varDefStt.TypeDescriptor, varDefStt.Name);
                }

                scope.IncrementStatements();
            }
        }