Polyglot Tutorial PLDI 2014 Steve Chong, Harvard University Chin - - PowerPoint PPT Presentation

polyglot tutorial
SMART_READER_LITE
LIVE PREVIEW

Polyglot Tutorial PLDI 2014 Steve Chong, Harvard University Chin - - PowerPoint PPT Presentation

Polyglot Tutorial PLDI 2014 Steve Chong, Harvard University Chin Isradisaikul, Cornell University Andrew Myers, Cornell University Nate Nystrom, University of Lugano Overview Today: Polyglot architecture Run through of an


slide-1
SLIDE 1

Polyglot Tutorial

PLDI 2014

  • Steve Chong, Harvard University

Chin Isradisaikul, Cornell University Andrew Myers, Cornell University Nate Nystrom, University of Lugano

slide-2
SLIDE 2

Overview

Today:

  • Polyglot architecture
  • Run through of an example compiler extension
  • Accrue

2

slide-3
SLIDE 3

Download

You’ll need Java 7 or later Eclipse 3.4.2 or later is useful but not required.

  • Download the following zip file:

http://www.cs.cornell.edu/Projects/polyglot/pldi14/tutorial/polyglot-tutorial.zip

  • Unzip and import the included projects into Eclipse

3

slide-4
SLIDE 4

Language extension

Language designers often create extensions to existing languages

  • e.g., C++, PolyJ, Pizza, AspectJ, Jif, ESCJava, X10,

Java5, Java6, Java7, Java8

  • Want to reuse existing compiler infrastructure as much as

possible

  • Polyglot is a framework for writing compiler extensions for

Java

4

slide-5
SLIDE 5

Requirements

Language extension

  • Modify both syntax and semantics of the base

language

  • Changes are not necessarily backward compatible

Goals:

  • Easy to build and maintain extensions
  • Extensibility should be modular and scalable
  • No changing base compiler, no code duplication
  • Compilers for language extensions should be open to

further extension

5

slide-6
SLIDE 6

Polyglot base compiler

Base compiler is a complete Java 1.4 front end

  • Can reuse and extend through inheritance
  • 53K lines of Java
  • Parsing, name resolution, inner class support, type

checking, exception checking, uninitialized variable analysis, unreachable code analysis, …

  • And … 25K more lines of Java
  • Java5 and Java7 extensions

6

slide-7
SLIDE 7

Polyglot family tree

7

Java 1.4 compiler Java 5 compiler Java 7 compiler Jif compiler Jif/split compiler X10 compiler Resilient X10 compiler JMatch compiler

XXX

slide-8
SLIDE 8

Architecture

Base compiler compiles Java 1.4 source to Java 1.4 source

  • Extensions implement new language features by …
  • extending the parser
  • adding new abstract syntax
  • adding new types
  • adding new compiler passes
  • overriding existing passes
  • translating new features into Java 1.4

8

slide-9
SLIDE 9

Polyglot pass architecture

9

Parser Type Builder Ambiguit y Remover Type Checker source Code Generato r

bytecode

  • ther semantic

checking passes

slide-10
SLIDE 10

Overview of the base compiler

Let’s do a quick run through the base compiler code

  • parsing
  • ASTs
  • visitors
  • types
  • But first, download:

http://www.cs.cornell.edu/Projects/polyglot/pldi14/tutorial/polyglot-tutorial.zip 10

slide-11
SLIDE 11

Parsing (polyglot.parse)

The parser reads the source text and creates ASTs

  • Base compiler Java parser implemented using LALR(1)

JavaCUP parser generator

  • Extensions can use the Polyglot Parser Generator (PPG)

to extend the parser by adding, modifying, or removing rules

11

slide-12
SLIDE 12

ASTs (polyglot.ast)

  • AST nodes created by factory methods in the

NodeFactory

  • AST nodes are persistent data structures
  • Methods to modify a node, return a modified copy
  • f the node
  • We use clone() to ensure any fields added by

subclasses are preserved

12

slide-13
SLIDE 13

ASTs (polyglot.ast)

13

Node Expr Stmt TypeNode ClassDecl FieldDecl MethodDecl ConstructorDecl ProcedureDecl ClassMember Binary IntLit Cast Call Local If Try While New … …

slide-14
SLIDE 14

Visitors (polyglot.visit)

Visitors traverse the AST, executing operations at each node in the tree, returning a new node to reconstruct the tree if needed

  • Visitors follow the following protocol at each Node:
  • override – if returns a Node, return that Node;
  • therwise, continue
  • enter – returns a new Visitor used to visit children of

this node

  • (recursively visitChildren)
  • leave – returns a new Node

14

slide-15
SLIDE 15

NodeVisitor

15

v2 v v2 n n2 n3 v2 = .enter( ) v n n

= .visitChildren( )

v2 n2 n2 n n

= v.leave( , , )

v2 n3 n3 n n n2 n2

slide-16
SLIDE 16

TypeObjects and TypeSystem

TypeSystem implements methods for semantic checking

  • isSubtype(Type, Type)
  • isCastValid(Type, Type)
  • methodCallValid(MethodInstance, String, List<Type>)
  • Types (and other type-level entities) are represented as

TypeObjects: Type, PrimitiveType, ArrayType, ClassType, … MethodInstance, FieldInstance, ConstructorInstance, …

  • TypeSystem also serves as a factory for TypeObjects

16

slide-17
SLIDE 17

Extending Java with constant arrays

slide-18
SLIDE 18

Covariant arrays

18

Java array types are covariant Bird <: Animal ⇒ Bird[] <: Animal[]

class C { void foo() { Bird[] birds = { chicken, duck }; Animal[] animals = birds;

  • }

}

slide-19
SLIDE 19

Covariant arrays

19

class C { void foo() { Bird[] birds = { chicken, duck }; Animal[] animals = birds; animals[0] = cow; // what happens here? } }

Java array types are covariant Bird <: Animal ⇒ Bird[] <: Animal[]

slide-20
SLIDE 20

Covariant arrays

20

class C { void foo() { Bird[] birds = { chicken, duck }; Animal[] animals = birds; animals[0] = cow; // throws ArrayStoreException } }

Java array types are covariant Bird <: Animal ⇒ Bird[] <: Animal[]

slide-21
SLIDE 21

Constant arrays

Let’s write a Polyglot extension to fix this problem

  • Make traditional non-const arrays invariant
  • Object[]
  • Introduce covariant const arrays
  • Object const[]

21

slide-22
SLIDE 22

22

class C { void foo() { Bird[] birds = { chicken, duck }; Animal[] animals = birds; // compile-time error } }

Make traditional arrays invariant

slide-23
SLIDE 23

23

class C { void foo() { Bird const[] birds = { chicken, duck }; Animal const[] animals = birds; animals[0] = cow; // compile-time error } }

Introduce covariant const arrays

slide-24
SLIDE 24

Implementing the extension

  • 1. Extend the parser with const array types
  • 2. Add a const array AST node
  • 3. Add a const array type
  • 4. Prevent assignment to const arrays
  • 5. Implement subtyping for const arrays
  • 6. Change the subtyping rules for Java arrays
  • 7. Translate const arrays to Java arrays

24

slide-25
SLIDE 25

Testing

First let’s write some tests …

  • Polyglot provides a testing harness (pth)
  • give test inputs and specify tests that should pass, fail

25

slide-26
SLIDE 26

Implementing the extension

  • 1. Extend the parser with const array types
  • 2. Add a const array AST node
  • 3. Add a const array type
  • 4. Prevent assignment to const arrays
  • 5. Implement subtyping for const arrays
  • 6. Change the subtyping rules for Java arrays
  • 7. Translate const arrays to Java arrays

26

slide-27
SLIDE 27

Parsing

The parser reads the source text and creates the AST

  • NodeFactory creates AST nodes

27

slide-28
SLIDE 28

Parsing

Original rule for array types in java12.cup:

  • array_type ::=

// array of primitive types such as int[] and char[][] primitive_type:a dims:b {: RESULT = parser.array(a, b.intValue()); :} // array of object types such as String[] and Object[][] | name:a dims:b {: RESULT = parser.array(a.toType(), b.intValue()); :} ;

28

slide-29
SLIDE 29

Parsing

Extended rule in carray.ppg:

  • extend array_type ::= // RESULT of array_type is a TypeNode

primitive_type:a CONST dims:b {: RESULT = parser.constArray(a, b); :} | name:a CONST dims:b {: RESULT = parser.constArray(a.toType(), b); :} ; 29

slide-30
SLIDE 30

Parsing

Helper function for creating const array ASTs:

  • /**

* Return a TypeNode representing a {@code dims}-dimensional constant array * of ultimate base {@code n}. */ public TypeNode constArray(TypeNode n, int dims) throws Exception { if (dims > 0) return nf.ConstArrayTypeNode(n.position(), constArray(n, dims - 1)); return n; } 30

slide-31
SLIDE 31

Parsing exercise

Implement carray types by extending the rules for array_type (as above) and cast_expression

  • Syntax for a const array type:

Type const [ ]

  • Examples:

int const [ ] String const [ ] [ ] [ ] java.lang.Number const [ ] [ ]

31

slide-32
SLIDE 32

Implementing the extension

  • 1. Extend the parser with const array types
  • 2. Add a const array AST node
  • 3. Add a const array type
  • 4. Prevent assignment to const arrays
  • 5. Implement subtyping for const arrays
  • 6. Change the subtyping rules for Java arrays
  • 7. Translate const arrays to Java arrays

32

slide-33
SLIDE 33

ASTs

  • 1. Create an interface and class for the new AST node
  • 2. Extend NodeFactory to create an instance of the class
  • 3. Extend ExtFactory to provide a hook for future

language extensions to override functionality

33

slide-34
SLIDE 34

AST interface

package carray.ast;

  • import polyglot.ast.ArrayTypeNode;
  • /**

* A {@code ConstArrayTypeNode} is a type node for a non-canonical * const array type. */ public interface ConstArrayTypeNode extends ArrayTypeNode { } 34

slide-35
SLIDE 35

AST class

package carray.ast;

  • import polyglot.ast.ArrayTypeNode_c;
  • /**

* A {@code ConstArrayTypeNode} is a type node for a non-canonical * const array type. */ public class ConstArrayTypeNode_c extends ArrayTypeNode_c implements ConstArrayTypeNode { super(pos, base); } 35

slide-36
SLIDE 36

Exercise

Implement ConstArrayTypeNode_c.toString()

36

slide-37
SLIDE 37

NodeFactory

AST nodes are created using a NodeFactory

  • NodeFactory attaches zero or more extension object to

the new nodes

  • Extension objects provide a hook for language extensions

to add functionality to the node

  • Extension objects are created with ExtFactory

37

slide-38
SLIDE 38

Extending NodeFactory

@Override public ConstArrayTypeNode ConstArrayTypeNode(Position pos, TypeNode base) { ConstArrayTypeNode_c n = new ConstArrayTypeNode_c(pos, base);

  • return n;

} 38

slide-39
SLIDE 39

Extending NodeFactory

@Override public ConstArrayTypeNode ConstArrayTypeNode(Position pos, TypeNode base) { ConstArrayTypeNode_c n = new ConstArrayTypeNode_c(pos, base); n = ext(n, extFactory().extConstArrayTypeNode()); return n; } 39

slide-40
SLIDE 40

Extension chaining

40

An AST node can have zero or more extension objects

Java 1.4 node Java 5 extension Java 1.4 node Java 5 extension Java 7 extension Java 8 extension Java 1.4 node CArray extension Java 1.4 node Java 5 extension Java 7 extension

slide-41
SLIDE 41

Extension objects

Used to add/modify operations on AST node types

  • Should only create a new extension object class if needed
  • By default: the extension object class for an AST is the same

as for the superclass of the AST class.

  • Example:
  • In the Java compiler, ArrayTypeNode is a subclass of

TypeNode

  • In CArray, the extension object for an ArrayTypeNode can

be from the same class as extension objects for TypeNode

41

slide-42
SLIDE 42

Extension chaining

For new kinds of AST nodes, extension objects forward

  • perations to the base language
  • If the next extension knows about CArray,

extConstArrayTypeNode is invoked

  • If the next extension does not know about CArray,

extArrayTypeNode is invoked

42

slide-43
SLIDE 43

CArrayOps

// Interface for any new operations here. public interface CArrayOps extends NodeOps { }

  • public class CArrayExt extends Ext_c implements CArrayOps {

... }

43

slide-44
SLIDE 44

Extension objects

Extension objects are stored in a doubly-linked list

  • Extension objects are created by a per-language

ExtFactory

44

slide-45
SLIDE 45

Extension chaining

45

Extension objects are created by an ExtFactory, which are themselves chained (from the extension up)

Java 5 ExtFactory Java 5 ExtFactory Java 7 ExtFactory Java 8 ExtFactory CArray ExtFactory Java 5 ExtFactory Java 7 ExtFactory

slide-46
SLIDE 46

Language dispatchers

Every language extension has a language dispatcher

  • The language dispatcher maps a node to the extension object for

that language

  • NodeOps(n) (returns n)

CArrayOps(n) (returns n’s CArrayOps ext)

  • Every visitor has a language dispatcher.
  • For example, the TypeChecker visitor indirects calls to typeCheck

for node n through the dispatcher

  • tc.lang().typeCheck(n, v) -> NodeOps(n).typeCheck(v)

46

slide-47
SLIDE 47

CArrayLang

public interface CArrayLang extends JLang { }

47

slide-48
SLIDE 48

CArrayLang_c

public class CArrayLang_c extends JLang_c implements CArrayLang { public static final CArrayLang_c instance = new CArrayLang_c();

  • public static CArrayLang lang(NodeOps n) {

while (n != null) { Lang lang = n.lang(); if (lang instanceof CArrayLang) return (CArrayLang) lang; if (n instanceof Ext) n = ((Ext) n).pred(); else return null; } throw new InternalCompilerError("Impossible to reach"); }

  • protected CArrayLang_c() {

}

  • protected static CArrayExt carrayExt(Node n) {

return CArrayExt.ext(n); }

  • // Get the Node operations of n (returns this language’s ext for n)

protected NodeOps NodeOps(Node n) { return carrayExt(n); } // Get the Node operations of n (returns this language’s ext for n) protected CArrayOps CArrayOps(Node n) { return carrayExt(n); } }

48

slide-49
SLIDE 49

CArrayExt

public class CArrayExt extends Ext_c implements CArrayOps { private static final long serialVersionUID = SerialVersionUID.generate();

  • public static CArrayExt ext(Node n) {

Ext e = n.ext(); while (e != null && !(e instanceof CArrayExt)) { e = e.ext(); } if (e == null) { throw new InternalCompilerError("No CArray extension object for node " + n + " (" + n.getClass() + ")", n.position()); } return (CArrayExt) e; }

  • @Override

public final CArrayLang lang() { return CArrayLang_c.instance; } } 49

slide-50
SLIDE 50

Extending the type system

slide-51
SLIDE 51

Implementing the extension

  • 1. Extend the parser with const array types
  • 2. Add a const array AST node
  • 3. Add a const array type
  • 4. Implement subtyping for const arrays
  • 5. Change the subtyping rules for Java arrays
  • 6. Translate const arrays to Java arrays

51

slide-52
SLIDE 52

Extending the type system

  • 1. Create a Type subclass for the new type.
  • 2. Extend TypeSystem to provide a factory method for

the new type.

  • 3. Extend the AST node classes to use the new type.

52

slide-53
SLIDE 53

ConstArrayType

package carray.types;

  • /**

* A {@code ConstArrayType} represents an array of base java types, * whose elements cannot change after initialization. */ public interface ConstArrayType extends ArrayType { } 53

slide-54
SLIDE 54

ConstArrayType

package carray.types;

  • public class ConstArrayType_c extends ArrayType_c implements ConstArrayType {

private static final long serialVersionUID = SerialVersionUID.generate();

  • /** Used for deserializing types. */

protected ConstArrayType_c() { }

  • public ConstArrayType_c(TypeSystem ts, Position pos, Type base) {

super(ts, pos, base); }

  • ...

} 54

slide-55
SLIDE 55

Exercise

Implement ConstArrayType_c by extending ArrayType_c

  • Implement a factory method for ConstArrayType in

CArrayTypeSystem

55

slide-56
SLIDE 56

Using the ConstArrayType

  • Type building
  • Type checking

56

slide-57
SLIDE 57

Type building

The TypeBuilder constructs type objects from the AST

  • Invokes the buildTypes method on each AST node
  • Updates the system resolver, which maps fully qualified

names (e.g., “java.util.HashMap”) to a TypeObject (e.g., a ClassType)

57

slide-58
SLIDE 58

Exercise

Implement buildTypes for ConstArrayTypeNode

  • Model solution on ArrayTypeNode

58

slide-59
SLIDE 59

Type building

@Override public Node buildTypes(TypeBuilder tb) throws SemanticException { // Ask the type system to create a type object for constant array // of the base type. At this point, the base type might not be // canonical. The disambiguation phase will canonicalize the base type. CArrayTypeSystem ts = (CArrayTypeSystem) tb.typeSystem(); return type(ts.constArrayOf(position(), base().type())); } 59

slide-60
SLIDE 60

Disambiguation

Unlike ASTs, type objects are mutable, updated during disambiguation

  • A type object is canonical if all ambiguities have been

resolved

  • The AmbiguityRemover resolves names in the AST,

updating type objects

  • Object => java.lang.Object

60

slide-61
SLIDE 61

Disambiguation

The AmbiguityRemover … … may cause other compilation units to be loaded … runs multiple times, incrementally rewriting the AST

  • Example: ArrayTypeNode
  • Node disambiguate(AmbiguityRemover v) {

TypeSystem ts = v.typeSystem(); NodeFactory nf = v.nodeFactory(); if (base.isCanonical()) return nf.CanonicalTypeNode(ts.arrayOf(base.type()) ); else return this; // will rerun the pass later }

61

slide-62
SLIDE 62

Exercise

Implement disambiguate for ConstArrayTypeNode

  • Model solution on ArrayTypeNode

62

slide-63
SLIDE 63

Type checking

The TypeChecker pass type checks the AST

  • Invokes the typeCheck method on each AST node
  • 63
slide-64
SLIDE 64

Type checking

We need to:

  • disallow assignment to constant arrays
  • override typeCheck in extension object for

ArrayAccessAssign

  • implement covariant subtyping for const arrays
  • override isImplicitCastValidImpl in ConstArrayType
  • implement invariant subtyping for non-const arrays
  • introduce CArrayArrayType to replace ArrayType
  • override isImplicitCastValidImpl in CArrayArrayType

64

slide-65
SLIDE 65

Implementing the extension

  • 1. Extend the parser with const array types
  • 2. Add a const array AST node
  • 3. Add a const array type
  • 4. Prevent assignment to const arrays
  • 5. Implement subtyping for const arrays
  • 6. Change the subtyping rules for Java arrays
  • 7. Translate const arrays to Java arrays

65

slide-66
SLIDE 66

Implementing typeCheck

Override typeCheck in the extension object for ArrayAccessAssign

  • public Node typeCheck(TypeChecker tc) throws SemanticException {

// n is a[i] = v; ArrayAccessAssign n = (ArrayAccessAssign) this.node(); // left is a[i]. ArrayAccess left = n.left(); // array is a. Expr array = left.array();

  • if (array.type() instanceof ConstArrayType) {

throw new SemanticException("Cannot assign an element of a const array.", n.position()); }

  • // Let the base language deal with the default type checking.

return superLang().typeCheck(n, tc); } 66

slide-67
SLIDE 67

Implementing subtyping

Let’s look at how assignment is type-checked in Assign_c

  • if (op == ASSIGN) {

if (!ts.isImplicitCastValid(s, t) && !ts.typeEquals(s, t) && !ts.numericConversionValid(t, tc.lang().constantValue(right, tc.lang()))) {

  • throw new SemanticException("Cannot assign " + s + " to " + t

+ ".", position()); }

  • return type(t);

}

  • Need to change isImplicitCastValid to support constant arrays

67

slide-68
SLIDE 68

ArrayType_c

@Override public boolean isImplicitCastValidImpl(Type toType) { if (toType.isArray()) { if (base().isPrimitive() || toType.toArray().base().isPrimitive()) { return ts.typeEquals(base(), toType.toArray().base()); } else { return ts.isImplicitCastValid(base(), toType.toArray().base()); } }

  • // toType is not an array, but this is. Check if the array

// is a subtype of the toType. This happens when toType // is java.lang.Object. return ts.isSubtype(this, toType); } 68

slide-69
SLIDE 69

Subtyping rules

69

A const [] <: B const [] A <: B A[] <: A[] A [] <: A const []

Can assign a non-const array to a “const” array Const arrays are covariant Non-const arrays are invariant

slide-70
SLIDE 70

Implementing the extension

  • 1. Extend the parser with const array types
  • 2. Add a const array AST node
  • 3. Add a const array type
  • 4. Implement subtyping for const arrays
  • 5. Change the subtyping rules for Java arrays
  • 6. Translate const arrays to Java arrays

70

slide-71
SLIDE 71

Covariant const arrays

ConstArrayType_c

  • public boolean isImplicitCastValidImpl(Type toType) {

if (!toType.isArray()) { // ?1 = ?2 const[] // This const array type is assignable to ?1 only if ?1 is Object. // Let the base language check this fact. return super.isImplicitCastValidImpl(toType); }

  • // From this point, toType is an array.

if (toType instanceof ConstArrayType) { // ?1 const[] = ?2 const[] // Let the base language check whether ?2 is assignable to ?1. return super.isImplicitCastValidImpl(toType); }

  • // From this point, toType is a non-const array.

// ?1[] = ?2 const[] // We cannot assign a const array to a non-const array. return false; } 71

A const [] <: B const [] A <: B

slide-72
SLIDE 72

Implementing the extension

  • 1. Extend the parser with const array types
  • 2. Add a const array AST node
  • 3. Add a const array type
  • 4. Prevent assignment to const arrays
  • 5. Implement subtyping for const arrays
  • 6. Change the subtyping rules for Java arrays
  • 7. Translate const arrays to Java arrays

72

slide-73
SLIDE 73

Invariant non-const arrays

CArrayArrayType_c

  • public boolean isImplicitCastValidImpl(Type toType) {

if (!toType.isArray()) { // ?1 = ?2 const[] // This const array type is assignable to ?1 only if ?1 is Object. // Let the base language check this fact. return super.isImplicitCastValidImpl(toType); }

  • // From this point, toType is an array.

if (toType instanceof CArrayArrayType) { // ?1[] = ?2[] // Non-const arrays are invariant, so we need to check that ?1 = ?2. return ts.typeEquals(base, toType.toArray().base()); }

  • // From this point, toType is a const array.

// ?1 const[] = ?2[] // We can assign a non-const array to a const array only if ?2 is a // subtype of ?1. Java arrays have this semantics, so let the base // language deal with this. return super.isImplicitCastValidImpl(toType); } 73

A[] <: A[] A [] <: A const []

slide-74
SLIDE 74

Exercise: casting

Can also cast from a non-const array to a const array

  • Implement isCastValidImpl in ConstArrayType_c

74

slide-75
SLIDE 75

Implementing constant arrays

Override typeCheck for assignment to disallow assigning to constant arrays

  • 75
slide-76
SLIDE 76

Creating an extension object

package carray.ast;

  • import polyglot.ast.Ext;

import polyglot.ast.ExtFactory;

  • public final class CArrayExtFactory_c extends CArrayAbstractExtFactory_c {

public CArrayExtFactory_c() { super(); }

  • public CArrayExtFactory_c(ExtFactory nextExtFactory) {

super(nextExtFactory); }

  • @Override

protected Ext extNodeImpl() { return new CArrayExt(); // default extension }

  • @Override

protected Ext extArrayAccessAssignImpl() { return new CArrayArrayAccessAssignExt(); } }

76

slide-77
SLIDE 77

CArrayArrayAccessAssignExt

@Override public Node typeCheck(TypeChecker tc) throws SemanticException { // Suppose n is a[2] = 3; ArrayAccessAssign n = (ArrayAccessAssign) this.node(); // Then left is a[2]. ArrayAccess left = n.left(); // And array is a. Expr array = left.array();

  • // If the type of the array is a ConstArrayType, then this assignment

// is illegal. if (array.type() instanceof ConstArrayType) { throw new SemanticException("Cannot assign into a const array.", n.position()); }

  • // Let the base language deal with the default type checking.

return superLang().typeCheck(n, tc); } 77

slide-78
SLIDE 78

CArrayArrayAccessAssignExt

@Override public Node typeCheck(TypeChecker tc) throws SemanticException { // Suppose n is a[2] = 3; ArrayAccessAssign n = (ArrayAccessAssign) this.node(); // Then left is a[2]. ArrayAccess left = n.left(); // And array is a. Expr array = left.array();

  • // If the type of the array is a ConstArrayType, then this assignment

// is illegal. if (array.type() instanceof ConstArrayType) { throw new SemanticException("Cannot assign into a const array.", n.position()); }

  • // Let the base language deal with the default type checking.

return superLang().typeCheck(n, tc); } 78

slide-79
SLIDE 79

Translation

slide-80
SLIDE 80

Implementing the extension

  • 1. Extend the parser with const array types
  • 2. Add a const array AST node
  • 3. Add a const array type
  • 4. Prevent assignment to const arrays
  • 5. Implement subtyping for const arrays
  • 6. Change the subtyping rules for Java arrays
  • 7. Translate const arrays to Java arrays

80

slide-81
SLIDE 81

Translation

Polyglot will pretty print Java ASTs

  • To implement translation to Java, we can override pretty-

printing

  • Less error-prone is to translate ASTs into base language

ASTs

81

slide-82
SLIDE 82

Translation

To translate ASTs, we add a pass before the CodeGenerated pass

  • CodeGenerated requires a type-checked AST.
  • Rather than generate type-correct ASTs during

translation, we can generate untyped ASTs and run the type checker again

82

slide-83
SLIDE 83

Compiler maintains a dependency graph of goals

  • Goals have prerequisites
  • To fulfill a goal, all prerequisites must be reached and the pass

for the goal must complete

  • Typical goals:
  • type check a compilation unit
  • generate code for a compilation unit
  • resolve a single name reference
  • barrier (block until all compilation units have reached a goal)

83

Goals and passes

slide-84
SLIDE 84

Goals and passes

84

slide-85
SLIDE 85

Scheduling translation

85

Remove CArray

slide-86
SLIDE 86

Translating to Java arrays

class CArrayRewriter extends ExtensionRewriter { ... public TypeNode typeToJava(Type t, Position pos) throws SemanticException { // Convert constant arrays to regular Java 1.4 arrays if (t instanceof ConstArrayType) { // X const[] --> X[] ConstArrayType at = (ConstArrayType) t; Type base = at.base(); NodeFactory nf = to_nf(); return nf.ArrayTypeNode(pos, typeToJava(base, base.position())); } return super.typeToJava(t, pos); } 86

slide-87
SLIDE 87

Supporting separate compilation

To support separate compilation, need to store extension-specific type information in Java .class files

  • Before code generation, the serialization pass encodes

the type information into fields of the generated code

  • For this to work, TypeObjects must implement

java.lang.Serializable and cannot have (non volatile) references to non serializable objects

87

slide-88
SLIDE 88

Another translation

slide-89
SLIDE 89

Instanceof

A problem with translating constant arrays to Java arrays is that instanceof behaves incorrectly

  • Bird const[] birds = …

birds instanceof Animal const [] // should return false!

  • But in our translation:
  • Bird[] birds = …

birds instanceof Animal[] // returns true

89

slide-90
SLIDE 90

Another translation

Idea: wrap const array objects in an object

  • Extends the Java5 extension and generates Java5
  • See carray-full.zip for the complete implementation

90

slide-91
SLIDE 91

Contributing

If you want to contribute to Polyglot

  • http://www.cs.cornell.edu/Projects/polyglot

https://github.com/polyglot-compiler/polyglot

  • Email:

nate.nystrom@usi.ch andru@cs.cornell.edu chong@seas.harvard.edu

91