[Types-sig] Type annotations

Paul Prescod paul@prescod.net
Thu, 16 Dec 1999 10:17:56 -0800

Martijn Faassen wrote:
> And you don't have to deal with parsing only; that isn't the main
> problem. The main thing is that we need a way to express complex,
> composite types. Python is very expressive. You can make a Pythonic
> language to express types in later, but we can't yet as we don't fully
> know yet what we want to express.

Actually, we do. The Python type system is well understood. We just
don't have a way of talking about it statically. I'll attach some of my
half-formed ideas and then shut up for a little while.

> Yet another advantange of going the 'in Python' route is that you
> already have the backend for your parser. And if you have an
> implementation (that we'll undoubtedly will change several times,
> another advantage of using Python), you can actually start thinking
> about a good syntax with *knowledge*. You know what kind of data
> structures are actually involved, you have working experience. Something
> we don't really have right now.

I don't see how dictionaries are a decent back-end. The real back-end
will be type objects with direct references to other type objects.


Here are some Haskell-ish syntax ideas for type declarations:

First we need to be able to talk about types. We need a "type
expression" which evalutates to a type.

Rough Grammar: 

Type : Type ['|' Type] # allow unions
Unit : dotted_name | Parameterized | Function | Tuple | List | Dict
Parameterized : dotted_name '(' Basic (',' Basic)* ')'
Basic : dotted_name | PythonLiteral | "*" # * means anything.
PythonLiteral : atom
Function : Type '->' Type
Tuple : "(" Type ("," Type )* ) 
List: "[" Type "]"
Dict: "{" Type ":" Type "}"


[(Int, Int)]
{(String,Int), String}
BTree( String )
BTree( somepackage.somemod.someclass )

There is another syntax for declaring instance interface types, it
follows Python's class declaration syntax. More on that later.

Now we probably want to be able to invent names for types. This is
like C's typedef. We'll use simple Python assignment syntax.

Typedef = NAME["(" args ")"]  '=' Type

Examples :
StringOrList = String | List( String )
ElementNode = XMLNode( "Element" )
MyTuple = ( Integer, String, List( String ) )
Str50 = BoundedString( 0, 50 )
PositiveInteger = BoundedInteger( 0, sys.maxint )
PositiveInteger = BoundedInteger( -sys.maxint-1, 0 )
len = sequence(*) -> int
maptype(intype, outtype) = 
    (( intype -> outtype ), List( intype )) -> List( outtype )
intmap = maptype( int, int )
lenmap = maptype( sequence(*), int )

Interfaces look like Python classes but they use an "interface"

interfacedef: 'interface' NAME ['(' testlist ')'] asdecl ':'
interfacebody: funcdef | classdef | instancevar | interfacevar
asdecl: "as" type 

funcdef: 'def' NAME parameters ':' docstring?
parameters: '(' [varargslist] ')'
varargslist: (like Pythons but with added "as" operator.

"Interface" and instance variables may also be declared. 

interface (a,b) foo_interface(base_interface):
        k as String

        j as Integer

    def bar( self, arg1 as a ) as b:
        "This takes an argument of one paramterized type and rteturns
            the other."

    def baz( self, arg1 as a ) as b:
        "This takes an argument of one paramterized type and rteturns
            the other."

"Empty" class definitions are also possible in interface files:

class (a, b) foo_class (base_class) implements foo_interface:
    def newfunc( self, arg1 as a ) as b:
        "This takes an argument of one paramterized type and rteturns
            the other."

We can also export individual instances and other objects:

a as String
b as foo_interface
c as foo_class
const path as ["String"]
const version as Integer

 Paul Prescod  - ISOGEN Consulting Engineer speaking for himself
Three things never trust in: That's the vendor's final bill
The promises your boss makes, and the customer's good will