Presentation is loading. Please wait.

Presentation is loading. Please wait.

Optional Static Typing Guido van Rossum (with Paul Prescod, Greg Stein, and the types-SIG)

Similar presentations


Presentation on theme: "Optional Static Typing Guido van Rossum (with Paul Prescod, Greg Stein, and the types-SIG)"— Presentation transcript:

1 Optional Static Typing Guido van Rossum (with Paul Prescod, Greg Stein, and the types-SIG)

2 Talk Overview Why add static type checking? Checked vs. unchecked modules Declaration syntax Type expressions Dynamic casts Parameterized types Open issues Implementation...?

3 Why Add Static Typing? Two separate goals: –faster code (OPT) –better compile-time errors (ERR) Mostly interested in (ERR) –(OPT) will follow suit Of course it will be optional –and (mostly) backwards compatible

4 Checked vs. Unchecked A module is checked or unchecked –no partially checked modules Checked modules are: –guaranteed not to raise runtime type errors except at point of call from unchecked modules except at explicit dynamic casts –protected at runtime against violations by unchecked modules e.g. messing with __dict__ or assignment to module globals or class/instance variables

5 Declaration Syntax Two forms: inline and explicit –explicit form is easy to remove Inline: def gcd(a: int, b: int) -> int:... Explicit (two variants): decl gcd: def(int, int) -> int def gcd(a, b):... def gcd(a, b): decl a: int, b: int decl return: int...

6 Declaring Classes decl in class declares instance attributes –(by default, anyway) –can add syntax for private, protected etc. –methods declared excluding self derived classes must play by the rules –cant override methods w. conflicting types –must call Base.__init__() –once this exists, we can think about require/ensures again!

7 Type Expressions standard types (in __builtin__): –int, long, float, complex, str, tuple, list, dict int is same as types.IntType, etc. –None (special case: type == value) standard abstract types (__builtin__): –number, string, sequence, mapping, any class names: –may be imported from checked modules typedefs (decl myType = P.M.Type)

8 Constructing Types Syntax for type composition: –list with items of type T: [T] –tuple of T1, T2, T3: (T1, T2, T3) (this explains why we have both tuples and lists!) –dict with key/value types T1/T2: {T1: T2} –union of types T1 and T2: T1 | T2 –function (e.g.): def(T1, T2)->T3 Example: –{str: (int, int) | (int, int, str) | None}

9 Dynamic Casts Proposed by Greg Stein General syntax: expression ! type Example: x = y ! int –if y has type int: assign y to x –otherwise: raise TypeError Problem: –must catch exception to decide union type Alternative: typecase statement? –no syntax proposal exists yet

10 Parameterized Types Needed e.g. for container classes: class Stack : decl st: T def __init__(self): self.st = [] def push(self, x: T): self.st.append(x) def pop(self) -> T: x = self.st[-1]; del self.st[-1]; return x decl IntStack = Stack # template instantiation decl s: IntStack s = IntStack() # or s = Stack() ??? s.push(1) decl x: int x = s.pop() s.push("spam") # ERROR

11 Parameterized Functions Example: def bisect (a: [T], x: T) -> int: decl lo, mid, hi: int lo, hi = 0, len(a) while lo < hi: mid = (lo+hi)/2 if x < a[mid]: hi = mid else: lo = mid+1 return lo decl a: [int] Idea: –bisect() could be called without template instantiation –argument types will be matched against the type parameters

12 Open Issues (1) A subclass is not always a subtype! int is a subtype of any, but [int] not of [any] similar for parameterized classes Dynamic cast or typecase statement? Should we declare exceptions? How? How much type inference is needed? Interface declarations? var=default:type -or- var:type=default?

13 Open Issues (2) Access to type objects at runtime –reflection on types must be possible How to spell arbitrary tuple of T: (T*)? Typedef syntax (in expressions?) Type conformance rules Syntax ambiguity for lambda How to spell the type of self Should classes be types? (Yes!)

14 Open Issues (3) Avoid NameError and AttributeError? –Need flow analysis plus special rules e.g. all instance variables must be defined when __init__ returns (but what about calls it makes?) for local variables, its relatively easy for globals, how to do it? how to deal with recursive imports? blah! Choice of names –int/integer, str/string may be too confusing

15 Implementation...? Who? me? :-) Possible phases: –Experimental type checker written in Python can hide decl from Python in string literals –Allow alternate parsers in core Python checked modules could use *.cpy extension –Support for type checker in bytecode –Rewrite checker in C as part of core Python –Add aggressive optimizer

16 Typecase Strawman decl x: int | string | None | [any] |.... typecase x: int, i: print an int: %d % i string, s:print a string: %s % `s` None: print nothing else: print dont know All possible types must be accounted for, otherwise its a static error

17 Contravariance class B: def method(self, x: number) -> int|long:... def other(self): decl i: int|long i = self.method(3.14) class D(B): def method(self, x: int) -> int|long:...# ERROR class D(B): def method(self, x: any) -> int:...# ok class D(B): def method(self, x: number) -> any:...# ERROR


Download ppt "Optional Static Typing Guido van Rossum (with Paul Prescod, Greg Stein, and the types-SIG)"

Similar presentations


Ads by Google