[Types-sig] computing typedecl objects (was: New syntax?)

Greg Stein gstein@lyra.org
Tue, 21 Dec 1999 11:43:23 -0800 (PST)


On Mon, 20 Dec 1999, Paul Prescod wrote:
> Greg Stein wrote:
> > 
> > ...
> > 
> > Nah. No execution needs to take place. Just some data flow analysis. 
> 
> Let's be concrete:
> 1.
> 
> if somefunction():
> 	class a:
> 		def b(self)->String: return "abc"
> else:
> 	class a:
> 		def b(self)->Int: return 5
> 
> How many type objects are created? What are there names? What is the
> type of a? 

There are three typedecl objects (not "type object"!). Let's annotate your
code a bit to make this clearer:

if somefunction():
    class a:
        ...
    _internal_interface_a_1 = make_interface(a)  # compiler implies this
    a.__typedecl = _internal_interface_a_1  # compiler remembering the type
    first_interface = typedef a   # == _internal_interface_a_1
else:
    class a:
        ...
    _internal_interface_a_2 = make_interface(a)
    a.__typedecl = _internal_interface_a_2
    second_interface = typedef a
# type inferencer unions the type of a
a.__typedecl = typedef _internal_interface_a_1 or _internal_interface_a_2
final_interface = typedef a

The compiler does not create any names for these typedecl objects,
although it does imply them (the "_internal.*" names demo this). I've also
annotated that the compiler is remembering/associating a particular
typedecl with the class object. Finally, I've shown where the user is
explicitly fetching the typedecl object using the "typedef" keyword.

At the end of the above code, "a" has a union typedecl (for the purposes
of type checking/inferencing). The user has three typedecl objects held in
three variables (first_interface, second_interface, final_interface).

One point to make: "a" is a name referring to a class object. That is not
the same as a typedecl object, although it can be used in some contexts
where typedecl objects are needed. "typedef a" is definitely a typedecl
object and it cannot be used to instantiate an object. It refers to an
interface definition, actually.

> 2. 
> 
> class a:
> 	def b(self)->String: return "abc"
> for i in sys.argv:
> 	class a:
> 		def b(self)->Int: return 5

Just before the "for" statement, "typedef a" returns one typedecl. After
the "for" loop, it returns a different typedecl. Again: it will be a union
of the two interfaces (because we don't know whether the loop executes
zero or more iterations, so we can't know whether the class was
redefined).

If somebody gets smart and upgrades the type inferencer, it might be able
to detect:

class a: ...
for i in range(10):
  class a: ...

In this case, the inferencer knows the redefinition occurred, so it does
not have to create a union type.

> 3.
> 
> def makeClass():
> 	class a:
> 		def b( self ):
> 			return "abc"
> 	return a
> 
> j=makeClass()()

In this case, the "def" marks an analysis boundary. Its return type is
"any". In a type-safe world, the makeClass()() fails because we cannot
verify that a callable object was returned from makeClass. In a
type-checked world, there is nothing wrong with the above code.

> --------------------
> This seems intractable to me. I got around this in my original proposal
> by requiring all declaring classes to be *top-level*. In other words I
> formally defined the subset of Python that does not require code
> execution. If you can formally define the semantics of "data flow" then
> I will be able to compare the proposals.

The data flow merely replaces typedecls [that are associated with names],
or unions them if there are alternate code paths. The conditionals and
things that push classes away from "top-level" do not confuse an
inferencer. The type of your object will be a bit looser at type-check
time than at runtime, however.

The union will occur frequently when try/except is present:

  a = 1
  try:
    a = "foo"
    ...
  except:
    ...

  typedef a == typedef Int or String

> Note that I am half-way between you and Tim. I think that type objects
> should be more like Python objects but I am willing to restrict where
> they are created to make the problem tractable and the semantics
> understandable.

Please call them typedecl objects to avoid confusion with TypeType
objects. typedecl objects are created through type declarators or
implicitly by the inferencer and/or compiler.

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/