示例#1
0
    /// <summary>High-level function to parse the body of a function. Turns parseMe.body (a string) into parseMe.parsed_body
    /// (a List of Invocations) via multiple calls to ParseAnInvocation() and ParseListSeparator().</summary>
    public static void ParseInvocations(multimethod parseMe)
    {
        Console.WriteLine("#{0}: parsing body", parseMe.prompt);
        index               = 0;
        subprompt           = 0;
        parseMe.parsed_body = new List <invocation>();
        invocation invoke;

        do
        {
            ++subprompt;
            subsubprompt = 0;
            invoke       = ParseAnInvocation(parseMe.body);
            if (invoke != null)
            {
                parseMe.parsed_body.Add(invoke);
                invoke.definition.called++;
            }
            if (index < parseMe.body.Count - 1)
            {
                ParseListSeparator(parseMe.body.ToArray());
            }
        } while (invoke != null && index < parseMe.body.Count - 1);
        Console.WriteLine("  {0} statements in that function.", parseMe.parsed_body.Count);
        Console.WriteLine();
    }
示例#2
0
    /// <summary>Given a method signature and the types of the values being fed to it, this calculates how close of a match the values are for
    /// that signature.  It's used during multi-method dispatch when multiple methods can take that set of inputs to choose the
    /// best match for those inputs.</summary>
    public static long Distance(multimethod method, List <instance> inputs)
    {
        if (inputs.Count == 0)
        {
            return(0);                   // hopefully the signature's verb and the used verb match. If not, why call this function?
        }
        long summation = 0;
        int  i         = 0;
        int  squareme;

        foreach (term term in method.signature)
        {
            if (term.which != PartsOfSpeech.noun)
            {
                continue;
            }
            if (i >= inputs.Count)
            {
                return(999998);
            }
            squareme = DistanceFrom(inputs[i].type, term.noun.type);
            if (squareme < 0)
            {
                return(1000000);              // the inputs don't even match the signature.
            }
            summation += squareme * squareme;
            i++;
        }
        return(summation);
    }
示例#3
0
 public parameter(multimethod subfunction)
 {
     prompt   = subfunction.prompt;
     relation = subfunction.signature;
     foreach (var term in relation)
     {
         if (term.which == PartsOfSpeech.verb)
         {
             name = term.verb._ing;
         }
     }
     fullname1 = name;
     fullname2 = name;
 }
示例#4
0
    /// <summary>This is used while defining a higher-order function, tipped off by the -ing verb form that leads.</summary>
    static parameter CreateFunctionParameterObject(string[] words, fiveforms ing, bool isSubject = false)
    {
        long        savedIndex       = index;
        multimethod outerMethod      = method_being_constructed;
        string      savedDefinedVerb = definedVerb;

        method_being_constructed = new multimethod()
        {
            prompt = -outerMethod.prompt, question = ""
        };
        multimethod innerMethod = PredicateDefinition2(words, ing, isSubject); // returns method_being_constructed

        method_being_constructed = outerMethod;
        definedVerb = savedDefinedVerb;
        return(new parameter(innerMethod));
    }
示例#5
0
    /// <summary>For cases of "give someone the thing", we must back up and add "to" to the "someone"</summary>
    static void HandleSwappedDirectandIndirectObjects(multimethod method_being_constructed, string prep, fiveforms verb, bool isSubject)
    {
        if (isSubject)
        {
            return;
        }
        if (listType != null)
        {
            return;
        }
        switch (TheGiveSomebodyItException)
        {
        case DirectObjectPlacement.not_there_yet:
            TheGiveSomebodyItException = DirectObjectPlacement.normal;
            break;

        case DirectObjectPlacement.normal:
            // then the previous parameter is the indirect, not direct, object, and needs "to" prepended
            for (int i = 0; method_being_constructed.signature.Count > i; i++)
            {
                if (method_being_constructed.signature[i].which == PartsOfSpeech.noun)
                {
                    term newterm = method_being_constructed.signature[i];
                    newterm.noun.preposition = prep;
                    method_being_constructed.signature[i] = newterm;
                    CreateFullNames(method_being_constructed.signature[i].noun, verb);    //not sure why this is still needed
                    break;
                }
            }
            TheGiveSomebodyItException = DirectObjectPlacement.after_the_indirect_object;
            break;

        case DirectObjectPlacement.after_the_indirect_object:
        case DirectObjectPlacement.error:
            TheGiveSomebodyItException = DirectObjectPlacement.error;
            Console.WriteLine("  ERROR: I require those parameters to be separated by prepositions or commas.");
            method_being_constructed.problems++;
            break;
        }
    }
示例#6
0
    static void VerifyAbstractSyntaxTree()
    {
        // now check the whole abstract syntax tree

        // First, is there one and only one root?  "To do:"
        fiveforms   rootverb = FindVerb("do");
        multimethod main     = null;

        if (mms.ContainsKey(rootverb))
        {
            foreach (multimethod possibleRoot in mms[rootverb])
            {
                if (possibleRoot.signature.Count == 1)
                {
                    if (main == null)
                    {
                        main = possibleRoot;
                    }
                    else
                    {
                        Console.WriteLine("  ERROR:  I have too many definitions for \"To do:\", like #{0} and #{1}", main.prompt, possibleRoot.prompt);
                    }
                }
            }
        }
        if (main == null)
        {
            Console.WriteLine("  ERROR:  Where does the whole thing start?  I need a sentence which begins, \"To do:\"");
        }
        else
        {
            main.called++;
        }

        // dead code elimination?  unused structs elimination?
    }
示例#7
0
 public invocation(multimethod d, int from, int to, List <instance> bound)
 {
     definition = d; startWord = from; endWord = to; boundParameters = bound;
 }
示例#8
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();
    }