Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mapping Whiley to Java #10

Open
DavePearce opened this issue Jan 18, 2017 · 0 comments
Open

Mapping Whiley to Java #10

DavePearce opened this issue Jan 18, 2017 · 0 comments

Comments

@DavePearce
Copy link
Member

DavePearce commented Jan 18, 2017

Having spent some time thinking about this (see #1 and #2), my conclusion is that we need a mapping to Java which produces something as close to "normal" Java as possible. My proposed mapping is thus:

  • Primitives.
    • bool as JVM boolean. byte as JVM byte.
    • u8 and i8 as JVM byte. For u8, this requires jiggery pokery using & 0xFF in places.
    • u16 as JVM char, i16 as JVM short. This works since JVM char is unsigned 16-bit.
    • u32 as JVM long, i32 as JVM int. Potentially could try to map u32 to JVM int with jiggery pokery.
    • u64 unmapped, i64 as JVM long. Here, u64 is just treated as int.
    • int mapped to JVM BigInteger.
  • Arrays. T[] mapped to JVM array T[]. This works, though requires external method for array generators [v;n].
  • Records mapped to JVM classes of same name. These classes are implemented as structs, but include obvious methods: equals(), hashCode(), clone().
  • Unions, Intersections and Negations mapped to Object. An interesting question is whether or not we want tags of some kind. Also, a union of the form T|null can be mapped to reference type for T (e.g. i32|null maps to Integer).
  • References.
  • Function / Methods.

This is a pretty decent mapping in general, and should make interoperation with Java relatively easy. In particular, mapping records to Java classes means that external code can create and use them. However, there remain a number of questions:

  1. Representation. The used of specific representations (particularly for integer primitives) means that appropriate casts must be introduced. The following example illustrates:
     u16 x = 1
     u32 y = x // need to cast here.
     u32 z = x+y
     
    In addition, there are complications arising from the typing of arithmetic. For example, in x+y above, the calculated return type will be int. We need to back propagate from z to determine the appropriate type for the expression and its arguments.
  2. Anonymous Records. For example, the following is difficult to translate efficiently as its unclear what type to construct for {x: 1, y:2}?
     Point p = {x: 1, y: 2}
     
    We can resolve this in two ways. Firstly, anonymous records can be represented using e.g. HashMap<String,Object>, or a type from the Whiley Runtime. Secondly, we can use type inference to back propagate the type Point into the expression {x: 1, y: 2}. This does get tricky though, as it's not always clear what the right type is. For example, null|Point p = {x: 1, y: 2}, well we need to figure out the intended type to construct is Point. Another possibility here would be to introduced named record construction, to allow Point p = Point{x: 1, y: 2}. This syntax is similar to Rust, and I don't believe it would cause any ambiguity in the grammar.
  3. Ownership. Here, we will avoid reference counting. The reason being simply that we cannot retro-fit reference counting onto Java array types. Therefore, a live variables analysis will be used to determine when a variable must be copied, versus when it must be moved. For copying of non-primitive types, we employ clone(). However, care must be taken to minimise this as much as possible. For example, in the expression x == y, we do not need to clone either x or y (even if they are still live). This is somehow similar to Rust's notion of "reference lvals".
  4. Runtime Type Tests. The current JVM backend uses the Whiley runtime to handle runtime type tests. Specifically, traversing their structure to exhaustively determine what they are. This is not exactly idea. An alternative solution would be to translate union types using a specialised Union object which contains the necessary type tag. This makes the FFI harder though, since the user needs to then manually specify tags.
  5. Whiley Runtime. A small runtime library is almost certainly required here. In particular, for implementing array generators, and also presumably for runtime type tests.
@DavePearce DavePearce changed the title Generating Java Source Code Mapping Whiley to Java Jan 18, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant