Skip to content

Commit

Permalink
Support try-catch-finally
Browse files Browse the repository at this point in the history
This more or less rewrites how we do try-catch-finally. From an API point-of-view it looks
the same but behind the scenes we actually create the entire try-catch-finally in one go.
  • Loading branch information
pontusmelke committed May 17, 2016
1 parent 6834986 commit 1aa2a67
Show file tree
Hide file tree
Showing 15 changed files with 759 additions and 90 deletions.
46 changes: 46 additions & 0 deletions community/codegen/src/main/java/org/neo4j/codegen/CatchClause.java
@@ -0,0 +1,46 @@
/*
* Copyright (c) 2002-2016 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.codegen;

import java.util.List;
import java.util.function.Consumer;

public class CatchClause
{
private final Parameter exception;
private final List<Consumer<MethodEmitter>> actions;

public CatchClause( Parameter exception, List<Consumer<MethodEmitter>> actions )
{
this.exception = exception;
this.actions = actions;
}

public Parameter exception()
{
return exception;
}

public List<Consumer<MethodEmitter>> actions()
{
return actions;
}

}
76 changes: 31 additions & 45 deletions community/codegen/src/main/java/org/neo4j/codegen/CodeBlock.java
Expand Up @@ -19,39 +19,41 @@
*/
package org.neo4j.codegen;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;

import static org.neo4j.codegen.LocalVariables.copy;
import static org.neo4j.codegen.Resource.withResource;
import static org.neo4j.codegen.TypeReference.typeReference;

public class CodeBlock implements AutoCloseable
{

final ClassGenerator clazz;
private MethodEmitter emitter;
private final CodeBlock parent;
private boolean done;
private Map<String, LocalVariable> localVariables = new HashMap<>( );
private int varCount = 0;

protected LocalVariables localVariables = new LocalVariables();

CodeBlock( CodeBlock parent )
{
this.clazz = parent.clazz;
this.emitter = parent.emitter;
parent.emitter = InvalidState.IN_SUB_BLOCK;
this.parent = parent;
this.localVariables = parent.localVariables;
//copy over local variables from parent
this.localVariables = copy(parent.localVariables);
}

CodeBlock( ClassGenerator clazz, MethodEmitter emitter, Parameter...parameters )
{
this.clazz = clazz;
this.emitter = emitter;
this.parent = null;
localVariables.put("this", localVariable( clazz.handle(), "this" ) );
localVariables.createNew( clazz.handle(), "this" );
for ( Parameter parameter : parameters )
{
localVariables.put( parameter.name(), localVariable( parameter.type(), parameter.name() ) );
localVariables.createNew( parameter.type(), parameter.name() );
}
}

Expand All @@ -75,7 +77,7 @@ public void close()
this.emitter = InvalidState.BLOCK_CLOSED;
}

private void endBlock()
protected void endBlock()
{
if ( !done )
{
Expand All @@ -84,9 +86,14 @@ private void endBlock()
}
}

protected void emit( Consumer<MethodEmitter> emitFunction )
{
emitFunction.accept( emitter );
}

public void expression( Expression expression )
{
emitter.expression( expression );
emit( ( e ) -> e.expression( expression ) );
}

LocalVariable local( String name )
Expand All @@ -96,15 +103,14 @@ LocalVariable local( String name )

public LocalVariable declare( TypeReference type, String name )
{
LocalVariable local = localVariable( type, name );
localVariables.put(name, local);
emitter.declare( local );
LocalVariable local = localVariables.createNew( type, name );
emit( e -> e.declare( local ) );
return local;
}

public void assign( LocalVariable local, Expression value )
{
emitter.assignVariableInScope( local, value );
emit( e -> e.assignVariableInScope( local, value ) );
}

public void assign( Class<?> type, String name, Expression value )
Expand All @@ -114,14 +120,13 @@ public void assign( Class<?> type, String name, Expression value )

public void assign( TypeReference type, String name, Expression value )
{
LocalVariable variable = localVariable( type, name );
localVariables.put(name, variable );
emitter.assign( variable, value );
LocalVariable variable = localVariables.createNew( type, name );
emit( e -> e.assign( variable, value ) );
}

public void put( Expression target, FieldReference field, Expression value )
{
emitter.put( target, field, value );
emit( e -> e.put( target, field, value ) );
}

public Expression self()
Expand All @@ -136,74 +141,55 @@ public Expression load( String name )

public CodeBlock forEach( Parameter local, Expression iterable )
{
emitter.beginForEach( local, iterable );
emit( e -> e.beginForEach( local, iterable ) );
return new CodeBlock( this );
}

public CodeBlock whileLoop( Expression test )
{
emitter.beginWhile( test );
emit( e -> e.beginWhile( test ) );
return new CodeBlock( this );
}

public CodeBlock ifStatement( Expression test )
{
emitter.beginIf( test );
emit( e -> e.beginIf( test ) );
return new CodeBlock( this );
}

CodeBlock emitCatch( Parameter exception )
{
endBlock();
emitter.beginCatch( exception );
return new CodeBlock( this );
}

CodeBlock emitFinally()
{
endBlock();
emitter.beginFinally();
return new CodeBlock( this );
}

public CodeBlock tryBlock( Class<?> resourceType, String resourceName, Expression resource )
public TryBlock tryBlock( Class<?> resourceType, String resourceName, Expression resource )
{
return tryBlock( withResource( resourceType, resourceName, resource ) );
}

public CodeBlock tryBlock( TypeReference resourceType, String resourceName, Expression resource )
public TryBlock tryBlock( TypeReference resourceType, String resourceName, Expression resource )
{
return tryBlock( withResource( resourceType, resourceName, resource ) );
}

public TryBlock tryBlock( Resource... resources )
{
emitter.beginTry( resources );
return new TryBlock( this );
return new TryBlock( this, resources );
}

public void returns()
{
emitter.returns();
emit( MethodEmitter::returns );
}

public void returns( Expression value )
{
emitter.returns( value );
emit( e -> e.returns( value ) );
}

public void throwException( Expression exception )
{
emitter.throwException( exception );
emit( e -> e.throwException( exception ) );
}

public TypeReference owner()
{
return clazz.handle();
}

private LocalVariable localVariable( TypeReference type, String name )
{
return new LocalVariable( type, name, varCount++ );
}
}
Expand Up @@ -70,7 +70,7 @@ public void accept( ExpressionVisitor visitor )
};
}

static Expression load( final LocalVariable variable)
public static Expression load( final LocalVariable variable)
{
return new Expression()
{
Expand Down
Expand Up @@ -19,6 +19,9 @@
*/
package org.neo4j.codegen;

import java.util.List;
import java.util.function.Consumer;

class InvalidState implements MethodEmitter
{
public static final ClassEmitter CLASS_DONE = new ClassEmitter()
Expand Down Expand Up @@ -98,20 +101,15 @@ public void beginIf( Expression test )
throw new IllegalStateException( reason );
}

@Override
public void beginFinally()
{
throw new IllegalStateException( reason );
}

@Override
public void endBlock()
{
throw new IllegalStateException( reason );
}

@Override
public void beginTry( Resource... resources )
public void tryCatchBlock( List<Consumer<MethodEmitter>> body, List<CatchClause> catchClauses,
List<Consumer<MethodEmitter>> finalClauses, LocalVariables localVariables, Resource... resources )
{
throw new IllegalStateException( reason );
}
Expand All @@ -122,12 +120,6 @@ public void throwException( Expression exception )
throw new IllegalStateException( reason );
}

@Override
public void beginCatch( Parameter exception )
{
throw new IllegalStateException( reason );
}

@Override
public void declare( LocalVariable local )
{
Expand Down
@@ -0,0 +1,58 @@
/*
* Copyright (c) 2002-2016 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.codegen;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
* Repository of local variables.
*/
public class LocalVariables
{
private final AtomicInteger counter = new AtomicInteger( 0 );
private final Map<String,LocalVariable> localVariables = new HashMap<>();

public LocalVariable createNew( TypeReference type, String name )
{
LocalVariable localVariable = new LocalVariable( type, name, counter.getAndIncrement() );
localVariables.put( name, localVariable );
return localVariable;
}

public LocalVariable get( String name )
{
return localVariables.get( name );
}

public static LocalVariables copy( LocalVariables original )
{
LocalVariables variables = new LocalVariables();
variables.counter.set( original.counter.get() );
original.localVariables.forEach( variables.localVariables::put );
return variables;
}

public int nextIndex()
{
return counter.getAndIncrement();
}
}
Expand Up @@ -19,6 +19,9 @@
*/
package org.neo4j.codegen;

import java.util.List;
import java.util.function.Consumer;

public interface MethodEmitter
{
void done();
Expand All @@ -37,16 +40,15 @@ public interface MethodEmitter

void beginIf( Expression test );

void beginFinally();

void endBlock();

void beginTry( Resource... resources );
void tryCatchBlock( List<Consumer<MethodEmitter>> body,
List<CatchClause> catchClauses,
List<Consumer<MethodEmitter>> finalClauses,
LocalVariables localVariables, Resource... resources );

void throwException( Expression exception );

void beginCatch( Parameter exception );

void declare( LocalVariable local );

void assignVariableInScope( LocalVariable local, Expression value );
Expand Down
Expand Up @@ -46,6 +46,12 @@ private static MethodReference methodReference( Class<?> owner, TypeReference re
return methodReference( typeReference( owner ), returns, name, modifiers, parameters );
}

public static MethodReference methodReference( TypeReference owner, TypeReference returns, String name,
TypeReference... parameters )
{
return new MethodReference( owner, name, returns, Modifier.PUBLIC, parameters );
}

public static MethodReference methodReference( TypeReference owner, TypeReference returns, String name,
int modifiers, TypeReference... parameters )
{
Expand Down

0 comments on commit 1aa2a67

Please sign in to comment.