public virtual bool Match(Context env, IParsedPhrase check)
        {
            if (IsMatch(check))
            {
                Propogate(env, check, 1.0);
                env.Map[StarUtilities.NextStarName(env, name)] = check.Text;

                return(true);
            }

            return(false);
        }
        public override bool Match(object check, Context context, IContinuation succ, IFailure fail)
        {
            if (!(check is IParsedPhrase))
            {
                fail.Fail("Cannot match a " + check.GetType(), succ);
                return(true);
            }

            // Set up main check
            IParsedPhrase full = (IParsedPhrase)check;

            GroupPhrase sofar = context.LookupDefaulted <GroupPhrase>("$active$" + name, null);

            if (sofar != null)
            {
                full = sofar.AddBranch(full);
            }

            bool?isMatch = IsMatch(full);

            if (!isMatch.HasValue)
            {
                List <IContent> contents = new List <IContent>();
                contents.Add(new Value(this));
                Context tryagain = new Context(context, contents);
                tryagain.Map["$active$" + name] = new GroupPhrase(full);
                // Continue with same context
                succ.Continue(tryagain, fail);
            }
            else
            {
                if (isMatch.Value)
                {
                    Propogate(context, full, 1.0);
                    context.Map[StarUtilities.NextStarName(context, name)] = full.Text;

                    succ.Continue(context.ChildRange(1), fail);
                }
                else
                {
                    fail.Fail("Does not match " + full.Text, succ);
                }
            }

            return(true);
        }
        public override bool Evaluate()
        {
            List <IContent> contents = context.Contents;

            if (contents.Count == 0)
            {
                Unilog.Notice(this, "Ran out of template before input");
                fail.Fail("Ran out of tokens before matched all input", succ);
                return(true);
            }

            // Does our first element match the whole thing?
            IContent first = contents[0];

            //Console.WriteLine("Match " + first.Name + " against " + input.Text + " + " + unmatched.Count);

            // always consider dropping interjections
            IFailure myfail = fail;

            if (input.Part == "UH")
            {
                IFailure skipfail;
                if (unmatched.Count == 0)
                {
                    // then fail becomes success!
                    skipfail = new ContinueCodelet(salience, context, succ, fail);
                }
                else
                {
                    Matcher matchskip = new Matcher(salience, unmatched[0], unmatched.GetRange(1, unmatched.Count - 1), succ);
                    skipfail = new ContinueCodelet(salience, context, matchskip, fail);
                }

                myfail = skipfail;
            }

            if (first.Name == "*")
            {
                // Failure state has the first POS eaten by the star
                StarEater eater = new StarEater(coderack, salience, this, StarUtilities.NextStarName(context, "*"), true);

                if (context.Contents.Count == 1)
                {
                    // We ran out elements, but we still have some unmatched
                    coderack.AddCodelet(eater, "Evaluate *");
                    return(true);
                }
                else
                {
                    MatchAgainst(salience, context.ChildRange(1), input, unmatched, succ, eater);
                    return(true);
                }
            }
            else if (first.Name == "_")
            {
                StarEater eater = new StarEater(coderack, salience, this, StarUtilities.NextStarName(context, "_"), true);

                coderack.AddCodelet(eater, "Evaluate _");
                return(true);
            }
            else if (first.Name == "%opt")
            {
                // Try with, and if that fails, do without
                int end = context.Contents.IndexOf(Special.EndDelimSpecial);
                if (end == -1)
                {
                    // It's all optional-- but on fail return to match to ensure blank
                    Context   without     = new Context(context, new List <IContent>());
                    Evaluator evalfail    = MakeMatcherContinue(salience, without, input, unmatched, succ);
                    IFailure  withoutfail = new ContinueCodelet(salience, without, evalfail, myfail);

                    Context with = new Context(context, context.Contents.GetRange(1, context.Contents.Count - 1));
                    Matcher.MatchAgainst(salience, with, input, unmatched, succ, withoutfail);
                }
                else
                {
                    Context   without     = new Context(context, context.Contents.GetRange(end + 1, context.Contents.Count - (end + 1)));
                    Evaluator evalfail    = MakeMatcherContinue(salience, without, input, unmatched, succ);
                    IFailure  withoutfail = new ContinueCodelet(salience, without, evalfail, myfail);

                    Context with = new Context(context, context.Contents.GetRange(1, end - 1));
                    with.Contents.AddRange(without.Contents);
                    Matcher.MatchAgainst(salience, with, input, unmatched, succ, withoutfail);
                }
                return(true);
            }
            else if (first is Variable)
            {
                if (((Variable)first).Match(context, input))
                {
                    ContinueNextUnmatched(context.ChildRange(1));
                    return(true);
                }
                else if (input.IsLeaf)
                {
                    // we didn't match-- fail!
                    Unilog.Notice(this, first.Name + " does not match " + input.Text);
                    fail.Fail("Initial variable didn't match", succ);
                    return(true);
                }
                else
                {
                    GroupPhrase groupPhrase = new GroupPhrase(input);
                    unmatched.InsertRange(0, groupPhrase.GetRange(1));
                    // Call again with the same evaluated first argument
                    Matcher matchrest = new Matcher(salience, groupPhrase.GetBranch(0), unmatched, succ);
                    matchrest.Continue(context, myfail);
                    return(true);
                }
            }
            else if (first is Value && ((Value)first).Data is MatchProduceAgent)
            {
                IContinuation mysucc = succ;
                // Check if we have values to match later
                if (unmatched.Count != 0)
                {
                    mysucc = MakeNextUnmatchedContinue(mysucc);
                }
                ContextAppender appender = new ContextAppender(salience, context, -1, mysucc);

                MatchProduceAgent agent = (MatchProduceAgent)((Value)first).Data;
                context.Map["$check"] = input;
                ContinueToCallAgent codelet = new ContinueToCallAgent(agent, appender);

                IFailure deepenfail = myfail;
                if (!input.IsLeaf)
                {
                    // Continue to deeper
                    GroupPhrase groupPhrase = new GroupPhrase(input);
                    unmatched.InsertRange(0, groupPhrase.GetRange(1));
                    // Call again with the same evaluated first argument
                    Matcher matchrest = new Matcher(salience, groupPhrase.GetBranch(0), unmatched, succ);
                    deepenfail = new FailToContinue(context, matchrest, myfail);
                }

                codelet.Continue(context, deepenfail);
                return(true);
            }

            if (first is Word && input.IsLeaf)
            {
                WordComparer comparer = (WordComparer)context.LookupSimple("$Compare");
                if (comparer.Match(input.Text, first.Name))
                {
                    ContinueNextUnmatched(context.ChildRange(1));
                    return(true);
                }
                else
                {
                    // failure!
                    fail.Fail(string.Format("Pattern [{0}] does not match [{1}]", first.Name, input.Text), succ);
                    return(true);
                }
            }
            else if (first is Word)
            {
                GroupPhrase groupPhrase = new GroupPhrase(input);
                unmatched.InsertRange(0, groupPhrase.GetRange(1));
                Matcher matchcont = new Matcher(salience, groupPhrase.GetBranch(0), unmatched, succ);
                matchcont.Continue(context, myfail);
                return(true);
            }

            // We can't handle this!  fail
            fail.Fail("Unknown first element", succ);

            return(true);
        }
        public override bool Evaluate()
        {
            // Look through my concepts for a possible match
            List <IContent> contents = context.Contents;

            if (contents.Count == 1)
            {
                if (contents[0] is Variable)
                {
                    Variable check = (Variable)contents[0];

                    // If we already have a concept in mind, just check its data
                    Concept left = context.LookupDefaulted <Concept>("$knowConcept", null);
                    if (left != null)
                    {
                        List <Datum> data = memory.GetData(left);
                        foreach (Datum datum in data)
                        {
                            if (datum.Left == left && kinds.Contains(datum.Relation) && check.Match(context, datum.Right))
                            {
                                List <Datum> completes = context.LookupAndAdd <List <Datum> >("$knowCompletes", new List <Datum>());
                                completes.Add(datum);

                                succ.Continue(new Context(context, new List <IContent>()), fail);
                                return(true);
                            }
                        }

                        // Can't match anything!
                        fail.Fail("Initial variable didn't match anything", succ);
                        return(true);
                    }

                    // Does anything here match?
                    for (int ii = 0; ii < directchecks.Count; ii++)
                    {
                        bool matched = kinds.Contains(directchecks[ii].Relation);
                        if (matched)
                        {
                            matched = check.Match(context, directchecks[ii].Right);
                            if (propfunc != null) // always do propfuncs, but only affect matched if failed
                            {
                                matched = check.Match(context, directchecks[ii].Right, propfunc, propargs) || matched;
                            }
                        }

                        if (matched)
                        {
                            Context child = new Context(context, new List <IContent>());
                            child.Map["$knowConcept"] = directchecks[ii].Left;

                            List <Datum> completes = child.LookupAndAdd <List <Datum> >("$knowCompletes", new List <Datum>());
                            completes.Add(directchecks[ii]);

                            // Make a clone of ourselves, if this fails
                            succ.Continue(child, MakeContinuingFailure(ii));
                            return(true);
                        }
                    }
                }
                else if (contents[0].Name == "*" || contents[0].Name == "_")
                {
                    // If we already have a concept in mind, just check its data
                    Concept left = context.LookupDefaulted <Concept>("$knowConcept", null);
                    if (left != null)
                    {
                        List <Datum> data = memory.GetData(left);
                        foreach (Datum datum in data)
                        {
                            if (datum.Left == left && kinds.Contains(datum.Relation))
                            {
                                List <IContent> words = new List <IContent>();
                                if (!datum.Right.IsUnknown)
                                {
                                    words.Add(new Word(datum.Right.Name));
                                }
                                context.Map.Add(StarUtilities.NextStarName(context, contents[0].Name), words);

                                List <Datum> completes = context.LookupAndAdd <List <Datum> >("$knowCompletes", new List <Datum>());
                                completes.Add(datum);

                                succ.Continue(new Context(context, new List <IContent>()), fail);
                                return(true);
                            }
                        }

                        // Can't match anything!
                        fail.Fail("Could not find a matching datum", succ);
                        return(true);
                    }

                    // Does anything here match?
                    for (int ii = 0; ii < directchecks.Count; ii++)
                    {
                        if (kinds.Contains(directchecks[ii].Relation))
                        {
                            Context child = new Context(context, new List <IContent>());

                            List <IContent> words = new List <IContent>();
                            if (!directchecks[ii].Right.IsUnknown)
                            {
                                words.Add(new Word(directchecks[ii].Right.Name));
                            }
                            child.Map.Add(StarUtilities.NextStarName(child, contents[0].Name), words);
                            child.Map["$knowConcept"] = directchecks[ii].Left;

                            List <Datum> completes = child.LookupAndAdd <List <Datum> >("$knowCompletes", new List <Datum>());
                            completes.Add(directchecks[ii]);

                            succ.Continue(child, MakeContinuingFailure(ii));
                            return(true);
                        }
                    }
                }

                // Nothing matched!  Expand search
                if (parentchecks.Count > 0)
                {
                    Concept parent = parentchecks.Dequeue();
                    directchecks = memory.GetData(parent);
                    Continue(new Context(context, context.Contents, context.Weight * 0.95), fail);
                    return(true);
                }
            }

            // Don't fail if it's just a *
            if (contents.Count == 1 && contents[0].Name == "*")
            {
                Context child = new Context(context, new List <IContent>());

                List <IContent> empty = new List <IContent>();
                child.Map.Add(StarUtilities.NextStarName(child, contents[0].Name), empty);

                succ.Continue(child, fail);
                return(true);
            }

            fail.Fail("No data matches", succ);
            return(true);
        }