Example #1
0
    static void TestSignatures()
    {
        //// And now, all the input sentences have been read in, if not processed.

        // test output only
        TestHarness.Reset();
        foreach (multimethod func in multimethods)
        {
            TestHarness.BeginTurn();
            Console.WriteLine("{0}{1}", (TestHarness.NextTestLine < TestHarness.testlines.Count()) ? TestHarness.testlines[TestHarness.NextTestLine].Trim() : func.prompt.ToString(), (func.problems > 0) ? " (problematic)" : "");
            foreach (term term in func.signature)
            {
                switch (term.which)
                {
                case PartsOfSpeech.noun:        Console.WriteLine("  parameter '{1}{0}'", term.noun.fullname1, term.noun.isAggregate ? "" : "the "); break;

                case PartsOfSpeech.verb:        Console.WriteLine("  verb '{0}'", term.verb.plural); break;

                case PartsOfSpeech.preposition: Console.WriteLine("  keywords '{0}'", term.preposition); break;

                default:                        Console.WriteLine("ERROR IN COMPILER: unknown term"); break;
                }
            }
            TestHarness.EndTurn(1);
            if (func.fully_parsed)
            {
                Console.WriteLine("({0} fully parsed{1})", func.prompt, func.problems + func.todo > 0 ? ", but with problems/to-dos" : "");
            }
        }
    }
Example #2
0
    static int prompt = 1, subprompt, subsubprompt; // the sentence#, invocation#, and relative clause #

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static void Main(string[] args)
    {
        ReadForms();
        TheVerbIs = FindVerb("is");
        InitNumberUnitSystem();
        InitInheritanceTree();

        string input = null;

        string[] words = null;
        int      maxWords;

        TestHarness.loadTestScript("me");
        for (Console.Write("{0}: ", prompt); (input = TestHarness.LineFeeder()) != null; TestHarness.EndTurn(2), Console.Write("{0}: ", ++prompt))
        {
            TestHarness.BeginTurn();

            // Move string literals into the string table, leaving placeholders behind.
            while (input.Contains('"'))
            {
                int from  = input.IndexOf('"');
                int endAt = from + 1;
loopPastDquoteLiteral:
                endAt += input.Substring(endAt).IndexOf('"');
                if (input.Length > endAt + 1 && input.ElementAt(endAt + 1) == '"')
                {
                    endAt += 2;
                    goto loopPastDquoteLiteral;
                }
                int    len     = endAt - (from + 1);
                string literal = input.Substring(from + 1, len);
                input = input.Substring(0, from - 1) + String.Format(" __litstring{0}__ ", literalStrings.Count) + input.Substring(endAt + 1);
                literalStrings.Add(literal.Replace("\"\"", "\""));
            }

            // cleanse the input
            input    = input.ToLowerInvariant() + " ";
            input    = input.Replace(", ", " , ").Replace(". ", " . ").Replace(": ", " : ").Replace("? ", " ? ");
            input    = input + " " + stringnums.EOL[0];
            words    = input.Split(new[] { ' ', '\t', '\n' }, StringSplitOptions.RemoveEmptyEntries);
            maxWords = (int)words.Count();
            if (maxWords < 2)
            {
                break;               // EOL is always appended
            }
            // debugging / testharness feature: input a line number
            if (maxWords == 2 && Int32.TryParse(words[0], out subjectAt))
            {
                Console.WriteLine(TestHarness.testlines[--subjectAt * 3]);
                Console.WriteLine(TestHarness.testlines[subjectAt * 3 + 1]);
                Console.WriteLine(TestHarness.testlines[subjectAt * 3 + 2]);
                continue;
            }

            // meta / macro command: tell the compiler to run another file.
            if (maxWords == 3 && words[0] == "regard" && words[1].StartsWith("__litstring"))
            {
                TestHarness.loadTestScript(Say(words[1]));
                continue;
            }

            // initialize vars
            index       = 0;
            definedVerb = "";
            preposition = "";
            method_being_constructed = new multimethod()
            {
                prompt = prompt, question = ""
            };
            //method_being_constructed.prompt = prompt;
            subjectAt              = -1;
            isQuestion             = false;
            incarnations           = null;
            listType               = null;
            IdentEndsAt            = maxWords;
            just_declared_new_type = false;

            // Absorb any prepositions at the beginning, as in "To give..." or "To boldly go..." or "To a person give...", etc.
            while (stringnums.prepositions.Contains(words[index]))
            {
                if (preposition != "")
                {
                    preposition += " ";
                }
                preposition += words[index++];
            }

            // if the first word(s) indicate a question, read it.
            //method_being_constructed.question = "";

            /*if (stringnums.QuestionWords.Contains(words[index]))
             * {
             *  string question = "";
             *  while (stringnums.QuestionWords.Contains(words[index]))
             *  {
             *      if (question != "") question += " ";
             *      question += words[index++];
             *  }
             *  incarnations = FindVerb(words[index]); // Catches "What is.." but not "Which car is..."
             *  method_being_constructed.question = question;
             *  isQuestion = true;
             * }*/

            // if first word(s) indicated a subject, read it
            if (stringnums.DefiniteArticles.Contains(words[index]) || stringnums.IndefiniteArticles.Contains(words[index]) || stringnums.ListDeterminers.Contains(words[index]) || words[index].EndsWith("ing") || (method_being_constructed.question != "" && incarnations == null))
            {
                ParseSubject(words);
            }

            if (prompt >= 37)
            {
                Console.WriteLine();
            }

            // Regardless, parse the predicate:  a verb and the nouns that go with.
            incarnations = PredicateDefinition(words);

            // If we haven't found a verb yet, but we do have a subject, look for the verb in the subject's name.
            if (incarnations == null && subjectAt >= 0)
            {
                string[] subnames = method_being_constructed.signature[subjectAt].noun.name.Split(' ');
                for (int i = subnames.Count() - 1; i >= 0; i--)
                {
                    index--;
                    incarnations = FindMainVerb(subnames[i]);
                    if (incarnations == null)
                    {
                        continue;
                    }

                    // Ah, there's the verb. Shorten the subject's name, and try parsing the predicate again from this index position.
                    definedVerb = subnames[i];
                    string newname = subnames[0];
                    for (int j = 1; j < i; j++)
                    {
                        newname += " " + subnames[j];
                    }
                    method_being_constructed.signature[subjectAt].noun.name = newname;
                    Console.WriteLine("  oops; verb is '{1}' and subject is '{0}'", newname, definedVerb);
                    incarnations = PredicateDefinition(words);
                    break;
                }
            }

            // If we still don't have a verb, we're going to have to search for it the long way.
            if (incarnations == null)
            {
                int savedIndex = index;
                while (incarnations == null && index < maxWords - 1 && !stringnums.EndsInfinitiveDefinition.Contains(words[index]))
                {
                    incarnations = FindMainVerb(words[++index]); // this is an expensive loop
                }
                if (incarnations != null)
                {
                    // ah, found it. There must be a subject in front of it...
                    definedVerb = words[index];
                    IdentEndsAt = index;
                    index       = 0; // back to first word of sentence
                    if (ParseSubject(words) == null)
                    {
                        method_being_constructed.signature.Add(new term(incarnations));
                        Console.Write("ERROR: verb is '{0}' but I don't know what to do with the subject: ", definedVerb);
                        for (int i = savedIndex; i < IdentEndsAt; i++)
                        {
                            Console.Write("{0} ", words[i]);
                        }
                        Console.WriteLine();
                        method_being_constructed.problems++;
                        multimethods.Add(method_being_constructed);
                        continue;
                    }
                    index++;                                            // advance past verb
                    IdentEndsAt = (int)words.Count();                   // un-set the hint
                    var mm = PredicateDefinition2(words, incarnations); // and finish the predicate as normal
                    multimethods.Add(mm);
                }
            }

            // If we STILL don't have a verb, abort this sentence.
            if (incarnations == null)
            {
                method_being_constructed.signature.Add(new term("..."));
                Console.Write("ERROR: I couldn't find a verb in: ");
                for (int i = 0; i < index; i++)
                {
                    Console.Write("{0} ", words[i]);
                }
                Console.WriteLine();
                method_being_constructed.problems++;
                multimethods.Add(method_being_constructed);
                continue;
            }

            //if (prompt == 32)
            //    Console.WriteLine("debug");

            // OK, we have a verb, and processed the rest of the definition with it.  We should be at a marker separating
            // the function head from the function body.  Or if it's a type/struct/object definition, we're at the end of
            // the sentence entirely.
            method_being_constructed.fully_parsed = stringnums.EOL.Contains(words[index]);
            if (stringnums.EndsInfinitiveDefinition.Contains(words[index]))
            {
                index++; // advance past the comma, colon, BY, VIA, MEANS, or whatever separates head from body
            }
            else if (words[index] != ".")
            {
                Console.WriteLine("I didn't expect this definition of '{1}' end with a '{0}'", words[index], definedVerb);
                method_being_constructed.problems++;
                continue;
            }

            // If we had a valid definition, save away its body. We can't parse the bodies until we read all the heads.
            // That's because what names, esp. parameter names and other function invocations, that appear in the bodies
            // aren't even known yet.
            if (!method_being_constructed.fully_parsed)
            {
                method_being_constructed.body = new List <string>();
                while (index < maxWords - 1 && !stringnums.EOL.Contains(words[index]))
                {
                    method_being_constructed.body.Add(words[index++]);  //ParseParameterInvocation(words);
                }
            }


            // for case of "X is Y..."
            // if the subject is already a type, and is now being used with "IS" again,
            // Ensure we don't use a known type with "is" unless
            // 1) there's a "when", or
            // 2) the subject is "the" instance of the type, or
            // 3) the subject is a gerund phrase (function type), so the predicate is a categorical name, a "class" or "name of enum" for signatures
            if (subjectAt != -1 && incarnations._en == "been" && method_being_constructed.fully_parsed)
            {
                parameter theSubject = method_being_constructed.signature[subjectAt].noun;
                if (just_declared_new_type && theSubject.art == Article.the)
                {
                    Console.WriteLine("  global variable or singleton instance '{0}' created", theSubject.name);
                    PermanentDataSegment.Add(theSubject);
                }
                else if (theSubject.isAggregate && method_being_constructed.signature.Count == 3)
                {   // "Xing... is Y." so define Y as a category for verbs
                    var ident   = method_being_constructed.signature[2].which == PartsOfSpeech.noun ? method_being_constructed.signature[2].noun.name : method_being_constructed.signature[2].preposition;
                    var newType = CreateNewType(ident, StandardType.homogene);
                    Console.WriteLine("  assuming '{0}' categorizes verbs", ident);
                }
                else if (!just_declared_new_type)
                {
                    if (theSubject.type == StandardType.anything)
                    {
                        Console.WriteLine("  ERROR: I have no idea what a '{0}' is. It could be anything.", theSubject.name);
                    }
                    else
                    {
                        Console.WriteLine("  ERROR: trying to re-define the type '{0}'", NameOfType(theSubject.type));
                    }
                    method_being_constructed.problems++;
                }
            }

            // Create the various names for each parameter in the new method.
            // This isn't perfect because we don't know where a noun phrase ends and where adverbs and verbs begin.
            // We'll keep it all as the possible noun phrase, but when we start parsing the body, we'll look at
            // what the parameters are actually called in there. Then we can shorten our parameter names to match
            // sensibly.
            TheGiveSomebodyItException = DirectObjectPlacement.not_there_yet;
            for (int i = 0; i < method_being_constructed.signature.Count; i++)
            {
                if (method_being_constructed.signature[i].which == PartsOfSpeech.noun)
                {
                    term      newterm  = method_being_constructed.signature[i];
                    parameter oldparam = newterm.noun;
                    newterm.noun = NamedParameter(oldparam, incarnations, (i == subjectAt));
                    method_being_constructed.signature[i] = newterm;
                }
                else if (method_being_constructed.signature[i].which == PartsOfSpeech.verb)
                {
                    TheGiveSomebodyItException = DirectObjectPlacement.not_there_yet;
                }
            }

            // Now we should be at the end of line: a period, question mark, or exclamation mark
            // If not, throw a helpful error.
            method_being_constructed.problems++;
            if (index >= words.Count())
            {
                Console.WriteLine("COMPILER ERROR: EOL eaten: index too high");
            }
            else if (words[index] != "ENDOFINPUT" && words[index] != ".")
            {
                if (index < words.Count())
                {
                    Console.WriteLine("  ERROR: I wasn't expecting '{0}' there, but rather, the end of the sentence.", words[index]);
                }
                else
                {
                    Console.WriteLine("COMPILER ERROR: EOL eaten");
                }
            }
            else
            {
                method_being_constructed.problems--;
            }


            // Sentence processed. Get next sentence
        }

        TestSignatures();
        Pass2ResolveImplicitTypesAndCreateMultimethodDictionary();
        Pass3MethodBodies();
        VerifyAbstractSyntaxTree();
        CodeGeneration();
    }