Minor improvements to scarpet annotation API (#1239)
This commit is contained in:
1 parent
212eb07131
commit
9fb6ec91cb
5 files changed
+30
-17
No files matched your search
@@ -481,9 +481,9 @@ public class Expression
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void addLazyFunction(String name, int num_params, TriFunction<Context, Context.Type, List<LazyValue>, LazyValue> fun)
|
public void addLazyFunction(String name, int numParams, TriFunction<Context, Context.Type, List<LazyValue>, LazyValue> fun)
|
||||||
{
|
{
|
||||||
functions.put(name, new AbstractLazyFunction(num_params, name)
|
functions.put(name, new AbstractLazyFunction(numParams, name)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public boolean pure() {
|
public boolean pure() {
|
||||||
@@ -499,8 +499,11 @@ public class Expression
|
|||||||
public LazyValue lazyEval(Context c, Context.Type i, Expression e, Tokenizer.Token t, List<LazyValue> lazyParams)
|
public LazyValue lazyEval(Context c, Context.Type i, Expression e, Tokenizer.Token t, List<LazyValue> lazyParams)
|
||||||
{
|
{
|
||||||
ILazyFunction.checkInterrupts();
|
ILazyFunction.checkInterrupts();
|
||||||
if (num_params >= 0 && lazyParams.size() != num_params)
|
if (numParams >= 0 && lazyParams.size() != numParams)
|
||||||
throw new InternalExpressionException("'"+name+"' requires "+num_params+" parameters, "+lazyParams.size()+" provided.");
|
{
|
||||||
|
String error = "Function '"+name+"' requires "+numParams+" arguments, got "+lazyParams.size()+". ";
|
||||||
|
throw new InternalExpressionException(error + (fun instanceof Fluff.UsageProvider up ? up.getUsage() : ""));
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ public abstract class Fluff
|
|||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface SexFunction<A, B, C, D, E, F, R> { R apply(A a, B b, C c, D d, E e, F f);}
|
public interface SexFunction<A, B, C, D, E, F, R> { R apply(A a, B b, C c, D d, E e, F f);}
|
||||||
|
|
||||||
|
public interface UsageProvider { String getUsage();}
|
||||||
|
|
||||||
public interface EvalNode
|
public interface EvalNode
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import carpet.script.Context;
|
|||||||
import carpet.script.Expression;
|
import carpet.script.Expression;
|
||||||
import carpet.script.Fluff.AbstractLazyFunction;
|
import carpet.script.Fluff.AbstractLazyFunction;
|
||||||
import carpet.script.Fluff.TriFunction;
|
import carpet.script.Fluff.TriFunction;
|
||||||
|
import carpet.script.Fluff.UsageProvider;
|
||||||
import carpet.script.exception.InternalExpressionException;
|
import carpet.script.exception.InternalExpressionException;
|
||||||
import carpet.script.LazyValue;
|
import carpet.script.LazyValue;
|
||||||
import carpet.script.value.Value;
|
import carpet.script.value.Value;
|
||||||
@@ -73,6 +74,7 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
|||||||
*/
|
*/
|
||||||
public final class AnnotationParser
|
public final class AnnotationParser
|
||||||
{
|
{
|
||||||
|
static final int UNDEFINED_PARAMS = -2;
|
||||||
private static final List<ParsedFunction> functionList = new ArrayList<>();
|
private static final List<ParsedFunction> functionList = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -90,8 +92,8 @@ public final class AnnotationParser
|
|||||||
* {@link InternalExpressionException}).
|
* {@link InternalExpressionException}).
|
||||||
* Basically, it's fine as long as you don't add a {@code throws} declaration to your methods.</li>
|
* Basically, it's fine as long as you don't add a {@code throws} declaration to your methods.</li>
|
||||||
* <li>Varargs (or effectively varargs) annotated methods must explicitly declare a maximum number of parameters to ingest in the {@link ScarpetFunction}
|
* <li>Varargs (or effectively varargs) annotated methods must explicitly declare a maximum number of parameters to ingest in the {@link ScarpetFunction}
|
||||||
* annotation. They can still declare an unlimited amount by setting that maximum to {@code -1}. "Effectively varargs" means a function that has
|
* annotation. They can still declare an unlimited amount by setting that maximum to {@link ScarpetFunction#UNLIMITED_PARAMS}. "Effectively varargs"
|
||||||
* a parameter using/requiring a {@link ValueConverter} that has declared {@link ValueConverter#consumesVariableArgs()}.</li>
|
* means a function that has at least a parameter requiring a {@link ValueConverter} that has declared {@link ValueConverter#consumesVariableArgs()}.</li>
|
||||||
* <li>Annotated methods must not have a parameter with generics as the varargs parameter. This is just because it was painful for me (altrisi) and
|
* <li>Annotated methods must not have a parameter with generics as the varargs parameter. This is just because it was painful for me (altrisi) and
|
||||||
* didn't want to support it. Those will crash with a {@code ClassCastException}</li>
|
* didn't want to support it. Those will crash with a {@code ClassCastException}</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
@@ -141,7 +143,7 @@ public final class AnnotationParser
|
|||||||
expr.addLazyFunction(function.name, function.scarpetParamCount, function);
|
expr.addLazyFunction(function.name, function.scarpetParamCount, function);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ParsedFunction implements TriFunction<Context, Context.Type, List<LazyValue>, LazyValue>
|
private static class ParsedFunction implements TriFunction<Context, Context.Type, List<LazyValue>, LazyValue>, UsageProvider
|
||||||
{
|
{
|
||||||
private final String name;
|
private final String name;
|
||||||
private final boolean isMethodVarArgs;
|
private final boolean isMethodVarArgs;
|
||||||
@@ -186,14 +188,14 @@ public final class AnnotationParser
|
|||||||
if (this.isEffectivelyVarArgs)
|
if (this.isEffectivelyVarArgs)
|
||||||
{
|
{
|
||||||
maxParams = method.getAnnotation(ScarpetFunction.class).maxParams();
|
maxParams = method.getAnnotation(ScarpetFunction.class).maxParams();
|
||||||
if (maxParams == -2)
|
if (maxParams == UNDEFINED_PARAMS)
|
||||||
throw new IllegalArgumentException("No maximum number of params specified for " + name + ", use -1 for unlimited. "
|
throw new IllegalArgumentException("No maximum number of params specified for " + name + ", use ScarpetFunction.UNLIMITED_PARAMS for unlimited. "
|
||||||
+ "Provided in " + instance.getClass());
|
+ "Provided in " + instance.getClass());
|
||||||
|
if (maxParams == ScarpetFunction.UNLIMITED_PARAMS)
|
||||||
|
maxParams = Integer.MAX_VALUE;
|
||||||
if (maxParams < this.minParams)
|
if (maxParams < this.minParams)
|
||||||
throw new IllegalArgumentException("Provided maximum number of params for " + name + " is smaller than method's param count."
|
throw new IllegalArgumentException("Provided maximum number of params for " + name + " is smaller than method's param count."
|
||||||
+ "Provided in " + instance.getClass());
|
+ "Provided in " + instance.getClass());
|
||||||
if (maxParams == -1)
|
|
||||||
maxParams = Integer.MAX_VALUE;
|
|
||||||
}
|
}
|
||||||
this.maxParams = maxParams;
|
this.maxParams = maxParams;
|
||||||
|
|
||||||
@@ -293,7 +295,8 @@ public final class AnnotationParser
|
|||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getUsage()
|
@Override
|
||||||
|
public String getUsage()
|
||||||
{
|
{
|
||||||
// Possibility: More descriptive messages using param.getName()? Would need changing gradle setup to keep those
|
// Possibility: More descriptive messages using param.getName()? Would need changing gradle setup to keep those
|
||||||
StringBuilder builder = new StringBuilder("Usage: '");
|
StringBuilder builder = new StringBuilder("Usage: '");
|
||||||
|
|||||||
@@ -51,6 +51,11 @@ import carpet.script.value.Value;
|
|||||||
@Retention(RUNTIME)
|
@Retention(RUNTIME)
|
||||||
public @interface ScarpetFunction
|
public @interface ScarpetFunction
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* <p>Used to define that this {@link ScarpetFunction} can accept an unlimited number of parameters</p>
|
||||||
|
*/
|
||||||
|
public static final int UNLIMITED_PARAMS = -1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>If the function can accept a variable number of parameters, either by declaring its last parameter as a varargs parameter or by having one
|
* <p>If the function can accept a variable number of parameters, either by declaring its last parameter as a varargs parameter or by having one
|
||||||
* of their parameters use a converter that consumes a variable number of arguments, this must define the maximum number of parameters this
|
* of their parameters use a converter that consumes a variable number of arguments, this must define the maximum number of parameters this
|
||||||
@@ -65,11 +70,11 @@ public @interface ScarpetFunction
|
|||||||
* consider that those can take either a single triple of values or 3 independent values, that would be counted in the maximum number of
|
* consider that those can take either a single triple of values or 3 independent values, that would be counted in the maximum number of
|
||||||
* parameters.</p>
|
* parameters.</p>
|
||||||
*
|
*
|
||||||
* <p>Use -1 to specify an unlimited number of parameters.</p>
|
* <p>Use {@link ScarpetFunction#UNLIMITED_PARAMS} to allow an unlimited number of parameters.</p>
|
||||||
*
|
*
|
||||||
* @return The maximum number of parameters this function can accept
|
* @return The maximum number of parameters this function can accept
|
||||||
*/
|
*/
|
||||||
int maxParams() default -2;
|
int maxParams() default AnnotationParser.UNDEFINED_PARAMS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Defines the Context Type that will be used when evaluating arguments to annotated methods.</p>
|
* <p>Defines the Context Type that will be used when evaluating arguments to annotated methods.</p>
|
||||||
|
|||||||
@@ -162,13 +162,13 @@ public interface ValueConverter<R>
|
|||||||
* constraints as {@link #convert(Value)}</p>
|
* constraints as {@link #convert(Value)}</p>
|
||||||
* @param valueIterator An {@link Iterator} holding the {@link Value} to convert in next position
|
* @param valueIterator An {@link Iterator} holding the {@link Value} to convert in next position
|
||||||
* @param context The {@link Context} this function has been called with. This was used when this passed lazy values instead in order to
|
* @param context The {@link Context} this function has been called with. This was used when this passed lazy values instead in order to
|
||||||
* evaluate, now it's used to get the context. It is now ignored by the default implementation
|
* evaluate, now it's used to get the context
|
||||||
* @param theLazyT The {@code t} that the original function was called with. It is ignored by the default implementation.
|
* @param contextType The {@link Context.Type} that the original function was called with
|
||||||
* @return The next {@link Value} (s) converted to the type {@code <R>} of this {@link ValueConverter}
|
* @return The next {@link Value} (s) converted to the type {@code <R>} of this {@link ValueConverter}
|
||||||
* @implNote This method's default implementation runs the {@link #convert(Value)} function in the next {@link Value} ignoring {@link Context} and
|
* @implNote This method's default implementation runs the {@link #convert(Value)} function in the next {@link Value} ignoring {@link Context} and
|
||||||
* {@code theLazyT}.
|
* {@code theLazyT}.
|
||||||
*/
|
*/
|
||||||
default public R checkAndConvert(Iterator<Value> valueIterator, Context context, Context.Type theLazyT)
|
default public R checkAndConvert(Iterator<Value> valueIterator, Context context, Context.Type contextType)
|
||||||
{
|
{
|
||||||
if (!valueIterator.hasNext())
|
if (!valueIterator.hasNext())
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
Reference in new issue
Block a user