コード例 #1
0
        /// <summary>
        ///  Finds the first scoped variable matching the name, using Rule as the current rule to work backwards from
        /// </summary>
        public Rule FindVariable(string name, Node rule)
        {
            var previousNode = rule;

            foreach (var frame in Frames)
            {
                var v = frame.Variable(name, null);
                if (v)
                {
                    return(v);
                }
                previousNode = frame;
            }

            Rule result = null;

            if (Parent != null)
            {
                result = Parent.FindVariable(name, rule);
            }

            if (result != null)
            {
                return(result);
            }

            if (ClosureEnvironment != null)
            {
                return(ClosureEnvironment.FindVariable(name, rule));
            }

            return(null);
        }
コード例 #2
0
ファイル: Env.cs プロジェクト: xhute/Kooboo
        /// <summary>
        ///  Finds the first Ruleset matching the selector argument that inherits from or is of type TRuleset (pass this as Ruleset if
        ///  you are trying to find ANY Ruleset that matches the selector)
        /// </summary>
        public IEnumerable <Closure> FindRulesets(Selector selector)
        {
            var matchingRuleSets = Frames
                                   .Select(frame => frame.Find <Ruleset>(this, selector, null))
                                   .Select(
                matchedClosuresList => matchedClosuresList.Where(
                    matchedClosure => {
                if (!Frames.Any(frame => frame.IsEqualOrClonedFrom(matchedClosure.Ruleset)))
                {
                    return(true);
                }

                var mixinDef = matchedClosure.Ruleset as MixinDefinition;
                if (mixinDef != null)
                {
                    return(mixinDef.Condition != null);
                }

                return(false);
            }
                    )
                )
                                   .FirstOrDefault(matchedClosuresList => matchedClosuresList.Count() != 0);

            if (matchingRuleSets != null)
            {
                return(matchingRuleSets);
            }

            if (Parent != null)
            {
                matchingRuleSets = Parent.FindRulesets(selector);
            }

            if (matchingRuleSets != null)
            {
                return(matchingRuleSets);
            }

            if (ClosureEnvironment != null)
            {
                return(ClosureEnvironment.FindRulesets(selector));
            }

            return(null);
        }
コード例 #3
0
        /// <summary>
        ///  Finds the first Ruleset matching the selector argument that inherits from or is of type TRuleset (pass this as Ruleset if
        ///  you are trying to find ANY Ruleset that matches the selector)
        /// </summary>
        public IEnumerable <Closure> FindRulesets(Selector selector)
        {
            var matchingRuleSets = Frames
                                   .Reverse()
                                   .SelectMany(frame => frame.Find <Ruleset>(this, selector, null))
                                   .Where(matchedClosure => {
                if (!Frames.Any(frame => frame.IsEqualOrClonedFrom(matchedClosure.Ruleset)))
                {
                    return(true);
                }

                var mixinDef = matchedClosure.Ruleset as MixinDefinition;
                if (mixinDef != null)
                {
                    return(mixinDef.Condition != null);
                }

                return(false);
            }).ToList();

            if (matchingRuleSets.Any())
            {
                return(matchingRuleSets);
            }

            if (Parent != null)
            {
                var parentRulesets = Parent.FindRulesets(selector);
                if (parentRulesets != null)
                {
                    return(parentRulesets);
                }
            }

            if (ClosureEnvironment != null)
            {
                return(ClosureEnvironment.FindRulesets(selector));
            }

            return(null);
        }
コード例 #4
0
            private void MakeAndAssignEnvironments()
            {
                VisitScopeTree(ScopeTree, scope =>
                {
                    // Currently all variables declared in the same scope are added
                    // to the same closure environment
                    var variablesInEnvironment = scope.DeclaredVariables;

                    // Don't create empty environments
                    if (variablesInEnvironment.Count == 0)
                    {
                        return;
                    }

                    // First walk the nested scopes to find all closures which
                    // capture variables from this scope. They all need to capture
                    // this environment. This includes closures which captured local
                    // functions that capture those variables, so multiple passes may
                    // be needed. This will also decide if the environment is a struct
                    // or a class.
                    bool isStruct = true;
                    var closures  = new SetWithInsertionOrder <Closure>();
                    bool addedItem;

                    // This loop is O(n), where n is the length of the chain
                    //   L_1 <- L_2 <- L_3 ...
                    // where L_1 represents a local function that directly captures the current
                    // environment, L_2 represents a local function that directly captures L_1,
                    // L_3 represents a local function that captures L_2, and so on.
                    //
                    // Each iteration of the loop runs a visitor that is proportional to the
                    // number of closures in nested scopes, so we hope that the total number
                    // of nested functions and function chains is small in any real-world code.
                    do
                    {
                        addedItem = false;
                        VisitClosures(scope, (closureScope, closure) =>
                        {
                            if (!closures.Contains(closure) &&
                                (closure.CapturedVariables.Overlaps(scope.DeclaredVariables) ||
                                 closure.CapturedVariables.Overlaps(closures.Select(c => c.OriginalMethodSymbol))))
                            {
                                closures.Add(closure);
                                addedItem = true;
                                isStruct &= CanTakeRefParameters(closure.OriginalMethodSymbol);
                            }
                        });
                    } while (addedItem == true);

                    // Next create the environment and add it to the declaration scope
                    var env = new ClosureEnvironment(variablesInEnvironment, isStruct);
                    scope.DeclaredEnvironments.Add(env);

                    _topLevelMethod.TryGetThisParameter(out var thisParam);
                    foreach (var closure in closures)
                    {
                        closure.CapturedEnvironments.Add(env);
                        if (thisParam != null && env.CapturedVariables.Contains(thisParam))
                        {
                            closure.CapturesThis = true;
                        }
                    }
                });
            }