[Types-sig] check.py

Greg Stein gstein@lyra.org
Wed, 29 Dec 1999 04:14:15 -0800 (PST)


On Wed, 29 Dec 1999, scott wrote:
>...
> I was just working under the assumption that if it was a complete
> framework -- filled in or not, there'd be a way to do things like
> declare types.  Then I threw a couple of off-the-cuff basic things at
> it, and it didn't do well, so I figured it wasn't done enough to
> warrant a basic framework to develop on.

If you want to hack some code, you can declare types. The framework is
there, you just need to figure out how to do something like:

  self.ns.declare('x', typedecl.Int)

(and then fix the code to handle the exception condition that will arise
if you attempt to assign something other than Int to 'x')

But your point still stands: it is missing some of the more interesting
stuff that is being generated in this SIG lately. But hey... I only hacked
on it for a day or two :-)

>...
> So we all know that exactly how .pyi info and embedded declarations
> maps runtime namespaces is a touchy issue -- we can't really account
> for exec, and there are lots of things which may act odd, such as
> get/set-attr hooks and global and del what not that can cause some
> real issues.

Right.

> We also know that whatever inaccuries or mismatches there might be
> between the picture of runtime namespaces available at compile time
> and how they work at runtime will probably become a royal pain in the
> ass down the road.

That would suck. But I'm pretty darn sure that we can figure out at
compile-time what 99% of the software out there will do at runtime (in
terms of storing values into namespaces). For that other 1%, I'm not sure
if we just won't work right, or whether we can at least warn the person
that we won't work as expected.
[ in other words, there are times when we can detect a bad situation, but
  can't do anything about it. other times, we just outright fail :-) ]

> So check.py uses the parser module to gain a pretty darn accurate
> picture of runtime name spaces via the parse tree. That's a *very*
> good thing

Yup. And yah, I think so :-)

> when compared to some half-assed namespace picture that
> sortof works like you expect, but is bound to blow up in way too many
> cases and create reams of new faqs down the road.

Quite true. I wouldn't think of doing it some other way.

> It also has some drawbacks:  it's a little awkward to have compile
> time activity depend so heavily on a module that is optional.

Well, we actually use just a single function from the parser module. And
the underlying C code is quite simplistic. Most of the parser module
actually deals with building AST nodes from Python and passing the result
to the Python bytecode compiler.

You could really view the parser module as an interface to two things: to
the parser output, and to the compiler input. We just want the parser
output.

Optional? The module may be, but the parser itself isn't :-). The parser
is enabled by default in recent distributions. Some code shifting or other
structural changes could ensure that we always have access to parser
output. We could also just say "type checking not available unless the
parser module is built."

> Also,
> compile-time activity IMO is rightly done in C (or Java or whatever)
> and not in the language that is being interpretted, though prototyping
> can of course be anything.

1) This isn't necessarily a compile-time activity. It could be an external
   tool that is occasionally run.

   We could also argue semantics and say that type-checking isn't part of
   compilation (since the output is not necessarily used/consumed by the
   compilation step).

2) I disagree that it is "rightly done in C", but recognize the "IMO" you
   inserted there :-). I see no issue whatsoever in using Python as part
   of the Python runtime environment. In fact, I would hope that Python
   1.6 allows you to write its parser and compiler entirely in Python. The
   only C code would be the builtin types and the VM.

> The module seems to be built primarily for
> availability from within python, and not so much from the interpreter
> itself; while the end product seems like it should be (mostly atleast)
> in the interpreter itself.  

I'm not sure that I understand the basis of this perception. However, I
don't really need to, I think... we can certainly restructure some of the
interfaces to make it follow whatever requirements/pattern that you're
thinking of.

> The list of drawbacks goes on a bit, but all the points rest on one
> question that I'm not sure of:  Does the framework presented in
> check.py actually depend on the parser module, or is this just a
> functional relationship that can be met by some reasonable alternative
> means in the interpreter itself? 

If you integrate the thing directly into the interpreter, then the need
for the parser module doesn't exist. The parser module is just a Python
API for the internal C API to the parser -- the interpreter definitely has
that access.

But again: I would disagree with the notion of integrating it tightly into
the interpreter. check.py is currently sitting at 929 lines of code. My
historical yardstick says this would expand to 9290 lines of C code -- for
its CURRENT form. I believe that check.py is going to get bigger once
all those missing expression handling checks are inserted. Maybe 2000
to 3000 lines of Python. Dropping that into C increases your bug count and
reduces flexibility/maintenance.

But hey... as I mentioned to Paul a week ago or so: feel free to code a
type-checker in C. I won't stop you. But I can guarantee that a Python
version will be ready before yours :-). And when the SIG comes up with
additional, nifty rules to check for... the Python version will have them
implemented much faster. In fact, people could very well present the new
rules as patches to the type-checker.

Cheers,
-g

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