[Types-sig] check.py (was: PyDL RFC 0.02)

Greg Stein gstein@lyra.org
Tue, 28 Dec 1999 22:52:56 -0800 (PST)


On Wed, 29 Dec 1999, scott wrote:
>...
> While there may be a lot of value in walking the parse tree as your
> checker does, it doesn't seem to do much in terms of what I expect out
> of a type checker.  

It isn't done. I thought that I made that very clear. It provides a
framework for how to do this work. It tracks expression types, records the
types that should be associated with variables, etc.

The problem is that it does not yet have a way to declare types. Also,
some of the type recording (e.g. for types for an interface) is not yet
complete.

> What I want to be able to do:  declare types, and have things which
> contradict the declarations reported nicely at compile time.  A little
> searching through the code you posted didn't show any clear way to
> declare types,

To do this, I would need to change the Python grammar, or suck in .pyi
files. I plan to do the latter once some kind of formal grammar is
specified. If that doesn't happen soon, then I'll be using the grammar
that I posted in my type-proposal.html. It is complete and is sufficient
(yet Paul seems to be starting from scratch... :-( ).

> it just seems to spit out lots of attribute warnings
> when run it on itself, and it fails to detect anything wrong with the
> few simple cases I've thrown at it.  for example:
> 
> a = 1
> b = "3"
> a + b
> 
> yields no warnings, but is an error I'd expect a type checker to
> understand.
> 
> 
> def foo(x, y): return x + y
> 
> foo(2)
> 
> also yields no warnings, and is something I'd expect a type checker to
> understand.

Correct. It does not check these types of errors yet.

Try this, however:

a = { }
a.append(1)

b = [ ]
b.append(1)

You will get an error on that a.append. The attribute does not exist. But
it allows the b.append.

This demonstrates that it is tracking that "a" is a dictionary and that
"b" is a list. Further, it understands that "append" is only defined on a
list.

The first problem you list "a + b" is because _arith_expr() is not filled
in. It does not handle verification of the left/right operands as being
compatible with the "+" operator.

The second problem (with the foo(2)) is because _check_function_call() is
not yet filled in. However, the code *does* know that foo() has two
parameters named "x" and "y" (of type "Any" right now). This implies that
_check_function_call() has enough information to check the number of
arguments and to verify that if you use keywords, they must be "x" or "y".
[ but I don't record defaults yet, handle varargs or keyword funcs, or
  deal with things like: def foo(x, (y, z)):. ]

>...
> The checker you posted either falls way short of being able to declare
> and check static types,

It does fall way short. It is a prototype/demo. It is *not* complete. It
can be filled in to provide for this -- the necessary structure is there.

> or it's sufficiently unclear how to make it do
> that that I'd only accept existence proof as a series of examples of
> making it do that.

Fine. I'll accept that you don't see it as having the future capability to
do this. Not a problem, as I'll just work on it some more until it reaches
that point.

I feel that it *does* show you can do full namespace tracking without
running code (the original issue that stemmed this mini-thread). I believe
it also provides a good structure for writing a type-checker (in fact, if
somebody else were to write a type-checker, I think it would have so much
of the same form that I would recommend against duplication of work; I'd 
rather see a couple people contributing to the same chunk o' code).

> For example, how do you make it check the two
> examples above properly?

Described above. Fill in _arith_expr() and _check_function_call(). The
type information is present, although I need to think of a way to have a
TypeDeclarator object say "I can support addition" (at the moment, it can
only say "I have <this> attribute").

> How can I declare variable 'a' to be an
> integer,

We need an external file format and/or to change the grammar. It just
isn't possible right now since it is using Python's internal parser.

> and then have the checker report something remotely
> meaningful when I assign a string to the variable 'a' in the same
> namespace?

Currently, the checker understands the difference between something being
declared, and something having a specified type by virtue of an
assignment. It will issue an error for the former case, and allow a
redefinition in the latter case.

But: since you can't declare something to have a given type, this
functionality can't be exercised.

But #2: it raises a namespace.TypeMismatchError (and stops) rather than
printing an error; I simply need to add the appropriate try/except for
that and print the right message.

> in another namespace via ``global''?

Dunno. I haven't thought about how to handle the "global" statement yet. I
suspect that the Namespace class will simply understand that it must
delegate certain names to a different namespace; that target namespace
will then raise the appropriate error in case of a type mismatch.

Cheers,
-g

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