Example #1
0
 private Delegate CreateDefaultDelegate()
 {
     return(CompileVisitor.CompileAst(
                EngineIntrinsics,
                (ScriptBlockAst)ScriptBlock.Ast,
                Locals.Values.ToArray()));
 }
Example #2
0
        private Delegate ConvertToDelegate(PSDelegate psDelegate, Type destinationType)
        {
            lock (s_syncObject)
            {
                Dictionary <Type, Delegate> cacheEntry;
                if (!s_delegateCache.TryGetValue(psDelegate, out cacheEntry))
                {
                    cacheEntry = new Dictionary <Type, Delegate>();
                    s_delegateCache.Add(psDelegate, cacheEntry);
                }

                Delegate compiledDelegate;
                if (!cacheEntry.TryGetValue(destinationType, out compiledDelegate))
                {
                    compiledDelegate = CompileVisitor.CompileAst(
                        psDelegate.EngineIntrinsics,
                        (ScriptBlockAst)psDelegate.ScriptBlock.Ast,
                        psDelegate.Locals.Values.ToArray(),
                        destinationType);

                    cacheEntry.Add(destinationType, compiledDelegate);
                }

                return(compiledDelegate);
            }
        }
Example #3
0
        /// <summary>
        /// Creates a Linq expression for a <see cref="CommandAst" /> representing
        /// the "lock" command.
        /// </summary>
        /// <param name="commandAst">The AST to convert.</param>
        /// <param name="targetAst">The AST containing the target of the keyword.</param>
        /// <param name="bodyAst">The AST containing the body of the keyword.</param>
        /// <param name="visitor">The <see cref="CompileVisitor" /> requesting the expression.</param>
        /// <returns>An expression representing the command.</returns>
        protected override Expression ProcessObjectAndBody(
            CommandAst commandAst,
            CommandElementAst targetAst,
            ScriptBlockExpressionAst bodyAst,
            CompileVisitor visitor)
        {
            var lockVar      = Expression.Variable(typeof(object));
            var lockTakenVar = Expression.Variable(typeof(bool));

            return(visitor.NewBlock(() =>
                                    Expression.Block(
                                        typeof(void),
                                        new[] { lockVar, lockTakenVar },
                                        Expression.Call(
                                            ReflectionCache.Monitor_Enter,
                                            Expression.Assign(
                                                lockVar,
                                                Expression.Convert(
                                                    targetAst.Compile(visitor),
                                                    typeof(object))),
                                            lockTakenVar),
                                        Expression.TryFinally(
                                            bodyAst.ScriptBlock.EndBlock.Compile(visitor),
                                            Expression.IfThen(
                                                lockTakenVar,
                                                Expression.Call(
                                                    ReflectionCache.Monitor_Exit,
                                                    lockVar))))));
        }
Example #4
0
        /// <summary>
        /// Creates a Linq expression for a <see cref="CommandAst" /> representing
        /// a custom command.
        /// </summary>
        /// <param name="commandAst">The AST to convert.</param>
        /// <param name="visitor">The <see cref="CompileVisitor" /> requesting the expression.</param>
        /// <returns>An expression representing the command.</returns>
        public Expression ProcessAst(CommandAst commandAst, CompileVisitor visitor)
        {
            if (commandAst.CommandElements.Count != 3)
            {
                visitor.Errors.ReportParseError(
                    commandAst.Extent,
                    nameof(ErrorStrings.MissingKeywordElements),
                    string.Format(
                        CultureInfo.CurrentCulture,
                        ErrorStrings.MissingKeywordElements,
                        CommandName));
                return(Expression.Empty());
            }

            if (!(commandAst.CommandElements[2] is ScriptBlockExpressionAst bodyAst))
            {
                visitor.Errors.ReportParseError(
                    commandAst.Extent,
                    nameof(ErrorStrings.MissingKeywordBody),
                    string.Format(
                        CultureInfo.CurrentCulture,
                        ErrorStrings.MissingKeywordBody,
                        CommandName));
                return(Expression.Empty());
            }

            return(ProcessObjectAndBody(
                       commandAst,
                       commandAst.CommandElements[1],
                       bodyAst,
                       visitor));
        }
        /// <summary>
        /// Creates a Linq expression for a <see cref="CommandAst" /> representing
        /// the "default" command.
        /// </summary>
        /// <param name="commandAst">The AST to convert.</param>
        /// <param name="visitor">The <see cref="CompileVisitor" /> requesting the expression.</param>
        /// <returns>An expression representing the command.</returns>
        public Expression ProcessAst(CommandAst commandAst, CompileVisitor visitor)
        {
            if (commandAst.CommandElements == null || commandAst.CommandElements.Count != 2)
            {
                visitor.TryResolveType(null, out _);
                return(Expression.Empty());
            }

            // Is using syntax "default([TypeName])"
            if (commandAst.CommandElements[1] is ParenExpressionAst paren &&
                paren.Pipeline is PipelineAst pipeline &&
                pipeline.PipelineElements.Count == 1 &&
                pipeline.PipelineElements[0] is CommandExpressionAst commandExpression &&
                commandExpression.Expression is TypeExpressionAst &&
                visitor.TryResolveType(commandExpression.Expression, out Type resolvedType))
            {
                return(Expression.Default(resolvedType));
            }

            // Is using syntax "default TypeName"
            if (commandAst.CommandElements[1] is StringConstantExpressionAst stringConstant &&
                LanguagePrimitives.TryConvertTo(stringConstant.Value, out resolvedType))
            {
                return(Expression.Default(resolvedType));
            }

            // Unknown syntax, but this method will produce parse errors for us.
            if (visitor.TryResolveType(commandAst.CommandElements[1], out resolvedType))
            {
                return(Expression.Default(resolvedType));
            }

            return(Expression.Empty());
        }
        private void RewriteIL(MethodBody body, Dictionary <Expr, Instruction> instructionLookup, Expr remove, Expr insert)
        {
            var         il = body.GetILProcessor();
            Instruction instInsertBefore;

            if (remove != null)
            {
                var vInstExtent = new InstructionExtentVisitor(instructionLookup);
                vInstExtent.Visit(remove);
                instInsertBefore = vInstExtent.Instructions.Last().Next;
                foreach (var instRemove in vInstExtent.Instructions)
                {
                    il.Remove(instRemove);
                }
            }
            else
            {
                instInsertBefore = body.Instructions [0];
            }
            if (insert != null)
            {
                var compiler = new CompileVisitor(il, instructionLookup, inst => il.InsertBefore(instInsertBefore, inst));
                compiler.Visit(insert);
            }
        }
Example #7
0
 private Expression ReportInvalidSyntax(IScriptExtent extent, CompileVisitor visitor)
 {
     visitor.Errors.ReportParseError(
         extent,
         nameof(ErrorStrings.InvalidGenericSyntax),
         ErrorStrings.InvalidGenericSyntax);
     return(Expression.Empty());
 }
Example #8
0
        /// <summary>
        /// Creates a Linq expression for a <see cref="CommandAst" /> representing
        /// the "generic" command.
        /// </summary>
        /// <param name="commandAst">The AST to convert.</param>
        /// <param name="visitor">The <see cref="CompileVisitor" /> requesting the expression.</param>
        /// <returns>An expression representing the command.</returns>
        public Expression ProcessAst(CommandAst commandAst, CompileVisitor visitor)
        {
            if (commandAst.CommandElements.Count != 2)
            {
                return(ReportInvalidSyntax(commandAst.Extent, visitor));
            }

            var paren = commandAst.CommandElements[1] as ParenExpressionAst;

            if (paren == null)
            {
                return(ReportInvalidSyntax(commandAst.Extent, visitor));
            }

            var pipeline = paren.Pipeline as PipelineAst;

            if (pipeline == null || pipeline.PipelineElements.Count != 1)
            {
                return(ReportInvalidSyntax(commandAst.Extent, visitor));
            }

            var commandExpression = pipeline.PipelineElements[0] as CommandExpressionAst;

            if (commandExpression == null)
            {
                return(ReportInvalidSyntax(commandAst.Extent, visitor));
            }

            var arrayLiteral = commandExpression.Expression as ArrayLiteralAst;

            if (arrayLiteral.Elements.Count < 2)
            {
                return(ReportInvalidSyntax(commandAst.Extent, visitor));
            }

            var memberExpression = arrayLiteral.Elements[0] as InvokeMemberExpressionAst;

            if (memberExpression == null)
            {
                return(ReportInvalidSyntax(commandAst.Extent, visitor));
            }

            var genericArguments = new Type[arrayLiteral.Elements.Count - 1];

            for (var i = 1; i < arrayLiteral.Elements.Count; i++)
            {
                if (visitor.TryResolveType(arrayLiteral.Elements[i], out Type resolvedType))
                {
                    genericArguments[i - 1] = resolvedType;
                    continue;
                }

                // If a type didn't resolve then a parse error was generated, so exit.
                return(Expression.Empty());
            }

            return(visitor.CompileInvokeMemberExpression(memberExpression, genericArguments));
        }
Example #9
0
        /// <summary>
        /// Attempt to process a <see cref="CommandAst" /> as a custom command.
        /// </summary>
        /// <param name="commandAst">The <see cref="CommandAst" /> to process.</param>
        /// <param name="visitor">
        /// The <see cref="CompileVisitor" /> requesting the expression.
        /// </param>
        /// <param name="expression">
        /// The <see cref="Expression" /> result if a command handler was found.
        /// </param>
        /// <returns><c>true</c> if a commmand handler was matched, otherwise <c>false</c>.</returns>
        public bool TryProcessAst(CommandAst commandAst, CompileVisitor visitor, out Expression expression)
        {
            if (_commandRegistry.TryGetValue(commandAst.GetCommandName(), out ICommandHandler handler))
            {
                expression = handler.ProcessAst(commandAst, visitor);
                return(true);
            }

            expression = null;
            return(false);
        }
Example #10
0
        public SlowRowVirtualChannel(IExpression virtualExpression, int virtualParameterId, int slowRowRateInMilliHz,
                                     IParametersSymbolTable symbolTable, ISlowRowStorage <TTime> slowRowStorage, ITimeUtils <TTime> timeUtils)
        {
            m_virtualParameterId   = virtualParameterId;
            m_slowRowRateInMilliHz = slowRowRateInMilliHz;
            m_timeUtils            = timeUtils;
            m_context = new SlowRowExpressionContext <TTime>(slowRowStorage);
            var compiler = new CompileVisitor(m_context, symbolTable, new DefaultCallContext());

            virtualExpression.Accept(compiler);
            m_evaluate = compiler.GetCompiledExpression();
        }
        public SingleLoggedParameterVirtualChannel(IExpression virtualExpression, int virtualParameterId, int loggedParameterId, int loggedParameterFrequencyInMilliHz,
                                                   IParametersSymbolTable symbolTable, ISlowRowStorage <TTime> slowRowStorage, ITimeUtils <TTime> timeUtils)
        {
            m_virtualParameterId = virtualParameterId;
            m_loggedParameterFrequencyInMilliHz = loggedParameterFrequencyInMilliHz;
            m_timeUtils = timeUtils;
            m_context   = new SingleValueWithSlowRowExpressionContext <TTime>(slowRowStorage, loggedParameterId);
            var compiler = new CompileVisitor(m_context, symbolTable, new DefaultCallContext());

            virtualExpression.Accept(compiler);
            m_evaluate = compiler.GetCompiledExpression();
        }
Example #12
0
        public void ParseAndCompileTest()
        {
            var expression = SMExpressionParser.ParseOrThrow("log(10) + $aaa + abs(nolog($adc_Controller)) + 1*2");

            var simpleExpressionContext = new TestExpressionContext();

            var compiler = new CompileVisitor(simpleExpressionContext, new TestSymbolTable(), new DefaultCallContext());

            expression.Accept(compiler);
            var compiledExpression = compiler.GetCompiledExpression();

            Assert.AreEqual(14.0, compiledExpression(), 1e-9);
        }
        public MultiLoggedParametersVirtualChannel(IExpression virtualExpression, int virtualParameterId, int[] loggedParametersIds, int loggedParametersFrequencyInMilliHz,
                                                   IParametersSymbolTable symbolTable, ISlowRowStorage <TTime> slowRowStorage, ITimeUtils <TTime> timeUtils)
        {
            m_virtualParameterId = virtualParameterId;
            m_loggedParametersFrequencyInMilliHz = loggedParametersFrequencyInMilliHz;
            m_timeUtils = timeUtils;
            m_coverageCircularBuffer = new CoverageCircularBuffer <TTime>(loggedParametersIds, loggedParametersFrequencyInMilliHz, 30, timeUtils);
            m_context = new MultiValueWithSlowRowExpressionContext <TTime>(slowRowStorage, loggedParametersIds);
            var compiler = new CompileVisitor(m_context, symbolTable, new DefaultCallContext());

            virtualExpression.Accept(compiler);
            m_evaluate = compiler.GetCompiledExpression();

            m_timeZero = timeUtils.Zero();
        }
Example #14
0
 /// <summary>
 /// Determines the correct member for an expression and creates a
 /// <see cref="Expression" /> representing it's invocation.
 /// </summary>
 /// <param name="visitor">The <see cref="CompileVisitor" /> requesting the bind.</param>
 /// <param name="instance">The instance <see cref="Expression" /> for the invocation.</param>
 /// <param name="name">The member name to use while resolving the method.</param>
 /// <param name="arguments">The arguments to use while resolving the method.</param>
 /// <param name="genericArguments">The generic arguments to use while resolving the method.</param>
 /// <returns>
 /// A <see cref="BindingResult" /> that either contains the
 /// <see cref="Expression" /> or the <see cref="ArgumentException" /> and
 /// error ID.
 /// </returns>
 internal BindingResult BindMethod(
     CompileVisitor visitor,
     Expression instance,
     string name,
     Ast[] arguments,
     Type[] genericArguments)
 {
     return(BindMethod(
                visitor,
                instance.Type,
                name,
                arguments,
                instance,
                genericArguments));
 }
Example #15
0
 /// <summary>
 /// Determines the correct member for an expression and creates a
 /// <see cref="Expression" /> representing it's invocation.
 /// </summary>
 /// <param name="visitor">The <see cref="CompileVisitor" /> requesting the bind.</param>
 /// <param name="sourceType">The source <see cref="Type" /> for the invocation.</param>
 /// <param name="name">The member name to use while resolving the method.</param>
 /// <param name="arguments">The arguments to use while resolving the method.</param>
 /// <param name="genericArguments">The generic arguments to use while resolving the method.</param>
 /// <returns>
 /// A <see cref="BindingResult" /> that either contains the
 /// <see cref="Expression" /> or the <see cref="ArgumentException" /> and
 /// error ID.
 /// </returns>
 internal BindingResult BindMethod(
     CompileVisitor visitor,
     Type sourceType,
     string name,
     Ast[] arguments,
     Type[] genericArguments)
 {
     return(BindMethod(
                visitor,
                sourceType,
                name,
                arguments,
                null,
                genericArguments));
 }
Example #16
0
        public Oc5Runner(string oc5Source)
        {
            Oc5Source = oc5Source;

            var inputStream = new AntlrInputStream(oc5Source);
            var lexer       = new Oc5Lexer(inputStream);
            var tokenStream = new CommonTokenStream(lexer);
            var parser      = new Oc5Parser(tokenStream);

            var ocfileContext = parser.ocfile();

            var visitor = new CompileVisitor(ocfileContext);

            Oc5Model      = visitor.Oc5Model;
            Oc5ModelState = visitor.Oc5ModelState;
        }
Example #17
0
 /// <summary>
 /// Compile a <see cref="Ast" /> into a <see cref="Expression" />.
 /// </summary>
 /// <param name="ast">The <see cref="Ast" /> to compile.</param>
 /// <param name="visitor">The <see cref="CompileVisitor" /> requesting the compile.</param>
 /// <returns>The compiled <see cref="Expression" /> object.</returns>
 public static Expression Compile(this Ast ast, CompileVisitor visitor)
 {
     try
     {
         return((Expression)ast.Visit(visitor));
     }
     catch (ArgumentException e)
     {
         visitor.Errors.ReportParseError(ast.Extent, e);
         return(Expression.Empty());
     }
     catch (InvalidOperationException e)
     {
         visitor.Errors.ReportParseError(ast.Extent, e);
         return(Expression.Empty());
     }
 }
Example #18
0
        /// <summary>
        /// Compile all asts in a given <see cref="IList{TAst}" />.
        /// </summary>
        /// <param name="asts">The <see cref="Ast" /> objects to compile.</param>
        /// <param name="visitor">The <see cref="CompileVisitor" /> requesting the compile.</param>
        /// <typeparam name="TAst">The type of <see cref="Ast" /> to expect in the list.</typeparam>
        /// <returns>The compiled <see cref="Expression" /> objects.</returns>
        public static Expression[] CompileAll <TAst>(this IList <TAst> asts, CompileVisitor visitor)
            where TAst : Ast
        {
            if (asts == null || asts.Count == 0)
            {
                return(s_emptyExpressions);
            }

            var expressions = new Expression[asts.Count];

            for (var i = 0; i < asts.Count; i++)
            {
                expressions[i] = (Expression)asts[i].Visit(visitor);
            }

            return(expressions);
        }
Example #19
0
        /// <summary>
        /// 准备运行代码
        /// </summary>
        private CompileVisitor prepareForRunning(IParseTree tree)
        {
            if (tree == null)
            {
                return(null);
            }

            var visitor = new CompileVisitor();

            try {
                visitor.generateCodes(tree);

                //中间代码存为字符串。
                intermediateCode = "";
                for (int i = 0; i < visitor.codes.Count; i++)
                {
                    string newLine = i + ":\t" + visitor.codes[i].toString() + "\n";
                    intermediateCode += newLine;
                }
            }
            catch (VariableNotFountException exp) {
                handleCompileTimeError(new List <ErrorInfo> {
                    exp.Error
                });
                intermediateCode = null;
                return(null);
            }
            catch (VariableRedefinedException exp) {
                handleCompileTimeError(new List <ErrorInfo> {
                    exp.Error
                });
                intermediateCode = null;
                return(null);
            }

            if (!State.ConsoleShowed)
            {
                extraPanelButton_Click(btnConsoleWindow, null);
            }

            consoleTextBox.Text = "";

            return(visitor);
        }
Example #20
0
        /// <summary>
        /// 调试代码
        /// </summary>
        private void btnDebug_Click(object sender, RoutedEventArgs e)
        {
            IParseTree     tree    = prepareForCodeGen();
            CompileVisitor visitor = prepareForRunning(tree);

            if (visitor == null)
            {
                return;
            }

            prepareForDebug();

            // 断点列表
            List <int> breakpoints = textEditor.GetBreakPoints();

            // 初始化调试器
            cmmDebuger = new CMMDebuger(visitor.codes, breakpoints);
            cmmDebuger.LoadDebugInformation(visitor.GetGlobalSymbolTable(), visitor.GetFunctionInformations());
            cmmDebuger.setListener(this);
            cmmDebuger.OutputStream = this;
            cmmDebuger.NeedDebug   += HandlerDebug;
            cmmDebuger.DebugFinish += CmmDebugerDebugFinish;

            debugThread = new Thread(() => {
                try {
                    //Print("\n调试模式\n");
                    isDebug = true;
                    cmmDebuger.Run();
                    Print("\nprogram exit\n");
                    isDebug = false;
                }
                catch (RuntimeException e1) {
                    Print("Line:" + e1.line.ToString() + " " + e1.Message);
                }
                catch (Exception e2) {
                    Print(e2.Message);
                }
            });

            debugThread.Name = "Debug";
            debugThread.Start();
        }
Example #21
0
        /// <summary>
        /// Creates a Linq expression for a <see cref="CommandAst" /> representing
        /// the "with" command.
        /// </summary>
        /// <param name="commandAst">The AST to convert.</param>
        /// <param name="targetAst">The AST containing the target of the keyword.</param>
        /// <param name="bodyAst">The AST containing the body of the keyword.</param>
        /// <param name="visitor">The <see cref="CompileVisitor" /> requesting the expression.</param>
        /// <returns>An expression representing the command.</returns>
        protected override Expression ProcessObjectAndBody(
            CommandAst commandAst,
            CommandElementAst targetAst,
            ScriptBlockExpressionAst bodyAst,
            CompileVisitor visitor)
        {
            var disposeVar = Expression.Variable(typeof(IDisposable));

            return(visitor.NewBlock(() =>
                                    Expression.Block(
                                        typeof(void),
                                        new[] { disposeVar },
                                        Expression.Assign(
                                            disposeVar,
                                            Expression.Convert(
                                                targetAst.Compile(visitor),
                                                typeof(IDisposable))),
                                        Expression.TryFinally(
                                            bodyAst.ScriptBlock.EndBlock.Compile(visitor),
                                            Expression.Call(disposeVar, ReflectionCache.IDisposable_Dispose)))));
        }
Example #22
0
        /// <summary>
        /// 运行代码
        /// </summary>
        private void run_Click(object sender, RoutedEventArgs e)
        {
            IParseTree     tree    = prepareForCodeGen();
            CompileVisitor visitor = prepareForRunning(tree);

            if (visitor == null)
            {
                return;
            }

            VirtualMachine vm = new VirtualMachine();

            this.vm = vm;
            vm.register(this);
            vm.needInput += handleNeedInput;

            runnerThread = new Thread(() =>
            {
                vm.interpret(visitor.codes);
            });
            runnerThread.Start();
        }
Example #23
0
        /// <summary>
        /// The EndProcessing method.
        /// </summary>
        protected override void EndProcessing()
        {
            var variables = SessionState.InvokeCommand.InvokeScript(
                "Get-Variable -Scope 0",
                false,
                PipelineResultTypes.Output,
                null,
                null)
                            .Select(pso => pso.BaseObject)
                            .Cast <PSVariable>()
                            .Where(v => !SpecialVariables.IgnoreLocal.Contains(v.Name));

            try
            {
                if (DelegateType == null)
                {
                    WriteObject(
                        CompileVisitor.CompileAst(
                            (EngineIntrinsics)SessionState.PSVariable.GetValue(Strings.ExecutionContextVariableName),
                            (ScriptBlockAst)Expression.Ast,
                            variables.ToArray()),
                        enumerateCollection: false);
                    return;
                }

                WriteObject(
                    CompileVisitor.CompileAst(
                        (EngineIntrinsics)SessionState.PSVariable.GetValue(Strings.ExecutionContextVariableName),
                        (ScriptBlockAst)Expression.Ast,
                        variables.ToArray(),
                        DelegateType),
                    enumerateCollection: false);
            }
            catch (ParseException e)
            {
                ThrowTerminatingError(new ErrorRecord(e.ErrorRecord, e));
            }
        }
Example #24
0
        public void ParseAndCompilePerformanceTest()
        {
            var expression = SMExpressionParser.ParseOrThrow("log(10) + $aaa + abs(nolog($adc_Controller)) + 1*2");

            var simpleExpressionContext = new TestExpressionContext();

            var compiler = new CompileVisitor(simpleExpressionContext, new TestSymbolTable(), new DefaultCallContext());

            expression.Accept(compiler);
            var compiledExpression = compiler.GetCompiledExpression();

            var times = 1000000;
            var sw    = Stopwatch.StartNew();

            for (int i = 0; i < times; ++i)
            {
                compiledExpression();
            }

            var elapsed = sw.ElapsedMilliseconds;

            Console.WriteLine($"Compiled: {elapsed}ms");
        }
Example #25
0
        private bool ShouldBind(
            MethodInfo method,
            MethodArgument[] arguments,
            CompileVisitor visitor,
            out MethodInfo resolvedMethod)
        {
            var parameters = method.GetParameters();

            if (parameters.Length != arguments.Length)
            {
                resolvedMethod = null;
                return(false);
            }

            BindingStatus status;

            status._map = new Dictionary <Type, Type>();
            status._hasGenericParams = method.IsGenericMethod;
            for (var i = 0; i < parameters.Length; i++)
            {
                if (arguments[i].Ast != null &&
                    (arguments[i].Ast is ScriptBlockExpressionAst ||
                     arguments[i].Ast is ScriptBlockAst))
                {
                    if (!(typeof(Delegate).IsAssignableFrom(parameters[i].ParameterType) ||
                          typeof(LambdaExpression).IsAssignableFrom(parameters[i].ParameterType)))
                    {
                        resolvedMethod = null;
                        return(false);
                    }

                    if (status.IsDelegateMatch(parameters[i].ParameterType, arguments[i], visitor))
                    {
                        continue;
                    }

                    resolvedMethod = null;
                    return(false);
                }

                if (arguments[i].Expression == null)
                {
                    arguments[i].Expression = arguments[i].Ast.Compile(visitor);
                }

                if (!status.IsTypeMatch(parameters[i].ParameterType, arguments[i].Expression.Type))
                {
                    resolvedMethod = null;
                    return(false);
                }
            }

            if (!status._hasGenericParams || !method.IsGenericMethodDefinition)
            {
                resolvedMethod = method;
                return(true);
            }

            var genericParameters = method.GetGenericArguments();
            var genericArguments  = new Type[genericParameters.Length];

            for (var i = 0; i < genericParameters.Length; i++)
            {
                genericArguments[i] = status._map[genericParameters[i]];
            }

            resolvedMethod = method.MakeGenericMethod(genericArguments);
            return(true);
        }
Example #26
0
        private BindingResult BindMethod(
            CompileVisitor visitor,
            Type sourceType,
            string name,
            Ast[] arguments,
            Expression instance,
            Type[] genericArguments)
        {
            var methodArgs = new MethodArgument[arguments.Length];

            for (var i = 0; i < methodArgs.Length; i++)
            {
                methodArgs[i] = (MethodArgument)arguments[i];
            }

            var           didFindName = false;
            var           isInstance  = instance != null;
            var           methods     = sourceType.GetMethods(isInstance ? _instanceFlags : _staticFlags);
            MethodInfo    boundMethod;
            BindingResult bindingResult = default(BindingResult);

            for (var i = 0; i < methods.Length; i++)
            {
                if (!methods[i].Name.Equals(name, StringComparison.InvariantCultureIgnoreCase))
                {
                    continue;
                }

                if (!didFindName)
                {
                    didFindName = true;
                }

                if (genericArguments.Length > 0 &&
                    (!methods[i].IsGenericMethod ||
                     !AreGenericArgumentsValid(methods[i], genericArguments)))
                {
                    continue;
                }

                if (genericArguments.Length > 0)
                {
                    methods[i] = methods[i].MakeGenericMethod(genericArguments);
                }

                if (ShouldBind(methods[i], methodArgs, visitor, out boundMethod))
                {
                    var expressions = new Expression[methodArgs.Length];
                    for (var j = 0; j < methodArgs.Length; j++)
                    {
                        expressions[j] = methodArgs[j].Expression;
                    }

                    bindingResult.Expression = Expression.Call(instance, boundMethod, expressions);
                    return(bindingResult);
                }
            }

            if (!isInstance)
            {
                bindingResult.Reason = new ArgumentException(
                    string.Format(
                        CultureInfo.CurrentCulture,
                        ErrorStrings.NoMemberArgumentMatch,
                        sourceType.FullName,
                        name));
                bindingResult.Id = nameof(ErrorStrings.NoMemberArgumentMatch);
                return(bindingResult);
            }

            var extensionArgs = new MethodArgument[methodArgs.Length + 1];

            extensionArgs[0] = (MethodArgument)instance;
            for (var i = 1; i < extensionArgs.Length; i++)
            {
                extensionArgs[i] = methodArgs[i - 1];
            }

            methods = GetExtensionMethods();
            for (var i = 0; i < methods.Length; i++)
            {
                if (!methods[i].Name.Equals(name, StringComparison.InvariantCultureIgnoreCase))
                {
                    continue;
                }

                if (!didFindName)
                {
                    didFindName = true;
                }

                if (genericArguments.Length > 0 &&
                    (!methods[i].IsGenericMethod ||
                     !AreGenericArgumentsValid(methods[i], genericArguments)))
                {
                    continue;
                }

                if (genericArguments.Length > 0)
                {
                    methods[i] = methods[i].MakeGenericMethod(genericArguments);
                }

                if (ShouldBind(methods[i], extensionArgs, visitor, out boundMethod))
                {
                    var expressions = new Expression[extensionArgs.Length];
                    for (var j = 0; j < extensionArgs.Length; j++)
                    {
                        expressions[j] = extensionArgs[j].Expression;
                    }

                    bindingResult.Expression = Expression.Call(boundMethod, expressions);
                    return(bindingResult);
                }
            }

            if (!didFindName)
            {
                bindingResult.Reason =
                    new ArgumentException(
                        string.Format(
                            CultureInfo.CurrentCulture,
                            ErrorStrings.NoMemberNameMatch,
                            sourceType.FullName,
                            name));

                bindingResult.Id = nameof(ErrorStrings.NoMemberNameMatch);
                return(bindingResult);
            }

            bindingResult.Reason = new ArgumentException(
                string.Format(
                    CultureInfo.CurrentCulture,
                    ErrorStrings.NoMemberArgumentMatch,
                    sourceType.FullName,
                    name));
            bindingResult.Id = nameof(ErrorStrings.NoMemberArgumentMatch);
            return(bindingResult);
        }
Example #27
0
 /// <summary>
 /// Creates a Linq expression for a <see cref="CommandAst" /> representing
 /// a custom command.
 /// </summary>
 /// <param name="commandAst">The AST to convert.</param>
 /// <param name="targetAst">The AST containing the target of the keyword.</param>
 /// <param name="bodyAst">The AST containing the body of the keyword.</param>
 /// <param name="visitor">The <see cref="CompileVisitor" /> requesting the expression.</param>
 /// <returns>An expression representing the command.</returns>
 protected abstract Expression ProcessObjectAndBody(
     CommandAst commandAst,
     CommandElementAst targetAst,
     ScriptBlockExpressionAst bodyAst,
     CompileVisitor visitor);
Example #28
0
            internal bool IsDelegateMatch(Type parameterType, MethodArgument argument, CompileVisitor visitor)
            {
                ScriptBlockAst sbAst;

                if (argument.Ast is ScriptBlockExpressionAst sbExpression)
                {
                    sbAst = (ScriptBlockAst)sbExpression.ScriptBlock.Visit(
                        new DelegateSyntaxVisitor(visitor.Errors));
                }
                else
                {
                    sbAst = (ScriptBlockAst)((ScriptBlockAst)argument.Ast).Visit(
                        new DelegateSyntaxVisitor(visitor.Errors));
                }

                argument.Ast = sbAst;
                var parameterMethod = parameterType.GetMethod(Strings.DelegateInvokeMethodName);

                if (parameterMethod == null && typeof(Expression).IsAssignableFrom(parameterType))
                {
                    parameterMethod = parameterType
                                      .GetGenericArguments()[0]
                                      .GetMethod(Strings.DelegateInvokeMethodName);
                }

                var astHasExplicitReturn = ExplicitReturnVisitor.TryFindExplicitReturn(
                    sbAst,
                    out PipelineBaseAst returnValue);

                if (astHasExplicitReturn)
                {
                    if (parameterMethod.ReturnType == typeof(void) &&
                        returnValue != null)
                    {
                        return(false);
                    }
                }

                var parameterParameters = parameterMethod.GetParameters();

                ParameterAst[] sbParameters;
                if (sbAst.ParamBlock != null)
                {
                    sbParameters = new ParameterAst[sbAst.ParamBlock.Parameters.Count];
                    for (var i = 0; i < sbParameters.Length; i++)
                    {
                        sbParameters[i] = sbAst.ParamBlock.Parameters[i];
                    }
                }
                else
                {
                    sbParameters = s_emptyParameterAsts;
                }

                if (parameterParameters.Length != sbParameters.Length)
                {
                    return(false);
                }

                var expectedParameterTypes = new Type[parameterParameters.Length];

                for (var i = 0; i < parameterParameters.Length; i++)
                {
                    if (parameterParameters[i].ParameterType.IsGenericParameter)
                    {
                        if (_map.TryGetValue(parameterParameters[i].ParameterType, out Type resolvedType))
                        {
                            expectedParameterTypes[i] = resolvedType;
                            continue;
                        }

                        // TODO: Check if parameter is strongly typed in the AST and use that to
                        //       resolve the targ.
                        return(false);
                    }

                    expectedParameterTypes[i] = parameterParameters[i].ParameterType;
                }

                var expectedReturnType = parameterMethod.ReturnType.IsGenericParameter
                    ? null
                    : parameterMethod.ReturnType;

                if (expectedReturnType == null)
                {
                    _map.TryGetValue(parameterMethod.ReturnType, out expectedReturnType);
                }

                var oldErrorWriter = visitor.Errors;

                try
                {
                    visitor.Errors      = ParseErrorWriter.CreateNull();
                    argument.Expression = visitor.CompileAstImpl(
                        sbAst,
                        s_emptyVariables,
                        expectedParameterTypes,
                        expectedReturnType,
                        null);
                }
                catch (Exception)
                {
                    // TODO: Better reporting here if all method resolution fails.
                    return(false);
                }
                finally
                {
                    visitor.Errors = oldErrorWriter;
                }

                if (parameterMethod.ReturnType.IsGenericParameter &&
                    !_map.ContainsKey(parameterMethod.ReturnType))
                {
                    _map.Add(parameterMethod.ReturnType, ((LambdaExpression)argument.Expression).ReturnType);
                }

                if (parameterType.IsGenericType)
                {
                    var genericParameters    = parameterType.GetGenericArguments();
                    var newGenericParameters = new Type[genericParameters.Length];
                    for (var i = 0; i < genericParameters.Length; i++)
                    {
                        if (genericParameters[i].IsGenericParameter)
                        {
                            _map.TryGetValue(genericParameters[i], out Type resolvedType);
                            newGenericParameters[i] = resolvedType;
                            continue;
                        }

                        newGenericParameters[i] = genericParameters[i];
                    }

                    parameterType = parameterType
                                    .GetGenericTypeDefinition()
                                    .MakeGenericType(newGenericParameters);
                }

                argument.Expression = Expression.Lambda(
                    parameterType,
                    ((LambdaExpression)argument.Expression).Body,
                    ((LambdaExpression)argument.Expression).Parameters);
                return(true);
            }