A type object (termtype object?) is returned by the type() method of a term. For example, if t is the term foo(3,bar), then t.type() is a type object representing the type foo. The following methods get details about that type.
Also need ways to get the type with a particular Dyna or C++ name without actually constructing a term of that type. Probably just foo::type().
However, to find out whether t has type foo, just do t.is_foo(), or if you insist, t.type().is_foo(). Don't ask whether t.type() equals foo::type(), because it is possible that t is implemented as a subtype of foo rather than as foo directly (unbeknowst to you!).
Questions that we can ask about a base type:
- if not, how many arguments and what are their types?
- if so, what is the value type?
- if so, what is the accumulation operator?
- if so, is it trainable?
- equal to another type?
- subtype of another type? (if we allow union types as first-class objects)
Maybe also methods for exploring the type hierarchy: get from a union type to an iterator over the base types that make it up, and maybe from a collection of base types to a union type over them.
Finally, maybe methods for asking about a type's pragmas, etc. This is just a matter of exposing the internal interface.