/// <summary>Calculates if the child is the same type as parent (zero), or how many levels of inheritance it's /// removed from. Returns -1 if the child isn't a subclass of (or equal to) the parent.</summary> public static int DistanceFrom(string child, string parent = "anything")// StandardType st, StandardType from = StandardType.anything) { int distance; for (distance = 0; child != null && child != parent; distance++) { child = InheritanceTree.Find(item => item.name == child).parent; } if (child != parent) { distance = -1; } return(distance); // Distance of 0 means same exact type. Distance of 1 means one's a direct parent, etc. }
/// <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); }
/*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)); }