private Func <FunctionInvoker, Delegate> CompileFunction(CompileContext ctx)
        {
            if (!string.IsNullOrEmpty(name))
            {
                ctx.AddVariable(ValueType, name);
            }

            CompiledDelegate evalBody;

            var arguments = this.arguments;
            var child     = new CompileContext(ctx, BlockType.Method);

            foreach (var arg in arguments)
            {
                child.AddVariable(arg.ValueType, arg.Name);
            }
            evalBody = body.Compile(child);

            return((funcInvoke) =>
            {
                funcInvoke.body = evalBody;
                funcInvoke.arguments = arguments;

                switch (arguments.Count)
                {
                case 0: return Func0(funcInvoke);

                case 1: return Func1(funcInvoke);

                case 2: return Func2(funcInvoke);

                case 3: return Func3(funcInvoke);

                case 4: return Func4(funcInvoke);
                }
                return null;
            });
        }
        public override CompiledDelegate Compile(CompileContext ctx)
        {
            var variables = this.variables;

            CompiledDelegate[]           evals;
            Action <InvocationContext>[] evalVars;
            var child = new CompileContext(ctx, BlockType.Block);

            foreach (var variable in variables)
            {
                child.AddVariable(variable.ValueType, variable.Name);
            }

            evals    = expressions.Select(o => o.Compile(child)).ToArray();
            evalVars = variables.Select(o => o.CompileInitValue(child)).ToArray();

            return((invoke) =>
            {
                var childInvoke = invoke.CreateChild(BlockType.Block);

                foreach (var evalVar in evalVars)
                {
                    evalVar(childInvoke);
                }

                foreach (var expr in evals)
                {
                    expr(childInvoke);
                    if (childInvoke.GotoType != GotoType.None)
                    {
                        childInvoke.BubblingGoto();
                        break;
                    }
                }
                return null;
            });
        }