Download presentation
Presentation is loading. Please wait.
Published byStephen Simpson Modified over 9 years ago
1
Implementing a Language with Flow-Sensitive and Structural Subtyping on the JVM David J. Pearce and James Noble Victoria University of Wellington
2
void buildLabelMap(List bytecodes) { HashMap labels = new HashMap (); int idx = 0 for(Bytecode b : bytecodes) { if(b instanceof Bytecode.Label) { Bytecode.Label lab = (Bytecode.Label) b; labels.put(lab.name, idx); } idx = idx + 1; } def buildLabelMap(bytecodes): labels = {} idx = 0 for b in bytecodes: if type(b) == “Label”: labels[b.name] = idx idx = idx + 1 Python: Java:
3
The Whiley Language Design Goals: –Look and feel of a dynamically typed language –But, still provide static type checking –Simple programming model –Amenable to program verification void buildLabelMap([Bytecode] bytecodes): labels = {} idx = 0 for b in bytecodes: if b ~= Label: labels[b.name] = idx idx = idx + 1 Whiley:
4
The Whiley Language Design Goals: –Look and feel of a dynamically typed language –But, still provide static type checking –Simple programming model –Amenable to program verification void buildLabelMap([Bytecode] bytecodes): labels = {} idx = 0 for b in bytecodes: if b ~= Label: labels[b.name] = idx idx = idx + 1 Whiley:
5
The Whiley Language Design Goals: –Look and feel of a dynamically typed language –But, still provide static type checking –Simple programming model –Amenable to program verification void buildLabelMap([Bytecode] bytecodes): labels = {} idx = 0 for b in bytecodes: if b ~= Label: labels[b.name] = idx idx = idx + 1 Whiley:
6
Union Types Union types have many uses –Such as neatly handling null references –Or, combining different kinds (i.e. union s of struct s) null|int indexOf(string str, char c): … [string] split(string str, char c): idx = indexOf(str,c) if idx ~= int: below = str[0..idx] above = str[idx..] return [below,above] else: return [str]
7
Union Types Union types have many uses –Such as neatly handling null references –Or, combining different kinds (i.e. union s of struct s) null|int indexOf(string str, char c): … [string] split(string str, char c): idx = indexOf(str,c) if idx ~= int: below = str[0..idx] above = str[idx..] return [below,above] else: return [str]
8
Structural Subtyping Defined types are not nominal –i.e. LinkedList is just a name that “expands” define LinkedList as null | {int dat, LinkedList nxt} define NonEmptyList as {int dat, LinkedList nxt} int sum(LinkedList l): if !(l ~= NonEmptyList): return 0 else: return l.dat + sum(l.nxt) void main([string] args): l={dat: 1, nxt: null} l={dat: 2, nxt: l} out->println(sum(l))
9
Structural Subtyping Defined types are not nominal –i.e. LinkedList is just a name that “expands” define LinkedList as null | {int dat, LinkedList nxt} define NonEmptyList as {int dat, LinkedList nxt} int sum(LinkedList l): if l ~= NonEmptyList: return 0 else: return l.dat + sum(l.nxt) void main([string] args): l={dat: 1, nxt: null} // l->{int dat, null nxt} l={dat: 2, nxt: l} // l->{int dat, {int dat, null nxt} nxt}} out->println(sum(l))
10
Implementation
11
Numbers Unbounded Integers & Rationals –How to implement efficiently on JVM? 1)BigInteger and BigRational 2)SmallInt, BigInt and BigRational [Clojure & Erjang] 3)int[] Adding 100,000 random (small) ints –BigInteger(11ms), SmallInt/BigInt (1ms), int[] (1ms) real weird(real x, [int] map): if x ~= int: // convert x to int x = map[x] // convert x back to real return x
12
Records HashMap implementation: –Map field names to objects –Record access are HashMap lookups Array implementation –Fields allocated to array elements –Faster lookup times –Problem with width subtyping of records define Point as {int x, int y} define Point3D as {int x, int y, int z} int weird(Point p): return p.x + p.y int alsoWierd(Point3D p3d): return weird(p3d) “x” 12 “y” 3
13
Runtime Type Tests Type testing without names is difficult! –Elements may require recursive type test void f([real] xs): if xs ~= [int]: … else: … void f(List xs): for(Object _x : xs) { Number x = (Number) x; if(!x.isInteger()) { goto elseLab; } } … return elseLab: … return
14
Type Testing Records Type testing records == checking for fields –Can do better than brute-force “check all” approach –Test smallest set of “uniquely identifying” fields define Point as {int x, int y} define Point3D as {int x, int y, int z} int weird(Point p): if p ~= Point3D: … else: …
15
Testing Recursive Types Recursive types are also awkward –Must recursively check every node –Potentially expensive – like for lists define LinkedList as {int data, LinkedList y} define WeirdList as {null|int data, WeirdList y} int weird(WeirdList p): if p ~= LinedList: … else: …
16
JVM not fully flow-sensitive!!! JVM uses flow-sensitive typing algorithm –Doesn’t account for instanceof tests –Have to insert casts to keep verifier happy define nstring as null|string int length(nstring ns): if ns ~= string: return |ns| else: return 0 0: aload_0 1: dup 2: instanceof java/util/List 3: ifeq… 4: checkcast java/util/List 5: invokeinterface size()I 6: …
17
Cloning Data types have value semantics: –i.e. lists are not references (as in Java) –E.g. must “clone” lists on assignment –This is inefficient – want to reduce number of clones –E.g. 28125 clones in Chess benchmark (508LOC) void System::main([string] args): xs = [1,2,3] ys = xs // clone required ys[0] = 2 out->println(str(xs)) out->println(str(ys))
18
Conclusion Design Goals: –Look and feel of a dynamically typed language –But, still provide static type checking Implementation on JVM –Efficient representation of integers / rationals –Efficient representation of records –Efficient type testing … ? –Efficient value semantics … ?
19
http://whiley.org
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.