Top Banner
Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge
30

Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge.

Dec 29, 2015

Download

Documents

Ross Parsons
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge.

Interlanguage Working Without Tears:

Blending SML with Java

Andrew Kennedy

Nick Benton

Microsoft Research Cambridge

Page 2: Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge.

Goal

Fun for functional programmers: GUIs, 3-d, sound, video, email, crypto,

imaging, server-side code, phone, TV, … Achieved by an interface between SML and

Java. Implemented in MLj, a compiler that

generates Java class files from SML’97 source.

Page 3: Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge.

Three approaches to interop

1. Bilateral interface with marshalling and explicit calling conventions (e.g. JNI, O’Caml interface for C).

2. Multilateral interface with IDL (e.g. COM, CORBA) together with particular language mappings (e.g. H/Direct, Caml COM, MCORBA).

3. Language integration (MLj).

Page 4: Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge.

1. Explicit Bilateral Interface

Two languages have distinct type systems and calling conventions.

Interface by: Marshalling data between “compatible” types (e.g. java.lang.String to const char* by copying). Often restricted to a subset of the type system.

Giving directives for exporting and importing functions with language-specific calling conventions (e.g. _pascal _cdecl).

Usually tied to particular compiler implementations (e.g. SML/NJ and MLWorks have different C interfaces).

Realistically used only by experts.

Page 5: Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge.

Example: JNI

JNIEXPORT jstring JNICALL Java_Prompt_getLine(JNIEnv *env, jobject obj, jstring prompt) { char buf[128]; const char *str = (*env)->GetStringUTFChars(env,prompt,0);

printf("%s", str); (*env)->ReleaseStringUTFChars(env, prompt, str); … scanf("%s", buf); return (*env)->NewStringUTF(env, buf);}

Page 6: Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge.

2. IDL-based interop

Idea: Use a language-independent interface definition

language (IDL) to describe the signatures of functions that are to be called across the border.

Generate stub code using a language-specific tool. Good because it separates the interface from

the language and supports multilateral interop. But: the programmer has to write IDL code.

Page 7: Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge.

3. Our approach: Integration

Idea: When the “semantic gap” between two languages is

small, integrate features of one language into the other.

If done well, can be used by novices. But: language (and perhaps implementation)

specific.

Page 8: Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge.

Our languages: SML & Java

Both languages are strongly typed with good correspondences: Numeric types match closely Strings are immutable vectors Arrays have run-time sizing and bounds checking Neither language has explicit pointer types

Both languages have automatic storage management.

Exception handling in both languages is similar. But: there are significant differences too.

Page 9: Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge.

Interop in MLj 0.1

The bolt-it-on approach:

SML Java

Page 10: Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge.

Interop in MLj 0.1

Name Java types (Java.int, “java.util.Vector”) and provide coercions between ML and Java types (e.g. Java.fromInt, Java.toInt)

Provide new constructs corresponding to some Java language constructs (in fact, often closer to JVM bytecodes)

MLj 0.1

The bolt-it-on approach:

Page 11: Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge.

Example

_public _method "handleEvent" (e : Event option) : Java.boolean = if Java.toInt(_getfield "id" (valOf e)) = Java.toInt(_getfield Event "WINDOW_DESTROY") then OS.Process.terminate OS.Process.success else _invoke "handleEvent" (_super, e)

Response from some users:

Ugh!

Page 12: Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge.

New design for MLj

The blending approach:

SML Java

Page 13: Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge.

New design for MLj

The blending approach:

MLj 1.0

Don’t just attempt to replicate Java constructs Instead:

re-use SML concepts where appropriate invent clean new syntax elsewhere

Page 14: Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge.

Design goals

Simplicity Lightweight syntax Easy to convert Java code into MLj

Compatibility: SML’97 programs typecheck and run without change

Safety: Java-style type safety + avoid NullPointerException

Power: Improve on Java where possible

Page 15: Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge.

A non-goal

To pass ML-specific values into Java It’s less useful – write code in MLj instead It could compromise safety (e.g. by mutating

ML values) It requires uniform data representations, but

we want the chance to optimise the representations

Page 16: Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge.

Example codeopen javax.swing java.awt java.awt.event_classtype SampleApplet () : JApplet () with local val prefix = "Counter: “ val count = ref 0 val label = JLabel (prefix ^ "0", JLabel.CENTER) fun makeButton (title, increment) = let val button = JButton (title:string) val listener = ActionListener () with actionPerformed (e : ActionEvent option) = (count := !count + increment; label.#setText(prefix ^ Int.toString (!count))) end in button.#addActionListener(listener); button endin init () = let val SOME pane = this.#getContentPane () val button1 = makeButton ("Add One", 1) val button2 = makeButton ("Add Two", 2) in pane.#add(button1, BorderLayout.WEST); pane.#add(label, BorderLayout.CENTER); pane.#add(button2, BorderLayout.EAST) end end

Page 17: Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge.

Analogies between ML and Java

static field

static method

package

void

null

multiple args

mutability

non-static methods

ref

open

unit

structure

NONE

val binding

fun binding

tuple

type identifier

Java SML

class name

import

casts

instanceof

private fields local decs

class defs

non-static fields

Page 18: Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge.

Types

Java type ML typeboolean boolbyte Int8.intchar chardouble realfloat Real32.realint intlong Int64.intshort Int16.int

java.lang.String stringjava.lang.Exception exnjava.math.BigInteger IntInf.intjava.util.Calendar Date.date

X[] X array

Page 19: Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge.

Null values

Java reference values (arrays & objects) can take the value null

ML doesn’t have this notion, so values of array and class types are interpreted as “non-null instance” Then

datatype ‘a option = NONE | SOME of ‘a

is used for possibly-null objects and arrays

Page 20: Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge.

Fields and methods

Final fields (Java’s “const”) = ML values Non-final fields = ML refs Methods are given function types with

Tuples for multiple args Unit for void arg and result Implicit Java-style casts on arguments + T to

T option

Page 21: Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge.

Fields and methods, cont.

Static fields & methods are just bindings in ML structures (= Java class) embedded in a hierarchy of structures (= Java packages)

Non-static members are accessed through .# notation Constructors are just bindings with the same name as

the type (= Java new C) Improving on Java: first-class fields and methods e.g.

val colours = map (valOf o java.awt.Color.getColor) [“red”,“green”]

val labels = map javax.swing.JLabel [“ICFP”,”PLI”]

Page 22: Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge.

Casts and typecase

Java-style upcasts, using Caml-like syntax val c = Jbutton (“My button”) :> Component

Also used for downcasts, but neater alternative is “cast patterns”:

case (e : Expr) of ce :> CondExpr => … | ae :> AssignExpr => …

Page 23: Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge.

Creating Java classes in ML

1. Export an ML structure as a class, with functional values interpreted as static methods, non-functional values interpreted as static fields

2. New _classtype construct

Page 24: Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge.

Example

_classtype Point(xinit, yinit)With local val x = ref xinit val y = ref yinitin getX() = !x and getY() = !y and move(xinc,yinc) = (x := !x+xinc; y := !y+yinc) and moveHoriz xinc = this.#move(0, yinc) and moveVert yinc = this.#move(xinc, 0)end

Page 25: Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge.

Example

Single constructor, with args used throughout definition (as in O’Caml)

No fields! (Instead, use local definitions) Use of this as in Java

_classtype Point(xinit, yinit)With local val x = ref xinit val y = ref yinitin getX() = !x and getY() = !y and move(xinc,yinc) = (x := !x+xinc; y := !y+yinc) and moveHoriz xinc = this.#move(0, yinc) and moveVert yinc = this.#move(xinc, 0)end

Page 26: Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge.

Example, cont.

_classtype ColouredPoint(x,y,c) : Point(x,y)with getColour() = c : java.awt.Color and move (xinc,yinc) = this.##move(xinc*2, yinc*2)end

Page 27: Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge.

Example, cont.

_classtype ColouredPoint(x,y,c) : Point(x,y)with getColour() = c : java.awt.Color and move (xinc,yinc) = this.##move(xinc*2, yinc*2)end

Superclass specified with arguments to its constructor Overriding of methods Special syntax for superclass method invocation

Page 28: Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge.

Finale

Classic functional techniques: Backtracking & lazy lists to solve Eight

Queens Combinators for music (à la Hudak)

Interpreted using Java multimedia libraries…

Page 29: Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge.
Page 30: Interlanguage Working Without Tears: Blending SML with Java Andrew Kennedy Nick Benton Microsoft Research Cambridge.

Conclusion

Language interop is hard to get right – it’s a language design problem like any other

We think we’ve done a good job! See the paper for formalisation in the style of the

Definition of Standard ML Main line of future work: better inference

Currently, some programs with unique typings are rejected because types are inferred on-the-fly

Instead, first do pass over term generating constraints, then solve them.

Available soon in MLj – for now, see http://www.dcs.ed.ac.uk/~mlj