Skip to content

Commit

Permalink
Fix error catcher evaluation order (#719)
Browse files Browse the repository at this point in the history
* Fix error catcher evaluation order

* Run spotless
  • Loading branch information
gdavid04 authored May 15, 2021
1 parent 96d9559 commit f7631e8
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 17 deletions.
1 change: 1 addition & 0 deletions src/main/java/vazkii/psi/api/spell/IErrorCatcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

/**
* Interface for a SpellPiece that can catch exceptions of pieces it's attached to.
* Pieces implementing this should be of type {@link EnumPieceType#ERROR_HANDLER}.
*/
public interface IErrorCatcher {

Expand Down
51 changes: 34 additions & 17 deletions src/main/java/vazkii/psi/common/spell/SpellCompiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ public final class SpellCompiler implements ISpellCompiler {
/** The current spell being compiled. */
private CompiledSpell compiled;

private final Set<SpellPiece> processedHandlers = new HashSet<>();

private final Set<SpellPiece> redirectionPieces = new HashSet<>();

@Override
Expand All @@ -54,10 +52,13 @@ public CompiledSpell doCompile(Spell spell) throws SpellCompilationException {
throw new SpellCompilationException(SpellCompilationException.NO_SPELL);
}

processedHandlers.clear();
redirectionPieces.clear();
compiled = new CompiledSpell(spell);

for (SpellPiece piece : findPieces(EnumPieceType.ERROR_HANDLER::equals)) {
buildHandler(piece);
}

List<SpellPiece> tricks = findPieces(EnumPieceType::isTrick);
if (tricks.isEmpty()) {
throw new SpellCompilationException(SpellCompilationException.NO_TRICKS);
Expand All @@ -66,12 +67,6 @@ public CompiledSpell doCompile(Spell spell) throws SpellCompilationException {
buildPiece(trick);
}

for (SpellPiece piece : findPieces(EnumPieceType.ERROR_HANDLER::equals)) {
if (processedHandlers.add(piece)) {
buildPiece(piece);
}
}

if (compiled.metadata.getStat(EnumSpellStat.COST) < 0 || compiled.metadata.getStat(EnumSpellStat.POTENCY) < 0) {
throw new SpellCompilationException(SpellCompilationException.STAT_OVERFLOW);
}
Expand Down Expand Up @@ -102,12 +97,6 @@ public void buildPiece(SpellPiece piece, Set<SpellPiece> visited) throws SpellCo
piece.addToMetadata(compiled.metadata);
}

CompiledSpell.CatchHandler errorHandler = null;
if (piece instanceof IErrorCatcher) {
errorHandler = compiled.new CatchHandler(piece);
processedHandlers.add(piece);
}

// error handler params must be evaluated before the handled piece
CatchHandler catchHandler = compiled.errorHandlers.get(piece);
if (catchHandler != null) {
Expand All @@ -134,8 +123,7 @@ public void buildPiece(SpellPiece piece, Set<SpellPiece> visited) throws SpellCo
throw new SpellCompilationException(SpellCompilationException.INVALID_PARAM, piece.x, piece.y);
}

if (errorHandler != null && ((IErrorCatcher) piece).catchParam(param)) {
compiled.errorHandlers.putIfAbsent(pieceAt, errorHandler);
if (piece instanceof IErrorCatcher && ((IErrorCatcher) piece).catchParam(param)) {
handledErrors.add(pieceAt);
} else {
params.add(pieceAt);
Expand All @@ -149,6 +137,35 @@ public void buildPiece(SpellPiece piece, Set<SpellPiece> visited) throws SpellCo
}
}

public void buildHandler(SpellPiece piece) throws SpellCompilationException {
if (!(piece instanceof IErrorCatcher)) {
return;
}
IErrorCatcher errorCatcher = (IErrorCatcher) piece;
CompiledSpell.CatchHandler errorHandler = compiled.new CatchHandler(piece);

EnumSet<SpellParam.Side> usedSides = EnumSet.noneOf(SpellParam.Side.class);

for (SpellParam<?> param : piece.paramSides.keySet()) {
if (!errorCatcher.catchParam(param) || checkSideDisabled(param, piece, usedSides)) {
continue;
}

SpellParam.Side side = piece.paramSides.get(param);

SpellPiece pieceAt = compiled.sourceSpell.grid.getPieceAtSideWithRedirections(piece.x, piece.y, side, this::buildRedirect);

if (pieceAt == null) {
throw new SpellCompilationException(SpellCompilationException.NULL_PARAM, piece.x, piece.y);
}
if (!param.canAccept(pieceAt)) {
throw new SpellCompilationException(SpellCompilationException.INVALID_PARAM, piece.x, piece.y);
}

compiled.errorHandlers.put(pieceAt, errorHandler);
}
}

public void buildRedirect(SpellPiece piece) throws SpellCompilationException {
if (redirectionPieces.add(piece)) {
piece.addToMetadata(compiled.metadata);
Expand Down

0 comments on commit f7631e8

Please sign in to comment.