Exemple #1
0
    /// <summary>Creates a new type defined by the user, as a subclass of another user-defined type.</summary>
    public static InheritedType CreateNewType(string ident, string parentClassName)
    {
        if (string.IsNullOrWhiteSpace(parentClassName))
        {
            return(CreateNewType(ident));
        }
        var newType = new InheritedType()
        {
            name = ident, parent = parentClassName, typeid = (StandardType)(InheritanceTree.Count + 2)
        };

        InheritanceTree.Add(newType);
        just_declared_new_type = true;
        return(newType);
    }
Exemple #2
0
    /// <summary> Creates the lookup table for what types inherit from what. This would be hard-coded if C# would allow. </summary>
    public static void InitInheritanceTree()
    {
        for (StandardType st = StandardType.anything; st < StandardType.Count; st++)
        {
            var it = new InheritedType()
            {
                name = st.ToString(), subtypes = null, typeid = st
            };
            switch (st)
            {
            case StandardType.anything: it.parent = null; break;

            case StandardType.something:
            case StandardType.nothing: it.parent = StandardType.anything.ToString(); break;

            case StandardType.valueType:
            case StandardType.referenceType: it.parent = StandardType.something.ToString(); break;

            case StandardType.number:
            case StandardType.discrete:
            case StandardType.reference:
            case StandardType.structure: it.parent = StandardType.valueType.ToString(); break;

            case StandardType.homogene:
            case StandardType.heterogene:
            case StandardType.value: it.parent = StandardType.referenceType.ToString(); break;

            case StandardType.percent:
            case StandardType.money: it.parent = StandardType.number.ToString(); break;

            case StandardType.position:
            case StandardType.boole: it.parent = StandardType.discrete.ToString(); break;

            case StandardType.time: it.parent = StandardType.structure.ToString(); break;

            case StandardType.text:
            case StandardType.list: it.parent = StandardType.homogene.ToString(); break;

            case StandardType.sequence:
            case StandardType.Object: it.parent = StandardType.heterogene.ToString(); break;

            default: Console.WriteLine("ERROR IN COMPILER: unknown base type {0}", st); break;
            }
            InheritanceTree.Add(it);
        }
        //TestInheritanceTree();
    }
Exemple #3
0
    /// <summary>Returns the parent of the passed-in type. Returns Anything for unrecognized types as well as Anything
    /// itself.  Returns Object (which is assumed) for types which claim to have no parent.  (Those were implicitly
    /// created by a "list of" construction, and will presumably be filled in later.) </summary>
    public static StandardType ParentOf(StandardType st)
    {
        if (st == StandardType.anything)
        {
            return(StandardType.anything);                             // anything is anything, the root type
        }
        InheritedType it = InheritanceTree.Find(item => item.typeid == st);

        if (it == null)
        {
            return(StandardType.anything);
        }
        if (it.parent == null)
        {
            return(StandardType.Object);                   // only happens with used but undefined types
        }
        return(InheritanceTree.Find(item => item.name == it.parent).typeid);
    }
Exemple #4
0
    /*public static void TestInheritanceTree()
     * {
     *  IsA(StandardType.number, StandardType.number);
     *  Console.WriteLine("Is {0} a {1}? {2}.", StandardType.number, StandardType.number, (distance > -1));
     *  IsA(StandardType.number, StandardType.valueType);
     *  Console.WriteLine("Is {0} a {1}? {2}.", StandardType.number, StandardType.valueType, (distance > -1));
     *  IsA(StandardType.Object, StandardType.anything);
     *  Console.WriteLine("Is {0} a {1}? {2}.", StandardType.Object, StandardType.anything, (distance > -1));
     *  IsA(StandardType.anything, StandardType.anything);
     *  Console.WriteLine("Is {0} a {1}? {2}.", StandardType.anything, StandardType.anything, (distance > -1));
     *  IsA(StandardType.text, StandardType.valueType);
     *  Console.WriteLine("Is {0} a {1}? {2}.", StandardType.text, StandardType.valueType, (distance > -1));
     *  IsA(StandardType.text, StandardType.reference);
     *  Console.WriteLine("Is {0} a {1}? {2}.", StandardType.text, StandardType.reference, (distance > -1));
     *  IsA(StandardType.number, StandardType.percent);
     *  Console.WriteLine("Is {0} a {1}? {2}.", "number", "percent", (distance > -1));
     *  IsA(StandardType.percent, StandardType.number);
     *  Console.WriteLine("Is {0} a {1}? {2}.", "percent", "number", (distance > -1));
     *  IsA(StandardType.number, StandardType.anything);
     *  Console.WriteLine("Is {0} a {1}? {2}.", "number", "anything", (distance > -1));
     *  IsA(StandardType.number, StandardType.something);
     *  Console.WriteLine("Is {0} a {1}? {2}.", "number", "something", (distance > -1));
     *  /*IsA(StandardType.money, StandardType.car);
     *  Console.WriteLine("Is {0} a {1}? {2}.", "money", "car", (distance > -1));
     *  IsA("car", "object");
     *  Console.WriteLine("Is {0} a {1}? {2}.", "car", "object", (distance > -1));
     *  IsA("car", "something");
     *  Console.WriteLine("Is {0} a {1}? {2}.", "car", "something", (distance > -1));
     * }*/

    /// <summary>Returns the name of the given StandardType, including newly-defined types in the source. </summary>
    public static string NameOfType(StandardType?s)
    {
        if (s == null)
        {
            return("whatever");
        }
        var st = s.Value;

        if (st <= StandardType.anything)
        {
            return(StandardType.anything.ToString());
        }
        if (st < StandardType.Count)
        {
            return(st.ToString());
        }
        InheritedType it = InheritanceTree.Find(item => item.typeid == st);

        return(it.name);
    }
    /// <summary>Part of CreateParameterObject, which does the work for ParseNounPhraseForParameter.
    /// When declaring the parameters of a function's signature, this helper digests the "many..." parameter, which isn't
    /// a trivial operation, considering that lists have subtypes, some of which may not be known yet.</summary>
    static parameter CreateListParameterObject(ref StandardType?type, string ident, bool adjnounswap)
    {
        if (ident == null && type == null)
        {
            Console.WriteLine("  ERROR: many whats?");
            method_being_constructed.problems++;
            return(new parameter("", ident, Article.many, (StandardType)0, adjnounswap));
        }

        //either ident has value, type has value, or both have value
        // if basetype has value, then ident must not be a type. i.e., warn of "numeric car" or "many numeric cars" when car is of type object
        if (ident.HasValue() && type.HasValue)
        {
            InheritedType it = InheritanceTree.Find(item => item.name == ident);
            if (it != null && it.typeid != type.Value)
            {
                Console.WriteLine("  WARNING: '{0}' is declared elsewhere as a '{1}', not a '{2}'", it.name, NameOfType(it.typeid), NameOfType(type.Value));
            }
        }

        // for the term "several/many/multiple numbers", set ident to the whole term "many numbers" -- a generated name
        if (string.IsNullOrEmpty(ident))
        {
            ident = string.Format("many {0}", type);
        }

        // for the term "many gadgets", set type to "gadgets" by finding the type by name, or making a new one
        if (type == null)
        {
            InheritedType subtype = InheritanceTree.Find(item => item.name == ident);
            if (subtype == null)
            {   // make a new type, "gadgets", whose parent (and subtype, if applicable) to be filled out later?
                subtype = new InheritedType()
                {
                    name = ident, typeid = (StandardType)(InheritanceTree.Count + 2)
                };
                InheritanceTree.Add(subtype);
            }
            type = subtype.typeid;
        }

        // now all three are populated:  mode, type, ident
        // now, does our composite type already exist? Else make a new typeid
        string        typeAsString = type.Value.ToString();
        InheritedType aggregate    = InheritanceTree.Find(item => item.name == ident && item.parent == StandardType.list.ToString() && item.subtypes == typeAsString);

        if (aggregate != null)
        {
            Console.WriteLine("  another '{0}' (a list of {1})", ident, NameOfType(type.Value));
            return(new parameter("", ident, Article.many, type.Value, adjnounswap));
        }
        aggregate = new InheritedType()
        {
            name = ident, parent = StandardType.list.ToString(), subtypes = type.Value.ToString(), typeid = (StandardType)(InheritanceTree.Count + 2)
        };
        InheritanceTree.Add(aggregate);
        just_declared_new_type = true;

        string typename = NameOfType(type.Value);

        if (ident != typename)
        {
            Console.WriteLine("  a list of {0}, called {1}", typename, ident);
        }
        else
        {
            Console.WriteLine("  a list of {0}", typename);
        }

        return(new parameter("", ident, Article.many, type.Value, adjnounswap));
    }
    /// <summary>When defining a parameter of a new function's signature, and once parsing of that parameter is done, this converts
    /// the information into a parameter object. Uses CreateListParameterObject since that is a tome in itself.</summary>
    static parameter CreateParameterObject(string[] words, Article?mode, StandardType?type, StandardTypeAdjective?adjtype, string ident, bool identIsAdjectiveTypeIsNoun = false, bool isSubject = false)
    {
        // something/nothing/anything aren't preceded by an article. Treat as "a thing"
        if (type.HasValue && type <= StandardType.something)
        {
            Console.WriteLine("  declaring a parameter which {0}", type == StandardType.nothing ? "must be nothing" : type == StandardType.anything ? "could be anything" : "mustn't be nothing");
            return(new parameter("", type.Value.ToString(), Article.a, type.Value, identIsAdjectiveTypeIsNoun));
        }

        switch (mode)
        {
        case Article.the:
            if (type.HasValue)
            {
                if (adjtype == null)
                {
                    Console.WriteLine("ERROR: we say 'the {0}' to use it later in the sentence. Here we should say 'a {0}'.", NameOfType(type.Value));
                }
                else
                {
                    Console.WriteLine("ERROR: we say 'the {0}' to use it later in the sentence. Here we should say 'a {0} {1}'.", adjtype, ident == "" ? "name-of-it" : ident);
                }
                method_being_constructed.problems++;
                return(null);
            }
            if (isSubject || isQuestion)
            {
                just_declared_new_type = isSubject;     // and a global instance, as well
                return(new parameter("", ident, mode ?? Article.the, type ?? StandardType.number, identIsAdjectiveTypeIsNoun));
            }
            Console.WriteLine("ERROR: we should use 'a' not 'the' in this part of the sentence.");
            method_being_constructed.problems++;
            return(null);

        case Article.many:
            return(CreateListParameterObject(ref type, ident, identIsAdjectiveTypeIsNoun));

        case Article.a:
            if (type.HasValue)     // also, should we disallow it when the ident is also a type? "numeric car"
            {
                Console.WriteLine("  declaring a parameter of type {0} called '{1}'", NameOfType(type.Value), ident);
                InheritedType it = InheritanceTree.Find(item => item.name == ident);
                if (it != null && it.typeid != type.Value)
                {
                    Console.WriteLine("  WARNING: '{0}' is declared elsewhere as a '{1}', not a '{2}'", it.name, NameOfType(it.typeid), NameOfType(type.Value));
                }
            }
            else if (isQuestion && incarnations == TheVerbIs)
            {
                for (IdentEndsAt = index; IdentEndsAt < words.Length && words[IdentEndsAt] != "?"; IdentEndsAt++)
                {
                    ;
                }
                if (IdentEndsAt >= words.Length)
                {
                    Console.WriteLine("  ERROR: I thought #{0} was a question because it began with '{1}', but I couldn't find a question mark afterward.", method_being_constructed.prompt, method_being_constructed.question);
                    method_being_constructed.problems++;
                    return(null);
                }
                Console.WriteLine("  defining a {0} by Q&A.", ident);
                ident = ParseNewIdentifier(words, ref type);
            }
            else if (!isSubject)
            {
                if (ident == "")     // then we have no type info whatsoever. Just get a new ident
                {
                    ident = ParseNewIdentifier(words, ref type);
                }
                Console.WriteLine("  TODO: is '{0}' textual? Numeric? Or something more complex?", ident);
                method_being_constructed.todo++;
            }
            // defining a new type
            else if (InheritanceTree.Find(item => item.name == ident) != null)
            {
                Console.WriteLine("  ERROR: re-defining type '{0}'.", ident);
                method_being_constructed.problems++;
                //return null; // let it parse for now
                return(new parameter("", ident, mode ?? Article.a, type ?? (StandardType)0, identIsAdjectiveTypeIsNoun));
            }
            else
            {
                // object until proven otherwise. heck, it may not even be a type, it might be an instance or variable.
                var newType = CreateNewType(ident);
                Console.WriteLine("  assuming '{0}' is a new type", newType.name, newType.typeid);
            }
            break;

        case null:
            if (type == null)
            {
                return(null);
            }
            if (ident == null)
            {
                Console.WriteLine("  plural(?) parameter of type {0}", type);
            }
            else
            {
                Console.WriteLine("  plural(?) parameter of type {1} called the {0}", ident, NameOfType(type.Value));
            }
            break;
        }
        return(new parameter("", ident, mode ?? Article.a, type ?? (StandardType)0, identIsAdjectiveTypeIsNoun));
    }
Exemple #7
0
    static void Pass2ResolveImplicitTypesAndCreateMultimethodDictionary()
    {
        // Next up, ensure we've resolved the types of all parameters.
        // (and to speed up later processing, create a sorted dictionary of all the multimethods)
        // (and to speed up later processing, create a sorted dictionary of all the multimethods which don't begin with a parameter)
        List <term> badterms = new List <term>();

        foreach (multimethod function in multimethods)
        {
            foreach (term term in function.signature)
            {
                switch (term.which)
                {
                case PartsOfSpeech.verb: // create a sorted dictionary of all multimethods
                    if (!mms.ContainsKey(term.verb))
                    {
                        mms.Add(term.verb, new List <multimethod>());
                    }
                    mms[term.verb].Add(function);
                    continue;

                case PartsOfSpeech.noun: // find the type of any unknown-type parameters
                    if (term.noun.type != (StandardType)0)
                    {
                        break;
                    }
                    if (term.noun.isAggregate)
                    {
                        foreach (term innerTerm in term.noun.relation)
                        {
                            if (innerTerm.which != PartsOfSpeech.noun)
                            {
                                continue;
                            }
                            InheritedType it = InheritanceTree.Find(x => x.name == innerTerm.noun.name);
                            if (it != null)
                            {
                                innerTerm.noun.type = it.typeid;
                            }
                            else
                            {
                                badterms.Add(innerTerm);
                            }
                        }
                        break;
                    }
                    foreach (var t in InheritanceTree)
                    {
                        if (t.name != term.noun.name)
                        {
                            continue;
                        }
                        term.noun.type = t.typeid;
                        goto breakOverElseBecauseFoundIt;
                    }
                    badterms.Add(term);
//                    Console.WriteLine("  ERROR: is '{0}' a number? A text? Something else? You haven't said.", term.noun.name);
                    function.problems++;
                    break;
                }
breakOverElseBecauseFoundIt:
                ;
            }
        }
        if (badterms.Count > 0)
        {
            Console.WriteLine("  ERROR: What are these? A number? A text? Something else? You haven't said.");
        }
        foreach (var term in badterms)
        {
            Console.Write("{0}, ", term.noun.name);
        }
        Console.WriteLine();

        // When creating aggregate types like List Of X, we might create X as a placeholder. But if the real X is never defined...
        List <InheritedType> badtypes = new List <InheritedType>();

        foreach (InheritedType t in InheritanceTree)
        {
            if (t.parent == null && t.typeid != StandardType.anything)
            {
                badtypes.Add(t);
            }
        }
        if (badtypes.Count > 0)
        {
            Console.WriteLine("  ERROR: Are these the plural form of a word I don't know? Or is it a number? A text? Something else? We have 'many' of them but I need to know what just one of them is.");
        }
        foreach (var t in badtypes)
        {
            Console.Write("{0}, ", t.name);
        }
        Console.WriteLine();

        // Now that all types are resolved, ensure we haven't re-declared the same verb with the same signature.
        Console.WriteLine("{0} different verbs: ", mms.Count);
        foreach (KeyValuePair <fiveforms, List <multimethod> > entry in mms)
        {
            Console.WriteLine(entry.Key.plural);
            if (entry.Value.Count < 2)
            {
                continue;
            }
            var sigs = new Dictionary <string, multimethod>();
            foreach (multimethod method in entry.Value)
            {
                string newsig = method.signature.ToString(false);//"";

                /*foreach (term t in method.signature)
                 * {
                 *  switch (t.which)
                 *  {
                 *      case PartsOfSpeech.noun:
                 *          newsig += (t.noun.isAggregate) ? t.noun.signatureToString() : t.noun.name;
                 *          break;
                 *      case PartsOfSpeech.preposition: newsig += t.preposition; break;
                 *      case PartsOfSpeech.verb:
                 *          newsig += t.verb.plural;
                 *          break;
                 *  }
                 *  newsig += " ";
                 * }*/
                var preexisting = (sigs.ContainsKey(newsig)) ? sigs[newsig] : null;
                if (preexisting != null)
                {
                    Console.WriteLine("  ERROR: we have more than one method for {0}:", entry.Key._ing);
                    Console.WriteLine("#{0} '{1}'", preexisting.prompt, newsig);
                    Console.WriteLine("#{0} '{1}'", method.prompt, newsig);
                }
                else
                {
                    sigs.Add(newsig, method);
                }
            }
        }
    }