/**
* Copyright 2012 Tobias Gierke <tobias.gierke@code-sourcery.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.codesourcery.jasm16.compiler;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import de.codesourcery.jasm16.compiler.ICompiler.CompilerOption;
import de.codesourcery.jasm16.compiler.io.IObjectCodeWriterFactory;
import de.codesourcery.jasm16.compiler.io.IResourceResolver;
/**
* Abstract base-class for compiler phase implementations.
*
* @author tobias.gierke@code-sourcery.de
* @see ICompilerPhase
*/
public abstract class CompilerPhase implements ICompilerPhase {
private static final Logger LOG = Logger.getLogger( CompilerPhase.class );
private final String name;
private boolean stopAfterExecution;
public CompilerPhase(String name)
{
if ( StringUtils.isBlank( name ) ) {
throw new IllegalArgumentException("name must not be NULL/blank.");
}
this.name = name;
}
@Override
public String getName()
{
return name;
}
private boolean hasErrors(List<ICompilationUnit> units)
{
for ( ICompilationUnit unit : units ) {
if ( unit.hasErrors() ) {
return true;
}
}
return false;
}
public boolean isStopAfterExecution() {
return stopAfterExecution;
}
protected boolean isAbortOnErrors() {
return false;
}
@Override
public String toString()
{
return name.toString();
}
protected boolean isProcessCompilationUnit(ICompilationUnit unit) {
return true;
}
@Override
public boolean execute(List<ICompilationUnit> units,
DebugInfo debugInfo,
IParentSymbolTable globalSymbolTable,
IObjectCodeWriterFactory writerFactory ,
ICompilationListener listener,
IResourceResolver resourceResolver,
Set<CompilerOption> options,
ICompilationUnitResolver compUnitResolver)
{
/*
* NEED to create a copy for the for() loop here since
* createCompilationContext() instantiates an
* ICompilationUnitResolver that MODIFIES the
* input list (and thus the for() loop would otherwise
* fail with a ConcurrentModificationExcption) ...
*/
final List<ICompilationUnit> internalCopy = new ArrayList<ICompilationUnit>( units );
for ( ICompilationUnit unit : internalCopy )
{
if ( ! isProcessCompilationUnit( unit ) ) {
listener.skipped( this , unit );
continue;
}
listener.start( this , unit );
try
{
final ICompilationContext context = createCompilationContext( units , globalSymbolTable, writerFactory , resourceResolver , options , compUnitResolver , unit );
run( unit , context );
if ( hasErrors( units ) )
{
listener.failure( this , unit );
if ( isAbortOnErrors() ) {
return false;
}
} else {
listener.success( this , unit );
}
}
catch (Exception e)
{
listener.failure( this , unit );
unit.addMarker( new GenericCompilationError("Unexpected error while compiling "+unit, unit,e) );
LOG.error("execute(): [ phase "+this+"] "+e.getMessage() , e );
return ! isAbortOnErrors();
}
}
return true;
}
protected final ICompilationContext createCompilationContext(
final List<ICompilationUnit> units,
IParentSymbolTable symbolTable,
IObjectCodeWriterFactory writerFactory,
IResourceResolver resourceResolver,
final Set<CompilerOption> options,
ICompilationUnitResolver compUnitResolver,
ICompilationUnit unit)
{
return new CompilationContext( unit , units , symbolTable, writerFactory , resourceResolver ,compUnitResolver ,options );
}
@Override
public void setStopAfterExecution(boolean yesNo) {
this.stopAfterExecution = yesNo;
}
protected abstract void run(ICompilationUnit unit , ICompilationContext context) throws IOException;
}