goto java; (Jfokus)

Click here to load reader

  • date post

    14-Feb-2017
  • Category

    Software

  • view

    248
  • download

    0

Embed Size (px)

Transcript of goto java; (Jfokus)

Groovy en 2014 et au-del

Martin SkarsauneJava Developer and Co-Owner

A peek into the OpenJDK compiler : goto java;

Were Hiring!

@MSkarsauneHello everyone.My name is Martin Skarsaune, developer working for Kantega.

Today we are going to have a peek into the compiler. I assume everyone here rely on a Java compiler in their everyday work. Just out of curiosity, have anyone had a look at the compiler source code ?I guess a lot of clever developers out here have read articles, have debugged a lot of Java applications and disassempled class files to see what your Java code turns into on the other end. So some of the stuff may be known to you, never the less I think it is worth while to look at the process step by step from the inside and see with out own eyes what goes on.1

GOTO Statements in Java!

@MSkarsauneGOTO Statement ObjectiveSyntax goto identifier;RuntimeProgram control moves to target statementOther Semantics Target (statement label) must be defined in same scope, compilation error if notPotential circular gotos should give compilation warning.

@MSkarsauneGOTO Statement MeansOpenJDKOpen source Java implementationJavac is implemented in plain Java Modify compiler to support GOTO

@MSkarsaune public class GotoSuccess {public static void main(String[] args) {one: System.out.print("goto ");two: System.out.print(J");goto four;three: System.out.print(2017");goto five;four: System.out.print(Fokus ");goto three;five: System.out.print("!");}}

Success Case

@MSkarsaune

GOTOAHEAD

Dijkstra 1968:

@MSkarsaune

6

What is a Compiler?

Compiler

@MSkarsauneA compiler is a tool that accepts input in some sort of programming language and produces output targeted for another language or instruction set. 7

What is a Compiler?

frontendbackend

@MSkarsauneA common compiler architecture is to try to decouple the input from the output. The front end deals with specifics handling, checks and optimizations for the given programming language, and the back end deals with generation, dependencies and optimizations for a given target platform. This separation is an obvious choice for compilers that generate native code.I was involved in a big project over several years, where we developed tools and routines for automated translation from Smalltalk to Java. In that project we did exactly this, we reused the parser and internal representation from the built in Smalltalk compiler, but instead of generating Smalltalk byte codes, we generated Java source code.

8

processAnnotations(enterTrees( parseFiles())),)generate(desugar(flow(attribute())))

@MSkarsauneprocessAnnotations(enterTrees( parseFiles())),)generate(desugar(flow(attribute())))

@MSkarsauneSyntax: goto identifier;First convert character stream to token stream (Scanner.java)

[g][o][t][o][ ][f][o][u][r][;]

@MSkarsaunegoto is already a reserved word in Java!Lucky for us, goto is therefore defined as a TokenKind. Tokens.java:141: GOTO(goto)The scanner therefore works out of the box!

@MSkarsaune

...import com.sun.tools.javac.parser.Scanner;...final Scanner scanner=factory.newScanner(goto identifier;, false);

@MSkarsaune

final Scanner scanner=factory.newScanner(goto identifier;, false);

scanner.nextToken();

@MSkarsaune

final Scanner scanner=factory.newScanner(goto identifier;, false);

scanner.nextToken();assertThat(First token is GOTO, scanner.token().kind, is(GOTO));

@MSkarsaune

final Scanner scanner=factory.newScanner(goto identifier;, false);

scanner.nextToken();assertThat(First token is GOTO, scanner.token().kind, is(GOTO));

scanner.nextToken();

@MSkarsaune

final Scanner scanner=factory.newScanner(goto identifier;, false);

scanner.nextToken();assertThat(First token is GOTO, scanner.token().kind, is(GOTO));

scanner.nextToken();assertThat("Second token is IDENTIFIER", scanner.token().kind,is(IDENTIFIER));

@MSkarsaune

final Scanner scanner=factory.newScanner(goto identifier;, false);

scanner.nextToken();assertThat(First token is GOTO, scanner.token().kind, is(GOTO));

scanner.nextToken();assertThat("Second token is IDENTIFIER", scanner.token().kind,is(IDENTIFIER));

scanner.nextToken();

@MSkarsaune

final Scanner scanner=factory.newScanner(goto identifier;, false);

scanner.nextToken();assertThat(First token is GOTO, scanner.token().kind, is(GOTO));

scanner.nextToken();assertThat("Second token is IDENTIFIER", scanner.token().kind,is(IDENTIFIER));

scanner.nextToken(); assertThat("Third token is SEMI", scanner.token().kind, is(SEMI));

@MSkarsaune

visitClassDef(..)visitMethodDef(..)visitIf(..)Abstract Syntax Tree[g][o][t][o][ ][f][o][u][r][;]Wikipedia: the visitor design pattern is a way of separating an algorithm from an object structure on which it operates

@MSkarsaune

ClassInterface

@MSkarsaune

Interface based visitors

@MSkarsauneClass based visitors

public void visitGoto(JCGoto tree) { try { print("goto " + tree.label + ";"); } catch (IOException e) { throw new UncheckedIOException(e); } }

public void visitGoto(JCGoto tree) { //TODOimplement}

@MSkarsaune

public static class JCLabeledStatement extends JCStatement implements LabeledStatementTree {public GotoResolver handler;}

public class GotoResolver { Map gotos; Map targets; List statementsInSequence; ...}Helper object

@MSkarsaune

JavacParser.parseStatement() case GOTO: { nextToken(); Name label = ident(); JCGoto t = to(F.at(pos).Goto(label, getGotoResolver()); accept(SEMI); return t; }

TreeMaker.java:

public JCGoto Goto(Name label, GotoResolver resolver) { JCGoto tree = new JCGoto(label, resolver); tree.pos = pos; return tree;}

@MSkarsaune

Demo

@MSkarsauneprocessAnnotations(enterTrees( parseFiles())),)generate(desugar(flow(attribute())))

@MSkarsauneprocessAnnotations(enterTrees( parseFiles())),)generate(desugar(flow(attribute())))

@MSkarsauneBasic sanity testing of compilation unit:File name and folder locationDuplicate class namesCorrectionsAdd default constructor if no constructors are declared

@MSkarsaune

Default Constructorpublic class SimpleClass {

}

@MSkarsaune

Default Constructorpublic class SimpleClass { public SimpleClass() { super(); }}

@MSkarsaune

processAnnotations(enterTrees( parseFiles())),)generate(desugar(flow(attribute())))

@MSkarsauneprocessAnnotations(enterTrees( parseFiles())),)generate(desugar(flow(attribute())))

@MSkarsauneProcess AnnitationsAnnotation processing APIPart of ordinary javac process since Java 1.6Plugin API (see javac documentation)

@MSkarsauneOutput controlled by command line switches

@- proc:only only process annotations, do not compile

- proc:none do not process annotations

@MSkarsauneprocessAnnotations(enterTrees( parseFiles())),)generate(desugar(flow(attribute())))

@MSkarsauneprocessAnnotations(enterTrees( parseFiles())),)generate(desugar(flow(attribute())))

@MSkarsauneAttributionSemantic checksTypesReferencesCorrectionsAdd required calls to super constructor

@MSkarsaune

Ensure target label exists in current scopepublic class GotoMissingLabel {public static void main(String[] args) {one: System.out.print("goto ");two: System.out.print(Java");goto six;three: System.out.print(2016");goto five;four: System.out.print(One ");goto three;five: System.out.print("!");}}

@MSkarsaune

Attr.java: @Override public void visitGoto(JCGoto that) {that.findTarget();if(that.target==null)log.error(that.pos(), "undef.label", that.label);result = null; }

class JCGoto: public void findTarget() { this.target = (JCLabeledStatement)this.handler.findTarget(this);}

@MSkarsaune

Demo

@MSkarsauneprocessAnnotations(enterTrees( parseFiles())),)generate(desugar(flow(attribute())))

@MSkarsaune

processAnnotations(enterTrees( parseFiles())),)generate(desugar(flow(attribute())))

@MSkarsauneFlow analysisDetect unreachable codeVerify assignmentsEnsure proper method returnVerify (effectively) finalCheck exception flow

@MSkarsaune

Detect circular gotospublic class GotoCircularWarning {public static void main(String[] args) { one: System.out.print("goto "); two: System.out.print(Java"); goto four; three: System.out.print(2016"); goto five; four: System.out.print(One "); goto three; five: System.out.println("!"); goto one;//forms infinite loop }}

@MSkarsaune

Flow.FlowAnalyzer class:

compiler.properties: @Override public void visitGoto(JCGoto tree) { if (tree.handler.detectCircularGotoPosition(tree)) log.warning(tree.pos, "circular.goto"); }

...compiler.warn.circular.goto=circular goto...

@MSkarsaune

Demo

@MSkarsaune

processAnnotations(enterTrees( parseFiles())),)generate(desugar(flow(attribute())))

@MSkarsauneprocessAnnotations(enterTrees( parseFiles())),)generate(desugar(flow(attribute())))

@MSkarsaune

Erase generic types

public class Bridge implements Comparator {

}public interface Comparator {int compare(T o1, T o1); }or {

@MSkarsaune

Erase generic types

public class Bridge implements Comparator {public int compare(Integer first, Integer second) {return first - second;}}public interface Comparator {int compare(T o1, T o1)