diff --git a/core/stratego.common/src/main/java/mb/stratego/common/StrategoRuntime.java b/core/stratego.common/src/main/java/mb/stratego/common/StrategoRuntime.java index 6016d9224..989b33883 100644 --- a/core/stratego.common/src/main/java/mb/stratego/common/StrategoRuntime.java +++ b/core/stratego.common/src/main/java/mb/stratego/common/StrategoRuntime.java @@ -1,6 +1,7 @@ package mb.stratego.common; import mb.common.util.ListView; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spoofax.interpreter.core.Interpreter; import org.spoofax.interpreter.core.InterpreterException; import org.spoofax.interpreter.terms.IStrategoAppl; @@ -8,6 +9,8 @@ import org.spoofax.interpreter.terms.ITermFactory; import org.strategoxt.HybridInterpreter; +import java.util.Optional; + public class StrategoRuntime { private final HybridInterpreter hybridInterpreter; private final StrategoIOAgent ioAgent; @@ -40,49 +43,160 @@ public StrategoRuntime(StrategoRuntime other, StrategoIOAgent ioAgent, Adaptable this(other.hybridInterpreter, ioAgent, contextObject); } - + /** + * Invokes a Stratego strategy with no term arguments, + * throwing {@link StrategoException} if the strategy fails. + * + * @param strategy the name of the strategy to invoke + * @param input the input term + * @return the resulting term + * @throws StrategoException if the strategy or its invocation failed + */ public IStrategoTerm invoke(String strategy, IStrategoTerm input) throws StrategoException { + @Nullable final IStrategoTerm result = invokeOrNull(strategy, input); + if (result == null) + throw StrategoException.strategyFail(strategy, input, hybridInterpreter.getCompiledContext().getTrace()); + return result; + } + + /** + * Invokes a Stratego strategy with the specified term arguments, + * throwing {@link StrategoException} if the strategy fails. + * + * @param strategy the name of the strategy to invoke + * @param input the input term + * @param arguments the term arguments + * @return the resulting term + * @throws StrategoException if the strategy or its invocation failed + */ + public IStrategoTerm invoke(String strategy, IStrategoTerm input, ListView arguments) throws StrategoException { + @Nullable final IStrategoTerm result = invokeOrNull(strategy, input, arguments); + if (result == null) + throw StrategoException.strategyFail(strategy, input, hybridInterpreter.getCompiledContext().getTrace()); + return result; + } + + /** + * Invokes a Stratego strategy with the specified term arguments, + * throwing {@link StrategoException} if the strategy fails. + * + * @param strategy the name of the strategy to invoke + * @param input the input term + * @param arguments the term arguments + * @return the resulting term + * @throws StrategoException if the strategy or its invocation failed + */ + public IStrategoTerm invoke(String strategy, IStrategoTerm input, IStrategoTerm... arguments) throws StrategoException { + @Nullable final IStrategoTerm result = invokeOrNull(strategy, input, arguments); + if (result == null) + throw StrategoException.strategyFail(strategy, input, hybridInterpreter.getCompiledContext().getTrace()); + return result; + } + + /** + * Invokes a Stratego strategy with no term arguments, + * returning {@link Optional#empty()} if the strategy fails. + * + * @param strategy the name of the strategy to invoke + * @param input the input term + * @return an {@link Optional} with the resulting term; or {@link Optional#empty()} if the strategy failed + * @throws StrategoException if the strategy invocation failed + */ + public Optional tryInvoke(String strategy, IStrategoTerm input) throws StrategoException { + return Optional.ofNullable(invokeOrNull(strategy, input)); + } + + /** + * Invokes a Stratego strategy with the specified term arguments, + * returning {@link Optional#empty()} if the strategy fails. + * + * @param strategy the name of the strategy to invoke + * @param input the input term + * @param arguments the term arguments + * @return an {@link Optional} with the resulting term; or {@link Optional#empty()} if the strategy failed + * @throws StrategoException if the strategy invocation failed + */ + public Optional tryInvoke(String strategy, IStrategoTerm input, ListView arguments) throws StrategoException { + return Optional.ofNullable(invokeOrNull(strategy, input, arguments)); + } + + /** + * Invokes a Stratego strategy with the specified term arguments, + * returning {@link Optional#empty()} if the strategy fails. + * + * @param strategy the name of the strategy to invoke + * @param input the input term + * @param arguments the term arguments + * @return an {@link Optional} with the resulting term; or {@link Optional#empty()} if the strategy failed + * @throws StrategoException if the strategy invocation failed + */ + public Optional tryInvoke(String strategy, IStrategoTerm input, IStrategoTerm... arguments) throws StrategoException { + return Optional.ofNullable(invokeOrNull(strategy, input, arguments)); + } + + /** + * Invokes a Stratego strategy with no term arguments, + * returning {@code null} if the strategy fails. + * + * @param strategy the name of the strategy to invoke + * @param input the input term + * @return the resulting term; or {@code null} if the strategy failed + * @throws StrategoException if the strategy invocation failed + */ + public @Nullable IStrategoTerm invokeOrNull(String strategy, IStrategoTerm input) throws StrategoException { + return invokeOrNull(strategy, input, ListView.of()); + } + + /** + * Invokes a Stratego strategy with the specified term arguments, + * returning {@code null} if the strategy fails. + * + * @param strategy the name of the strategy to invoke + * @param input the input term + * @param arguments the term arguments + * @return the resulting term; or {@code null} if the strategy failed + * @throws StrategoException if the strategy invocation failed + */ + public @Nullable IStrategoTerm invokeOrNull(String strategy, IStrategoTerm input, ListView arguments) throws StrategoException { hybridInterpreter.setCurrent(input); hybridInterpreter.setIOAgent(ioAgent); hybridInterpreter.getContext().setContextObject(contextObject); hybridInterpreter.getCompiledContext().setContextObject(contextObject); - try { - final boolean success = hybridInterpreter.invoke(strategy); - if(!success) { - throw StrategoException.strategyFail(strategy, input, hybridInterpreter.getCompiledContext().getTrace()); - } - return hybridInterpreter.current(); - } catch(InterpreterException e) { - throw StrategoException.fromInterpreterException(strategy, input, hybridInterpreter.getCompiledContext().getTrace(), e); - } - } - public IStrategoTerm invoke(String strategy, IStrategoTerm input, ListView termArguments) throws StrategoException { - hybridInterpreter.setCurrent(input); - hybridInterpreter.setIOAgent(ioAgent); - hybridInterpreter.getContext().setContextObject(contextObject); - hybridInterpreter.getCompiledContext().setContextObject(contextObject); - ITermFactory termFactory = getTermFactory(); - IStrategoTerm strategyName = termFactory.makeString(Interpreter.cify(strategy) + "_0_" + termArguments.size()); - IStrategoTerm strategyNameTerm = termFactory.makeAppl("SVar", strategyName); - IStrategoAppl strategyCallTerm = termFactory.makeAppl( - "CallT", - strategyNameTerm, - termFactory.makeList(), - termFactory.makeList(termArguments.asUnmodifiable()) - ); try { - final boolean success = hybridInterpreter.evaluate(strategyCallTerm); - if(!success) { - throw StrategoException.strategyFail(strategy, input, hybridInterpreter.getCompiledContext().getTrace()); + final boolean success; + if (arguments.isEmpty()) { + success = hybridInterpreter.invoke(strategy); + } else { + ITermFactory termFactory = getTermFactory(); + IStrategoTerm strategyName = termFactory.makeString(Interpreter.cify(strategy) + "_0_" + arguments.size()); + IStrategoTerm strategyNameTerm = termFactory.makeAppl("SVar", strategyName); + IStrategoAppl strategyCallTerm = termFactory.makeAppl( + "CallT", + strategyNameTerm, + termFactory.makeList(), + termFactory.makeList(arguments.asUnmodifiable()) + ); + success = hybridInterpreter.evaluate(strategyCallTerm); } + if(!success) return null; return hybridInterpreter.current(); } catch(InterpreterException e) { throw StrategoException.fromInterpreterException(strategy, input, hybridInterpreter.getCompiledContext().getTrace(), e); } } - public IStrategoTerm invoke(String strategy, IStrategoTerm input, IStrategoTerm... arguments) throws StrategoException { + /** + * Invokes a Stratego strategy with the specified term arguments, + * returning {@code null} if the strategy fails. + * + * @param strategy the name of the strategy to invoke + * @param input the input term + * @param arguments the term arguments + * @return the resulting term; or {@code null} if the strategy failed + * @throws StrategoException if the strategy invocation failed + */ + public @Nullable IStrategoTerm invokeOrNull(String strategy, IStrategoTerm input, IStrategoTerm... arguments) throws StrategoException { return invoke(strategy, input, ListView.of(arguments)); }