From a65d16c9ba7d74321d295105fbfc0dcdd5502cc7 Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 21 Apr 2021 12:21:47 -0300 Subject: [PATCH 1/7] WIP unpacking of parameters. --- src/main/java/carpet/script/Context.java | 1 + src/main/java/carpet/script/Expression.java | 16 +++++---- src/main/java/carpet/script/Fluff.java | 34 ++++++++++++++++--- .../java/carpet/script/api/Auxiliary.java | 7 ++-- src/main/java/carpet/script/api/Entities.java | 4 +-- .../script/argument/FunctionArgument.java | 11 ++++++ .../carpet/script/language/Functions.java | 19 +++++++++-- .../carpet/script/language/Threading.java | 4 +-- .../value/FunctionUnpackedArgumentsValue.java | 10 ++++++ .../carpet/script/value/FunctionValue.java | 28 ++++++++++----- .../java/carpet/script/value/ListValue.java | 2 +- 11 files changed, 106 insertions(+), 30 deletions(-) create mode 100644 src/main/java/carpet/script/value/FunctionUnpackedArgumentsValue.java diff --git a/src/main/java/carpet/script/Context.java b/src/main/java/carpet/script/Context.java index fb9b583e..ad87fa17 100644 --- a/src/main/java/carpet/script/Context.java +++ b/src/main/java/carpet/script/Context.java @@ -19,6 +19,7 @@ public class Context public static final int LOCALIZATION = 8; public static final int LVALUE = 9; public static final int MAPDEF = 10; + public static final int CALLARGS = 11; public Map variables = new HashMap<>(); diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index d0c36074..51443de7 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -773,12 +773,16 @@ public class Expression stack.set(stack.size() - 1, stack.peek() - 2 + 1); break; case FUNCTION: - ILazyFunction f = functions.get(token.surface);// don't validate global - userdef functions - int numParams = stack.pop(); - if (f != null && !f.numParamsVaries() && numParams != f.getNumParams()) - { - throw new ExpressionException(c, this, token, "Function " + token + " expected " + f.getNumParams() + " parameters, got " + numParams); - } + //ILazyFunction f = functions.get(token.surface);// don't validate global - userdef functions + //int numParams = stack.pop(); + //if (f != null && !f.numParamsVaries() && numParams != f.getNumParams()) + //{ + // throw new ExpressionException(c, this, token, "Function " + token + " expected " + f.getNumParams() + " parameters, got " + numParams); + //} + stack.pop(); + // due to unpacking, all functions can have variable number of arguments + // we will be checking that at runtime. + // TODO try analyze arguments and assess if its possible that they are static if (stack.size() <= 0) { throw new ExpressionException(c, this, token, "Too many function calls, maximum scope exceeded"); diff --git a/src/main/java/carpet/script/Fluff.java b/src/main/java/carpet/script/Fluff.java index 9662f265..f492c830 100644 --- a/src/main/java/carpet/script/Fluff.java +++ b/src/main/java/carpet/script/Fluff.java @@ -1,6 +1,9 @@ package carpet.script; import carpet.script.exception.ExpressionException; +import carpet.script.exception.InternalExpressionException; +import carpet.script.value.FunctionUnpackedArgumentsValue; +import carpet.script.value.ListValue; import carpet.script.value.Value; import java.util.ArrayList; @@ -85,6 +88,30 @@ public abstract class Fluff super(numParams); } + public static List unpackArgs(List lzargs, Context c) + { + List args = new ArrayList<>(); + for (LazyValue lv : lzargs) + { + Value arg = lv.evalValue(c, Context.CALLARGS); + if (arg instanceof FunctionUnpackedArgumentsValue) + { + args.addAll(((ListValue) arg).getItems()); + } + else + { + args.add(arg); + } + } + return args; + } + + public void checkArgs(int candidates) + { + if (!numParamsVaries() && getNumParams() !=candidates) + throw new InternalExpressionException("Function " + getName() + " expected " + getNumParams() + " parameters, got " + candidates); + } + @Override public LazyValue lazyEval(Context cc, Integer type, Expression e, Tokenizer.Token t, final List lazyParams) { @@ -100,10 +127,9 @@ public abstract class Fluff private List getParams(Context c) { if (params == null) { - params = new ArrayList<>(); - for (LazyValue lazyParam : lazyParams) { - params.add(lazyParam.evalValue(c)); // none type default by design - } + // very likely needs to be dynamic, so not static like here, or remember if it was. + params = unpackArgs(lazyParams, c); + checkArgs(params.size()); } return params; } diff --git a/src/main/java/carpet/script/api/Auxiliary.java b/src/main/java/carpet/script/api/Auxiliary.java index 76d73c31..9859bcb3 100644 --- a/src/main/java/carpet/script/api/Auxiliary.java +++ b/src/main/java/carpet/script/api/Auxiliary.java @@ -834,12 +834,13 @@ public class Auxiliary { throw new InternalExpressionException("'schedule' should have at least 2 arguments, delay and call name"); long delay = NumericValue.asNumber(lv.get(0).evalValue(c)).getLong(); - FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 1, false, true); + FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 1, false, false); + List args = functionArgument.unpackArgs(c); CarpetServer.scriptServer.events.scheduleCall( (CarpetContext) c, functionArgument.function, - FunctionValue.resolveArgs(functionArgument.args, c, t), + args, delay ); return (c_, t_) -> Value.TRUE; @@ -1043,7 +1044,7 @@ public class Auxiliary { } else { - success = host.getScriptServer().events.handleCustomEvent(event, host, callback.function, FunctionValue.resolveArgs(callback.args, c, t) )?Value.TRUE:Value.FALSE; + success = host.getScriptServer().events.handleCustomEvent(event, host, callback.function, callback.unpackArgs(c) )?Value.TRUE:Value.FALSE; } return (cc, tt) -> success; }); diff --git a/src/main/java/carpet/script/api/Entities.java b/src/main/java/carpet/script/api/Entities.java index 68a02904..ce2cd3b5 100644 --- a/src/main/java/carpet/script/api/Entities.java +++ b/src/main/java/carpet/script/api/Entities.java @@ -308,7 +308,7 @@ public class Entities { } else { - types.forEach(et -> events.addBuiltInEvent(CarpetEventServer.Event.getEntityLoadEventName(et), c.host, funArg.function, FunctionValue.resolveArgs(funArg.args, c, t))); + types.forEach(et -> events.addBuiltInEvent(CarpetEventServer.Event.getEntityLoadEventName(et), c.host, funArg.function, funArg.unpackArgs(c))); } Value ret = new NumericValue(types.size()); return (cc, tt) -> ret; @@ -326,7 +326,7 @@ public class Entities { FunctionArgument funArg = FunctionArgument.findIn(c, expression.module, lv, 2, true, false); - ((EntityValue) v).setEvent((CarpetContext)c, what, funArg.function, FunctionValue.resolveArgs(funArg.args, c, t)); + ((EntityValue) v).setEvent((CarpetContext)c, what, funArg.function, funArg.unpackArgs(c)); return LazyValue.NULL; }); diff --git a/src/main/java/carpet/script/argument/FunctionArgument.java b/src/main/java/carpet/script/argument/FunctionArgument.java index 8c52c8d5..ecd09034 100644 --- a/src/main/java/carpet/script/argument/FunctionArgument.java +++ b/src/main/java/carpet/script/argument/FunctionArgument.java @@ -1,6 +1,7 @@ package carpet.script.argument; import carpet.script.Context; +import carpet.script.Fluff; import carpet.script.LazyValue; import carpet.script.ScriptHost; import carpet.script.bundled.Module; @@ -94,4 +95,14 @@ public class FunctionArgument extends Argument return new FunctionArgument<>(function, 0, args); } + + public void checkArgs() { + function.checkArgs(args.size()); + } + + public List unpackArgs(Context c) { + List unpackedArgs = Fluff.AbstractFunction.unpackArgs((List) args, c); + function.checkArgs(unpackedArgs.size()); + return unpackedArgs; + } } diff --git a/src/main/java/carpet/script/language/Functions.java b/src/main/java/carpet/script/language/Functions.java index 1588a3e0..5c03dd13 100644 --- a/src/main/java/carpet/script/language/Functions.java +++ b/src/main/java/carpet/script/language/Functions.java @@ -6,12 +6,14 @@ import carpet.script.LazyValue; import carpet.script.argument.FunctionArgument; import carpet.script.exception.InternalExpressionException; import carpet.script.exception.ReturnStatement; +import carpet.script.value.AbstractListValue; import carpet.script.value.FunctionSignatureValue; import carpet.script.value.FunctionValue; import carpet.script.value.FunctionAnnotationValue; import carpet.script.value.ListValue; import carpet.script.value.StringValue; import carpet.script.value.Value; +import com.google.common.collect.ImmutableList; import java.util.ArrayList; import java.util.List; @@ -90,9 +92,20 @@ public class Functions { expression.addLazyUnaryOperator("...", Operators.precedence.get("def->..."), false, (c, t, lv) -> { - if (t != Context.LOCALIZATION) - throw new InternalExpressionException("That functionality has not been implemented yet."); - return (cc, tt) -> new FunctionAnnotationValue(lv.evalValue(c), 1); + if (t == Context.LOCALIZATION) + return (cc, tt) -> new FunctionAnnotationValue(lv.evalValue(c), 1); + if (t == Context.CALLARGS) + { + Value params = lv.evalValue(c, Context.NONE); + if (params instanceof ListValue) + return (cc, tt) -> params; + if (!(params instanceof AbstractListValue)) + throw new InternalExpressionException("Unable to unpack a non-list"); + Value unpacked = ListValue.wrap(ImmutableList.copyOf(((AbstractListValue) params).iterator())); + return (cc, tt) -> unpacked; + } + throw new InternalExpressionException("That functionality has not been implemented yet."); + }); //assigns const procedure to the lhs, returning its previous value diff --git a/src/main/java/carpet/script/language/Threading.java b/src/main/java/carpet/script/language/Threading.java index f3149ae6..f7dd0389 100644 --- a/src/main/java/carpet/script/language/Threading.java +++ b/src/main/java/carpet/script/language/Threading.java @@ -19,7 +19,7 @@ public class Threading if (lv.size() == 0) throw new InternalExpressionException("'task' requires at least function to call as a parameter"); FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 0, false, true); - ThreadValue thread = new ThreadValue(Value.NULL, functionArgument.function, expr, tok, c, FunctionValue.resolveArgs(functionArgument.args, c, t)); + ThreadValue thread = new ThreadValue(Value.NULL, functionArgument.function, expr, tok, c, functionArgument.unpackArgs(c)); Thread.yield(); return (cc, tt) -> thread; }); @@ -30,7 +30,7 @@ public class Threading throw new InternalExpressionException("'task' requires at least function to call as a parameter"); Value queue = lv.get(0).evalValue(c); FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 1, false, true); - ThreadValue thread = new ThreadValue(queue, functionArgument.function, expr, tok, c, FunctionValue.resolveArgs(functionArgument.args, c, t)); + ThreadValue thread = new ThreadValue(queue, functionArgument.function, expr, tok, c, functionArgument.unpackArgs(c)); Thread.yield(); return (cc, tt) -> thread; }); diff --git a/src/main/java/carpet/script/value/FunctionUnpackedArgumentsValue.java b/src/main/java/carpet/script/value/FunctionUnpackedArgumentsValue.java new file mode 100644 index 00000000..8c053e7b --- /dev/null +++ b/src/main/java/carpet/script/value/FunctionUnpackedArgumentsValue.java @@ -0,0 +1,10 @@ +package carpet.script.value; + +import java.util.List; + +public class FunctionUnpackedArgumentsValue extends ListValue +{ + public FunctionUnpackedArgumentsValue(List list) { + super(list); + } +} diff --git a/src/main/java/carpet/script/value/FunctionValue.java b/src/main/java/carpet/script/value/FunctionValue.java index 61e97b18..a05e87b1 100644 --- a/src/main/java/carpet/script/value/FunctionValue.java +++ b/src/main/java/carpet/script/value/FunctionValue.java @@ -11,7 +11,6 @@ import carpet.script.exception.ContinueStatement; import carpet.script.exception.ExpressionException; import carpet.script.exception.InternalExpressionException; import carpet.script.exception.ReturnStatement; -import carpet.script.exception.ThrowStatement; import net.minecraft.nbt.StringTag; import net.minecraft.nbt.Tag; @@ -173,15 +172,26 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction } } - @Override - public LazyValue lazyEval(Context c, Integer type, Expression e, Tokenizer.Token t, List lazyParams) + public void checkArgs(int candidates) { - assertArgsOk(lazyParams, (fixedArgs) ->{ + int actual = getArguments().size(); + + if (candidates < actual) + throw new InternalExpressionException("Function " + getPrettyString() + " requires at least " + actual + " arguments"); + if (candidates > actual && getVarArgs() == null) + throw new InternalExpressionException("Function " + getPrettyString() + " requires " + actual + " arguments"); + } + + @Override + public LazyValue lazyEval(Context c, Integer type, Expression e, Tokenizer.Token t, List lazyPrams) + { + List resolvedArgs = Fluff.AbstractFunction.unpackArgs(lazyPrams, c); + assertArgsOk(resolvedArgs, (fixedArgs) ->{ if (fixedArgs) // wrong number of args for fixed args { throw new ExpressionException(c, e, t, "Incorrect number of arguments for function "+name+ - ". Should be "+args.size()+", not "+lazyParams.size()+" like "+args + ". Should be "+args.size()+", not "+resolvedArgs.size()+" like "+args ); } else // too few args for varargs @@ -190,7 +200,7 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction argList.add("... "+varArgs); throw new ExpressionException(c, e, t, "Incorrect number of arguments for function "+name+ - ". Should be at least "+args.size()+", not "+lazyParams.size()+" like "+argList + ". Should be at least "+args.size()+", not "+resolvedArgs.size()+" like "+argList ); } }); @@ -200,15 +210,15 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction for (int i=0; i val); } if (varArgs != null) { List extraParams = new ArrayList<>(); - for (int i = args.size(), mx = lazyParams.size(); i < mx; i++) + for (int i = args.size(), mx = resolvedArgs.size(); i < mx; i++) { - extraParams.add(lazyParams.get(i).evalValue(c).reboundedTo(null)); // copy by value I guess + extraParams.add(resolvedArgs.get(i).reboundedTo(null)); // copy by value I guess } Value rest = ListValue.wrap(extraParams).bindTo(varArgs); // didn't we just copied that? newFrame.setVariable(varArgs, (cc, tt) -> rest); diff --git a/src/main/java/carpet/script/value/ListValue.java b/src/main/java/carpet/script/value/ListValue.java index de316668..7da9ee92 100644 --- a/src/main/java/carpet/script/value/ListValue.java +++ b/src/main/java/carpet/script/value/ListValue.java @@ -70,7 +70,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf items.addAll(list); } - private ListValue(List list) + protected ListValue(List list) { items = list; } From 74bd0bb81e40d1a2f7e588bfb56143962542a4b1 Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 22 Apr 2021 20:37:48 -0300 Subject: [PATCH 2/7] dont be lazy refactor --- .../java/carpet/script/CarpetScriptHost.java | 22 +- src/main/java/carpet/script/Context.java | 1 - src/main/java/carpet/script/Expression.java | 84 +++ src/main/java/carpet/script/Fluff.java | 60 +- .../java/carpet/script/api/Auxiliary.java | 435 ++++++--------- .../carpet/script/api/BlockIterators.java | 49 +- src/main/java/carpet/script/api/Entities.java | 141 ++--- .../java/carpet/script/api/Inventories.java | 202 +++---- .../java/carpet/script/api/Monitoring.java | 34 +- .../java/carpet/script/api/Scoreboards.java | 390 +++++-------- .../java/carpet/script/api/Threading.java | 8 +- .../java/carpet/script/api/WorldAccess.java | 515 ++++++++---------- .../carpet/script/argument/BlockArgument.java | 13 +- .../carpet/script/argument/FileArgument.java | 6 +- .../script/argument/FunctionArgument.java | 31 +- .../script/argument/Vector3Argument.java | 65 +-- .../script/command/CommandArgument.java | 2 +- .../carpet/script/language/Arithmetic.java | 10 +- .../carpet/script/language/ControlFlow.java | 12 +- .../script/language/DataStructures.java | 73 +-- .../carpet/script/language/Functions.java | 53 +- .../java/carpet/script/language/Loops.java | 1 + .../carpet/script/language/Operators.java | 13 +- src/main/java/carpet/script/language/Sys.java | 134 ++--- .../carpet/script/language/Threading.java | 31 +- .../java/carpet/script/value/EntityValue.java | 4 +- .../script/value/FunctionAnnotationValue.java | 10 +- .../carpet/script/value/FunctionValue.java | 39 +- .../carpet/script/value/LContainerValue.java | 1 + .../script/value/NBTSerializableValue.java | 20 +- .../java/carpet/script/value/ThreadValue.java | 2 +- 31 files changed, 1078 insertions(+), 1383 deletions(-) diff --git a/src/main/java/carpet/script/CarpetScriptHost.java b/src/main/java/carpet/script/CarpetScriptHost.java index c265ac11..0d74b4fd 100644 --- a/src/main/java/carpet/script/CarpetScriptHost.java +++ b/src/main/java/carpet/script/CarpetScriptHost.java @@ -134,7 +134,7 @@ public class CarpetScriptHost extends ScriptHost return host; } - private static int execute(CommandContext ctx, String hostName, FunctionArgument funcSpec, List paramNames) throws CommandSyntaxException + private static int execute(CommandContext ctx, String hostName, FunctionArgument funcSpec, List paramNames) throws CommandSyntaxException { CarpetProfiler.ProfilerToken currentSection = CarpetProfiler.start_section(null, "Scarpet command", CarpetProfiler.TYPE.GENERAL); CarpetScriptHost cHost = CarpetServer.scriptServer.modules.get(hostName).retrieveOwnForExecution(ctx.getSource()); @@ -158,7 +158,7 @@ public class CarpetScriptHost extends ScriptHost public LiteralArgumentBuilder addPathToCommand( LiteralArgumentBuilder command, List path, - FunctionArgument functionSpec + FunctionArgument functionSpec ) throws CommandSyntaxException { String hostName = main.getName(); @@ -180,14 +180,14 @@ public class CarpetScriptHost extends ScriptHost } public LiteralArgumentBuilder getNewCommandTree( - List,FunctionArgument>> entries, Function useValidator + List,FunctionArgument>> entries, Function useValidator ) throws CommandSyntaxException { String hostName = main.getName(); Function configValidator = getCommandConfigPermissions(); LiteralArgumentBuilder command = literal(hostName). requires((player) -> CarpetServer.scriptServer.modules.containsKey(hostName) && useValidator.apply(player) && configValidator.apply(player)); - for (Pair,FunctionArgument> commandData : entries) + for (Pair,FunctionArgument> commandData : entries) { command = this.addPathToCommand(command, commandData.getKey(), commandData.getValue()); } @@ -547,12 +547,12 @@ public class CarpetScriptHost extends ScriptHost if (commands == null) return null; if (!(commands instanceof MapValue)) throw CommandArgument.error("'commands' element in config should be a map"); - List,FunctionArgument>> commandEntries = new ArrayList<>(); + List,FunctionArgument>> commandEntries = new ArrayList<>(); for (Map.Entry commandsData : ((MapValue)commands).getMap().entrySet().stream().sorted(Map.Entry.comparingByKey()).collect(Collectors.toList())) { List elements = CommandToken.parseSpec(commandsData.getKey().getString(), this); - FunctionArgument funSpec = FunctionArgument.fromCommandSpec(this, commandsData.getValue()); + FunctionArgument funSpec = FunctionArgument.fromCommandSpec(this, commandsData.getValue()); commandEntries.add(Pair.of(elements, funSpec)); } commandEntries.sort(new ListComparator<>()); @@ -806,20 +806,18 @@ public class CarpetScriptHost extends ScriptHost } } - public Value call(ServerCommandSource source, FunctionValue function, List suppliedArgs) + public Value call(ServerCommandSource source, FunctionValue function, List argv) { if (CarpetServer.scriptServer.stopAll) throw new CarpetExpressionException("SCARPET PAUSED", null); - List argv = FunctionValue.lazify(suppliedArgs); - List args = function.getArguments(); if (argv.size() != args.size()) { String error = "Fail: stored function "+function.getPrettyString()+" takes "+args.size()+" arguments, not "+argv.size()+ ":\n"; for (int i = 0; i < max(argv.size(), args.size()); i++) { - error += (i "+(i "+(i function.lazyEval(context, Context.VOID, function.getExpression(), function.getToken(), argv), + () -> function.execute(context, Context.VOID, function.getExpression(), function.getToken(), argv), context, Context.VOID ); @@ -857,7 +855,7 @@ public class CarpetScriptHost extends ScriptHost // TODO: this is just for now - invoke would be able to invoke other hosts scripts Context context = new CarpetContext(this, source, pos); return fun.getExpression().evalValue( - () -> fun.lazyEval(context, Context.VOID, fun.getExpression(), fun.getToken(), FunctionValue.lazify(argv)), + () -> fun.execute(context, Context.VOID, fun.getExpression(), fun.getToken(), argv), context, Context.VOID); } diff --git a/src/main/java/carpet/script/Context.java b/src/main/java/carpet/script/Context.java index ad87fa17..fb9b583e 100644 --- a/src/main/java/carpet/script/Context.java +++ b/src/main/java/carpet/script/Context.java @@ -19,7 +19,6 @@ public class Context public static final int LOCALIZATION = 8; public static final int LVALUE = 9; public static final int MAPDEF = 10; - public static final int CALLARGS = 11; public Map variables = new HashMap<>(); diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index 51443de7..28b6a2fa 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -205,6 +205,27 @@ public class Expression }); } + public void addFunctionWithDelegation(String name, int numpar, + QuinnFunction, Value> fun) + { + functions.put(name, new AbstractLazyFunction(numpar) + { + @Override + public LazyValue lazyEval(Context c, Integer type, Expression e, Tokenizer.Token t, List lv) + { + try + { + Value res = fun.apply(c, type, e, t, unpackArgs(lv, c, Context.NONE)); + return (cc, tt) -> res; + } + catch (RuntimeException exc) + { + throw handleCodeException(c, exc, e, t); + } + } + }); + } + public void addLazyBinaryOperator(String surface, int precedence, boolean leftAssoc, QuadFunction lazyfun) { @@ -226,6 +247,28 @@ public class Expression }); } + public void addBinaryContextOperator(String surface, int precedence, boolean leftAssoc, + QuadFunction fun) + { + operators.put(surface, new AbstractLazyOperator(precedence, leftAssoc) + { + @Override + public LazyValue lazyEval(Context c, Integer t, Expression e, Tokenizer.Token token, LazyValue v1, LazyValue v2) + { + try + { + Value.assertNotNull(v1, v2); // does anybody needs those + Value ret = fun.apply(c, t, v1.evalValue(c, Context.NONE), v2.evalValue(c, Context.NONE)); + return (cc, tt) -> ret; + } + catch (RuntimeException exc) + { + throw handleCodeException(c, exc, e, token); + } + } + }); + } + public static RuntimeException handleCodeException(Context c, RuntimeException exc, Expression e, Tokenizer.Token token) { if (exc instanceof ExitStatement) @@ -343,6 +386,47 @@ public class Expression } }); } + + public void addContextFunction(String name, int num_params, TriFunction, Value> fun) + { + functions.put(name, new AbstractLazyFunction(num_params) + { + @Override + public LazyValue lazyEval(Context c, Integer i, Expression e, Tokenizer.Token t, List lazyParams) + { + try + { + Value ret = fun.apply(c, i, unpackArgs(lazyParams, c, Context.NONE)); + return (cc, tt) -> ret; + } + catch (RuntimeException exc) + { + throw handleCodeException(c, exc, e, t); + } + } + }); + } + + public void addTypedContextFunction(String name, int num_params, int reqType, TriFunction, Value> fun) + { + functions.put(name, new AbstractLazyFunction(num_params) + { + @Override + public LazyValue lazyEval(Context c, Integer i, Expression e, Tokenizer.Token t, List lazyParams) + { + try + { + Value ret = fun.apply(c, i, unpackArgs(lazyParams, c, reqType)); + return (cc, tt) -> ret; + } + catch (RuntimeException exc) + { + throw handleCodeException(c, exc, e, t); + } + } + }); + } + public FunctionValue createUserDefinedFunction(Context context, String name, Expression expr, Tokenizer.Token token, List arguments, String varArgs, List outers, LazyValue code) { if (functions.containsKey(name)) diff --git a/src/main/java/carpet/script/Fluff.java b/src/main/java/carpet/script/Fluff.java index f492c830..dc41d936 100644 --- a/src/main/java/carpet/script/Fluff.java +++ b/src/main/java/carpet/script/Fluff.java @@ -1,5 +1,6 @@ package carpet.script; +import carpet.CarpetSettings; import carpet.script.exception.ExpressionException; import carpet.script.exception.InternalExpressionException; import carpet.script.value.FunctionUnpackedArgumentsValue; @@ -80,6 +81,36 @@ public abstract class Fluff public boolean numParamsVaries() { return numParams < 0; } + + public static List unpackLazy(List lzargs, Context c, int contextType) + { + List args = new ArrayList<>(); + for (LazyValue lv : lzargs) + { + Value arg = lv.evalValue(c, contextType); + if (arg instanceof FunctionUnpackedArgumentsValue) + args.addAll(((ListValue) arg).getItems()); + else + args.add(arg); + } + return args; + } + + public List unpackArgs(List lzargs, Context c, int contextType) + { + List args = new ArrayList<>(); + for (LazyValue lv : lzargs) + { + Value arg = lv.evalValue(c, contextType); + if (arg instanceof FunctionUnpackedArgumentsValue) + args.addAll(((ListValue) arg).getItems()); + else + args.add(arg); + } + if (!numParamsVaries() && getNumParams() != args.size()) + throw new InternalExpressionException("Function " + getName() + " expected " + getNumParams() + " parameters, got " + args.size()); + return args; + } } public abstract static class AbstractFunction extends AbstractLazyFunction implements IFunction @@ -88,29 +119,7 @@ public abstract class Fluff super(numParams); } - public static List unpackArgs(List lzargs, Context c) - { - List args = new ArrayList<>(); - for (LazyValue lv : lzargs) - { - Value arg = lv.evalValue(c, Context.CALLARGS); - if (arg instanceof FunctionUnpackedArgumentsValue) - { - args.addAll(((ListValue) arg).getItems()); - } - else - { - args.add(arg); - } - } - return args; - } - public void checkArgs(int candidates) - { - if (!numParamsVaries() && getNumParams() !=candidates) - throw new InternalExpressionException("Function " + getName() + " expected " + getNumParams() + " parameters, got " + candidates); - } @Override public LazyValue lazyEval(Context cc, Integer type, Expression e, Tokenizer.Token t, final List lazyParams) @@ -128,8 +137,11 @@ public abstract class Fluff private List getParams(Context c) { if (params == null) { // very likely needs to be dynamic, so not static like here, or remember if it was. - params = unpackArgs(lazyParams, c); - checkArgs(params.size()); + params = unpackArgs(lazyParams, c, Context.NONE); + } + else + { + CarpetSettings.LOG.error("How did we get here 1"); } return params; } diff --git a/src/main/java/carpet/script/api/Auxiliary.java b/src/main/java/carpet/script/api/Auxiliary.java index 9859bcb3..0db652ca 100644 --- a/src/main/java/carpet/script/api/Auxiliary.java +++ b/src/main/java/carpet/script/api/Auxiliary.java @@ -15,7 +15,6 @@ import carpet.script.CarpetScriptHost; import carpet.script.CarpetScriptServer; import carpet.script.Context; import carpet.script.Expression; -import carpet.script.LazyValue; import carpet.script.argument.BlockArgument; import carpet.script.argument.FunctionArgument; import carpet.script.argument.Vector3Argument; @@ -28,9 +27,9 @@ import carpet.script.utils.InputValidator; import carpet.script.utils.ScarpetJsonDeserializer; import carpet.script.utils.ShapeDispatcher; import carpet.script.utils.WorldTools; +import carpet.script.value.BooleanValue; import carpet.script.value.EntityValue; import carpet.script.value.FormattedTextValue; -import carpet.script.value.FunctionValue; import carpet.script.value.ListValue; import carpet.script.value.MapValue; import carpet.script.value.NBTSerializableValue; @@ -147,16 +146,15 @@ public class Auxiliary { public static void apply(Expression expression) { - expression.addLazyFunction("sound", -1, (c, t, lv) -> { + expression.addContextFunction("sound", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; if (lv.size() == 0) { - Value ret = ListValue.wrap(Registry.SOUND_EVENT.getIds().stream().map(ValueConversions::of)); - return (_c, _t) -> ret; + return ListValue.wrap(Registry.SOUND_EVENT.getIds().stream().map(ValueConversions::of)); } - String rawString = lv.get(0).evalValue(c).getString(); + String rawString = lv.get(0).getString(); Identifier soundName = new Identifier(rawString); - Vector3Argument locator = Vector3Argument.findIn(cc, lv, 1); + Vector3Argument locator = Vector3Argument.findIn(lv, 1); if (Registry.SOUND_EVENT.get(soundName) == null) throw new ThrowStatement(rawString, Throwables.UNKNOWN_SOUND); float volume = 1.0F; @@ -164,13 +162,13 @@ public class Auxiliary { SoundCategory mixer = SoundCategory.MASTER; if (lv.size() > 0+locator.offset) { - volume = (float) NumericValue.asNumber(lv.get(0+locator.offset).evalValue(c)).getDouble(); + volume = (float) NumericValue.asNumber(lv.get(0+locator.offset)).getDouble(); if (lv.size() > 1+locator.offset) { - pitch = (float) NumericValue.asNumber(lv.get(1+locator.offset).evalValue(c)).getDouble(); + pitch = (float) NumericValue.asNumber(lv.get(1+locator.offset)).getDouble(); if (lv.size() > 2+locator.offset) { - String mixerName = lv.get(2+locator.offset).evalValue(c).getString(); + String mixerName = lv.get(2+locator.offset).getString(); mixer = mixerMap.get(mixerName.toLowerCase(Locale.ROOT)); if (mixer == null) throw new InternalExpressionException(mixerName +" is not a valid mixer name"); } @@ -184,39 +182,33 @@ public class Auxiliary { count++; player.networkHandler.sendPacket(new PlaySoundIdS2CPacket(soundName, mixer, vec, volume, pitch)); } - int totalPlayed = count; - return (_c, _t) -> new NumericValue(totalPlayed); + return new NumericValue(count); }); - expression.addLazyFunction("particle", -1, (c, t, lv) -> + expression.addContextFunction("particle", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; - if (lv.size() == 0) - { - Value ret = ListValue.wrap(Registry.PARTICLE_TYPE.getIds().stream().map(ValueConversions::of)); - return (_c, _t) -> ret; - } - + if (lv.size() == 0) return ListValue.wrap(Registry.PARTICLE_TYPE.getIds().stream().map(ValueConversions::of)); MinecraftServer ms = cc.s.getMinecraftServer(); ServerWorld world = cc.s.getWorld(); - Vector3Argument locator = Vector3Argument.findIn(cc, lv, 1); - String particleName = lv.get(0).evalValue(c).getString(); + Vector3Argument locator = Vector3Argument.findIn(lv, 1); + String particleName = lv.get(0).getString(); int count = 10; double speed = 0; float spread = 0.5f; ServerPlayerEntity player = null; if (lv.size() > locator.offset) { - count = (int) NumericValue.asNumber(lv.get(locator.offset).evalValue(c)).getLong(); + count = (int) NumericValue.asNumber(lv.get(locator.offset)).getLong(); if (lv.size() > 1+locator.offset) { - spread = (float) NumericValue.asNumber(lv.get(1+locator.offset).evalValue(c)).getDouble(); + spread = (float) NumericValue.asNumber(lv.get(1+locator.offset)).getDouble(); if (lv.size() > 2+locator.offset) { - speed = NumericValue.asNumber(lv.get(2 + locator.offset).evalValue(c)).getDouble(); + speed = NumericValue.asNumber(lv.get(2 + locator.offset)).getDouble(); if (lv.size() > 3 + locator.offset) // should accept entity as well as long as it is player { - player = ms.getPlayerManager().getPlayer(lv.get(3 + locator.offset).evalValue(c).getString()); + player = ms.getPlayerManager().getPlayer(lv.get(3 + locator.offset).getString()); } } } @@ -238,29 +230,29 @@ public class Auxiliary { spread, spread, spread, speed); } - return (c_, t_) -> Value.TRUE; + return Value.TRUE; }); - expression.addLazyFunction("particle_line", -1, (c, t, lv) -> + expression.addContextFunction("particle_line", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; ServerWorld world = cc.s.getWorld(); - String particleName = lv.get(0).evalValue(c).getString(); + String particleName = lv.get(0).getString(); ParticleEffect particle = ShapeDispatcher.getParticleData(particleName); - Vector3Argument pos1 = Vector3Argument.findIn(cc, lv, 1); - Vector3Argument pos2 = Vector3Argument.findIn(cc, lv, pos1.offset); + Vector3Argument pos1 = Vector3Argument.findIn(lv, 1); + Vector3Argument pos2 = Vector3Argument.findIn(lv, pos1.offset); double density = 1.0; ServerPlayerEntity player = null; if (lv.size() > pos2.offset+0 ) { - density = NumericValue.asNumber(lv.get(pos2.offset+0).evalValue(c)).getDouble(); + density = NumericValue.asNumber(lv.get(pos2.offset+0)).getDouble(); if (density <= 0) { throw new InternalExpressionException("Particle density should be positive"); } if (lv.size() > pos2.offset+1) { - Value playerValue = lv.get(pos2.offset+1).evalValue(c); + Value playerValue = lv.get(pos2.offset+1); if (playerValue instanceof EntityValue) { Entity e = ((EntityValue) playerValue).getEntity(); @@ -274,34 +266,33 @@ public class Auxiliary { } } - Value retval = new NumericValue(ShapeDispatcher.drawParticleLine( + return new NumericValue(ShapeDispatcher.drawParticleLine( (player == null)?world.getPlayers(): Collections.singletonList(player), - particle, pos1.vec, pos2.vec, density)); - - return (c_, t_) -> retval; + particle, pos1.vec, pos2.vec, density + )); }); - expression.addLazyFunction("particle_box", -1, (c, t, lv) -> + expression.addContextFunction("particle_box", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; ServerWorld world = cc.s.getWorld(); - String particleName = lv.get(0).evalValue(c).getString(); + String particleName = lv.get(0).getString(); ParticleEffect particle = ShapeDispatcher.getParticleData(particleName); - Vector3Argument pos1 = Vector3Argument.findIn(cc, lv, 1); - Vector3Argument pos2 = Vector3Argument.findIn(cc, lv, pos1.offset); + Vector3Argument pos1 = Vector3Argument.findIn(lv, 1); + Vector3Argument pos2 = Vector3Argument.findIn(lv, pos1.offset); double density = 1.0; ServerPlayerEntity player = null; if (lv.size() > pos2.offset+0 ) { - density = NumericValue.asNumber(lv.get(pos2.offset+0).evalValue(c)).getDouble(); + density = NumericValue.asNumber(lv.get(pos2.offset+0)).getDouble(); if (density <= 0) { throw new InternalExpressionException("Particle density should be positive"); } if (lv.size() > pos2.offset+1) { - Value playerValue = lv.get(pos2.offset+1).evalValue(c); + Value playerValue = lv.get(pos2.offset+1); if (playerValue instanceof EntityValue) { Entity e = ((EntityValue) playerValue).getEntity(); @@ -322,13 +313,13 @@ public class Auxiliary { player==null?world.getPlayers():Collections.singletonList(player), particle, density, from, to ); - return (c_, t_) -> new NumericValue(particleCount); + return new NumericValue(particleCount); }); // deprecated expression.alias("particle_rect", "particle_box"); - expression.addLazyFunction("draw_shape", -1, (c, t, lv) -> + expression.addContextFunction("draw_shape", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; ServerWorld world = cc.s.getWorld(); @@ -337,7 +328,7 @@ public class Auxiliary { List>> shapes = new ArrayList<>(); if (lv.size() == 1) // bulk { - Value specLoad = lv.get(0).evalValue(c); + Value specLoad = lv.get(0); if (!(specLoad instanceof ListValue)) throw new InternalExpressionException("In bulk mode - shapes need to be provided as a list of shape specs"); for (Value list : ((ListValue) specLoad).getItems()) { @@ -347,19 +338,17 @@ public class Auxiliary { } else { - List params = new ArrayList<>(); - for (LazyValue v : lv) params.add(v.evalValue(c)); - shapes.add(ShapeDispatcher.fromFunctionArgs(server, world, params, player)); + shapes.add(ShapeDispatcher.fromFunctionArgs(server, world, lv, player)); } ShapeDispatcher.sendShape( (player[0]==null)?cc.s.getWorld().getPlayers():Collections.singletonList(player[0]), shapes ); - return LazyValue.TRUE; + return Value.TRUE; }); - expression.addLazyFunction("create_marker", -1, (c, t, lv) ->{ + expression.addContextFunction("create_marker", -1, (c, t, lv) ->{ CarpetContext cc = (CarpetContext)c; BlockState targetBlock = null; Vector3Argument pointLocator; @@ -367,16 +356,16 @@ public class Auxiliary { String name; try { - Value nameValue = lv.get(0).evalValue(c); + Value nameValue = lv.get(0); name = nameValue instanceof NullValue ? "" : nameValue.getString(); - pointLocator = Vector3Argument.findIn(cc, lv, 1, true, false); + pointLocator = Vector3Argument.findIn(lv, 1, true, false); if (lv.size()>pointLocator.offset) { BlockArgument blockLocator = BlockArgument.findIn(cc, lv, pointLocator.offset, true, true, false); if (blockLocator.block != null) targetBlock = blockLocator.block.getBlockState(); if (lv.size() > blockLocator.offset) { - interactable = lv.get(blockLocator.offset).evalValue(c, Context.BOOLEAN).getBoolean(); + interactable = lv.get(blockLocator.offset).getBoolean(); } } } @@ -429,11 +418,10 @@ public class Auxiliary { armorstand.setInvulnerable(true); armorstand.getDataTracker().set(ArmorStandEntity.ARMOR_STAND_FLAGS, (byte)(interactable?8 : 16|8)); cc.s.getWorld().spawnEntity(armorstand); - EntityValue result = new EntityValue(armorstand); - return (_c, _t) -> result; + return new EntityValue(armorstand); }); - expression.addLazyFunction("remove_all_markers", 0, (c, t, lv) -> { + expression.addContextFunction("remove_all_markers", 0, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; int total = 0; String markerName = MARKER_STRING+"_"+((cc.host.getName()==null)?"":cc.host.getName()); @@ -442,34 +430,18 @@ public class Auxiliary { total ++; e.remove(); } - int finalTotal = total; - return (_cc, _tt) -> new NumericValue(finalTotal); + return new NumericValue(total); }); - expression.addLazyFunction("nbt", 1, (c, t, lv) -> { - Value ret = NBTSerializableValue.fromValue(lv.get(0).evalValue(c)); - return (cc, tt) -> ret; - }); + expression.addUnaryFunction("nbt", NBTSerializableValue::fromValue); - expression.addLazyFunction("escape_nbt", 1, (c, t, lv) -> { - Value v = lv.get(0).evalValue(c); - String string = v.getString(); - Value ret = new StringValue(StringTag.escape(string)); - return (cc, tt) -> ret; - }); + expression.addUnaryFunction("escape_nbt", v -> new StringValue(StringTag.escape(v.getString()))); - expression.addLazyFunction("parse_nbt", 1, (c, t, lv) -> { - Value v = lv.get(0).evalValue(c); - if (v instanceof NBTSerializableValue) - { - Value parsed = ((NBTSerializableValue) v).toValue(); - return (cc, tt) -> parsed; - } + expression.addUnaryFunction("parse_nbt", v -> { + if (v instanceof NBTSerializableValue) return ((NBTSerializableValue) v).toValue(); NBTSerializableValue ret = NBTSerializableValue.parseString(v.getString(), false); - if (ret == null) - return LazyValue.NULL; - Value parsed = ret.toValue(); - return (cc, tt) -> parsed; + if (ret == null) return Value.NULL; + return ret.toValue(); }); expression.addFunction("tag_matches", (lv) -> { @@ -482,11 +454,11 @@ public class Auxiliary { return new NumericValue(NbtHelper.matches(match, source, numParam == 2 || lv.get(2).getBoolean())); }); - expression.addLazyFunction("encode_nbt", -1, (c, t, lv) -> { + expression.addFunction("encode_nbt", lv -> { int argSize = lv.size(); if (argSize==0 || argSize > 2) throw new InternalExpressionException("'encode_nbt' requires 1 or 2 parameters"); - Value v = lv.get(0).evalValue(c); - boolean force = (argSize > 1) && lv.get(1).evalValue(c).getBoolean(); + Value v = lv.get(0); + boolean force = (argSize > 1) && lv.get(1).getBoolean(); Tag tag; try { @@ -496,17 +468,16 @@ public class Auxiliary { { throw new InternalExpressionException("cannot reliably encode to a tag the value of '"+ignored.val.getPrettyString()+"'"); } - Value tagValue = new NBTSerializableValue(tag); - return (cc, tt) -> tagValue; + return new NBTSerializableValue(tag); }); //"overridden" native call that prints to stderr - expression.addLazyFunction("print", -1, (c, t, lv) -> + expression.addContextFunction("print", -1, (c, t, lv) -> { if (lv.size() == 0 || lv.size() > 2) throw new InternalExpressionException("'print' takes one or two arguments"); ServerCommandSource s = ((CarpetContext)c).s; MinecraftServer server = s.getMinecraftServer(); - Value res = lv.get(0).evalValue(c); + Value res = lv.get(0); List targets = null; if (lv.size() == 2) { @@ -518,7 +489,7 @@ public class Auxiliary { playerTargets.add(player); }); targets = playerTargets; - res = lv.get(1).evalValue(c); + res = lv.get(1); } Text message = FormattedTextValue.getTextByValue(res); if (targets == null) @@ -529,12 +500,12 @@ public class Auxiliary { { targets.forEach(p -> p.getCommandSource().sendFeedback(message, false)); } - Value finalRes = res; - return (_c, _t) -> finalRes; // pass through for variables + return res; // pass through for variables }); - expression.addLazyFunction("display_title", -1, (c, t, lv) -> { + + expression.addContextFunction("display_title", -1, (c, t, lv) -> { if (lv.size() < 2) throw new InternalExpressionException("'display_title' needs at least a target, type and message, and optionally times"); - Value pVal = lv.get(0).evalValue(c); + Value pVal = lv.get(0); if (!(pVal instanceof ListValue)) pVal = ListValue.of(pVal); MinecraftServer server = ((CarpetContext)c).s.getMinecraftServer(); Stream targets = ((ListValue) pVal).getItems().stream().map(v -> @@ -544,7 +515,7 @@ public class Auxiliary { return player; }); TitleS2CPacket.Action action; - String actionString = lv.get(1).evalValue(c).getString().toLowerCase(Locale.ROOT); + String actionString = lv.get(1).getString().toLowerCase(Locale.ROOT); switch (actionString) { case "title": @@ -572,7 +543,7 @@ public class Auxiliary { boolean soundsTrue = false; if (lv.size() > 2) { - pVal = lv.get(2).evalValue(c); + pVal = lv.get(2); title = FormattedTextValue.getTextByValue(pVal); soundsTrue = pVal.getBoolean(); } @@ -598,15 +569,15 @@ public class Auxiliary { total.getAndIncrement(); }); HUDController.update_hud(((CarpetContext)c).s.getMinecraftServer(), targetList); - Value ret = NumericValue.of(total.get()); - return (cc, tt) -> ret; + return NumericValue.of(total.get()); } TitleS2CPacket timesPacket; if (lv.size() > 3) { - int in = NumericValue.asNumber(lv.get(3).evalValue(c),"fade in for display_title" ).getInt(); - int stay = NumericValue.asNumber(lv.get(4).evalValue(c),"stay for display_title" ).getInt(); - int out = NumericValue.asNumber(lv.get(5).evalValue(c),"fade out for display_title" ).getInt(); + if (lv.size() != 6) throw new InternalExpressionException("'display_title' needs all fade-in, stay and fade-out times"); + int in = NumericValue.asNumber(lv.get(3),"fade in for display_title" ).getInt(); + int stay = NumericValue.asNumber(lv.get(4),"stay for display_title" ).getInt(); + int out = NumericValue.asNumber(lv.get(5),"fade out for display_title" ).getInt(); timesPacket = new TitleS2CPacket(Action.TIMES, null, in, stay, out); } else timesPacket = null; @@ -618,20 +589,17 @@ public class Auxiliary { p.networkHandler.sendPacket(packet); total.getAndIncrement(); }); - Value ret = NumericValue.of(total.get()); - return (cc, tt) -> ret; + return NumericValue.of(total.get()); }); - expression.addLazyFunction("format", -1, (c, t, lv) -> { - if (lv.size() == 0 ) throw new InternalExpressionException("'format' requires at least one component"); - List values = lv.stream().map(lazy -> lazy.evalValue(c)).collect(Collectors.toList()); + expression.addFunction("format", values -> { + if (values.size() == 0 ) throw new InternalExpressionException("'format' requires at least one component"); if (values.get(0) instanceof ListValue && values.size()==1) values = ((ListValue) values.get(0)).getItems(); - Value ret = new FormattedTextValue(Messenger.c(values.stream().map(Value::getString).toArray())); - return (cc, tt) -> ret; + return new FormattedTextValue(Messenger.c(values.stream().map(Value::getString).toArray())); }); - expression.addLazyFunction("run", 1, (c, t, lv) -> { + expression.addContextFunction("run", 1, (c, t, lv) -> { BlockPos target = ((CarpetContext)c).origin; Vec3d posf = new Vec3d((double)target.getX()+0.5D, target.getY(),(double)target.getZ()+0.5D); ServerCommandSource s = ((CarpetContext)c).s; @@ -641,56 +609,48 @@ public class Auxiliary { List output = new ArrayList<>(); Value retval = new NumericValue(s.getMinecraftServer().getCommandManager().execute( new SnoopyCommandSource(s, posf, error, output), - lv.get(0).evalValue(c).getString()) + lv.get(0).getString()) ); - Value ret = ListValue.of( + return ListValue.of( retval, ListValue.wrap(output.stream().map(FormattedTextValue::new).collect(Collectors.toList())), FormattedTextValue.of(error[0]) ); - return (c_, t_) -> ret; } catch (Exception exc) { - Value ret = ListValue.of(Value.NULL, ListValue.of(), new FormattedTextValue(new LiteralText(exc.getMessage()))); - return (c_, t_) -> ret; + return ListValue.of(Value.NULL, ListValue.of(), new FormattedTextValue(new LiteralText(exc.getMessage()))); } }); - expression.addLazyFunction("save", 0, (c, t, lv) -> { + expression.addContextFunction("save", 0, (c, t, lv) -> { ServerCommandSource s = ((CarpetContext)c).s; s.getMinecraftServer().getPlayerManager().saveAllPlayerData(); s.getMinecraftServer().save(true,true,true); s.getWorld().getChunkManager().tick(() -> true); CarpetSettings.LOG.warn("Saved chunks"); - return (cc, tt) -> Value.TRUE; + return Value.TRUE; }); - expression.addLazyFunction("tick_time", 0, (c, t, lv) -> - { - Value time = new NumericValue(((CarpetContext) c).s.getMinecraftServer().getTicks()); - return (cc, tt) -> time; - }); + expression.addContextFunction("tick_time", 0, (c, t, lv) -> + new NumericValue(((CarpetContext) c).s.getMinecraftServer().getTicks())); - expression.addLazyFunction("world_time", 0, (c, t, lv) -> - { - Value time = new NumericValue(((CarpetContext) c).s.getWorld().getTime()); - return (cc, tt) -> time; - }); + expression.addContextFunction("world_time", 0, (c, t, lv) -> + new NumericValue(((CarpetContext) c).s.getWorld().getTime())); - expression.addLazyFunction("day_time", -1, (c, t, lv) -> + expression.addContextFunction("day_time", -1, (c, t, lv) -> { Value time = new NumericValue(((CarpetContext) c).s.getWorld().getTimeOfDay()); if (lv.size() > 0) { - long newTime = NumericValue.asNumber(lv.get(0).evalValue(c)).getLong(); + long newTime = NumericValue.asNumber(lv.get(0)).getLong(); if (newTime < 0) newTime = 0; ((CarpetContext) c).s.getWorld().setTimeOfDay(newTime);// setTimeOfDay(newTime); } - return (cc, tt) -> time; + return time; }); - expression.addLazyFunction("last_tick_times", -1, (c, t, lv) -> + expression.addContextFunction("last_tick_times", -1, (c, t, lv) -> { //assuming we are in the tick world section // might be off one tick when run in the off tasks or asynchronously. @@ -701,12 +661,11 @@ public class Auxiliary { { ticks.add(new NumericValue(((double)tickArray[i % 100])/1000000.0)); } - Value ret = ListValue.wrap(ticks); - return (cc, tt) -> ret; + return ListValue.wrap(ticks); }); - expression.addLazyFunction("game_tick", -1, (c, t, lv) -> { + expression.addContextFunction("game_tick", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; ServerCommandSource s = cc.s; if (!s.getMinecraftServer().isOnThread()) throw new InternalExpressionException("Unable to run ticks from threads"); @@ -717,7 +676,7 @@ public class Auxiliary { ((MinecraftServerInterface) s.getMinecraftServer()).forceTick(() -> System.nanoTime() - CarpetServer.scriptServer.tickStart < 50000000L); if (lv.size() > 0) { - long ms_total = NumericValue.asNumber(lv.get(0).evalValue(c)).getLong(); + long ms_total = NumericValue.asNumber(lv.get(0)).getLong(); long end_expected = CarpetServer.scriptServer.tickStart + ms_total * 1000000L; long wait = end_expected - System.nanoTime(); if (wait > 0L) @@ -740,17 +699,16 @@ public class Auxiliary { } if(CarpetServer.scriptServer.stopAll) throw new ExitStatement(Value.NULL); - return (_c, _t) -> Value.TRUE; + return Value.TRUE; }); - expression.addLazyFunction("seed", -1, (c, t, lv) -> { + expression.addContextFunction("seed", -1, (c, t, lv) -> { ServerCommandSource s = ((CarpetContext)c).s; c.host.issueDeprecation("seed()"); - Value ret = new NumericValue(s.getWorld().getSeed()); - return (cc, tt) -> ret; + return new NumericValue(s.getWorld().getSeed()); }); - expression.addLazyFunction("relight", -1, (c, t, lv) -> + expression.addContextFunction("relight", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext) c; BlockArgument locator = BlockArgument.findIn(cc, lv, 0); @@ -758,21 +716,16 @@ public class Auxiliary { ServerWorld world = cc.s.getWorld(); ((ThreadedAnvilChunkStorageInterface) world.getChunkManager().threadedAnvilChunkStorage).relightChunk(new ChunkPos(pos)); WorldTools.forceChunkUpdate(pos, world); - return LazyValue.TRUE; + return Value.TRUE; }); - expression.addLazyFunction("current_dimension", 0, (c, t, lv) -> { - ServerCommandSource s = ((CarpetContext)c).s; - Value retval = ValueConversions.of(s.getWorld()); - return (cc, tt) -> retval; - }); + expression.addContextFunction("current_dimension", 0, (c, t, lv) -> + ValueConversions.of( ((CarpetContext)c).s.getWorld())); - expression.addLazyFunction("view_distance", 0, (c, t, lv) -> { - ServerCommandSource s = ((CarpetContext)c).s; - Value retval = new NumericValue(s.getMinecraftServer().getPlayerManager().getViewDistance()); - return (cc, tt) -> retval; - }); + expression.addContextFunction("view_distance", 0, (c, t, lv) -> + new NumericValue(((CarpetContext)c).s.getMinecraftServer().getPlayerManager().getViewDistance())); + // lazy due to passthrough and context changing ability expression.addLazyFunction("in_dimension", 2, (c, t, lv) -> { ServerCommandSource outerSource = ((CarpetContext)c).s; Value dimensionValue = lv.get(0).evalValue(c); @@ -786,7 +739,7 @@ public class Auxiliary { return (cc, tt) -> retval; }); - expression.addLazyFunction("plop", -1, (c, t, lv) ->{ + expression.addContextFunction("plop", -1, (c, t, lv) ->{ if (lv.size() == 0) { Map plopData = new HashMap<>(); @@ -807,13 +760,12 @@ public class Auxiliary { plopData.put(StringValue.of("configured_structures"), ListValue.wrap(registryManager.get(Registry.CONFIGURED_STRUCTURE_FEATURE_WORLDGEN).getIds().stream().sorted().map(ValueConversions::of).collect(Collectors.toList())) ); - Value ret = MapValue.wrap(plopData); - return (_c, _t) -> ret; + return MapValue.wrap(plopData); } BlockArgument locator = BlockArgument.findIn((CarpetContext)c, lv, 0); if (lv.size() <= locator.offset) throw new InternalExpressionException("'plop' needs extra argument indicating what to plop"); - String what = lv.get(locator.offset).evalValue(c).getString(); + String what = lv.get(locator.offset).getString(); Value [] result = new Value[]{Value.NULL}; ((CarpetContext)c).s.getMinecraftServer().submitAndJoin( () -> { @@ -825,41 +777,38 @@ public class Auxiliary { WorldTools.forceChunkUpdate(locator.block.getPos(), ((CarpetContext) c).s.getWorld()); result[0] = new NumericValue(res); }); - Value ret = result[0]; // preventing from lazy evaluating of the result in case a future completes later - return (_c, _t) -> ret; + return result[0]; }); - expression.addLazyFunction("schedule", -1, (c, t, lv) -> { + expression.addContextFunction("schedule", -1, (c, t, lv) -> { if (lv.size()<2) throw new InternalExpressionException("'schedule' should have at least 2 arguments, delay and call name"); - long delay = NumericValue.asNumber(lv.get(0).evalValue(c)).getLong(); - - FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 1, false, false); - List args = functionArgument.unpackArgs(c); + long delay = NumericValue.asNumber(lv.get(0)).getLong(); + FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 1, false, false); CarpetServer.scriptServer.events.scheduleCall( (CarpetContext) c, functionArgument.function, - args, + functionArgument.checkedArgs(), delay ); - return (c_, t_) -> Value.TRUE; + return Value.TRUE; }); - expression.addLazyFunction("logger", -1, (c, t, lv) -> + expression.addFunction("logger", lv -> { //CarpetSettings.LOG.error(Registry.ENTITY_TYPE.getIds().stream().sorted().map(ValueConversions::simplify).collect(Collectors.joining("`, `"))); Value res; if(lv.size()==1) { - res = lv.get(0).evalValue(c); + res = lv.get(0); CarpetSettings.LOG.info(res.getString()); } else if(lv.size()==2) { - String level = lv.get(0).evalValue(c).getString().toLowerCase(Locale.ROOT); - res = lv.get(1).evalValue(c); + String level = lv.get(0).getString().toLowerCase(Locale.ROOT); + res = lv.get(1); switch(level){ case "error": CarpetSettings.LOG.error(res.getString()); break; case "warn": CarpetSettings.LOG.warn(res.getString()); break; @@ -871,26 +820,25 @@ public class Auxiliary { } else throw new InternalExpressionException("logger takes 1 or 2 arguments"); - return (_c, _t) -> res; // pass through for variables + return res; // pass through for variables }); - expression.addLazyFunction("list_files", 2, (c, t, lv) -> + expression.addContextFunction("list_files", 2, (c, t, lv) -> { - FileArgument fdesc = FileArgument.from(lv, c, true, FileArgument.Reason.READ); + FileArgument fdesc = FileArgument.from(lv,true, FileArgument.Reason.READ); Stream files = ((CarpetScriptHost) c.host).listFolder(fdesc); - if (files == null) return LazyValue.NULL; - Value ret = ListValue.wrap(files.map(StringValue::of).collect(Collectors.toList())); - return (cc, tt) -> ret; + if (files == null) return Value.NULL; + return ListValue.wrap(files.map(StringValue::of).collect(Collectors.toList())); }); - expression.addLazyFunction("read_file", 2, (c, t, lv) -> + expression.addContextFunction("read_file", 2, (c, t, lv) -> { - FileArgument fdesc = FileArgument.from(lv, c, false, FileArgument.Reason.READ); + FileArgument fdesc = FileArgument.from(lv,false, FileArgument.Reason.READ); Value retVal; if (fdesc.type == FileArgument.Type.NBT) { Tag state = ((CarpetScriptHost) c.host).readFileTag(fdesc); - if (state == null) return LazyValue.NULL; + if (state == null) return Value.NULL; retVal = new NBTSerializableValue(state); } else if (fdesc.type == FileArgument.Type.JSON) @@ -906,25 +854,23 @@ public class Auxiliary { else { List content = ((CarpetScriptHost) c.host).readTextResource(fdesc); - if (content == null) return LazyValue.NULL; + if (content == null) return Value.NULL; retVal = ListValue.wrap(content.stream().map(StringValue::new).collect(Collectors.toList())); } - return (cc, tt) -> retVal; + return retVal; }); - expression.addLazyFunction("delete_file", 2, (c, t, lv) -> { - FileArgument fdesc = FileArgument.from(lv, c, false, FileArgument.Reason.DELETE); - return ((CarpetScriptHost) c.host).removeResourceFile(fdesc) ? LazyValue.TRUE : LazyValue.FALSE; - }); + expression.addContextFunction("delete_file", 2, (c, t, lv) -> + BooleanValue.of(((CarpetScriptHost) c.host).removeResourceFile(FileArgument.from(lv,false, FileArgument.Reason.DELETE)))); - expression.addLazyFunction("write_file", -1, (c, t, lv) -> { + expression.addContextFunction("write_file", -1, (c, t, lv) -> { if (lv.size() < 3) throw new InternalExpressionException("'write_file' requires three or more arguments"); - FileArgument fdesc = FileArgument.from(lv, c, false, FileArgument.Reason.CREATE); + FileArgument fdesc = FileArgument.from(lv, false, FileArgument.Reason.CREATE); boolean success; if (fdesc.type == FileArgument.Type.NBT) { - Value val = lv.get(2).evalValue(c); + Value val = lv.get(2); NBTSerializableValue tagValue = (val instanceof NBTSerializableValue) ? (NBTSerializableValue) val : new NBTSerializableValue(val.getString()); @@ -933,7 +879,7 @@ public class Auxiliary { } else if (fdesc.type == FileArgument.Type.JSON) { - List data = Collections.singletonList(GSON.toJson(lv.get(2).evalValue(c).toJson())); + List data = Collections.singletonList(GSON.toJson(lv.get(2).toJson())); ((CarpetScriptHost) c.host).removeResourceFile(fdesc); success = ((CarpetScriptHost) c.host).appendLogFile(fdesc, data); } @@ -942,7 +888,7 @@ public class Auxiliary { List data = new ArrayList<>(); if (lv.size()==3) { - Value val = lv.get(2).evalValue(c); + Value val = lv.get(2); if (val instanceof ListValue) { List lval = ((ListValue) val).getItems(); @@ -957,166 +903,144 @@ public class Auxiliary { { for(int i = 2; i < lv.size(); i++) { - data.add(lv.get(i).evalValue(c).getString()); + data.add(lv.get(i).getString()); } } success = ((CarpetScriptHost) c.host).appendLogFile(fdesc, data); } - return success?LazyValue.TRUE:LazyValue.FALSE; + return BooleanValue.of(success); }); - expression.addLazyFunction("load_app_data", -1, (c, t, lv) -> + expression.addContextFunction("load_app_data", -1, (c, t, lv) -> { FileArgument fdesc = new FileArgument(null, FileArgument.Type.NBT, null, false, false, FileArgument.Reason.READ); if (lv.size()>0) { c.host.issueDeprecation("load_app_data(...) with arguments"); - String resource = recognizeResource(lv.get(0).evalValue(c), false); - boolean shared = lv.size() > 1 && lv.get(1).evalValue(c).getBoolean(); + String resource = recognizeResource(lv.get(0), false); + boolean shared = lv.size() > 1 && lv.get(1).getBoolean(); fdesc = new FileArgument(resource, FileArgument.Type.NBT, null, false, shared, FileArgument.Reason.READ); } - Tag state = ((CarpetScriptHost) c.host).readFileTag(fdesc); - if (state == null) - return (cc, tt) -> Value.NULL; - Value retVal = new NBTSerializableValue(state); - return (cc, tt) -> retVal; + return NBTSerializableValue.of(((CarpetScriptHost) c.host).readFileTag(fdesc)); }); - expression.addLazyFunction("store_app_data", -1, (c, t, lv) -> + expression.addContextFunction("store_app_data", -1, (c, t, lv) -> { if (lv.size() == 0) throw new InternalExpressionException("'store_app_data' needs NBT tag and an optional file"); - Value val = lv.get(0).evalValue(c); + Value val = lv.get(0); FileArgument fdesc = new FileArgument(null, FileArgument.Type.NBT, null, false, false, FileArgument.Reason.CREATE); if (lv.size()>1) { c.host.issueDeprecation("store_app_data(...) with more than one argument"); - String resource = recognizeResource(lv.get(1).evalValue(c), false); - boolean shared = lv.size() > 2 && lv.get(2).evalValue(c).getBoolean(); + String resource = recognizeResource(lv.get(1), false); + boolean shared = lv.size() > 2 && lv.get(2).getBoolean(); fdesc = new FileArgument(resource, FileArgument.Type.NBT, null, false, shared, FileArgument.Reason.CREATE); } NBTSerializableValue tagValue = (val instanceof NBTSerializableValue) ? (NBTSerializableValue) val : new NBTSerializableValue(val.getString()); - Tag tag = tagValue.getTag(); - boolean success = ((CarpetScriptHost) c.host).writeTagFile(tag, fdesc); - return success?LazyValue.TRUE:LazyValue.FALSE; + return BooleanValue.of(((CarpetScriptHost) c.host).writeTagFile(tagValue.getTag(), fdesc)); }); - expression.addLazyFunction("statistic", 3, (c, t, lv) -> + expression.addContextFunction("statistic", 3, (c, t, lv) -> { - Value playerValue = lv.get(0).evalValue(c); CarpetContext cc = (CarpetContext)c; - ServerPlayerEntity player = EntityValue.getPlayerByValue(cc.s.getMinecraftServer(), playerValue); - if (player == null) return LazyValue.NULL; + ServerPlayerEntity player = EntityValue.getPlayerByValue(cc.s.getMinecraftServer(), lv.get(0)); + if (player == null) return Value.NULL; Identifier category; Identifier statName; try { - category = new Identifier(lv.get(1).evalValue(c).getString()); - statName = new Identifier(lv.get(2).evalValue(c).getString()); + category = new Identifier(lv.get(1).getString()); + statName = new Identifier(lv.get(2).getString()); } catch (InvalidIdentifierException e) { - return LazyValue.NULL; + return Value.NULL; } StatType type = Registry.STAT_TYPE.get(category); - if (type == null) - return LazyValue.NULL; + if (type == null) return Value.NULL; Stat stat = getStat(type, statName); - if (stat == null) - return LazyValue.NULL; - return (_c, _t) -> new NumericValue(player.getStatHandler().getStat(stat)); + if (stat == null) return Value.NULL; + return new NumericValue(player.getStatHandler().getStat(stat)); }); //handle_event('event', function...) - expression.addLazyFunction("handle_event", -1, (c, t, lv) -> + expression.addContextFunction("handle_event", -1, (c, t, lv) -> { if (lv.size() < 2) throw new InternalExpressionException("'handle_event' requires at least two arguments, event name, and a callback"); - String event = lv.get(0).evalValue(c).getString(); - FunctionArgument callback = FunctionArgument.findIn(c, expression.module, lv, 1, true, false); + String event = lv.get(0).getString(); + FunctionArgument callback = FunctionArgument.findIn(c, expression.module, lv, 1, true, false); CarpetScriptHost host = ((CarpetScriptHost)c.host); - Value success; if (callback.function == null) - { - success = host.getScriptServer().events.removeBuiltInEvent(event, host)?Value.TRUE:Value.FALSE; - } - else - { - success = host.getScriptServer().events.handleCustomEvent(event, host, callback.function, callback.unpackArgs(c) )?Value.TRUE:Value.FALSE; - } - return (cc, tt) -> success; + return BooleanValue.of(host.getScriptServer().events.removeBuiltInEvent(event, host)); + // args don't need to be checked will be checked at the event + return BooleanValue.of( host.getScriptServer().events.handleCustomEvent(event, host, callback.function, callback.args )); }); //signal_event('event', player or null, args.... ) -> number of apps notified - expression.addLazyFunction("signal_event", -1, (c, t, lv) -> + expression.addContextFunction("signal_event", -1, (c, t, lv) -> { if (lv.size() == 0) throw new InternalExpressionException("'signal' requires at least one argument"); CarpetContext cc = (CarpetContext)c; CarpetScriptServer server = ((CarpetScriptHost)c.host).getScriptServer(); - String eventName = lv.get(0).evalValue(c).getString(); + String eventName = lv.get(0).getString(); // no such event yet - if (CarpetEventServer.Event.getEvent(eventName, server) == null) return LazyValue.NULL; + if (CarpetEventServer.Event.getEvent(eventName, server) == null) return Value.NULL; ServerPlayerEntity player = null; List args = Collections.emptyList(); if (lv.size() > 1) { - player = EntityValue.getPlayerByValue(server.server, lv.get(1).evalValue(c)); - if (lv.size() > 2) - { - args = FunctionValue.resolveArgs(lv.subList(2, lv.size()), c, t); - } + player = EntityValue.getPlayerByValue(server.server, lv.get(1)); + if (lv.size() > 2) args = lv.subList(2, lv.size()); } int counts = ((CarpetScriptHost)c.host).getScriptServer().events.signalEvent(eventName, cc, player, args); - if (counts < 0) return LazyValue.NULL; - Value ret = new NumericValue(counts); - return (c_, t_) -> ret; + if (counts < 0) return Value.NULL; + return new NumericValue(counts); }); // nbt_storage() // nbt_storage(key) // nbt_storage(key, nbt) - expression.addLazyFunction("nbt_storage", -1, (c, t, lv) -> { + expression.addContextFunction("nbt_storage", -1, (c, t, lv) -> { if (lv.size() > 2) throw new InternalExpressionException("'nbt_storage' requires 0, 1 or 2 arguments."); CarpetContext cc = (CarpetContext) c; DataCommandStorage storage = cc.s.getMinecraftServer().getDataCommandStorage(); - if (lv.size() == 0) { - Value ret = ListValue.wrap(storage.getIds().map(i -> new StringValue(nameFromRegistryId(i))).collect(Collectors.toList())); - return (_c, _t) -> ret; - } - String key = lv.get(0).evalValue(c).getString(); + if (lv.size() == 0) + return ListValue.wrap(storage.getIds().map(i -> new StringValue(nameFromRegistryId(i))).collect(Collectors.toList())); + String key = lv.get(0).getString(); CompoundTag old_nbt = storage.get(new Identifier(key)); if (lv.size() == 2) { - Value nbt = lv.get(1).evalValue(c); + Value nbt = lv.get(1); NBTSerializableValue new_nbt = (nbt instanceof NBTSerializableValue) ? (NBTSerializableValue) nbt : NBTSerializableValue.parseString(nbt.getString(), true); storage.set(new Identifier(key), new_nbt.getCompoundTag()); } - if (old_nbt == null) return LazyValue.NULL; - return (_c, _t) -> new NBTSerializableValue(old_nbt); + return NBTSerializableValue.of(old_nbt); }); // script run create_datapack('foo', {'foo' -> {'bar.json' -> {'c' -> true,'d' -> false,'e' -> {'foo' -> [1,2,3]},'a' -> 'foobar','b' -> 5}}}) - expression.addLazyFunction("create_datapack", 2, (c, t, lv) -> { + expression.addContextFunction("create_datapack", 2, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; - String origName = lv.get(0).evalValue(c).getString(); + String origName = lv.get(0).getString(); String name = InputValidator.validateSimpleString(origName, true); MinecraftServer server = cc.s.getMinecraftServer(); for (String dpName : server.getDataPackManager().getNames()) { if (dpName.equalsIgnoreCase("file/"+name+".zip") || dpName.equalsIgnoreCase("file/"+name)) - return LazyValue.NULL; + return Value.NULL; } - Value dpdata = lv.get(1).evalValue(c); + Value dpdata = lv.get(1); if (!(dpdata instanceof MapValue)) throw new InternalExpressionException("datapack data needs to be a valid map type"); ResourcePackManager packManager = server.getDataPackManager(); Path dbFloder = server.getSavePath(WorldSavePath.DATAPACKS); Path packFloder = dbFloder.resolve(name+".zip"); - if (Files.exists(packFloder) || Files.exists(dbFloder.resolve(name))) return LazyValue.NULL; + if (Files.exists(packFloder) || Files.exists(dbFloder.resolve(name))) return Value.NULL; Boolean [] successful = new Boolean[]{true}; server.submitAndJoin( () -> { @@ -1161,10 +1085,10 @@ public class Auxiliary { } }); - return successful[0]?LazyValue.TRUE:LazyValue.FALSE; + return BooleanValue.of(successful[0]); }); - expression.addLazyFunction("enable_hidden_dimensions", 0, (c, t, lv) -> { + expression.addContextFunction("enable_hidden_dimensions", 0, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; // from minecraft.server.Main.main MinecraftServer server = cc.s.getMinecraftServer(); @@ -1184,7 +1108,7 @@ public class Auxiliary { RegistryOps registryOps = RegistryOps.of(NbtOps.INSTANCE, serverRM.getResourceManager(), (DynamicRegistryManager.Impl) server.getRegistryManager()); SaveProperties saveProperties = session.readLevelProperties(registryOps, dataPackSettings2); - if (saveProperties == null) return LazyValue.NULL; + if (saveProperties == null) return Value.NULL; //session.backupLevelDataFile(server.getRegistryManager(), saveProperties); // no need // MinecraftServer.createWorlds @@ -1209,8 +1133,7 @@ public class Auxiliary { existing_worlds.put(registryKey2, serverWorld2); } } - Value ret = ListValue.wrap(addeds); - return (_c, _t) -> ret; + return ListValue.wrap(addeds); }); } @@ -1267,8 +1190,6 @@ public class Auxiliary { } } - - private static Stat getStat(StatType type, Identifier id) { T key = type.getRegistry().get(id); diff --git a/src/main/java/carpet/script/api/BlockIterators.java b/src/main/java/carpet/script/api/BlockIterators.java index 03582021..0c4ce028 100644 --- a/src/main/java/carpet/script/api/BlockIterators.java +++ b/src/main/java/carpet/script/api/BlockIterators.java @@ -3,6 +3,7 @@ package carpet.script.api; import carpet.script.CarpetContext; import carpet.script.Context; import carpet.script.Expression; +import carpet.script.Fluff; import carpet.script.LazyValue; import carpet.script.argument.BlockArgument; import carpet.script.argument.Vector3Argument; @@ -30,11 +31,14 @@ import static java.lang.Math.min; public class BlockIterators { public static void apply(Expression expression) { - expression.addLazyFunction("scan", -1, (c, t, lv) -> + // lazy cause of lazy expression + expression.addLazyFunction("scan", -1, (c, t, llv) -> { + if (llv.size() < 3) throw new InternalExpressionException("'scan' needs many more arguments"); + List lv = Fluff.AbstractFunction.unpackLazy(llv.subList(0, llv.size()-1), c, Context.NONE); CarpetContext cc = (CarpetContext)c; BlockArgument centerLocator = BlockArgument.findIn(cc, lv, 0); - Vector3Argument rangeLocator = Vector3Argument.findIn(cc, lv, centerLocator.offset); + Vector3Argument rangeLocator = Vector3Argument.findIn(lv, centerLocator.offset); BlockPos center = centerLocator.block.getPos(); Vec3i range; @@ -54,7 +58,7 @@ public class BlockIterators { Vec3i upperRange = range; if (lv.size() > rangeLocator.offset+1) // +1 cause we still need the expression { - rangeLocator = Vector3Argument.findIn(cc, lv, rangeLocator.offset); + rangeLocator = Vector3Argument.findIn(lv, rangeLocator.offset); if (rangeLocator.fromBlock) { upperRange = new Vec3i( @@ -69,11 +73,11 @@ public class BlockIterators { upperRange = new Vec3i(abs(rangeLocator.vec.x), abs(rangeLocator.vec.y), abs(rangeLocator.vec.z)); } } - if (lv.size() != rangeLocator.offset+1) + if (llv.size() != rangeLocator.offset+1) { throw new InternalExpressionException("'scan' takes two, or three block positions, and an expression: "+lv.size()+" "+rangeLocator.offset); } - LazyValue expr = lv.get(rangeLocator.offset); + LazyValue expr = llv.get(rangeLocator.offset); int cx = center.getX(); int cy = center.getY(); @@ -135,9 +139,12 @@ public class BlockIterators { return (c_, t_) -> new NumericValue(finalSCount); }); - expression.addLazyFunction("volume", -1, (c, t, lv) -> + // must be lazy + expression.addLazyFunction("volume", -1, (c, t, llv) -> { CarpetContext cc = (CarpetContext)c; + if (llv.size() < 3) throw new InternalExpressionException("'volume' needs many more arguments"); + List lv = Fluff.AbstractFunction.unpackLazy(llv.subList(0, llv.size()-1), c, Context.NONE); BlockArgument pos1Locator = BlockArgument.findIn(cc, lv, 0); BlockArgument pos2Locator = BlockArgument.findIn(cc, lv, pos1Locator.offset); @@ -156,7 +163,7 @@ public class BlockIterators { int maxx = max(x1, x2); int maxy = max(y1, y2); int maxz = max(z1, z2); - LazyValue expr = lv.get(pos2Locator.offset); + LazyValue expr = llv.get(pos2Locator.offset); //saving outer scope LazyValue _x = c.getVariable("_x"); @@ -207,9 +214,8 @@ public class BlockIterators { return (c_, t_) -> new NumericValue(finalSCount); }); - expression.addLazyFunction("neighbours", -1, (c, t, lv)-> + expression.addContextFunction("neighbours", -1, (c, t, lv)-> { - BlockPos center = BlockArgument.findIn((CarpetContext) c, lv,0).block.getPos(); ServerWorld world = ((CarpetContext) c).s.getWorld(); @@ -220,11 +226,10 @@ public class BlockIterators { neighbours.add(new BlockValue(null, world, center.south())); neighbours.add(new BlockValue(null, world, center.east())); neighbours.add(new BlockValue(null, world, center.west())); - Value retval = ListValue.wrap(neighbours); - return (c_, t_) -> retval; + return ListValue.wrap(neighbours); }); - expression.addLazyFunction("rect", -1, (c, t, lv)-> + expression.addContextFunction("rect", -1, (c, t, lv)-> { CarpetContext cc = (CarpetContext) c; int cx, cy, cz; @@ -237,7 +242,7 @@ public class BlockIterators { cz = cpos.getZ(); if (lv.size() > cposLocator.offset) { - Vector3Argument diffLocator = Vector3Argument.findIn(cc, lv, cposLocator.offset); + Vector3Argument diffLocator = Vector3Argument.findIn(lv, cposLocator.offset); if (diffLocator.fromBlock) { sminx = MathHelper.floor(abs(diffLocator.vec.x - cx)); @@ -252,7 +257,7 @@ public class BlockIterators { } if (lv.size() > diffLocator.offset) { - Vector3Argument posDiff = Vector3Argument.findIn(cc, lv, diffLocator.offset); + Vector3Argument posDiff = Vector3Argument.findIn(lv, diffLocator.offset); if (posDiff.fromBlock) { smaxx = MathHelper.floor(abs(posDiff.vec.x - cx)); @@ -283,7 +288,7 @@ public class BlockIterators { smaxz = 1; } - return (c_, t_) -> new LazyListValue() + return new LazyListValue() { final int minx = cx-sminx; final int miny = cy-sminy; @@ -348,7 +353,7 @@ public class BlockIterators { }; }); - expression.addLazyFunction("diamond", -1, (c, t, lv)-> + expression.addContextFunction("diamond", -1, (c, t, lv)-> { CarpetContext cc = (CarpetContext)c; @@ -377,17 +382,17 @@ public class BlockIterators { BlockValue.fromCoords(cc, cx, cy, cz+1), BlockValue.fromCoords(cc, cx, cy+1, cz) ); - return (_c, _t ) -> retval; + return retval; } else if (lv.size()==1+cposLocator.offset) { - width = (int) ((NumericValue) lv.get(cposLocator.offset).evalValue(c)).getLong(); + width = (int) ((NumericValue) lv.get(cposLocator.offset)).getLong(); height = 0; } else if(lv.size()==2+cposLocator.offset) { - width = (int) ((NumericValue) lv.get(cposLocator.offset).evalValue(c)).getLong(); - height = (int) ((NumericValue) lv.get(cposLocator.offset+1).evalValue(c)).getLong(); + width = (int) ((NumericValue) lv.get(cposLocator.offset)).getLong(); + height = (int) ((NumericValue) lv.get(cposLocator.offset+1)).getLong(); } else{ throw new InternalExpressionException("Incorrect number of arguments for 'diamond'"); } @@ -398,7 +403,7 @@ public class BlockIterators { } if (height == 0) { - return (c_, t_) -> new LazyListValue() + return new LazyListValue() { int curradius; int curpos; @@ -448,7 +453,7 @@ public class BlockIterators { } else { - return (c_, t_) -> new LazyListValue() + return new LazyListValue() { int curradius; int curpos; diff --git a/src/main/java/carpet/script/api/Entities.java b/src/main/java/carpet/script/api/Entities.java index ce2cd3b5..138ac844 100644 --- a/src/main/java/carpet/script/api/Entities.java +++ b/src/main/java/carpet/script/api/Entities.java @@ -4,12 +4,10 @@ import carpet.script.CarpetContext; import carpet.script.CarpetEventServer; import carpet.script.CarpetScriptHost; import carpet.script.Expression; -import carpet.script.LazyValue; import carpet.script.argument.FunctionArgument; import carpet.script.argument.Vector3Argument; import carpet.script.exception.InternalExpressionException; import carpet.script.value.EntityValue; -import carpet.script.value.FunctionValue; import carpet.script.value.ListValue; import carpet.script.value.NBTSerializableValue; import carpet.script.value.NumericValue; @@ -43,7 +41,7 @@ import java.util.stream.Collectors; public class Entities { public static void apply(Expression expression) { - expression.addLazyFunction("player", -1, (c, t, lv) -> + expression.addContextFunction("player", -1, (c, t, lv) -> { if (lv.size() == 0) { @@ -51,26 +49,15 @@ public class Entities { if (cc.host.user != null) { ServerPlayerEntity player = cc.s.getMinecraftServer().getPlayerManager().getPlayer(cc.host.user); - if (player == null) return LazyValue.NULL; - Value ret = new EntityValue(player); - return (_c, _t) -> ret; + return EntityValue.of(player); } Entity callingEntity = cc.s.getEntity(); - if (callingEntity instanceof PlayerEntity) - { - Value retval = new EntityValue(callingEntity); - return (_c, _t) -> retval; - } + if (callingEntity instanceof PlayerEntity) return EntityValue.of(callingEntity); Vec3d pos = ((CarpetContext)c).s.getPosition(); PlayerEntity closestPlayer = ((CarpetContext)c).s.getWorld().getClosestPlayer(pos.x, pos.y, pos.z, -1.0, EntityPredicates.VALID_ENTITY); - if (closestPlayer != null) - { - Value retval = new EntityValue(closestPlayer); - return (_c, _t) -> retval; - } - return (_c, _t) -> Value.NULL; + return EntityValue.of(closestPlayer); } - String playerName = lv.get(0).evalValue(c).getString(); + String playerName = lv.get(0).getString(); Value retval = Value.NULL; if ("all".equalsIgnoreCase(playerName)) { @@ -114,37 +101,36 @@ public class Entities { if (player != null) retval = new EntityValue(player); } - Value finalVar = retval; - return (_c, _t) -> finalVar; + return retval; }); - expression.addLazyFunction("spawn", -1, (c, t, lv) -> + expression.addContextFunction("spawn", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; if (lv.size() < 2) throw new InternalExpressionException("'spawn' function takes mob name, and position to spawn"); - String entityString = lv.get(0).evalValue(c).getString(); + String entityString = lv.get(0).getString(); Identifier entityId; try { entityId = Identifier.fromCommandInput(new StringReader(entityString)); EntityType type = Registry.ENTITY_TYPE.getOrEmpty(entityId).orElse(null); if (type == null || !type.isSummonable()) - return LazyValue.NULL; + return Value.NULL; } catch (CommandSyntaxException exception) { - return LazyValue.NULL; + return Value.NULL; } - Vector3Argument position = Vector3Argument.findIn(cc, lv, 1); + Vector3Argument position = Vector3Argument.findIn(lv, 1); if (position.fromBlock) position.vec = position.vec.subtract(0, 0.5, 0); CompoundTag tag = new CompoundTag(); boolean hasTag = false; if (lv.size() > position.offset) { - Value nbt = lv.get(position.offset).evalValue(c); + Value nbt = lv.get(position.offset); NBTSerializableValue v = (nbt instanceof NBTSerializableValue) ? (NBTSerializableValue) nbt : NBTSerializableValue.parseString(nbt.getString(), true); hasTag = true; @@ -160,51 +146,38 @@ public class Entities { return !serverWorld.tryLoadEntity(entity_1x) ? null : entity_1x; }); if (entity_1 == null) { - return LazyValue.NULL; + return Value.NULL; } else { if (!hasTag && entity_1 instanceof MobEntity) { ((MobEntity)entity_1).initialize(serverWorld, serverWorld.getLocalDifficulty(entity_1.getBlockPos()), SpawnReason.COMMAND, null, null); } - Value res = new EntityValue(entity_1); - return (_c, _t) -> res; + return new EntityValue(entity_1); } }); - expression.addLazyFunction("entity_id", 1, (c, t, lv) -> + expression.addContextFunction("entity_id", 1, (c, t, lv) -> { - Value who = lv.get(0).evalValue(c); - Entity e; + Value who = lv.get(0); if (who instanceof NumericValue) - { - e = ((CarpetContext)c).s.getWorld().getEntityById((int)((NumericValue) who).getLong()); - } - else - { - e = ((CarpetContext)c).s.getWorld().getEntity(UUID.fromString(who.getString())); - } - if (e==null) - { - return LazyValue.NULL; - } - return (cc, tt) -> new EntityValue(e); + return EntityValue.of(((CarpetContext)c).s.getWorld().getEntityById((int)((NumericValue) who).getLong())); + return EntityValue.of(((CarpetContext)c).s.getWorld().getEntity(UUID.fromString(who.getString()))); }); - expression.addLazyFunction("entity_list", 1, (c, t, lv) -> + expression.addContextFunction("entity_list", 1, (c, t, lv) -> { - String who = lv.get(0).evalValue(c).getString(); + String who = lv.get(0).getString(); ServerCommandSource source = ((CarpetContext)c).s; EntityValue.EntityClassDescriptor eDesc = EntityValue.getEntityDescriptor(who, source.getMinecraftServer()); List entityList = source.getWorld().getEntitiesByType(eDesc.directType, eDesc.filteringPredicate); - Value retval = ListValue.wrap(entityList.stream().map(EntityValue::new).collect(Collectors.toList())); - return (_c, _t ) -> retval; + return ListValue.wrap(entityList.stream().map(EntityValue::new).collect(Collectors.toList())); }); - expression.addLazyFunction("entity_area", -1, (c, t, lv) -> + expression.addContextFunction("entity_area", -1, (c, t, lv) -> { if (lv.size()<3) throw new InternalExpressionException("'entity_area' requires entity type, center and range arguments"); - String who = lv.get(0).evalValue(c).getString(); + String who = lv.get(0).getString(); CarpetContext cc = (CarpetContext)c; - Vector3Argument centerLocator = Vector3Argument.findIn(cc, lv, 1, false, true); + Vector3Argument centerLocator = Vector3Argument.findIn(lv, 1, false, true); Box centerBox; if (centerLocator.entity != null) @@ -217,90 +190,87 @@ public class Entities { if (centerLocator.fromBlock) center.add(0.5, 0.5, 0.5); centerBox = new Box(center, center); } - Vector3Argument rangeLocator = Vector3Argument.findIn(cc, lv, centerLocator.offset); + Vector3Argument rangeLocator = Vector3Argument.findIn(lv, centerLocator.offset); if (rangeLocator.fromBlock) throw new InternalExpressionException("Range of 'entity_area' cannot come from a block argument"); Vec3d range = rangeLocator.vec; Box area = centerBox.expand(range.x, range.y, range.z); EntityValue.EntityClassDescriptor eDesc = EntityValue.getEntityDescriptor(who, cc.s.getMinecraftServer()); List entityList = cc.s.getWorld().getEntitiesByType(eDesc.directType, area,eDesc.filteringPredicate); - Value retval = ListValue.wrap(entityList.stream().map(EntityValue::new).collect(Collectors.toList())); - return (_c, _t ) -> retval; + return ListValue.wrap(entityList.stream().map(EntityValue::new).collect(Collectors.toList())); }); - expression.addLazyFunction("entity_selector", -1, (c, t, lv) -> + expression.addContextFunction("entity_selector", -1, (c, t, lv) -> { - String selector = lv.get(0).evalValue(c).getString(); + String selector = lv.get(0).getString(); List retlist = new ArrayList<>(); for (Entity e: EntityValue.getEntitiesFromSelector(((CarpetContext)c).s, selector)) { retlist.add(new EntityValue(e)); } - return (c_, t_) -> ListValue.wrap(retlist); + return ListValue.wrap(retlist); }); - expression.addLazyFunction("query", -1, (c, t, lv) -> + expression.addContextFunction("query", -1, (c, t, lv) -> { if (lv.size()<2) { throw new InternalExpressionException("'query' takes entity as a first argument, and queried feature as a second"); } - Value v = lv.get(0).evalValue(c); + Value v = lv.get(0); if (!(v instanceof EntityValue)) throw new InternalExpressionException("First argument to query should be an entity"); - String what = lv.get(1).evalValue(c).getString().toLowerCase(Locale.ROOT); + String what = lv.get(1).getString().toLowerCase(Locale.ROOT); if (what.equals("tags")) c.host.issueDeprecation("'tags' for entity querying"); Value retval; if (lv.size()==2) retval = ((EntityValue) v).get(what, null); else if (lv.size()==3) - retval = ((EntityValue) v).get(what, lv.get(2).evalValue(c)); + retval = ((EntityValue) v).get(what, lv.get(2)); else - retval = ((EntityValue) v).get(what, ListValue.wrap(lv.subList(2, lv.size()).stream().map((vv) -> vv.evalValue(c)).collect(Collectors.toList()))); - return (cc, tt) -> retval; + retval = ((EntityValue) v).get(what, ListValue.wrap(lv.subList(2, lv.size()))); + return retval; }); // or update - expression.addLazyFunction("modify", -1, (c, t, lv) -> + expression.addContextFunction("modify", -1, (c, t, lv) -> { if (lv.size()<2) { throw new InternalExpressionException("'modify' takes entity as a first argument, and queried feature as a second"); } - Value v = lv.get(0).evalValue(c); + Value v = lv.get(0); if (!(v instanceof EntityValue)) throw new InternalExpressionException("First argument to modify should be an entity"); - String what = lv.get(1).evalValue(c).getString(); + String what = lv.get(1).getString(); if (lv.size()==2) ((EntityValue) v).set(what, null); else if (lv.size()==3) - ((EntityValue) v).set(what, lv.get(2).evalValue(c)); + ((EntityValue) v).set(what, lv.get(2)); else - ((EntityValue) v).set(what, ListValue.wrap(lv.subList(2, lv.size()).stream().map((vv) -> vv.evalValue(c)).collect(Collectors.toList()))); - return (cc, tt) -> v; + ((EntityValue) v).set(what, ListValue.wrap(lv.subList(2, lv.size()))); + return v; }); - expression.addLazyFunction("entity_types", -1, (c, t, lv) -> + expression.addContextFunction("entity_types", -1, (c, t, lv) -> { - if (lv.size() > 1) throw new InternalExpressionException("'entity_types' requires one or no arguments"); - String desc = (lv.size() == 1)?lv.get(0).evalValue(c).getString():"*"; - Value ret = EntityValue.getEntityDescriptor(desc, ((CarpetContext) c).s.getMinecraftServer()).listValue; - return (_c, _t) -> ret; + String desc = (lv.size() == 1)?lv.get(0).getString():"*"; + return EntityValue.getEntityDescriptor(desc, ((CarpetContext) c).s.getMinecraftServer()).listValue; }); - expression.addLazyFunction("entity_load_handler", -1, (c, t, lv) -> + expression.addContextFunction("entity_load_handler", -1, (c, t, lv) -> { if (c.host.isPerUser()) throw new InternalExpressionException("'entity_load_handler' can only be called in apps with global scope"); if (lv.size() < 2) throw new InternalExpressionException("'entity_load_handler' required the entity type, and a function to call"); - Value entityValue = lv.get(0).evalValue(c); + Value entityValue = lv.get(0); List descriptors = (entityValue instanceof ListValue) ? ((ListValue) entityValue).getItems().stream().map(Value::getString).collect(Collectors.toList()) : Collections.singletonList(entityValue.getString()); Set> types = new HashSet<>(); descriptors.forEach(s -> types.addAll(EntityValue.getEntityDescriptor(s, ((CarpetContext) c).s.getMinecraftServer()).typeList)); - FunctionArgument funArg = FunctionArgument.findIn(c, expression.module, lv, 1, true, false); + FunctionArgument funArg = FunctionArgument.findIn(c, expression.module, lv, 1, true, false); CarpetEventServer events = ((CarpetScriptHost)c.host).getScriptServer().events; if (funArg.function == null) { @@ -308,27 +278,26 @@ public class Entities { } else { - types.forEach(et -> events.addBuiltInEvent(CarpetEventServer.Event.getEntityLoadEventName(et), c.host, funArg.function, funArg.unpackArgs(c))); + types.forEach(et -> events.addBuiltInEvent(CarpetEventServer.Event.getEntityLoadEventName(et), c.host, funArg.function, funArg.args)); } - Value ret = new NumericValue(types.size()); - return (cc, tt) -> ret; + return new NumericValue(types.size()); }); // or update - expression.addLazyFunction("entity_event", -1, (c, t, lv) -> + expression.addContextFunction("entity_event", -1, (c, t, lv) -> { if (lv.size()<3) throw new InternalExpressionException("'entity_event' requires at least 3 arguments, entity, event to be handled, and function name, with optional arguments"); - Value v = lv.get(0).evalValue(c); + Value v = lv.get(0); if (!(v instanceof EntityValue)) throw new InternalExpressionException("First argument to entity_event should be an entity"); - String what = lv.get(1).evalValue(c).getString(); + String what = lv.get(1).getString(); - FunctionArgument funArg = FunctionArgument.findIn(c, expression.module, lv, 2, true, false); + FunctionArgument funArg = FunctionArgument.findIn(c, expression.module, lv, 2, true, false); - ((EntityValue) v).setEvent((CarpetContext)c, what, funArg.function, funArg.unpackArgs(c)); + ((EntityValue) v).setEvent((CarpetContext)c, what, funArg.function, funArg.args); - return LazyValue.NULL; + return Value.NULL; }); } } diff --git a/src/main/java/carpet/script/api/Inventories.java b/src/main/java/carpet/script/api/Inventories.java index 96dd35e1..a1a9af91 100644 --- a/src/main/java/carpet/script/api/Inventories.java +++ b/src/main/java/carpet/script/api/Inventories.java @@ -4,10 +4,10 @@ import carpet.fakes.IngredientInterface; import carpet.fakes.RecipeManagerInterface; import carpet.script.CarpetContext; import carpet.script.Expression; -import carpet.script.LazyValue; import carpet.script.exception.InternalExpressionException; import carpet.script.exception.ThrowStatement; import carpet.script.exception.Throwables; +import carpet.script.value.BooleanValue; import carpet.script.value.ListValue; import carpet.script.value.NBTSerializableValue; import carpet.script.value.NullValue; @@ -49,68 +49,52 @@ import java.util.stream.Collectors; public class Inventories { public static void apply(Expression expression) { - expression.addLazyFunction("stack_limit", 1, (c, t, lv) -> - { - ItemStackArgument item = NBTSerializableValue.parseItem(lv.get(0).evalValue(c).getString()); - Value res = new NumericValue(item.getItem().getMaxCount()); - return (_c, _t) -> res; - }); + expression.addUnaryFunction("stack_limit", v -> + new NumericValue(NBTSerializableValue.parseItem(v.getString()).getItem().getMaxCount())); - expression.addLazyFunction("item_category", 1, (c, t, lv) -> + expression.addUnaryFunction("item_category", v -> { - ItemStackArgument item = NBTSerializableValue.parseItem(lv.get(0).evalValue(c).getString()); - + ItemStackArgument item = NBTSerializableValue.parseItem(v.getString()); ItemGroup ig = item.getItem().getGroup(); - Value res = (ig==null)?Value.NULL:new StringValue(ig.getName()); - return (_c, _t) -> res; + return (ig==null)?Value.NULL:new StringValue(ig.getName()); }); - expression.addLazyFunction("item_list", -1, (c, t, lv) -> + expression.addContextFunction("item_list", -1, (c, t, lv) -> { if (lv.size() == 0) - { - Value res = ListValue.wrap(Registry.ITEM.getIds().stream().map(ValueConversions::of).collect(Collectors.toList())); - return (cc, tt) -> res; - } + return ListValue.wrap(Registry.ITEM.getIds().stream().map(ValueConversions::of).collect(Collectors.toList())); CarpetContext cc = (CarpetContext)c; TagManager tagManager = cc.s.getMinecraftServer().getTagManager(); - String tag = lv.get(0).evalValue(c).getString(); + String tag = lv.get(0).getString(); net.minecraft.tag.Tag itemTag = tagManager.getItems().getTag(new Identifier(tag)); - if (itemTag == null) return LazyValue.NULL; - Value ret = ListValue.wrap(itemTag.values().stream().map(b -> ValueConversions.of(Registry.ITEM.getId(b))).collect(Collectors.toList())); - return (_c, _t) -> ret; + if (itemTag == null) return Value.NULL; + return ListValue.wrap(itemTag.values().stream().map(b -> ValueConversions.of(Registry.ITEM.getId(b))).collect(Collectors.toList())); }); - expression.addLazyFunction("item_tags", -1, (c, t, lv) -> + expression.addContextFunction("item_tags", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; TagManager tagManager = cc.s.getMinecraftServer().getTagManager(); if (lv.size() == 0) - { - Value ret = ListValue.wrap(tagManager.getItems().getTagIds().stream().map(ValueConversions::of).collect(Collectors.toList())); - return (_c, _t) -> ret; - } - Item item = NBTSerializableValue.parseItem(lv.get(0).evalValue(c).getString()).getItem(); + return ListValue.wrap(tagManager.getItems().getTagIds().stream().map(ValueConversions::of).collect(Collectors.toList())); + Item item = NBTSerializableValue.parseItem(lv.get(0).getString()).getItem(); if (lv.size() == 1) - { - Value ret = ListValue.wrap(tagManager.getItems().getTags().entrySet().stream().filter(e -> e.getValue().contains(item)).map(e -> ValueConversions.of(e.getKey())).collect(Collectors.toList())); - return (_c, _t) -> ret; - } - String tag = lv.get(1).evalValue(c).getString(); + return ListValue.wrap(tagManager.getItems().getTags().entrySet().stream().filter(e -> e.getValue().contains(item)).map(e -> ValueConversions.of(e.getKey())).collect(Collectors.toList())); + String tag = lv.get(1).getString(); net.minecraft.tag.Tag itemTag = tagManager.getItems().getTag(new Identifier(tag)); - if (itemTag == null) return LazyValue.NULL; - return item.isIn(itemTag)?LazyValue.TRUE:LazyValue.FALSE; + if (itemTag == null) return Value.NULL; + return BooleanValue.of(item.isIn(itemTag)); }); - expression.addLazyFunction("recipe_data", -1, (c, t, lv) -> + expression.addContextFunction("recipe_data", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; if (lv.size() < 1) throw new InternalExpressionException("'recipe_data' requires at least one argument"); - String recipeName = lv.get(0).evalValue(c).getString(); + String recipeName = lv.get(0).getString(); RecipeType type = RecipeType.CRAFTING; if (lv.size() > 1) { - String recipeType = lv.get(1).evalValue(c).getString(); + String recipeType = lv.get(1).getString(); try { type = Registry.RECIPE_TYPE.get(new Identifier(recipeType)); @@ -123,7 +107,7 @@ public class Inventories { List> recipes; recipes = ((RecipeManagerInterface) cc.s.getMinecraftServer().getRecipeManager()).getAllMatching(type, new Identifier(recipeName)); if (recipes.isEmpty()) - return LazyValue.NULL; + return Value.NULL; List recipesOutput = new ArrayList<>(); for (Recipe recipe: recipes) { @@ -143,7 +127,7 @@ public class Inventories { else { List alternatives = new ArrayList<>(); - stacks.forEach(col -> col.stream().map(ListValue::fromItemStack).forEach(alternatives::add)); + stacks.forEach(col -> col.stream().map(ValueConversions::of).forEach(alternatives::add)); ingredientValue.add(ListValue.wrap(alternatives)); } } @@ -182,91 +166,75 @@ public class Inventories { recipeSpec = ListValue.of(new StringValue("custom")); } - recipesOutput.add(ListValue.of(ListValue.fromItemStack(result), ListValue.wrap(ingredientValue), recipeSpec)); + recipesOutput.add(ListValue.of(ValueConversions.of(result), ListValue.wrap(ingredientValue), recipeSpec)); } - Value ret = ListValue.wrap(recipesOutput); - return (_c, _t) -> ret; + return ListValue.wrap(recipesOutput); }); - expression.addLazyFunction("crafting_remaining_item", 1, (c, t, lv) -> + expression.addUnaryFunction("crafting_remaining_item", v -> { - String itemStr = lv.get(0).evalValue(c).getString(); + String itemStr = v.getString(); Item item; Identifier id = new Identifier(itemStr); item = Registry.ITEM.getOrEmpty(id).orElseThrow(() -> new ThrowStatement(itemStr, Throwables.UNKNOWN_ITEM)); - - if (!item.hasRecipeRemainder()) return LazyValue.NULL; - Value ret = new StringValue(NBTSerializableValue.nameFromRegistryId(Registry.ITEM.getId(item.getRecipeRemainder()))); - return (_c, _t ) -> ret; + if (!item.hasRecipeRemainder()) return Value.NULL; + return new StringValue(NBTSerializableValue.nameFromRegistryId(Registry.ITEM.getId(item.getRecipeRemainder()))); }); - - expression.addLazyFunction("inventory_size", -1, (c, t, lv) -> + expression.addContextFunction("inventory_size", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext) c; NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0); - if (inventoryLocator == null) - return (_c, _t) -> Value.NULL; - Value res = new NumericValue(inventoryLocator.inventory.size()); - return (_c, _t) -> res; + if (inventoryLocator == null) return Value.NULL; + return new NumericValue(inventoryLocator.inventory.size()); }); - expression.addLazyFunction("inventory_has_items", -1, (c, t, lv) -> + expression.addContextFunction("inventory_has_items", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext) c; NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0); - if (inventoryLocator == null) - return (_c, _t) -> Value.NULL; - Value res = new NumericValue(!inventoryLocator.inventory.isEmpty()); - return (_c, _t) -> res; + if (inventoryLocator == null) return Value.NULL; + return new NumericValue(!inventoryLocator.inventory.isEmpty()); }); //inventory_get(, ) -> item_triple - expression.addLazyFunction("inventory_get", -1, (c, t, lv) -> + expression.addContextFunction("inventory_get", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext) c; NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0); - if (inventoryLocator == null) - return (_c, _t) -> Value.NULL; + if (inventoryLocator == null) return Value.NULL; if (lv.size() == inventoryLocator.offset) { List fullInventory = new ArrayList<>(); for (int i = 0, maxi = inventoryLocator.inventory.size(); i < maxi; i++) - { - fullInventory.add(ListValue.fromItemStack(inventoryLocator.inventory.getStack(i))); - } - Value res = ListValue.wrap(fullInventory); - return (_c, _t) -> res; + fullInventory.add(ValueConversions.of(inventoryLocator.inventory.getStack(i))); + return ListValue.wrap(fullInventory); } - int slot = (int)NumericValue.asNumber(lv.get(inventoryLocator.offset).evalValue(c)).getLong(); + int slot = (int)NumericValue.asNumber(lv.get(inventoryLocator.offset)).getLong(); slot = NBTSerializableValue.validateSlot(slot, inventoryLocator.inventory); - if (slot == inventoryLocator.inventory.size()) - return (_c, _t) -> Value.NULL; - Value res = ListValue.fromItemStack(inventoryLocator.inventory.getStack(slot)); - return (_c, _t) -> res; + if (slot == inventoryLocator.inventory.size()) return Value.NULL; + return ValueConversions.of(inventoryLocator.inventory.getStack(slot)); }); //inventory_set(, , , , ) - expression.addLazyFunction("inventory_set", -1, (c, t, lv) -> + expression.addContextFunction("inventory_set", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext) c; NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0); - if (inventoryLocator == null) - return (_c, _t) -> Value.NULL; + if (inventoryLocator == null) return Value.NULL; if (lv.size() < inventoryLocator.offset+2) throw new InternalExpressionException("'inventory_set' requires at least slot number and new stack size, and optional new item"); - int slot = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset+0).evalValue(c)).getLong(); + int slot = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset+0)).getLong(); slot = NBTSerializableValue.validateSlot(slot, inventoryLocator.inventory); - if (slot == inventoryLocator.inventory.size()) - return (_c, _t) -> Value.NULL; - int count = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset+1).evalValue(c)).getLong(); + if (slot == inventoryLocator.inventory.size()) return Value.NULL; + int count = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset+1)).getLong(); if (count == 0) { // clear slot ItemStack removedStack = inventoryLocator.inventory.removeStack(slot); syncPlayerInventory(inventoryLocator, slot); //Value res = ListValue.fromItemStack(removedStack); // that tuple will be read only but cheaper if noone cares - return (_c, _t) -> ListValue.fromItemStack(removedStack); + return ValueConversions.of(removedStack); } if (lv.size() < inventoryLocator.offset+3) { @@ -275,12 +243,12 @@ public class Inventories { newStack.setCount(count); inventoryLocator.inventory.setStack(slot, newStack); syncPlayerInventory(inventoryLocator, slot); - return (_c, _t) -> ListValue.fromItemStack(previousStack); + return ValueConversions.of(previousStack); } CompoundTag nbt = null; // skipping one argument if (lv.size() > inventoryLocator.offset+3) { - Value nbtValue = lv.get(inventoryLocator.offset+3).evalValue(c); + Value nbtValue = lv.get(inventoryLocator.offset+3); if (nbtValue instanceof NBTSerializableValue) nbt = ((NBTSerializableValue)nbtValue).getCompoundTag(); else if (nbtValue instanceof NullValue) @@ -288,11 +256,7 @@ public class Inventories { else nbt = new NBTSerializableValue(nbtValue.getString()).getCompoundTag(); } - ItemStackArgument newitem = NBTSerializableValue.parseItem( - lv.get(inventoryLocator.offset+2).evalValue(c).getString(), - nbt - ); - + ItemStackArgument newitem = NBTSerializableValue.parseItem(lv.get(inventoryLocator.offset+2).getString(), nbt); ItemStack previousStack = inventoryLocator.inventory.getStack(slot); try { @@ -303,62 +267,52 @@ public class Inventories { { throw new InternalExpressionException(e.getMessage()); } - return (_c, _t) -> ListValue.fromItemStack(previousStack); + return ValueConversions.of(previousStack); }); //inventory_find(, or null (first empty slot), ) -> or null - expression.addLazyFunction("inventory_find", -1, (c, t, lv) -> + expression.addContextFunction("inventory_find", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext) c; NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0); - if (inventoryLocator == null) - return (_c, _t) -> Value.NULL; + if (inventoryLocator == null) return Value.NULL; ItemStackArgument itemArg = null; if (lv.size() > inventoryLocator.offset) { - Value secondArg = lv.get(inventoryLocator.offset+0).evalValue(c); + Value secondArg = lv.get(inventoryLocator.offset+0); if (!(secondArg instanceof NullValue)) itemArg = NBTSerializableValue.parseItem(secondArg.getString()); } int startIndex = 0; if (lv.size() > inventoryLocator.offset+1) { - startIndex = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset+1).evalValue(c)).getLong(); + startIndex = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset+1)).getLong(); } startIndex = NBTSerializableValue.validateSlot(startIndex, inventoryLocator.inventory); for (int i = startIndex, maxi = inventoryLocator.inventory.size(); i < maxi; i++) { ItemStack stack = inventoryLocator.inventory.getStack(i); if ( (itemArg == null && stack.isEmpty()) || (itemArg != null && itemArg.getItem().equals(stack.getItem())) ) - { - Value res = new NumericValue(i); - return (_c, _t) -> res; - } + return new NumericValue(i); } - return (_c, _t) -> Value.NULL; + return Value.NULL; }); //inventory_remove(, , ) -> bool - expression.addLazyFunction("inventory_remove", -1, (c, t, lv) -> + expression.addContextFunction("inventory_remove", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext) c; NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0); - if (inventoryLocator == null) - return (_c, _t) -> Value.NULL; + if (inventoryLocator == null) return Value.NULL; if (lv.size() <= inventoryLocator.offset) throw new InternalExpressionException("'inventory_remove' requires at least an item to be removed"); - ItemStackArgument searchItem = NBTSerializableValue.parseItem(lv.get(inventoryLocator.offset).evalValue(c).getString()); + ItemStackArgument searchItem = NBTSerializableValue.parseItem(lv.get(inventoryLocator.offset).getString()); int amount = 1; if (lv.size() > inventoryLocator.offset+1) - { - amount = (int)NumericValue.asNumber(lv.get(inventoryLocator.offset+1).evalValue(c)).getLong(); - } + amount = (int)NumericValue.asNumber(lv.get(inventoryLocator.offset+1)).getLong(); // not enough if (((amount == 1) && (!inventoryLocator.inventory.containsAny(Sets.newHashSet(searchItem.getItem())))) - || (inventoryLocator.inventory.count(searchItem.getItem()) < amount)) - { - return (_c, _t) -> Value.FALSE; - } + || (inventoryLocator.inventory.count(searchItem.getItem()) < amount)) return Value.FALSE; for (int i = 0, maxi = inventoryLocator.inventory.size(); i < maxi; i++) { ItemStack stack = inventoryLocator.inventory.getStack(i); @@ -372,7 +326,7 @@ public class Inventories { stack.setCount(left); inventoryLocator.inventory.setStack(i, stack); syncPlayerInventory(inventoryLocator, i); - return (_c, _t) -> Value.TRUE; + return Value.TRUE; } else { @@ -383,37 +337,30 @@ public class Inventories { } if (amount > 0) throw new InternalExpressionException("Something bad happened - cannot pull all items from inventory"); - return (_c, _t) -> Value.TRUE; + return Value.TRUE; }); //inventory_drop(, , ) -> entity_item (and sets slot) or null if cannot - expression.addLazyFunction("drop_item", -1, (c, t, lv) -> + expression.addContextFunction("drop_item", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext) c; NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0); - if (inventoryLocator == null) - return (_c, _t) -> Value.NULL; + if (inventoryLocator == null) return Value.NULL; if (lv.size() == inventoryLocator.offset) throw new InternalExpressionException("Slot number is required for inventory_drop"); - int slot = (int)NumericValue.asNumber(lv.get(inventoryLocator.offset).evalValue(c)).getLong(); + int slot = (int)NumericValue.asNumber(lv.get(inventoryLocator.offset)).getLong(); slot = NBTSerializableValue.validateSlot(slot, inventoryLocator.inventory); - if (slot == inventoryLocator.inventory.size()) - return (_c, _t) -> Value.NULL; + if (slot == inventoryLocator.inventory.size()) return Value.NULL; int amount = 0; if (lv.size() > inventoryLocator.offset+1) - amount = (int)NumericValue.asNumber(lv.get(inventoryLocator.offset+1).evalValue(c)).getLong(); + amount = (int)NumericValue.asNumber(lv.get(inventoryLocator.offset+1)).getLong(); if (amount < 0) throw new InternalExpressionException("Cannot throw negative number of items"); ItemStack stack = inventoryLocator.inventory.getStack(slot); - if (stack == null || stack.isEmpty()) - return (_c, _t) -> Value.ZERO; - if (amount == 0) - amount = stack.getCount(); + if (stack == null || stack.isEmpty()) return Value.ZERO; + if (amount == 0) amount = stack.getCount(); ItemStack droppedStack = inventoryLocator.inventory.removeStack(slot, amount); - if (droppedStack.isEmpty()) - { - return (_c, _t) -> Value.ZERO; - } + if (droppedStack.isEmpty()) return Value.ZERO; Object owner = inventoryLocator.owner; ItemEntity item; if (owner instanceof PlayerEntity) @@ -438,8 +385,7 @@ public class Inventories { item.setToDefaultPickupDelay(); cc.s.getWorld().spawnEntity(item); } - Value res = new NumericValue(item.getStack().getCount()); - return (_c, _t) -> res; + return new NumericValue(item.getStack().getCount()); }); } diff --git a/src/main/java/carpet/script/api/Monitoring.java b/src/main/java/carpet/script/api/Monitoring.java index a3b97b9b..fac14276 100644 --- a/src/main/java/carpet/script/api/Monitoring.java +++ b/src/main/java/carpet/script/api/Monitoring.java @@ -25,31 +25,29 @@ public class Monitoring { public static void apply(Expression expression) { - expression.addLazyFunction("system_info", -1, (c, t, lv) -> + expression.addContextFunction("system_info", -1, (c, t, lv) -> { if (lv.size() == 0) { - Value ret = SystemInfo.getAll((CarpetContext) c); - return (cc, tt) -> ret; + return SystemInfo.getAll((CarpetContext) c); } if (lv.size() == 1) { - String what = lv.get(0).evalValue(c).getString(); + String what = lv.get(0).getString(); Value res = SystemInfo.get(what, (CarpetContext) c); if (res == null) throw new InternalExpressionException("Unknown option for 'system_info': " + what); - return (cc, tt) -> res; + return res; } throw new InternalExpressionException("'system_info' requires one or no parameters"); }); // game processed snooper functions - expression.addLazyFunction("get_mob_counts", -1, (c, t, lv) -> + expression.addContextFunction("get_mob_counts", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; ServerWorld world = cc.s.getWorld(); SpawnHelper.Info info = world.getChunkManager().getSpawnInfo(); - if (info == null) return LazyValue.NULL; + if (info == null) return Value.NULL; Object2IntMap mobcounts = info.getGroupToCount(); int chunks = ((SpawnHelperInnerInterface)info).cmGetChunkCount(); - Value retVal; if (lv.size() == 0) { Map retDict = new HashMap<>(); @@ -63,19 +61,15 @@ public class Monitoring { new NumericValue(currentCap)) ); } - retVal = MapValue.wrap(retDict); + return MapValue.wrap(retDict); } - else - { - String catString = lv.get(0).evalValue(c).getString(); - SpawnGroup cat = SpawnGroup.byName(catString.toLowerCase(Locale.ROOT)); - if (cat == null) throw new InternalExpressionException("Unreconized mob category: "+catString); - retVal = ListValue.of( - new NumericValue(mobcounts.getInt(cat)), - new NumericValue((int)(cat.getCapacity() * chunks / SpawnReporter.currentMagicNumber())) - ); - } - return (_c, _t) -> retVal; + String catString = lv.get(0).getString(); + SpawnGroup cat = SpawnGroup.byName(catString.toLowerCase(Locale.ROOT)); + if (cat == null) throw new InternalExpressionException("Unreconized mob category: "+catString); + return ListValue.of( + new NumericValue(mobcounts.getInt(cat)), + new NumericValue((int)(cat.getCapacity() * chunks / SpawnReporter.currentMagicNumber())) + ); }); } } diff --git a/src/main/java/carpet/script/api/Scoreboards.java b/src/main/java/carpet/script/api/Scoreboards.java index a83812cf..c81128a1 100644 --- a/src/main/java/carpet/script/api/Scoreboards.java +++ b/src/main/java/carpet/script/api/Scoreboards.java @@ -64,77 +64,68 @@ public class Scoreboards { { // scoreboard(player,'objective') // scoreboard(player, objective, newValue) - expression.addLazyFunction("scoreboard", -1, (c, t, lv) -> + expression.addContextFunction("scoreboard", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; Scoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard(); if (lv.size()==0) - { - Value ret = ListValue.wrap(scoreboard.getObjectiveNames().stream().map(StringValue::new).collect(Collectors.toList())); - return (_c, _t) -> ret; - } - String objectiveName = lv.get(0).evalValue(c).getString(); + return ListValue.wrap(scoreboard.getObjectiveNames().stream().map(StringValue::new).collect(Collectors.toList())); + String objectiveName = lv.get(0).getString(); ScoreboardObjective objective = scoreboard.getObjective(objectiveName); - if (objective == null) return LazyValue.NULL; + if (objective == null) return Value.NULL; if (lv.size()==1) + return ListValue.wrap(scoreboard.getAllPlayerScores(objective).stream().map(s -> new StringValue(s.getPlayerName())).collect(Collectors.toList())); + String key = getScoreboardKeyFromValue(lv.get(1)); + if(lv.size()==2) { - Value ret = ListValue.wrap(scoreboard.getAllPlayerScores(objective).stream().map(s -> new StringValue(s.getPlayerName())).collect(Collectors.toList())); - return (_c, _t) -> ret; + if(!scoreboard.playerHasObjective(key, objective)) return Value.NULL; + return NumericValue.of(scoreboard.getPlayerScore(key,objective).getScore()); } - String key = getScoreboardKeyFromValue(lv.get(1).evalValue(c)); - if(lv.size()==2) { - if(scoreboard.playerHasObjective(key, objective)) { - return (_c,_t) -> NumericValue.of(scoreboard.getPlayerScore(key,objective).getScore()); - } - return LazyValue.NULL; - } - - Value value = lv.get(2).evalValue(c); + Value value = lv.get(2); if(value.isNull()) { ScoreboardPlayerScore score = scoreboard.getPlayerScore(key, objective); scoreboard.resetPlayerScore(key,objective); - return (_c,_t) -> NumericValue.of(score.getScore()); + return NumericValue.of(score.getScore()); } if (value instanceof NumericValue) { ScoreboardPlayerScore score = scoreboard.getPlayerScore(key, objective); score.setScore(NumericValue.asNumber(value).getInt()); - return (_c,_t) -> NumericValue.of(score.getScore()); + return NumericValue.of(score.getScore()); } throw new InternalExpressionException("'scoreboard' requires a number or null as the third parameter"); }); - expression.addLazyFunction("scoreboard_remove", -1, (c, t, lv)-> + expression.addContextFunction("scoreboard_remove", -1, (c, t, lv)-> { if (lv.size()==0) throw new InternalExpressionException("'scoreboard_remove' requires at least one parameter"); CarpetContext cc = (CarpetContext)c; Scoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard(); - String objectiveName = lv.get(0).evalValue(c).getString(); + String objectiveName = lv.get(0).getString(); ScoreboardObjective objective = scoreboard.getObjective(objectiveName); - if (objective == null) - return LazyValue.FALSE; + if (objective == null) return Value.FALSE; if (lv.size() == 1) { scoreboard.removeObjective(objective); - return LazyValue.TRUE; + return Value.TRUE; } - String key = getScoreboardKeyFromValue(lv.get(1).evalValue(c)); - if (!scoreboard.playerHasObjective(key, objective)) return LazyValue.NULL; + String key = getScoreboardKeyFromValue(lv.get(1)); + if (!scoreboard.playerHasObjective(key, objective)) return Value.NULL; ScoreboardPlayerScore scoreboardPlayerScore = scoreboard.getPlayerScore(key, objective); Value previous = new NumericValue(scoreboardPlayerScore.getScore()); scoreboard.resetPlayerScore(key, objective); - return (c_, t_) -> previous; + return previous; }); // objective_add('lvl','level') // objective_add('counter') - expression.addLazyFunction("scoreboard_add", -1, (c, t, lv)-> + expression.addContextFunction("scoreboard_add", -1, (c, t, lv)-> { CarpetContext cc = (CarpetContext)c; Scoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard(); if (lv.size() == 0 || lv.size()>2) throw new InternalExpressionException("'scoreboard_add' should have one or two parameters"); - String objectiveName = lv.get(0).evalValue(c).getString(); + String objectiveName = lv.get(0).getString(); ScoreboardCriterion criterion; if (lv.size() == 1 ) { @@ -142,7 +133,7 @@ public class Scoreboards { } else { - String critetionName = lv.get(1).evalValue(c).getString(); + String critetionName = lv.get(1).getString(); criterion = ScoreboardCriterion.createStatCriterion(critetionName).orElse(null); if (criterion==null) { @@ -153,62 +144,62 @@ public class Scoreboards { ScoreboardObjective objective = scoreboard.getObjective(objectiveName); if (objective != null) { c.host.issueDeprecation("reading or modifying an objective's criterion with scoreboard_add"); - if(lv.size() == 1) return (_c, _t) -> StringValue.of(objective.getCriterion().getName()); - if(objective.getCriterion().equals(criterion) || lv.size() == 1) return LazyValue.NULL; + if(lv.size() == 1) return StringValue.of(objective.getCriterion().getName()); + if(objective.getCriterion().equals(criterion) || lv.size() == 1) return Value.NULL; ((Scoreboard_scarpetMixin)scoreboard).getObjectivesByCriterion().get(objective.getCriterion()).remove(objective); ((ScoreboardObjective_scarpetMixin) objective).setCriterion(criterion); (((Scoreboard_scarpetMixin)scoreboard).getObjectivesByCriterion().computeIfAbsent(criterion, (criterion1) -> Lists.newArrayList())).add(objective); scoreboard.updateObjective(objective); - return LazyValue.FALSE; + return Value.FALSE; } scoreboard.addObjective(objectiveName, criterion, new LiteralText(objectiveName), criterion.getCriterionType()); - return LazyValue.TRUE; + return Value.TRUE; }); - expression.addLazyFunction("scoreboard_property", -1, (c, t, lv) -> + expression.addContextFunction("scoreboard_property", -1, (c, t, lv) -> { if(lv.size() < 2) throw new InternalExpressionException("'scoreboard_property' requires at least two parameters"); CarpetContext cc = (CarpetContext)c; Scoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard(); - ScoreboardObjective objective = scoreboard.getObjective(lv.get(0).evalValue(c).getString()); - if(objective == null) return LazyValue.NULL; + ScoreboardObjective objective = scoreboard.getObjective(lv.get(0).getString()); + if(objective == null) return Value.NULL; boolean modify = lv.size() > 2; Value setValue = null; if(modify) { - setValue = lv.get(2).evalValue(c); + setValue = lv.get(2); } - String property = lv.get(1).evalValue(c).getString(); + String property = lv.get(1).getString(); switch (property) { case "criterion": if(modify) { ScoreboardCriterion criterion = ScoreboardCriterion.createStatCriterion(setValue.getString()).orElse(null); if (criterion==null) throw new InternalExpressionException("Unknown scoreboard criterion: "+ setValue.getString()); - if(objective.getCriterion().equals(criterion) || lv.size() == 1) return LazyValue.FALSE; + if(objective.getCriterion().equals(criterion) || lv.size() == 1) return Value.FALSE; ((Scoreboard_scarpetMixin)scoreboard).getObjectivesByCriterion().get(objective.getCriterion()).remove(objective); ((ScoreboardObjective_scarpetMixin) objective).setCriterion(criterion); (((Scoreboard_scarpetMixin)scoreboard).getObjectivesByCriterion().computeIfAbsent(criterion, (criterion1) -> Lists.newArrayList())).add(objective); scoreboard.updateObjective(objective); - return LazyValue.TRUE; + return Value.TRUE; } - return (_c, _t) -> StringValue.of(objective.getCriterion().getName()); + return StringValue.of(objective.getCriterion().getName()); case "display_name": if(modify) { Text text = FormattedTextValue.getTextByValue(setValue); objective.setDisplayName(text); - return LazyValue.TRUE; + return Value.TRUE; } - return (_c, _t) -> new FormattedTextValue(objective.getDisplayName()); + return new FormattedTextValue(objective.getDisplayName()); case "display_slot": if(modify) { int slotId = Scoreboard.getDisplaySlotId(setValue.getString()); if(slotId == -1) throw new InternalExpressionException("Unknown scoreboard display slot: " + setValue.getString()); if(objective.equals(scoreboard.getObjectiveForSlot(slotId))) { - return LazyValue.FALSE; + return Value.FALSE; } scoreboard.setObjectiveSlot(slotId,objective); - return LazyValue.TRUE; + return Value.TRUE; } List slots = new ArrayList<>(); @@ -218,325 +209,247 @@ public class Scoreboards { slots.add(StringValue.of(slotName)); } } - return (_c, _t) -> ListValue.wrap(slots); + return ListValue.wrap(slots); case "render_type": if(modify) { ScoreboardCriterion.RenderType renderType = ScoreboardCriterion.RenderType.getType(setValue.getString().toLowerCase()); - if(objective.getRenderType().equals(renderType)) return LazyValue.FALSE; + if(objective.getRenderType().equals(renderType)) return Value.FALSE; objective.setRenderType(renderType); - return LazyValue.TRUE; + return Value.TRUE; } - return (_c, _t) -> StringValue.of(objective.getRenderType().getName()); + return StringValue.of(objective.getRenderType().getName()); default: throw new InternalExpressionException("scoreboard property '" + property + "' is not a valid property"); } }); - expression.addLazyFunction("scoreboard_display", 2, (c, t, lv) -> + expression.addContextFunction("scoreboard_display", 2, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; Scoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard(); - String location = lv.get(0).evalValue(c).getString(); + String location = lv.get(0).getString(); int slot = Scoreboard.getDisplaySlotId(location); if (slot < 0) throw new InternalExpressionException("Invalid objective slot: "+location); - Value target = lv.get(1).evalValue(c); + Value target = lv.get(1); if (target instanceof NullValue) { scoreboard.setObjectiveSlot(slot, null); - return (_c, _t) -> new NumericValue(slot); + return new NumericValue(slot); } String objectiveString = target.getString(); ScoreboardObjective objective = scoreboard.getObjective(objectiveString); - if (objective == null) return LazyValue.NULL; + if (objective == null) return Value.NULL; scoreboard.setObjectiveSlot(slot, objective); - return (_c, _t) -> new NumericValue(slot); + return new NumericValue(slot); }); - expression.addLazyFunction("team_list", -1, (c, t, lv) -> + expression.addContextFunction("team_list", -1, (c, t, lv) -> { if(lv.size() > 1) throw new InternalExpressionException("'team_list' requires zero or one parameters"); CarpetContext cc = (CarpetContext)c; ServerScoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard(); - if(lv.size() == 0) { - Value ret = ListValue.wrap(scoreboard.getTeamNames().stream().map(StringValue::of).collect(Collectors.toList())); - return (_c, _t) -> ret; - } else if(lv.size() == 1) { - Team team = scoreboard.getTeam(lv.get(0).evalValue(c).getString()); - if(team == null) return LazyValue.NULL; - Value ret = ListValue.wrap(team.getPlayerList().stream().map(StringValue::of).collect(Collectors.toList())); - return (_c, _t) -> ret; - } else { - return LazyValue.NULL; - } + if(lv.size() == 0) + return ListValue.wrap(scoreboard.getTeamNames().stream().map(StringValue::of).collect(Collectors.toList())); + if (lv.size() != 1) return Value.NULL; + Team team = scoreboard.getTeam(lv.get(0).getString()); + if(team == null) return Value.NULL; + return ListValue.wrap(team.getPlayerList().stream().map(StringValue::of).collect(Collectors.toList())); }); - expression.addLazyFunction("team_add", -1, (c, t, lv) -> + expression.addContextFunction("team_add", -1, (c, t, lv) -> { if(!(lv.size() < 3 && lv.size() > 0)) throw new InternalExpressionException("'team_add' requires one or two parameters"); CarpetContext cc = (CarpetContext)c; ServerScoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard(); - String teamName = lv.get(0).evalValue(c).getString(); + String teamName = lv.get(0).getString(); - if(lv.size() == 1) { - if(scoreboard.getTeam(teamName) == null) { - scoreboard.addTeam(teamName); - Value ret = new StringValue(teamName); - return (_c, _t) -> ret; - } else { - return LazyValue.NULL; - } - } else if(lv.size() == 2) { - Value playerVal = lv.get(1).evalValue(c); - - String player = EntityValue.getPlayerNameByValue(playerVal); - if(player == null) return LazyValue.NULL; - - Team team = scoreboard.getTeam(teamName); - if(team == null) return LazyValue.NULL; - - if(team.isEqual(scoreboard.getPlayerTeam(player))) { - return LazyValue.FALSE; - } else { - scoreboard.addPlayerToTeam(player,scoreboard.getTeam(teamName)); - return LazyValue.TRUE; - } - } else { - return LazyValue.NULL; + if(lv.size() == 1) + { + if (scoreboard.getTeam(teamName) != null) return Value.NULL; + scoreboard.addTeam(teamName); + return new StringValue(teamName); } - }); - - expression.addLazyFunction("team_remove", 1, (c, t, lv) -> - { - CarpetContext cc = (CarpetContext)c; - ServerScoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard(); - Value teamVal = lv.get(0).evalValue(c); - - String team = teamVal.getString(); - - if(scoreboard.getTeam(team) != null) { - scoreboard.removeTeam(scoreboard.getTeam(team)); - return LazyValue.TRUE; - } else { - return LazyValue.NULL; - } - }); - - - expression.addLazyFunction("team_leave", 1, (c, t, lv) -> - { - CarpetContext cc = (CarpetContext)c; - ServerScoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard(); - Value playerVal = lv.get(0).evalValue(c); - + if(lv.size() != 2) return Value.NULL; + Value playerVal = lv.get(1); String player = EntityValue.getPlayerNameByValue(playerVal); - if(player == null) return LazyValue.NULL; - - Value ret = new NumericValue(scoreboard.clearPlayerTeam(player)); - return (_c, _t) -> ret; + if(player == null) return Value.NULL; + Team team = scoreboard.getTeam(teamName); + if(team == null) return Value.NULL; + if(team.isEqual(scoreboard.getPlayerTeam(player))) return Value.FALSE; + scoreboard.addPlayerToTeam(player,scoreboard.getTeam(teamName)); + return Value.TRUE; }); - expression.addLazyFunction("team_property", -1, (c, t, lv) -> + expression.addContextFunction("team_remove", 1, (c, t, lv) -> + { + CarpetContext cc = (CarpetContext)c; + ServerScoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard(); + Value teamVal = lv.get(0); + String team = teamVal.getString(); + if(scoreboard.getTeam(team) == null) return Value.NULL; + scoreboard.removeTeam(scoreboard.getTeam(team)); + return Value.TRUE; + }); + + + expression.addContextFunction("team_leave", 1, (c, t, lv) -> + { + CarpetContext cc = (CarpetContext)c; + ServerScoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard(); + Value playerVal = lv.get(0); + String player = EntityValue.getPlayerNameByValue(playerVal); + if(player == null) return Value.NULL; + return new NumericValue(scoreboard.clearPlayerTeam(player)); + }); + + expression.addContextFunction("team_property", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; ServerScoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard(); if(lv.size() < 2 || lv.size() > 3) throw new InternalExpressionException("'team_property' requires two or three arguments"); - Value teamVal = lv.get(0).evalValue(c); - Value propertyVal = lv.get(1).evalValue(c); + Value teamVal = lv.get(0); + Value propertyVal = lv.get(1); Value settingVal = null; boolean modifying = false; - if(lv.size() == 3) { + if(lv.size() == 3) + { modifying = true; - settingVal = lv.get(2).evalValue(c); + settingVal = lv.get(2); } Team team = scoreboard.getTeam(teamVal.getString()); - if(team == null) return LazyValue.NULL; + if(team == null) return Value.NULL; if(!(propertyVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string as the second argument"); switch (propertyVal.getString()) { case "collisionRule": - if(!modifying) { - Value ret = new StringValue(team.getCollisionRule().name); - return (_c, _t) -> ret; - } - + if(!modifying) return new StringValue(team.getCollisionRule().name); if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string as the third argument for the property " + propertyVal.getString()); - AbstractTeam.CollisionRule collisionRule = AbstractTeam.CollisionRule.getRule(settingVal.getString()); if(collisionRule == null) throw new InternalExpressionException("Unknown value for property " + propertyVal.getString() + ": " + settingVal.getString()); team.setCollisionRule(collisionRule); break; case "color": - if(!modifying) { - Value ret = new StringValue(team.getColor().getName()); - return (_c, _t) -> ret; - } - + if(!modifying) return new StringValue(team.getColor().getName()); if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string as the third argument for the property " + propertyVal.getString()); - Formatting color = Formatting.byName(settingVal.getString().toUpperCase()); if(color == null || !color.isColor()) throw new InternalExpressionException("Unknown value for property " + propertyVal.getString() + ": " + settingVal.getString()); team.setColor(color); - break; case "deathMessageVisibility": - if(!modifying) { - Value ret = new StringValue(team.getDeathMessageVisibilityRule().name); - return (_c, _t) -> ret; - } - + if(!modifying) return new StringValue(team.getDeathMessageVisibilityRule().name); if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string as the third argument for the property " + propertyVal.getString()); - AbstractTeam.VisibilityRule deathMessageVisibility = AbstractTeam.VisibilityRule.getRule(settingVal.getString()); if(deathMessageVisibility == null) throw new InternalExpressionException("Unknown value for property " + propertyVal.getString() + ": " + settingVal.getString()); team.setDeathMessageVisibilityRule(deathMessageVisibility); - break; case "displayName": - if(!modifying) { - Value ret = new FormattedTextValue(team.getDisplayName()); - return (_c, _t) -> ret; - } - + if(!modifying) return new FormattedTextValue(team.getDisplayName()); if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string or formatted text as the third argument for the property " + propertyVal.getString()); - Text displayName; - displayName = FormattedTextValue.getTextByValue(settingVal); - team.setDisplayName(displayName); - break; case "friendlyFire": - if(!modifying) { - Value ret = new NumericValue(team.isFriendlyFireAllowed()); - return (_c, _t) -> ret; - } - + if(!modifying) return new NumericValue(team.isFriendlyFireAllowed()); if(!(settingVal instanceof NumericValue)) throw new InternalExpressionException("'team_property' requires a boolean as the third argument for the property " + propertyVal.getString()); - boolean friendlyFire = settingVal.getBoolean(); team.setFriendlyFireAllowed(friendlyFire); break; case "nametagVisibility": - if(!modifying) { - Value ret = new StringValue(team.getNameTagVisibilityRule().name); - return (_c, _t) -> ret; - } - + if(!modifying) return new StringValue(team.getNameTagVisibilityRule().name); if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string as the third argument for the property " + propertyVal.getString()); - AbstractTeam.VisibilityRule nametagVisibility = AbstractTeam.VisibilityRule.getRule(settingVal.getString()); if(nametagVisibility == null) throw new InternalExpressionException("Unknown value for property " + propertyVal.getString() + ": " + settingVal.getString()); team.setNameTagVisibilityRule(nametagVisibility); break; case "prefix": - if(!modifying) { - Value ret = new FormattedTextValue(team.getPrefix()); - return (_c, _t) -> ret; - } - + if(!modifying) return new FormattedTextValue(team.getPrefix()); if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property ' requires a string or formatted text as the third argument for the property " + propertyVal.getString()); - Text prefix; - prefix = FormattedTextValue.getTextByValue(settingVal); - team.setPrefix(prefix); break; case "seeFriendlyInvisibles": - if(!modifying) { - Value ret = new NumericValue(team.shouldShowFriendlyInvisibles()); - return (_c, _t) -> ret; - } - + if(!modifying) return new NumericValue(team.shouldShowFriendlyInvisibles()); if(!(settingVal instanceof NumericValue)) throw new InternalExpressionException("'team_property' requires a boolean as the third argument for the property " + propertyVal.getString()); - boolean seeFriendlyInvisibles = settingVal.getBoolean(); team.setShowFriendlyInvisibles(seeFriendlyInvisibles); - break; case "suffix": - if(!modifying) { - Value ret = new FormattedTextValue(team.getSuffix()); - return (_c, _t) -> ret; - } - + if(!modifying) return new FormattedTextValue(team.getSuffix()); if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string or formatted text as the third argument for the property " + propertyVal.getString()); - Text suffix; - suffix = FormattedTextValue.getTextByValue(settingVal); - team.setSuffix(suffix); break; default: throw new InternalExpressionException("team property '" + propertyVal.getString() + "' is not a valid property"); } - return LazyValue.TRUE; + return Value.TRUE; }); - expression.addLazyFunction("bossbar", -1, (c, t, lv) -> + expression.addContextFunction("bossbar", -1, (c, t, lv) -> { BossBarManager bossBarManager = ((CarpetContext)c).s.getMinecraftServer().getBossBarManager(); if(lv.size() > 3) throw new InternalExpressionException("'bossbar' accepts max three arguments"); - if(lv.size() == 0) { - Value ret = ListValue.wrap(bossBarManager.getAll().stream().map(CommandBossBar::getId).map(Identifier::toString).map(StringValue::of).collect(Collectors.toList())); - return (_c, _t) -> ret; - } + if(lv.size() == 0) return ListValue.wrap(bossBarManager.getAll().stream().map(CommandBossBar::getId).map(Identifier::toString).map(StringValue::of).collect(Collectors.toList())); - String id = lv.get(0).evalValue(c).getString(); + String id = lv.get(0).getString(); Identifier identifier; - try { + try + { identifier = new Identifier(id); - } catch (InvalidIdentifierException invalidIdentifierException) { - return LazyValue.NULL; + } + catch (InvalidIdentifierException invalidIdentifierException) + { + return Value.NULL; } - if(lv.size() == 1) { - if(bossBarManager.get(identifier) != null) return LazyValue.FALSE; - Value ret = StringValue.of(bossBarManager.add(identifier,new LiteralText(id)).getId().toString()); - return (_c, _t) -> ret; + if(lv.size() == 1) + { + if(bossBarManager.get(identifier) != null) return Value.FALSE; + return StringValue.of(bossBarManager.add(identifier,new LiteralText(id)).getId().toString()); } - String property = lv.get(1).evalValue(c).getString(); + String property = lv.get(1).getString(); CommandBossBar bossBar = bossBarManager.get(identifier); - if(bossBar == null) return LazyValue.NULL; + if(bossBar == null) return Value.NULL; - Value propertyValue = (lv.size() == 3)?lv.get(2).evalValue(c):null; + Value propertyValue = (lv.size() == 3)?lv.get(2):null; switch (property) { case "color": if(propertyValue == null) { BossBar.Color color = (bossBar).getColor(); - if(color == null) return LazyValue.NULL; - return (_c, _t) -> StringValue.of(color.getName()); + if(color == null) return Value.NULL; + return StringValue.of(color.getName()); } BossBar.Color color = BossBar.Color.byName(propertyValue.getString()); - if(color == null) return LazyValue.NULL; + if(color == null) return Value.NULL; bossBar.setColor(BossBar.Color.byName(propertyValue.getString())); - return LazyValue.TRUE; + return Value.TRUE; case "max": - if(propertyValue == null) return (_c, _t) -> NumericValue.of(bossBar.getMaxValue()); + if(propertyValue == null) return NumericValue.of(bossBar.getMaxValue()); if(!(propertyValue instanceof NumericValue)) throw new InternalExpressionException("'bossbar' requires a number as the value for the property " + property); bossBar.setMaxValue(((NumericValue) propertyValue).getInt()); - return LazyValue.TRUE; + return Value.TRUE; case "name": - if(propertyValue == null) return (_c, _t) -> new FormattedTextValue(bossBar.getName()); + if(propertyValue == null) return new FormattedTextValue(bossBar.getName()); bossBar.setName(FormattedTextValue.getTextByValue(propertyValue)); - return LazyValue.TRUE; + return Value.TRUE; case "add_player": if(propertyValue == null) throw new InternalExpressionException("Bossbar property " + property + " can't be queried, add a third parameter"); @@ -545,27 +458,25 @@ public class Scoreboards { ServerPlayerEntity player = EntityValue.getPlayerByValue(((CarpetContext)c).s.getMinecraftServer(),propertyValue); if(player != null) bossBar.addPlayer(player); }); - return LazyValue.TRUE; + return Value.TRUE; } ServerPlayerEntity player = EntityValue.getPlayerByValue(((CarpetContext) c).s.getMinecraftServer(), propertyValue); if(player != null) { bossBar.addPlayer(player); - return LazyValue.TRUE; + return Value.TRUE; } - return LazyValue.FALSE; + return Value.FALSE; case "players": - if(propertyValue == null) { - return (_c, _t) -> ListValue.wrap(bossBar.getPlayers().stream().map(EntityValue::new).collect(Collectors.toList())); - } - - if(propertyValue instanceof ListValue) { + if (propertyValue == null) return ListValue.wrap(bossBar.getPlayers().stream().map(EntityValue::new).collect(Collectors.toList())); + if(propertyValue instanceof ListValue) + { bossBar.clearPlayers(); ((ListValue) propertyValue).getItems().forEach((v) -> { ServerPlayerEntity p = EntityValue.getPlayerByValue(((CarpetContext) c).s.getMinecraftServer(), v); if (p != null) bossBar.addPlayer(p); }); - return LazyValue.TRUE; + return Value.TRUE; } @@ -573,32 +484,29 @@ public class Scoreboards { bossBar.clearPlayers(); if (p != null) { bossBar.addPlayer(p); - return LazyValue.TRUE; + return Value.TRUE; } - return LazyValue.FALSE; + return Value.FALSE; case "style": - if(propertyValue == null) { - return (_c, _t) -> StringValue.of(bossBar.getOverlay().getName()); - } - + if(propertyValue == null) return StringValue.of(bossBar.getOverlay().getName()); BossBar.Style style = BossBar.Style.byName(propertyValue.getString()); if(style == null) throw new InternalExpressionException("'" + propertyValue.getString() + "' is not a valid value for property " + property); bossBar.setOverlay(style); - return LazyValue.TRUE; + return Value.TRUE; case "value": - if(propertyValue == null) return (_c, _t) -> NumericValue.of(bossBar.getValue()); + if(propertyValue == null) return NumericValue.of(bossBar.getValue()); if(!(propertyValue instanceof NumericValue)) throw new InternalExpressionException("'bossbar' requires a number as the value for the property " + property); bossBar.setValue(((NumericValue) propertyValue).getInt()); - return LazyValue.TRUE; + return Value.TRUE; case "visible": - if(propertyValue == null) return (_c, _t) -> new NumericValue(bossBar.isVisible()); + if(propertyValue == null) return new NumericValue(bossBar.isVisible()); bossBar.setVisible(propertyValue.getBoolean()); - return LazyValue.TRUE; + return Value.TRUE; case "remove": bossBarManager.remove(bossBar); - return LazyValue.TRUE; + return Value.TRUE; default: throw new InternalExpressionException("Unknown bossbar property " + property); } diff --git a/src/main/java/carpet/script/api/Threading.java b/src/main/java/carpet/script/api/Threading.java index c17a3ad0..206977c5 100644 --- a/src/main/java/carpet/script/api/Threading.java +++ b/src/main/java/carpet/script/api/Threading.java @@ -15,16 +15,16 @@ public class Threading public static void apply(Expression expression) { //"overidden" native call to cancel if on main thread - expression.addLazyFunction("task_join", 1, (c, t, lv) -> { + expression.addContextFunction("task_join", 1, (c, t, lv) -> { if (((CarpetContext)c).s.getMinecraftServer().isOnThread()) throw new InternalExpressionException("'task_join' cannot be called from main thread to avoid deadlocks"); - Value v = lv.get(0).evalValue(c); + Value v = lv.get(0); if (!(v instanceof ThreadValue)) throw new InternalExpressionException("'task_join' could only be used with a task value"); - Value ret = ((ThreadValue) v).join(); - return (_c, _t) -> ret; + return ((ThreadValue) v).join(); }); + // has to be lazy due to deferred execution of the expression expression.addLazyFunctionWithDelegation("task_dock", 1, (c, t, expr, tok, lv) -> { CarpetContext cc = (CarpetContext)c; MinecraftServer server = cc.s.getMinecraftServer(); diff --git a/src/main/java/carpet/script/api/WorldAccess.java b/src/main/java/carpet/script/api/WorldAccess.java index 40f9c3ce..fcab18ee 100644 --- a/src/main/java/carpet/script/api/WorldAccess.java +++ b/src/main/java/carpet/script/api/WorldAccess.java @@ -24,6 +24,7 @@ import carpet.script.exception.Throwables; import carpet.script.utils.BiomeInfo; import carpet.script.utils.WorldTools; import carpet.script.value.BlockValue; +import carpet.script.value.BooleanValue; import carpet.script.value.EntityValue; import carpet.script.value.ListValue; import carpet.script.value.MapValue; @@ -127,33 +128,27 @@ public class WorldAccess { }}; // dummy entity for dummy requirements in the loot tables (see snowball) private static FallingBlockEntity DUMMY_ENTITY = null; - private static LazyValue booleanStateTest( + private static Value booleanStateTest( Context c, String name, - List params, + List params, BiFunction test ) { CarpetContext cc = (CarpetContext) c; if (params.size() == 0) - { throw new InternalExpressionException("'" + name + "' requires at least one parameter"); - } - Value v0 = params.get(0).evalValue(c); + Value v0 = params.get(0); if (v0 instanceof BlockValue) - { - Value retval = test.apply(((BlockValue) v0).getBlockState(), ((BlockValue) v0).getPos()) ? Value.TRUE : Value.FALSE; - return (c_, t_) -> retval; - } + return BooleanValue.of(test.apply(((BlockValue) v0).getBlockState(), ((BlockValue) v0).getPos())); BlockValue block = BlockArgument.findIn(cc, params, 0).block; - Value retval = test.apply(block.getBlockState(), block.getPos()) ? Value.TRUE : Value.FALSE; - return (c_, t_) -> retval; + return BooleanValue.of(test.apply(block.getBlockState(), block.getPos())); } - private static LazyValue stateStringQuery( + private static Value stateStringQuery( Context c, String name, - List params, + List params, BiFunction test ) { @@ -163,38 +158,32 @@ public class WorldAccess { throw new InternalExpressionException("'" + name + "' requires at least one parameter"); } - Value v0 = params.get(0).evalValue(c); + Value v0 = params.get(0); if (v0 instanceof BlockValue) { String strVal = test.apply( ((BlockValue) v0).getBlockState(), ((BlockValue) v0).getPos()); - Value retval = strVal != null ? new StringValue(strVal) : Value.NULL; - return (c_, t_) -> retval; + return StringValue.of(strVal); } BlockValue block = BlockArgument.findIn(cc, params, 0).block; - String strVal = test.apply(block.getBlockState(), block.getPos()); - Value retval = strVal != null ? new StringValue(strVal) : Value.NULL; - return (c_, t_) -> retval; + return StringValue.of(test.apply(block.getBlockState(), block.getPos())); } - private static LazyValue genericStateTest( + private static Value genericStateTest( Context c, String name, - List params, + List params, Fluff.TriFunction test ) { CarpetContext cc = (CarpetContext) c; if (params.size() == 0) - { throw new InternalExpressionException("'" + name + "' requires at least one parameter"); - } - Value v0 = params.get(0).evalValue(c); + Value v0 = params.get(0); if (v0 instanceof BlockValue) { try { - Value retval = test.apply(((BlockValue) v0).getBlockState(), ((BlockValue) v0).getPos(), cc.s.getWorld()); - return (_c, _t) -> retval; + return test.apply(((BlockValue) v0).getBlockState(), ((BlockValue) v0).getPos(), cc.s.getWorld()); } catch (NullPointerException ignored) { @@ -202,8 +191,7 @@ public class WorldAccess { } } BlockValue block = BlockArgument.findIn(cc, params, 0).block; - Value retval = test.apply(block.getBlockState(), block.getPos(), cc.s.getWorld()); - return (c_, t_) -> retval; + return test.apply(block.getBlockState(), block.getPos(), cc.s.getWorld()); } private static > BlockState setProperty(Property property, String name, String value, @@ -272,7 +260,7 @@ public class WorldAccess { public static void apply(Expression expression) { - expression.addLazyFunction("block", -1, (c, t, lv) -> + expression.addContextFunction("block", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext) c; if (lv.size() == 0) @@ -283,25 +271,19 @@ public class WorldAccess { // fixing block state and data retval.getBlockState(); retval.getData(); - return (c_, t_) -> retval; + return retval; }); - expression.addLazyFunction("block_data", -1, (c, t, lv) -> + expression.addContextFunction("block_data", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext) c; if (lv.size() == 0) - { throw new InternalExpressionException("Block requires at least one parameter"); - } - CompoundTag tag = BlockArgument.findIn(cc, lv, 0, true).block.getData(); - if (tag == null) - return (c_, t_) -> Value.NULL; - Value retval = new NBTSerializableValue(tag); - return (c_, t_) -> retval; + CompoundTag tag = BlockArgument.findIn( (CarpetContext) c, lv, 0, true).block.getData(); + return NBTSerializableValue.of(tag); }); // poi_get(pos, radius?, type?, occupation?, column_mode?) - expression.addLazyFunction("poi", -1, (c, t, lv) -> + expression.addContextFunction("poi", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext) c; if (lv.size() == 0) throw new InternalExpressionException("'poi' requires at least one parameter"); @@ -311,7 +293,7 @@ public class WorldAccess { if (lv.size() == locator.offset) { PointOfInterestType poiType = store.getType(pos).orElse(null); - if (poiType == null) return LazyValue.NULL; + if (poiType == null) return Value.NULL; // this feels wrong, but I don't want to mix-in more than I really need to. // also distance adds 0.5 to each point which screws up accurate distance calculations @@ -323,21 +305,20 @@ public class WorldAccess { PointOfInterestStorage.OccupationStatus.ANY ).filter(p -> p.getPos().equals(pos)).findFirst().orElse(null); if (poi == null) - return LazyValue.NULL; - Value ret = ListValue.of( + return Value.NULL; + return ListValue.of( new StringValue(poi.getType().toString()), new NumericValue(poiType.getTicketCount() - ((PointOfInterest_scarpetMixin)poi).getFreeTickets()) ); - return (_c, _t) -> ret; } - int radius = NumericValue.asNumber(lv.get(locator.offset+0).evalValue(c)).getInt(); - if (radius < 0) return ListValue.lazyEmpty(); + int radius = NumericValue.asNumber(lv.get(locator.offset+0)).getInt(); + if (radius < 0) return ListValue.of(); Predicate condition = PointOfInterestType.ALWAYS_TRUE; PointOfInterestStorage.OccupationStatus status = PointOfInterestStorage.OccupationStatus.ANY; boolean inColumn = false; if (locator.offset + 1 < lv.size()) { - String poiType = lv.get(locator.offset+1).evalValue(c).getString().toLowerCase(Locale.ROOT); + String poiType = lv.get(locator.offset+1).getString().toLowerCase(Locale.ROOT); if (!"any".equals(poiType)) { PointOfInterestType type = Registry.POINT_OF_INTEREST_TYPE.getOrEmpty(new Identifier(poiType)) @@ -346,7 +327,7 @@ public class WorldAccess { } if (locator.offset + 2 < lv.size()) { - String statusString = lv.get(locator.offset+2).evalValue(c).getString().toLowerCase(Locale.ROOT); + String statusString = lv.get(locator.offset+2).getString().toLowerCase(Locale.ROOT); if ("occupied".equals(statusString)) status = PointOfInterestStorage.OccupationStatus.IS_OCCUPIED; else if ("available".equals(statusString)) @@ -357,42 +338,37 @@ public class WorldAccess { ); if (locator.offset + 3 < lv.size()) { - inColumn = lv.get(locator.offset+3).evalValue(c, Context.BOOLEAN).getBoolean(); + inColumn = lv.get(locator.offset+3).getBoolean(); } } } Stream pois = inColumn? store.getInSquare(condition, pos, radius, status): store.getInCircle(condition, pos, radius, status); - Value ret = ListValue.wrap(pois.sorted(Comparator.comparingDouble(p -> p.getPos().getSquaredDistance(pos))).map(p -> + return ListValue.wrap(pois.sorted(Comparator.comparingDouble(p -> p.getPos().getSquaredDistance(pos))).map(p -> ListValue.of( new StringValue(p.getType().toString()), new NumericValue(p.getType().getTicketCount() - ((PointOfInterest_scarpetMixin)p).getFreeTickets()), ListValue.of(new NumericValue(p.getPos().getX()), new NumericValue(p.getPos().getY()), new NumericValue(p.getPos().getZ())) ) ).collect(Collectors.toList())); - - return (c_, t_) -> ret; }); //poi_set(pos, null) poi_set(pos, type, occupied?, - expression.addLazyFunction("set_poi", -1, (c, t, lv) -> + expression.addContextFunction("set_poi", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext) c; if (lv.size() == 0) throw new InternalExpressionException("'set_poi' requires at least one parameter"); BlockArgument locator = BlockArgument.findIn(cc, lv, 0, false); BlockPos pos = locator.block.getPos(); if (lv.size() < locator.offset) throw new InternalExpressionException("'set_poi' requires the new poi type or null, after position argument"); - Value poi = lv.get(locator.offset+0).evalValue(c); + Value poi = lv.get(locator.offset+0); PointOfInterestStorage store = cc.s.getWorld().getPointOfInterestStorage(); if (poi.isNull()) { // clear poi information - if (store.getType(pos).isPresent()) - { - store.remove(pos); - return LazyValue.TRUE; - } - return LazyValue.FALSE; + if (!store.getType(pos).isPresent()) return Value.FALSE; + store.remove(pos); + return Value.TRUE; } String poiTypeString = poi.getString().toLowerCase(Locale.ROOT); PointOfInterestType type = Registry.POINT_OF_INTEREST_TYPE.getOrEmpty(new Identifier(poiTypeString)) @@ -400,7 +376,7 @@ public class WorldAccess { int occupancy = 0; if (locator.offset + 1 < lv.size()) { - occupancy = (int)NumericValue.asNumber(lv.get(locator.offset + 1).evalValue(c)).getLong(); + occupancy = (int)NumericValue.asNumber(lv.get(locator.offset + 1)).getLong(); if (occupancy < 0) throw new InternalExpressionException("Occupancy cannot be negative"); } if (store.getType(pos).isPresent()) store.remove(pos); @@ -415,20 +391,17 @@ public class WorldAccess { for (int i=0; i < finalO; i++) ((PointOfInterest_scarpetMixin)p).callReserveTicket(); }); } - return LazyValue.TRUE; + return Value.TRUE; }); - expression.addLazyFunction("weather",-1,(c, t, lv) -> { + expression.addContextFunction("weather",-1,(c, t, lv) -> { ServerWorld world = ((CarpetContext) c).s.getWorld(); if(lv.size()==0)//cos it can thunder when raining or when clear. - { - Value ret = new StringValue(world.isThundering() ? "thunder" : (world.isRaining() ? "rain" : "clear")); - return (_c, _t) -> ret; - } + return new StringValue(world.isThundering() ? "thunder" : (world.isRaining() ? "rain" : "clear")); - Value weather = lv.get(0).evalValue(c); + Value weather = lv.get(0); ServerWorldProperties worldProperties = ((ServerWorldInterface) world).getWorldPropertiesCM(); if(lv.size()==1) { @@ -446,12 +419,11 @@ public class WorldAccess { default: throw new InternalExpressionException("Weather can only be 'clear', 'rain' or 'thunder'"); } - Value ret = new NumericValue(ticks); - return (_c,_t) -> ret; + return new NumericValue(ticks); } if(lv.size()==2) { - int ticks = NumericValue.asNumber(lv.get(1).evalValue(c), "tick_time in 'weather'").getInt(); + int ticks = NumericValue.asNumber(lv.get(1), "tick_time in 'weather'").getInt(); switch (weather.getString().toLowerCase(Locale.ROOT)) { case "clear": @@ -474,30 +446,26 @@ public class WorldAccess { default: throw new InternalExpressionException("Weather can only be 'clear', 'rain' or 'thunder'"); } - Value ret = NumericValue.of(ticks); - return (_c, _t) -> ret; + return NumericValue.of(ticks); } throw new InternalExpressionException("'weather' requires 0, 1 or 2 arguments"); }); - expression.addLazyFunction("pos", 1, (c, t, lv) -> + expression.addUnaryFunction("pos", v -> { - Value arg = lv.get(0).evalValue(c); - if (arg instanceof BlockValue) + if (v instanceof BlockValue) { - BlockPos pos = ((BlockValue) arg).getPos(); + BlockPos pos = ((BlockValue) v).getPos(); if (pos == null) throw new InternalExpressionException("Cannot fetch position of an unrealized block"); - Value retval = ListValue.of(new NumericValue(pos.getX()), new NumericValue(pos.getY()), new NumericValue(pos.getZ())); - return (c_, t_) -> retval; + return ListValue.of(new NumericValue(pos.getX()), new NumericValue(pos.getY()), new NumericValue(pos.getZ())); } - else if (arg instanceof EntityValue) + else if (v instanceof EntityValue) { - Entity e = ((EntityValue) arg).getEntity(); + Entity e = ((EntityValue) v).getEntity(); if (e == null) throw new InternalExpressionException("Null entity"); - Value retval = ListValue.of(new NumericValue(e.getX()), new NumericValue(e.getY()), new NumericValue(e.getZ())); - return (c_, t_) -> retval; + return ListValue.of(new NumericValue(e.getX()), new NumericValue(e.getY()), new NumericValue(e.getZ())); } else { @@ -505,85 +473,82 @@ public class WorldAccess { } }); - expression.addLazyFunction("pos_offset", -1, (c, t, lv) -> + expression.addContextFunction("pos_offset", -1, (c, t, lv) -> { BlockArgument locator = BlockArgument.findIn((CarpetContext)c, lv, 0); BlockPos pos = locator.block.getPos(); if (lv.size() <= locator.offset) throw new InternalExpressionException("'pos_offset' needs at least position, and direction"); - String directionString = lv.get(locator.offset).evalValue(c).getString(); + String directionString = lv.get(locator.offset).getString(); Direction dir = DIRECTION_MAP.get(directionString); if (dir == null) throw new InternalExpressionException("Unknown direction: "+directionString); int howMuch = 1; if (lv.size() > locator.offset+1) - howMuch = (int) NumericValue.asNumber(lv.get(locator.offset+1).evalValue(c)).getLong(); + howMuch = (int) NumericValue.asNumber(lv.get(locator.offset+1)).getLong(); BlockPos retpos = pos.offset(dir, howMuch); - Value ret = ListValue.of(new NumericValue(retpos.getX()), new NumericValue(retpos.getY()), new NumericValue(retpos.getZ())); - return (cc, tt) -> ret; + return ListValue.of(new NumericValue(retpos.getX()), new NumericValue(retpos.getY()), new NumericValue(retpos.getZ())); }); - expression.addLazyFunction("solid", -1, (c, t, lv) -> + expression.addContextFunction("solid", -1, (c, t, lv) -> genericStateTest(c, "solid", lv, (s, p, w) -> new NumericValue(s.isSolidBlock(w, p)))); // isSimpleFullBlock - expression.addLazyFunction("air", -1, (c, t, lv) -> + expression.addContextFunction("air", -1, (c, t, lv) -> booleanStateTest(c, "air", lv, (s, p) -> s.isAir())); - expression.addLazyFunction("liquid", -1, (c, t, lv) -> + expression.addContextFunction("liquid", -1, (c, t, lv) -> booleanStateTest(c, "liquid", lv, (s, p) -> !s.getFluidState().isEmpty())); - expression.addLazyFunction("flammable", -1, (c, t, lv) -> + expression.addContextFunction("flammable", -1, (c, t, lv) -> booleanStateTest(c, "flammable", lv, (s, p) -> s.getMaterial().isBurnable())); - expression.addLazyFunction("transparent", -1, (c, t, lv) -> + expression.addContextFunction("transparent", -1, (c, t, lv) -> booleanStateTest(c, "transparent", lv, (s, p) -> !s.getMaterial().isSolid())); - /*this.expr.addLazyFunction("opacity", -1, (c, t, lv) -> + /*this.expr.addContextFunction("opacity", -1, (c, t, lv) -> genericStateTest(c, "opacity", lv, (s, p, w) -> new NumericValue(s.getOpacity(w, p)))); - this.expr.addLazyFunction("blocks_daylight", -1, (c, t, lv) -> + this.expr.addContextFunction("blocks_daylight", -1, (c, t, lv) -> genericStateTest(c, "blocks_daylight", lv, (s, p, w) -> new NumericValue(s.propagatesSkylightDown(w, p))));*/ // investigate - expression.addLazyFunction("emitted_light", -1, (c, t, lv) -> + expression.addContextFunction("emitted_light", -1, (c, t, lv) -> genericStateTest(c, "emitted_light", lv, (s, p, w) -> new NumericValue(s.getLuminance()))); - expression.addLazyFunction("light", -1, (c, t, lv) -> + expression.addContextFunction("light", -1, (c, t, lv) -> genericStateTest(c, "light", lv, (s, p, w) -> new NumericValue(Math.max(w.getLightLevel(LightType.BLOCK, p), w.getLightLevel(LightType.SKY, p))))); - expression.addLazyFunction("block_light", -1, (c, t, lv) -> + expression.addContextFunction("block_light", -1, (c, t, lv) -> genericStateTest(c, "block_light", lv, (s, p, w) -> new NumericValue(w.getLightLevel(LightType.BLOCK, p)))); - expression.addLazyFunction("sky_light", -1, (c, t, lv) -> + expression.addContextFunction("sky_light", -1, (c, t, lv) -> genericStateTest(c, "sky_light", lv, (s, p, w) -> new NumericValue(w.getLightLevel(LightType.SKY, p)))); - expression.addLazyFunction("see_sky", -1, (c, t, lv) -> + expression.addContextFunction("see_sky", -1, (c, t, lv) -> genericStateTest(c, "see_sky", lv, (s, p, w) -> new NumericValue(w.isSkyVisible(p)))); - expression.addLazyFunction("brightness", -1, (c, t, lv) -> + expression.addContextFunction("brightness", -1, (c, t, lv) -> genericStateTest(c, "brightness", lv, (s, p, w) -> new NumericValue(w.getBrightness(p)))); - expression.addLazyFunction("hardness", -1, (c, t, lv) -> + expression.addContextFunction("hardness", -1, (c, t, lv) -> genericStateTest(c, "hardness", lv, (s, p, w) -> new NumericValue(s.getHardness(w, p)))); - expression.addLazyFunction("blast_resistance", -1, (c, t, lv) -> + expression.addContextFunction("blast_resistance", -1, (c, t, lv) -> genericStateTest(c, "blast_resistance", lv, (s, p, w) -> new NumericValue(s.getBlock().getBlastResistance()))); - expression.addLazyFunction("in_slime_chunk", -1, (c, t, lv) -> + expression.addContextFunction("in_slime_chunk", -1, (c, t, lv) -> { BlockPos pos = BlockArgument.findIn((CarpetContext)c, lv, 0).block.getPos(); ChunkPos chunkPos = new ChunkPos(pos); - Value ret = new NumericValue(ChunkRandom.getSlimeRandom( + return new NumericValue(ChunkRandom.getSlimeRandom( chunkPos.x, chunkPos.z, ((CarpetContext)c).s.getWorld().getSeed(), 987234911L ).nextInt(10) == 0); - return (_c, _t) -> ret; }); - - expression.addLazyFunction("top", -1, (c, t, lv) -> + expression.addContextFunction("top", -1, (c, t, lv) -> { - String type = lv.get(0).evalValue(c).getString().toLowerCase(Locale.ROOT); + String type = lv.get(0).getString().toLowerCase(Locale.ROOT); Heightmap.Type htype; switch (type) { @@ -598,63 +563,51 @@ public class WorldAccess { BlockPos pos = locator.block.getPos(); int x = pos.getX(); int z = pos.getZ(); - Value retval = new NumericValue(((CarpetContext)c).s.getWorld().getChunk(x >> 4, z >> 4).sampleHeightmap(htype, x & 15, z & 15) + 1); - return (c_, t_) -> retval; - //BlockPos pos = new BlockPos(x,y,z); - //return new BlockValue(source.getWorld().getBlockState(pos), pos); + return new NumericValue(((CarpetContext)c).s.getWorld().getChunk(x >> 4, z >> 4).sampleHeightmap(htype, x & 15, z & 15) + 1); }); - expression.addLazyFunction("loaded", -1, (c, t, lv) -> - { - Value retval = ((CarpetContext) c).s.getWorld().isChunkLoaded(BlockArgument.findIn((CarpetContext) c, lv, 0).block.getPos()) ? Value.TRUE : Value.FALSE; - return (c_, t_) -> retval; - }); + expression.addContextFunction("loaded", -1, (c, t, lv) -> + BooleanValue.of((((CarpetContext) c).s.getWorld().isChunkLoaded(BlockArgument.findIn((CarpetContext) c, lv, 0).block.getPos())))); // Deprecated, use loaded_status as more indicative - expression.addLazyFunction("loaded_ep", -1, (c, t, lv) -> + expression.addContextFunction("loaded_ep", -1, (c, t, lv) -> { c.host.issueDeprecation("loaded_ep(...)"); BlockPos pos = BlockArgument.findIn((CarpetContext)c, lv, 0).block.getPos(); - Value retval = ((CarpetContext)c).s.getWorld().getChunkManager().shouldTickChunk(new ChunkPos(pos))?Value.TRUE : Value.FALSE; - return (c_, t_) -> retval; + return BooleanValue.of(((CarpetContext)c).s.getWorld().getChunkManager().shouldTickChunk(new ChunkPos(pos))); }); - expression.addLazyFunction("loaded_status", -1, (c, t, lv) -> + expression.addContextFunction("loaded_status", -1, (c, t, lv) -> { BlockPos pos = BlockArgument.findIn((CarpetContext)c, lv, 0).block.getPos(); WorldChunk chunk = ((CarpetContext)c).s.getWorld().getChunkManager().getWorldChunk(pos.getX()>>4, pos.getZ()>>4, false); - if (chunk == null) - return LazyValue.ZERO; - Value retval = new NumericValue(chunk.getLevelType().ordinal()); - return (c_, t_) -> retval; + if (chunk == null) return Value.ZERO; + return new NumericValue(chunk.getLevelType().ordinal()); }); - expression.addLazyFunction("is_chunk_generated", -1, (c, t, lv) -> + expression.addContextFunction("is_chunk_generated", -1, (c, t, lv) -> { BlockArgument locator = BlockArgument.findIn((CarpetContext)c, lv, 0); BlockPos pos = locator.block.getPos(); boolean force = false; if (lv.size() > locator.offset) - force = lv.get(locator.offset).evalValue(c, Context.BOOLEAN).getBoolean(); - Value retval = new NumericValue(canHasChunk(((CarpetContext)c).s.getWorld(), new ChunkPos(pos), null, force)); - return (c_, t_) -> retval; + force = lv.get(locator.offset).getBoolean(); + return new NumericValue(canHasChunk(((CarpetContext)c).s.getWorld(), new ChunkPos(pos), null, force)); }); - expression.addLazyFunction("generation_status", -1, (c, t, lv) -> + expression.addContextFunction("generation_status", -1, (c, t, lv) -> { BlockArgument blockArgument = BlockArgument.findIn((CarpetContext)c, lv, 0); BlockPos pos = blockArgument.block.getPos(); boolean forceLoad = false; if (lv.size() > blockArgument.offset) - forceLoad = lv.get(blockArgument.offset).evalValue(c, Context.BOOLEAN).getBoolean(); + forceLoad = lv.get(blockArgument.offset).getBoolean(); Chunk chunk = ((CarpetContext)c).s.getWorld().getChunk(pos.getX()>>4, pos.getZ()>>4, ChunkStatus.EMPTY, forceLoad); - if (chunk == null) - return LazyValue.NULL; - Value retval = new StringValue(chunk.getStatus().getId()); - return (c_, t_) -> retval; + if (chunk == null) return Value.NULL; + return new StringValue(chunk.getStatus().getId()); }); - expression.addLazyFunction("chunk_tickets", -1, (c, t, lv) -> + expression.addContextFunction("chunk_tickets", -1, (c, t, lv) -> { ServerWorld world = ((CarpetContext) c).s.getWorld(); Long2ObjectOpenHashMap>> levelTickets = ( @@ -695,27 +648,26 @@ public class WorldAccess { } } res.sort(Comparator.comparing(e -> ((ListValue) e).getItems().get(1)).reversed()); - Value returnValue = ListValue.wrap(res); - return (_c, _t) -> returnValue; + return ListValue.wrap(res); }); - expression.addLazyFunction("suffocates", -1, (c, t, lv) -> + expression.addContextFunction("suffocates", -1, (c, t, lv) -> genericStateTest(c, "suffocates", lv, (s, p, w) -> new NumericValue(s.shouldSuffocate(w, p)))); // canSuffocate - expression.addLazyFunction("power", -1, (c, t, lv) -> + expression.addContextFunction("power", -1, (c, t, lv) -> genericStateTest(c, "power", lv, (s, p, w) -> new NumericValue(w.getReceivedRedstonePower(p)))); - expression.addLazyFunction("ticks_randomly", -1, (c, t, lv) -> + expression.addContextFunction("ticks_randomly", -1, (c, t, lv) -> booleanStateTest(c, "ticks_randomly", lv, (s, p) -> s.hasRandomTicks())); - expression.addLazyFunction("update", -1, (c, t, lv) -> + expression.addContextFunction("update", -1, (c, t, lv) -> booleanStateTest(c, "update", lv, (s, p) -> { ((CarpetContext) c).s.getWorld().updateNeighbor(p, s.getBlock(), p); return true; })); - expression.addLazyFunction("block_tick", -1, (c, t, lv) -> + expression.addContextFunction("block_tick", -1, (c, t, lv) -> booleanStateTest(c, "block_tick", lv, (s, p) -> { ServerWorld w = ((CarpetContext)c).s.getWorld(); @@ -723,7 +675,7 @@ public class WorldAccess { return true; })); - expression.addLazyFunction("random_tick", -1, (c, t, lv) -> + expression.addContextFunction("random_tick", -1, (c, t, lv) -> booleanStateTest(c, "random_tick", lv, (s, p) -> { ServerWorld w = ((CarpetContext)c).s.getWorld(); @@ -732,6 +684,7 @@ public class WorldAccess { return true; })); + // lazy cause its parked execution expression.addLazyFunction("without_updates", 1, (c, t, lv) -> { boolean previous = CarpetSettings.impendingFillSkipUpdates; @@ -752,7 +705,7 @@ public class WorldAccess { return (cc, tt) -> result[0]; }); - expression.addLazyFunction("set", -1, (c, t, lv) -> + expression.addContextFunction("set", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; ServerWorld world = cc.s.getWorld(); @@ -766,7 +719,7 @@ public class WorldAccess { List args = new ArrayList<>(); for (int i = sourceLocator.offset, m = lv.size(); i < m; i++) { - args.add(lv.get(i).evalValue(c)); + args.add(lv.get(i)); } if (args.get(0) instanceof ListValue) { @@ -822,7 +775,7 @@ public class WorldAccess { CompoundTag finalData = data; if (sourceBlockState == targetBlockState && data == null) - return (c_, t_) -> Value.FALSE; + return Value.FALSE; BlockState finalSourceBlockState = sourceBlockState; BlockPos targetPos = targetLocator.block.getPos(); Boolean[] result = new Boolean[]{true}; @@ -846,19 +799,17 @@ public class WorldAccess { } result[0] = success; }); - if (!result[0]) return LazyValue.FALSE; - Value retval = new BlockValue(finalSourceBlockState, world, targetLocator.block.getPos()); - return (c_, t_) -> retval; + if (!result[0]) return Value.FALSE; + return new BlockValue(finalSourceBlockState, world, targetLocator.block.getPos()); }); - expression.addLazyFunction("destroy", -1, (c, t, lv) -> + expression.addContextFunction("destroy", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; ServerWorld world = cc.s.getWorld(); BlockArgument locator = BlockArgument.findIn(cc, lv, 0); BlockState state = locator.block.getBlockState(); - if (state.isAir()) - return (c_, t_) -> Value.FALSE; + if (state.isAir()) return Value.FALSE; BlockPos where = locator.block.getPos(); BlockEntity be = world.getBlockEntity(where); long how = 0; @@ -866,7 +817,7 @@ public class WorldAccess { boolean playerBreak = false; if (lv.size() > locator.offset) { - Value val = lv.get(locator.offset).evalValue(c); + Value val = lv.get(locator.offset); if (val instanceof NumericValue) { how = ((NumericValue) val).getLong(); @@ -883,7 +834,7 @@ public class WorldAccess { if (lv.size() > locator.offset+1) { if (!playerBreak) throw new InternalExpressionException("tag is not necessary with 'destroy' with no item"); - Value tagValue = lv.get(locator.offset+1).evalValue(c); + Value tagValue = lv.get(locator.offset+1); if (tagValue instanceof NullValue) tag = null; else if (tagValue instanceof NBTSerializableValue) @@ -898,9 +849,9 @@ public class WorldAccess { ItemStack tool = new ItemStack(item, 1); if (tag != null) tool.setTag(tag); - if (playerBreak && state.getHardness(world, where) < 0.0) return LazyValue.FALSE; + if (playerBreak && state.getHardness(world, where) < 0.0) return Value.FALSE; boolean removed = world.removeBlock(where, false); - if (!removed) return LazyValue.FALSE; + if (!removed) return Value.FALSE; world.syncWorldEvent(null, 2001, where, Block.getRawIdFromState(state)); boolean toolBroke = false; @@ -939,29 +890,28 @@ public class WorldAccess { } } if (!playerBreak) // no tool info - block brokwn - return (c_, t_) -> Value.TRUE; + return Value.TRUE; if (toolBroke) - return LazyValue.NULL; + return Value.NULL; Tag outtag = tool.getTag(); if (outtag == null) - return LazyValue.TRUE; - Value ret = new NBTSerializableValue(() -> outtag); - return (_c, _t) -> ret; + return Value.TRUE; + return new NBTSerializableValue(() -> outtag); }); - expression.addLazyFunction("harvest", -1, (c, t, lv) -> + expression.addContextFunction("harvest", -1, (c, t, lv) -> { if (lv.size()<2) throw new InternalExpressionException("'harvest' takes at least 2 parameters: entity and block, or position, to harvest"); CarpetContext cc = (CarpetContext)c; World world = cc.s.getWorld(); - Value entityValue = lv.get(0).evalValue(cc); + Value entityValue = lv.get(0); if (!(entityValue instanceof EntityValue)) - return (c_, t_) -> Value.FALSE; + return Value.FALSE; Entity e = ((EntityValue) entityValue).getEntity(); if (!(e instanceof ServerPlayerEntity)) - return (c_, t_) -> Value.FALSE; + return Value.FALSE; ServerPlayerEntity player = (ServerPlayerEntity)e; BlockArgument locator = BlockArgument.findIn(cc, lv, 1); BlockPos where = locator.block.getPos(); @@ -972,10 +922,10 @@ public class WorldAccess { success = tryBreakBlock_copy_from_ServerPlayerInteractionManager(player, where); if (success) world.syncWorldEvent(null, 2001, where, Block.getRawIdFromState(state)); - return success ? LazyValue.TRUE : LazyValue.FALSE; + return BooleanValue.of(success); }); - expression.addLazyFunction("create_explosion", -1, (c, t, lv) -> + expression.addContextFunction("create_explosion", -1, (c, t, lv) -> { if (lv.isEmpty()) throw new InternalExpressionException("'create_explosion' requires at least a position to explode"); @@ -985,25 +935,25 @@ public class WorldAccess { boolean createFire = false; Entity source = null; LivingEntity attacker = null; - Vector3Argument location = Vector3Argument.findIn(cc, lv, 0, false, true); + Vector3Argument location = Vector3Argument.findIn(lv, 0, false, true); Vec3d pos = location.vec; if (lv.size() > location.offset) { - powah = NumericValue.asNumber(lv.get(location.offset).evalValue(c), "explosion power").getFloat(); + powah = NumericValue.asNumber(lv.get(location.offset), "explosion power").getFloat(); if (powah < 0) throw new InternalExpressionException("Explosion power cannot be negative"); if (lv.size() > location.offset+1) { - String strval = lv.get(location.offset+1).evalValue(c).getString(); + String strval = lv.get(location.offset+1).getString(); try { mode = Explosion.DestructionType.valueOf(strval.toUpperCase(Locale.ROOT)); } catch (IllegalArgumentException ile) { throw new InternalExpressionException("Illegal explosions block behaviour: "+strval); } if (lv.size() > location.offset+2) { - createFire = lv.get(location.offset+2).evalValue(c, Context.BOOLEAN).getBoolean(); + createFire = lv.get(location.offset+2).getBoolean(); if (lv.size() > location.offset+3) { - Value enVal= lv.get(location.offset+3).evalValue(c); + Value enVal= lv.get(location.offset+3); if (enVal.isNull()) {} // is null already else if (enVal instanceof EntityValue) { @@ -1015,7 +965,7 @@ public class WorldAccess { } if (lv.size() > location.offset+4) { - enVal = lv.get(location.offset+4).evalValue(c); + enVal = lv.get(location.offset+4); if (enVal.isNull()) {} // is null already else if (enVal instanceof EntityValue) { @@ -1054,25 +1004,25 @@ public class WorldAccess { if (spe.squaredDistanceTo(pos) < 4096.0D) spe.networkHandler.sendPacket(new ExplosionS2CPacket(pos.x, pos.y, pos.z, thePowah, explosion.getAffectedBlocks(), explosion.getAffectedPlayers().get(spe))); }); - return LazyValue.TRUE; + return Value.TRUE; }); // TODO rename to use_item - expression.addLazyFunction("place_item", -1, (c, t, lv) -> + expression.addContextFunction("place_item", -1, (c, t, lv) -> { if (lv.size()<2) throw new InternalExpressionException("'place_item' takes at least 2 parameters: item and block, or position, to place onto"); CarpetContext cc = (CarpetContext) c; - String itemString = lv.get(0).evalValue(c).getString(); - Vector3Argument locator = Vector3Argument.findIn(cc, lv, 1); + String itemString = lv.get(0).getString(); + Vector3Argument locator = Vector3Argument.findIn(lv, 1); ItemStackArgument stackArg = NBTSerializableValue.parseItem(itemString); BlockPos where = new BlockPos(locator.vec); String facing = "up"; if (lv.size() > locator.offset) - facing = lv.get(locator.offset).evalValue(c).getString(); + facing = lv.get(locator.offset).getString(); boolean sneakPlace = false; if (lv.size() > locator.offset+1) - sneakPlace = lv.get(locator.offset+1).evalValue(c).getBoolean(); + sneakPlace = lv.get(locator.offset+1).getBoolean(); BlockValue.PlacementContext ctx; try @@ -1089,14 +1039,13 @@ public class WorldAccess { ActionResult useResult = ctx.getStack().useOnBlock(ctx); if (useResult == ActionResult.CONSUME || useResult == ActionResult.SUCCESS) { - return LazyValue.TRUE; + return Value.TRUE; } } else { // not sure we need special case for block items, since useOnBlock can do that as well BlockItem blockItem = (BlockItem) stackArg.getItem(); - if (!ctx.canPlace()) - return (_c, _t) -> Value.FALSE; + if (!ctx.canPlace()) return Value.FALSE; BlockState placementState = blockItem.getBlock().getPlacementState(ctx); if (placementState != null) { @@ -1105,63 +1054,60 @@ public class WorldAccess { cc.s.getWorld().setBlockState(where, placementState, 2); BlockSoundGroup blockSoundGroup = placementState.getSoundGroup(); cc.s.getWorld().playSound(null, where, blockSoundGroup.getPlaceSound(), SoundCategory.BLOCKS, (blockSoundGroup.getVolume() + 1.0F) / 2.0F, blockSoundGroup.getPitch() * 0.8F); - return (_c, _t) -> Value.TRUE; + return Value.TRUE; } } } - return (_c, _t) -> Value.FALSE; + return Value.FALSE; }); - expression.addLazyFunction("blocks_movement", -1, (c, t, lv) -> + expression.addContextFunction("blocks_movement", -1, (c, t, lv) -> booleanStateTest(c, "blocks_movement", lv, (s, p) -> !s.canPathfindThrough(((CarpetContext) c).s.getWorld(), p, NavigationType.LAND))); - expression.addLazyFunction("block_sound", -1, (c, t, lv) -> + expression.addContextFunction("block_sound", -1, (c, t, lv) -> stateStringQuery(c, "block_sound", lv, (s, p) -> BlockInfo.soundName.get(s.getSoundGroup()))); - expression.addLazyFunction("material", -1, (c, t, lv) -> + expression.addContextFunction("material", -1, (c, t, lv) -> stateStringQuery(c, "material", lv, (s, p) -> BlockInfo.materialName.get(s.getMaterial()))); - expression.addLazyFunction("map_colour", -1, (c, t, lv) -> + expression.addContextFunction("map_colour", -1, (c, t, lv) -> stateStringQuery(c, "map_colour", lv, (s, p) -> BlockInfo.mapColourName.get(s.getTopMaterialColor(((CarpetContext)c).s.getWorld(), p)))); // Deprecated for block_state() - expression.addLazyFunction("property", -1, (c, t, lv) -> + expression.addContextFunction("property", -1, (c, t, lv) -> { c.host.issueDeprecation("property(...)"); BlockArgument locator = BlockArgument.findIn((CarpetContext) c, lv, 0); BlockState state = locator.block.getBlockState(); if (lv.size() <= locator.offset) throw new InternalExpressionException("'property' requires to specify a property to query"); - String tag = lv.get(locator.offset).evalValue(c).getString(); + String tag = lv.get(locator.offset).getString(); StateManager states = state.getBlock().getStateManager(); Property property = states.getProperty(tag); - if (property == null) - return LazyValue.NULL; - Value retval = new StringValue(state.get(property).toString().toLowerCase(Locale.ROOT)); - return (_c, _t) -> retval; + if (property == null) return Value.NULL; + return new StringValue(state.get(property).toString().toLowerCase(Locale.ROOT)); }); // Deprecated for block_state() - expression.addLazyFunction("block_properties", -1, (c, t, lv) -> + expression.addContextFunction("block_properties", -1, (c, t, lv) -> { c.host.issueDeprecation("block_properties(...)"); BlockArgument locator = BlockArgument.findIn((CarpetContext) c, lv, 0); BlockState state = locator.block.getBlockState(); StateManager states = state.getBlock().getStateManager(); - Value res = ListValue.wrap(states.getProperties().stream().map( + return ListValue.wrap(states.getProperties().stream().map( p -> new StringValue(p.getName())).collect(Collectors.toList()) ); - return (_c, _t) -> res; }); // block_state(block) // block_state(block, property) - expression.addLazyFunction("block_state", -1, (c, t, lv) -> + expression.addContextFunction("block_state", -1, (c, t, lv) -> { BlockArgument locator = BlockArgument.findIn((CarpetContext) c, lv, 0, true); BlockState state = locator.block.getBlockState(); @@ -1173,64 +1119,51 @@ public class WorldAccess { { properties.put(StringValue.of(p.getName()), ValueConversions.fromProperty(state, p));// ValueConversions.fromObject(state.get(p), false)); } - Value ret = MapValue.wrap(properties); - return (_c, _t) -> ret; + return MapValue.wrap(properties); } - String tag = lv.get(locator.offset).evalValue(c).getString(); + String tag = lv.get(locator.offset).getString(); Property property = states.getProperty(tag); if (property == null) - return LazyValue.NULL; - Value retval = ValueConversions.fromProperty(state, property); - return (_c, _t) -> retval; + return Value.NULL; + return ValueConversions.fromProperty(state, property); }); - expression.addLazyFunction("block_list", -1, (c, t, lv) -> + expression.addContextFunction("block_list", -1, (c, t, lv) -> { if (lv.size() == 0) - { - Value ret = ListValue.wrap(Registry.BLOCK.getIds().stream().map(ValueConversions::of).collect(Collectors.toList())); - return (_c, _t) -> ret; - } + return ListValue.wrap(Registry.BLOCK.getIds().stream().map(ValueConversions::of).collect(Collectors.toList())); CarpetContext cc = (CarpetContext)c; TagManager tagManager = cc.s.getMinecraftServer().getTagManager(); - String tag = lv.get(0).evalValue(c).getString(); + String tag = lv.get(0).getString(); net.minecraft.tag.Tag blockTag = tagManager.getBlocks().getTag(new Identifier(tag)); - if (blockTag == null) return LazyValue.NULL; - Value ret = ListValue.wrap(blockTag.values().stream().map(b -> ValueConversions.of(Registry.BLOCK.getId(b))).collect(Collectors.toList())); - return (_c, _t) -> ret; + if (blockTag == null) return Value.NULL; + return ListValue.wrap(blockTag.values().stream().map(b -> ValueConversions.of(Registry.BLOCK.getId(b))).collect(Collectors.toList())); }); - expression.addLazyFunction("block_tags", -1, (c, t, lv) -> + expression.addContextFunction("block_tags", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; TagManager tagManager = cc.s.getMinecraftServer().getTagManager(); if (lv.size() == 0) - { - Value ret = ListValue.wrap(tagManager.getBlocks().getTagIds().stream().map(ValueConversions::of).collect(Collectors.toList())); - return (_c, _t) -> ret; - } + return ListValue.wrap(tagManager.getBlocks().getTagIds().stream().map(ValueConversions::of).collect(Collectors.toList())); BlockArgument blockLocator = BlockArgument.findIn(cc, lv, 0, true); if (blockLocator.offset == lv.size()) { Block target = blockLocator.block.getBlockState().getBlock(); - Value ret = ListValue.wrap(tagManager.getBlocks().getTags().entrySet().stream().filter(e -> e.getValue().contains(target)).map(e -> ValueConversions.of(e.getKey())).collect(Collectors.toList())); - return (_c, _t) -> ret; + return ListValue.wrap(tagManager.getBlocks().getTags().entrySet().stream().filter(e -> e.getValue().contains(target)).map(e -> ValueConversions.of(e.getKey())).collect(Collectors.toList())); } - String tag = lv.get(blockLocator.offset).evalValue(c).getString(); + String tag = lv.get(blockLocator.offset).getString(); net.minecraft.tag.Tag blockTag = tagManager.getBlocks().getTag(new Identifier(tag)); - if (blockTag == null) return LazyValue.NULL; - return blockLocator.block.getBlockState().isIn(blockTag)?LazyValue.TRUE:LazyValue.FALSE; + if (blockTag == null) return Value.NULL; + return BooleanValue.of(blockLocator.block.getBlockState().isIn(blockTag)); }); - expression.addLazyFunction("biome", -1, (c, t, lv) -> { + expression.addContextFunction("biome", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; ServerWorld world = cc.s.getWorld(); if (lv.size() == 0) - { - Value ret = ListValue.wrap(world.getRegistryManager().get(Registry.BIOME_KEY).getIds().stream().map(ValueConversions::of)); - return (_c, _t) -> ret; - } + return ListValue.wrap(world.getRegistryManager().get(Registry.BIOME_KEY).getIds().stream().map(ValueConversions::of)); BlockArgument locator = BlockArgument.findIn(cc, lv, 0, false, false, true); Biome biome; @@ -1248,76 +1181,70 @@ public class WorldAccess { if (locator.offset == lv.size()) { Identifier biomeId = cc.s.getMinecraftServer().getRegistryManager().get(Registry.BIOME_KEY).getId(biome); - Value res = new StringValue(NBTSerializableValue.nameFromRegistryId(biomeId)); - return (_c, _t) -> res; + return new StringValue(NBTSerializableValue.nameFromRegistryId(biomeId)); } - String biomeFeature = lv.get(locator.offset).evalValue(c).getString(); + String biomeFeature = lv.get(locator.offset).getString(); BiFunction featureProvider = BiomeInfo.biomeFeatures.get(biomeFeature); if (featureProvider == null) throw new InternalExpressionException("Unknown biome feature: "+biomeFeature); - Value ret = featureProvider.apply(world, biome); - return (_c, _t) -> ret; + return featureProvider.apply(world, biome); }); - expression.addLazyFunction("set_biome", -1, (c, t, lv) -> + expression.addContextFunction("set_biome", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; BlockArgument locator = BlockArgument.findIn(cc, lv, 0); if (lv.size() == locator.offset) throw new InternalExpressionException("'set_biome' needs a biome name as an argument"); - String biomeName = lv.get(locator.offset+0).evalValue(c).getString(); + String biomeName = lv.get(locator.offset+0).getString(); // from locatebiome command code Biome biome = cc.s.getMinecraftServer().getRegistryManager().get(Registry.BIOME_KEY).getOrEmpty(new Identifier(biomeName)) .orElseThrow(() -> new ThrowStatement(biomeName, Throwables.UNKNOWN_BIOME)); boolean doImmediateUpdate = true; if (lv.size() > locator.offset+1) { - doImmediateUpdate = lv.get(locator.offset+1).evalValue(c).getBoolean(); + doImmediateUpdate = lv.get(locator.offset+1).getBoolean(); } ServerWorld world = cc.s.getWorld(); BlockPos pos = locator.block.getPos(); Chunk chunk = world.getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.BIOMES); ((BiomeArrayInterface)chunk.getBiomeArray()).setBiomeAtIndex(pos, world, biome); if (doImmediateUpdate) WorldTools.forceChunkUpdate(pos, world); - return LazyValue.TRUE; + return Value.TRUE; }); - expression.addLazyFunction("reload_chunk", -1, (c, t, lv) -> { + expression.addContextFunction("reload_chunk", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; BlockPos pos = BlockArgument.findIn(cc, lv, 0).block.getPos(); ServerWorld world = cc.s.getWorld(); cc.s.getMinecraftServer().submitAndJoin( () -> WorldTools.forceChunkUpdate(pos, world)); - return LazyValue.TRUE; + return Value.TRUE; }); - expression.addLazyFunction("structure_references", -1, (c, t, lv) -> { + expression.addContextFunction("structure_references", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; BlockArgument locator = BlockArgument.findIn(cc, lv, 0); ServerWorld world = cc.s.getWorld(); BlockPos pos = locator.block.getPos(); Map, LongSet> references = world.getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.STRUCTURE_REFERENCES).getStructureReferences(); if (lv.size() == locator.offset) - { - //CarpetSettings.LOG.error(references.keySet().stream().collect(Collectors.joining(","))); - List referenceList = references.entrySet().stream(). + return ListValue.wrap(references.entrySet().stream(). filter(e -> e.getValue()!= null && !e.getValue().isEmpty()). - map(e -> new StringValue(NBTSerializableValue.nameFromRegistryId(Registry.STRUCTURE_FEATURE.getId(e.getKey())))).collect(Collectors.toList()); - return (_c, _t ) -> ListValue.wrap(referenceList); - } - String simpleStructureName = lv.get(locator.offset).evalValue(c).getString().toLowerCase(Locale.ROOT); + map(e -> new StringValue(NBTSerializableValue.nameFromRegistryId(Registry.STRUCTURE_FEATURE.getId(e.getKey())))).collect(Collectors.toList()) + ); + String simpleStructureName = lv.get(locator.offset).getString().toLowerCase(Locale.ROOT); //CarpetSettings.LOG.error(FeatureGenerator.featureToStructure.keySet().stream().collect(Collectors.joining(","))); //CarpetSettings.LOG.error(FeatureGenerator.featureToStructure.values().stream().collect(Collectors.joining(","))); StructureFeature structureName = Registry.STRUCTURE_FEATURE.get(new Identifier(simpleStructureName)); - if (structureName == null) return LazyValue.NULL; + if (structureName == null) return Value.NULL; LongSet structureReferences = references.get(structureName); - if (structureReferences == null || structureReferences.isEmpty()) return ListValue.lazyEmpty(); - Value ret = ListValue.wrap(structureReferences.stream().map(l -> ListValue.of( + if (structureReferences == null || structureReferences.isEmpty()) return ListValue.of(); + return ListValue.wrap(structureReferences.stream().map(l -> ListValue.of( new NumericValue(16*ChunkPos.getPackedX(l)), Value.ZERO, new NumericValue(16*ChunkPos.getPackedZ(l)))).collect(Collectors.toList())); - return (_c, _t) -> ret; }); - expression.addLazyFunction("structure_eligibility", -1, (c, t, lv) -> + expression.addContextFunction("structure_eligibility", -1, (c, t, lv) -> {// TODO rename structureName to class CarpetContext cc = (CarpetContext)c; BlockArgument locator = BlockArgument.findIn(cc, lv, 0); @@ -1332,7 +1259,7 @@ public class WorldAccess { boolean needSize = false; if (lv.size() > locator.offset) { - Value requested = lv.get(locator.offset+0).evalValue(c); + Value requested = lv.get(locator.offset+0); if (!(requested instanceof NullValue)) { String reqString = requested.getString(); @@ -1341,16 +1268,15 @@ public class WorldAccess { } if (lv.size() > locator.offset+1) { - needSize = lv.get(locator.offset+1).evalValue(c).getBoolean(); + needSize = lv.get(locator.offset+1).getBoolean(); } } if (structure != null) { StructureStart start = FeatureGenerator.shouldStructureStartAt(world, pos, structure, needSize); - if (start == null) return LazyValue.NULL; - if (!needSize) return LazyValue.TRUE; - Value ret = ValueConversions.of(start); - return (_c, _t) -> ret; + if (start == null) return Value.NULL; + if (!needSize) return Value.TRUE; + return ValueConversions.of(start); } Map ret = new HashMap<>(); for(StructureFeature str : StructureFeature.STRUCTURES.values()) @@ -1371,11 +1297,10 @@ public class WorldAccess { Value key = new StringValue(NBTSerializableValue.nameFromRegistryId(Registry.STRUCTURE_FEATURE.getId(str))); ret.put(key, (!needSize)?Value.NULL: ValueConversions.of(start)); } - Value retMap = MapValue.wrap(ret); - return (_c, _t) -> retMap; + return MapValue.wrap(ret); }); - expression.addLazyFunction("structures", -1, (c, t, lv) -> { + expression.addContextFunction("structures", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; BlockArgument locator = BlockArgument.findIn(cc, lv, 0); @@ -1396,16 +1321,13 @@ public class WorldAccess { ListValue.of(ListValue.fromTriple(box.minX, box.minY, box.minZ), ListValue.fromTriple(box.maxX, box.maxY, box.maxZ)) ); } - Value ret = MapValue.wrap(structureList); - return (_c, _t) -> ret; + return MapValue.wrap(structureList); } - String structureName = lv.get(locator.offset).evalValue(c).getString().toLowerCase(Locale.ROOT); - StructureStart start = structures.get(Registry.STRUCTURE_FEATURE.get(new Identifier(structureName))); - Value ret = ValueConversions.of(start); - return (_c, _t) -> ret; + String structureName = lv.get(locator.offset).getString().toLowerCase(Locale.ROOT); + return ValueConversions.of(structures.get(Registry.STRUCTURE_FEATURE.get(new Identifier(structureName)))); }); - expression.addLazyFunction("set_structure", -1, (c, t, lv) -> + expression.addContextFunction("set_structure", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; BlockArgument locator = BlockArgument.findIn(cc, lv, 0); @@ -1415,7 +1337,7 @@ public class WorldAccess { if (lv.size() == locator.offset) throw new InternalExpressionException("'set_structure requires at least position and a structure name"); - String structureName = lv.get(locator.offset).evalValue(c).getString().toLowerCase(Locale.ROOT); + String structureName = lv.get(locator.offset).getString().toLowerCase(Locale.ROOT); ConfiguredStructureFeature configuredStructure = FeatureGenerator.resolveConfiguredStructure(structureName, world, pos); if (configuredStructure == null) throw new ThrowStatement(structureName, Throwables.UNKNOWN_STRUCTURE); // good 'ol pointer @@ -1432,7 +1354,7 @@ public class WorldAccess { result[0] = res?Value.TRUE:Value.FALSE; return; } - Value newValue = lv.get(locator.offset+1).evalValue(c); + Value newValue = lv.get(locator.offset+1); if (newValue instanceof NullValue) // remove structure { StructureFeature structure = configuredStructure.feature; @@ -1459,21 +1381,20 @@ public class WorldAccess { result[0] = Value.TRUE; } }); - Value ret = result[0]; // preventing from lazy evaluating of the result in case a future completes later - return (_c, _t) -> ret; + return result[0]; // preventing from lazy evaluating of the result in case a future completes later }); - expression.addLazyFunction("custom_dimension", -1, (c, t, lv) -> + expression.addContextFunction("custom_dimension", -1, (c, t, lv) -> { if (lv.size() == 0) throw new InternalExpressionException("'custom_dimension' requires at least one argument"); CarpetContext cc = (CarpetContext)c; cc.host.issueDeprecation("custom_dimension()"); - String worldKey = lv.get(0).evalValue(c).getString(); + String worldKey = lv.get(0).getString(); Long seed = null; if (lv.size() > 1) { - String seedKey = lv.get(1).evalValue(c).getString(); + String seedKey = lv.get(1).getString(); try { seed = Long.parseLong(seedKey); @@ -1485,35 +1406,35 @@ public class WorldAccess { } boolean success = WorldTools.createWorld(cc.s.getMinecraftServer(), worldKey, seed); - if (!success) return LazyValue.FALSE; + if (!success) return Value.FALSE; CarpetServer.settingsManager.notifyPlayersCommandsChanged(); - return LazyValue.TRUE; + return Value.TRUE; }); - expression.addLazyFunction("reset_chunk", -1, (c, t, lv) -> + expression.addContextFunction("reset_chunk", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; List requestedChunks = new ArrayList<>(); if (lv.size() == 1) { //either one block or list of chunks - Value first = lv.get(0).evalValue(c); + Value first = lv.get(0); if (first instanceof ListValue) { List listVal = ((ListValue) first).getItems(); int offset = 0; - BlockArgument locator = BlockArgument.findInValues(cc, listVal, 0, false, false); + BlockArgument locator = BlockArgument.findIn(cc, listVal, 0); requestedChunks.add(new ChunkPos(locator.block.getPos())); while (listVal.size() > locator.offset) { - locator = BlockArgument.findInValues(cc, listVal, locator.offset, false, false); + locator = BlockArgument.findIn(cc, listVal, locator.offset); requestedChunks.add(new ChunkPos(locator.block.getPos())); } } else { - BlockArgument locator = BlockArgument.findInValues(cc, Collections.singletonList(first), 0, false, false); + BlockArgument locator = BlockArgument.findIn(cc, Collections.singletonList(first), 0); requestedChunks.add(new ChunkPos(locator.block.getPos())); } } @@ -1531,7 +1452,6 @@ public class WorldAccess { { requestedChunks.add(new ChunkPos(x,z)); } - //CarpetSettings.LOG.error("Regenerating from "+Math.min(from.x, to.x)+", "+Math.min(from.z, to.z)+" to "+Math.max(from.x, to.x)+", "+Math.max(from.z, to.z)); } else { @@ -1559,45 +1479,43 @@ public class WorldAccess { e -> new NumericValue((Integer)((Map.Entry) e).getValue()) ))); }); - return (_c, _t) -> result[0]; + return result[0]; }); - expression.addLazyFunction("inhabited_time", -1, (c, t, lv) -> + expression.addContextFunction("inhabited_time", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; BlockArgument locator = BlockArgument.findIn(cc, lv, 0); BlockPos pos = locator.block.getPos(); - Value ret = new NumericValue(cc.s.getWorld().getChunk(pos).getInhabitedTime()); - return (_c, _t) -> ret; + return new NumericValue(cc.s.getWorld().getChunk(pos).getInhabitedTime()); }); - expression.addLazyFunction("spawn_potential", -1, (c, t, lv) -> + expression.addContextFunction("spawn_potential", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; BlockArgument locator = BlockArgument.findIn(cc, lv, 0); BlockPos pos = locator.block.getPos(); double required_charge = 1; if (lv.size() > locator.offset) - required_charge = NumericValue.asNumber(lv.get(locator.offset).evalValue(c)).getDouble(); + required_charge = NumericValue.asNumber(lv.get(locator.offset)).getDouble(); SpawnHelper.Info charger = cc.s.getWorld().getChunkManager().getSpawnInfo(); - if (charger == null) return LazyValue.NULL; - Value ret = new NumericValue( + if (charger == null) return Value.NULL; + return new NumericValue( ((SpawnHelperInnerInterface)charger).getPotentialCalculator(). calculate(pos, required_charge ) ); - return (_c, _t) -> ret; }); - expression.addLazyFunction("add_chunk_ticket", -1, (c, t, lv) -> + expression.addContextFunction("add_chunk_ticket", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; BlockArgument locator = BlockArgument.findIn(cc, lv, 0); BlockPos pos = locator.block.getPos(); if (lv.size() != locator.offset+2) throw new InternalExpressionException("'add_chunk_ticket' requires block position, ticket type and radius"); - String type = lv.get(locator.offset).evalValue(c).getString(); + String type = lv.get(locator.offset).getString(); ChunkTicketType ticket = ticketTypes.get(type.toLowerCase(Locale.ROOT)); if (ticket == null) throw new InternalExpressionException("Unknown ticket type: "+type); - int radius = NumericValue.asNumber(lv.get(locator.offset+1).evalValue(c)).getInt(); + int radius = NumericValue.asNumber(lv.get(locator.offset+1)).getInt(); if (radius < 1 || radius > 32) throw new InternalExpressionException("Ticket radius should be between 1 and 32 chunks"); // due to types we will wing it: ChunkPos target = new ChunkPos(pos); @@ -1607,8 +1525,7 @@ public class WorldAccess { cc.s.getWorld().getChunkManager().addTicket(ChunkTicketType.POST_TELEPORT, target, radius, 1); else cc.s.getWorld().getChunkManager().addTicket(ChunkTicketType.UNKNOWN, target, radius, target); - Value ret = new NumericValue(ticket.getExpiryTicks()); - return (_c, _t) -> ret; + return new NumericValue(ticket.getExpiryTicks()); }); } diff --git a/src/main/java/carpet/script/argument/BlockArgument.java b/src/main/java/carpet/script/argument/BlockArgument.java index 5a0f236f..97f3ffd2 100644 --- a/src/main/java/carpet/script/argument/BlockArgument.java +++ b/src/main/java/carpet/script/argument/BlockArgument.java @@ -29,21 +29,22 @@ public class BlockArgument extends Argument block = b; this.replacement = replacement; } - public static BlockArgument findIn(CarpetContext c, List params, int offset) + + public static BlockArgument findIn(CarpetContext c, List params, int offset) { return findIn(c, params,offset, false, false, false); } - public static BlockArgument findIn(CarpetContext c, List params, int offset, boolean acceptString) + public static BlockArgument findIn(CarpetContext c, List params, int offset, boolean acceptString) { return findIn(c, params,offset, acceptString, false, false); } - public static BlockArgument findIn(CarpetContext c, List params, int offset, boolean acceptString, boolean optional, boolean anyString) + public static BlockArgument findIn(CarpetContext c, List params, int offset, boolean acceptString, boolean optional, boolean anyString) { try { - Value v1 = params.get(0 + offset).evalValue(c); + Value v1 = params.get(0 + offset); //add conditional from string name if (optional && v1 instanceof NullValue) { @@ -76,8 +77,8 @@ public class BlockArgument extends Argument 1+offset); } int xpos = (int) NumericValue.asNumber(v1).getLong(); - int ypos = (int) NumericValue.asNumber( params.get(1 + offset).evalValue(c)).getLong(); - int zpos = (int) NumericValue.asNumber( params.get(2 + offset).evalValue(c)).getLong(); + int ypos = (int) NumericValue.asNumber( params.get(1 + offset)).getLong(); + int zpos = (int) NumericValue.asNumber( params.get(2 + offset)).getLong(); return new BlockArgument( new BlockValue( null, diff --git a/src/main/java/carpet/script/argument/FileArgument.java b/src/main/java/carpet/script/argument/FileArgument.java index 104f04f1..fa4cbed3 100644 --- a/src/main/java/carpet/script/argument/FileArgument.java +++ b/src/main/java/carpet/script/argument/FileArgument.java @@ -117,11 +117,11 @@ public class FileArgument return "path: "+resource+" zip: "+zipContainer+" type: "+type.id+" folder: "+isFolder+" shared: "+isShared+" reason: "+reason.toString(); } - public static FileArgument from(List lv, Context c, boolean isFolder, Reason reason) + public static FileArgument from(List lv, boolean isFolder, Reason reason) { if (lv.size() < 2) throw new InternalExpressionException("File functions require path and type as first two arguments"); - Pair resource = recognizeResource(lv.get(0).evalValue(c), isFolder); - String origtype = lv.get(1).evalValue(c).getString().toLowerCase(Locale.ROOT); + Pair resource = recognizeResource(lv.get(0), isFolder); + String origtype = lv.get(1).getString().toLowerCase(Locale.ROOT); boolean shared = origtype.startsWith("shared_"); String typeString = shared ? origtype.substring(7) : origtype; //len(shared_) Type type = Type.of.get(typeString); diff --git a/src/main/java/carpet/script/argument/FunctionArgument.java b/src/main/java/carpet/script/argument/FunctionArgument.java index ecd09034..64fc1587 100644 --- a/src/main/java/carpet/script/argument/FunctionArgument.java +++ b/src/main/java/carpet/script/argument/FunctionArgument.java @@ -16,12 +16,12 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -public class FunctionArgument extends Argument +public class FunctionArgument extends Argument { public FunctionValue function; - public List args; + public List args; - private FunctionArgument(FunctionValue function, int offset, List args) + private FunctionArgument(FunctionValue function, int offset, List args) { super(offset); this.function = function; @@ -39,18 +39,18 @@ public class FunctionArgument extends Argument * if the number of supplied arguments is right * @return argument data */ - public static FunctionArgument findIn( + public static FunctionArgument findIn( Context c, Module module, - List params, + List params, int offset, boolean allowNone, boolean checkArgs) { - Value functionValue = params.get(offset).evalValue(c); + Value functionValue = params.get(offset); if (functionValue.isNull()) { - if (allowNone) return new FunctionArgument<>(null, offset+1, Collections.emptyList()); + if (allowNone) return new FunctionArgument(null, offset+1, Collections.emptyList()); throw new InternalExpressionException("function argument cannot be null"); } if (!(functionValue instanceof FunctionValue)) @@ -68,12 +68,12 @@ public class FunctionArgument extends Argument if (extraargs > 0 && fun.getVarArgs() == null) throw new InternalExpressionException("Function " + fun.getPrettyString() + " requires " + fun.getArguments().size() + " arguments"); } - List lvargs = new ArrayList<>(); + List lvargs = new ArrayList<>(); for (int i = offset+1, mx = params.size(); i < mx; i++) lvargs.add(params.get(i)); - return new FunctionArgument<>(fun, offset + 1 + argsize, lvargs); + return new FunctionArgument(fun, offset + 1 + argsize, lvargs); } - public static FunctionArgument fromCommandSpec(ScriptHost host, Value funSpec) throws CommandSyntaxException { + public static FunctionArgument fromCommandSpec(ScriptHost host, Value funSpec) throws CommandSyntaxException { FunctionValue function; List args = Collections.emptyList(); if (!(funSpec instanceof ListValue)) @@ -93,16 +93,11 @@ public class FunctionArgument extends Argument } if (params.size() > 1) args = params.subList(1,params.size()); - return new FunctionArgument<>(function, 0, args); + return new FunctionArgument(function, 0, args); } - public void checkArgs() { + public List checkedArgs() { function.checkArgs(args.size()); - } - - public List unpackArgs(Context c) { - List unpackedArgs = Fluff.AbstractFunction.unpackArgs((List) args, c); - function.checkArgs(unpackedArgs.size()); - return unpackedArgs; + return args; } } diff --git a/src/main/java/carpet/script/argument/Vector3Argument.java b/src/main/java/carpet/script/argument/Vector3Argument.java index 003ffc4c..1dc440f1 100644 --- a/src/main/java/carpet/script/argument/Vector3Argument.java +++ b/src/main/java/carpet/script/argument/Vector3Argument.java @@ -47,66 +47,12 @@ public class Vector3Argument extends Argument return this; } - - public static Vector3Argument findIn(CarpetContext c, List params, int offset) + public static Vector3Argument findIn(List params, int offset) { - return findIn(c,params, offset, false, false); + return findIn(params, offset, false, false); } - public static Vector3Argument findIn(CarpetContext c, List params, int offset, boolean optionalDirection, boolean optionalEntity) - { - try - { - Value v1 = params.get(0 + offset).evalValue(c); - if (v1 instanceof BlockValue) - { - // pos + 0.5v - return (new Vector3Argument(Vec3d.ofCenter(((BlockValue) v1).getPos()), 1+offset)).fromBlock(); - } - if (optionalEntity && v1 instanceof EntityValue) - { - Entity e = ((EntityValue) v1).getEntity(); - return new Vector3Argument(e.getPos(), 1+offset).withEntity(e); - } - if (v1 instanceof ListValue) - { - List args = ((ListValue) v1).getItems(); - Vec3d pos = new Vec3d( - NumericValue.asNumber(args.get(0)).getDouble(), - NumericValue.asNumber(args.get(1)).getDouble(), - NumericValue.asNumber(args.get(2)).getDouble()); - double yaw = 0.0D; - double pitch = 0.0D; - if (args.size()>3 && optionalDirection) - { - yaw = NumericValue.asNumber(args.get(3)).getDouble(); - pitch = NumericValue.asNumber(args.get(4)).getDouble(); - } - return new Vector3Argument(pos,offset+1, yaw, pitch); - } - Vec3d pos = new Vec3d( - NumericValue.asNumber(v1).getDouble(), - NumericValue.asNumber(params.get(1 + offset).evalValue(c)).getDouble(), - NumericValue.asNumber(params.get(2 + offset).evalValue(c)).getDouble()); - double yaw = 0.0D; - double pitch = 0.0D; - int eatenLength = 3; - if (params.size()>3+offset && optionalDirection) - { - yaw = NumericValue.asNumber(params.get(3 + offset).evalValue(c)).getDouble(); - pitch = NumericValue.asNumber(params.get(4 + offset).evalValue(c)).getDouble(); - eatenLength = 5; - } - - return new Vector3Argument(pos,offset+eatenLength, yaw, pitch); - } - catch (IndexOutOfBoundsException e) - { - throw new InternalExpressionException("Position argument should be defined either by three coordinates (a triple or by three arguments), or a positioned block value"); - } - } - - public static Vector3Argument findIn(List params, int offset, boolean optionalDirection) + public static Vector3Argument findIn(List params, int offset, boolean optionalDirection, boolean optionalEntity) { try { @@ -115,6 +61,11 @@ public class Vector3Argument extends Argument { return (new Vector3Argument(Vec3d.ofCenter(((BlockValue) v1).getPos()), 1+offset)).fromBlock(); } + if (optionalEntity && v1 instanceof EntityValue) + { + Entity e = ((EntityValue) v1).getEntity(); + return new Vector3Argument(e.getPos(), 1+offset).withEntity(e); + } if (v1 instanceof ListValue) { List args = ((ListValue) v1).getItems(); diff --git a/src/main/java/carpet/script/command/CommandArgument.java b/src/main/java/carpet/script/command/CommandArgument.java index 5ca2f191..367558bc 100644 --- a/src/main/java/carpet/script/command/CommandArgument.java +++ b/src/main/java/carpet/script/command/CommandArgument.java @@ -291,7 +291,7 @@ public abstract class CommandArgument protected boolean needsMatching; protected boolean caseSensitive = true; protected SuggestionProvider suggestionProvider; - protected FunctionArgument customSuggester; + protected FunctionArgument customSuggester; protected CommandArgument( diff --git a/src/main/java/carpet/script/language/Arithmetic.java b/src/main/java/carpet/script/language/Arithmetic.java index c5e64034..8bdb3c94 100644 --- a/src/main/java/carpet/script/language/Arithmetic.java +++ b/src/main/java/carpet/script/language/Arithmetic.java @@ -64,10 +64,10 @@ public class Arithmetic { expression.addMathematicalUnaryIntFunction("floor", n -> (long)Math.floor(n)); expression.addMathematicalUnaryIntFunction("ceil", n -> (long)Math.ceil(n)); - expression.addLazyFunction("mandelbrot", 3, (c, t, lv) -> { - double a0 = NumericValue.asNumber(lv.get(0).evalValue(c)).getDouble(); - double b0 = NumericValue.asNumber(lv.get(1).evalValue(c)).getDouble(); - long maxiter = NumericValue.asNumber(lv.get(2).evalValue(c)).getLong(); + expression.addContextFunction("mandelbrot", 3, (c, t, lv) -> { + double a0 = NumericValue.asNumber(lv.get(0)).getDouble(); + double b0 = NumericValue.asNumber(lv.get(1)).getDouble(); + long maxiter = NumericValue.asNumber(lv.get(2)).getLong(); double a = 0.0D; double b = 0.0D; long iter = 0; @@ -79,7 +79,7 @@ public class Arithmetic { iter++; } long iFinal = iter; - return (cc, tt) -> new NumericValue(iFinal); + return new NumericValue(iFinal); }); expression.addFunction("max", (lv) -> diff --git a/src/main/java/carpet/script/language/ControlFlow.java b/src/main/java/carpet/script/language/ControlFlow.java index e094309e..cfb78fed 100644 --- a/src/main/java/carpet/script/language/ControlFlow.java +++ b/src/main/java/carpet/script/language/ControlFlow.java @@ -20,6 +20,7 @@ import java.util.stream.Collectors; public class ControlFlow { public static void apply(Expression expression) // public just to get the javadoc right { + // needs to be lazy cause of custom contextualization expression.addLazyBinaryOperator(";", Operators.precedence.get("nextop;"), true, (c, t, lv1, lv2) -> { lv1.evalValue(c, Context.VOID); @@ -27,7 +28,7 @@ public class ControlFlow { return (cc, tt) -> v2; }); - // if(cond1, expr1, cond2, expr2, ..., ?default) => value + // obvious lazy due to conditional evaluation of arguments expression.addLazyFunction("if", -1, (c, t, lv) -> { if ( lv.size() < 2 ) @@ -51,23 +52,24 @@ public class ControlFlow { expression.addFunction("exit", (lv) -> { throw new ExitStatement(lv.size()==0?Value.NULL:lv.get(0)); }); - expression.addLazyFunction("throw", -1, (c, t, lv)-> + expression.addFunction("throw", lv-> { switch (lv.size()) { case 0: throw new ThrowStatement(Value.NULL, Throwables.USER_DEFINED); case 1: - throw new ThrowStatement(lv.get(0).evalValue(c), Throwables.USER_DEFINED ); + throw new ThrowStatement(lv.get(0), Throwables.USER_DEFINED ); case 2: - throw new ThrowStatement(lv.get(1).evalValue(c), Throwables.getTypeForException(lv.get(0).evalValue(c).getString())); + throw new ThrowStatement(lv.get(1), Throwables.getTypeForException(lv.get(0).getString())); case 3: - throw new ThrowStatement(lv.get(2).evalValue(c), Throwables.getTypeForException(lv.get(1).evalValue(c).getString()), lv.get(0).evalValue(c).getString()); + throw new ThrowStatement(lv.get(2), Throwables.getTypeForException(lv.get(1).getString()), lv.get(0).getString()); default: throw new InternalExpressionException("throw() can't accept more than 3 parameters"); } }); + // needs to be lazy since execution of parameters but first one are conditional expression.addLazyFunction("try", -1, (c, t, lv) -> { if (lv.size()==0) diff --git a/src/main/java/carpet/script/language/DataStructures.java b/src/main/java/carpet/script/language/DataStructures.java index 59418de5..b97d3b49 100644 --- a/src/main/java/carpet/script/language/DataStructures.java +++ b/src/main/java/carpet/script/language/DataStructures.java @@ -95,6 +95,7 @@ public class DataStructures { return ListValue.wrap(toSort); }); + // needs lazy cause sort function is reused expression.addLazyFunction("sort_key", -1, (c, t, lv) -> //get working with iterators { if (lv.size() == 0) @@ -121,7 +122,8 @@ public class DataStructures { }); //revering scope c.setVariable("_", __); - return (cc, tt) -> ListValue.wrap(toSort); + Value ret = ListValue.wrap(toSort); + return (cc, tt) -> ret; }); expression.addFunction("range", (lv) -> @@ -147,18 +149,14 @@ public class DataStructures { : LazyListValue.rangeDouble(from.getDouble(), to.getDouble(), step.getDouble()); }); - expression.addLazyFunction("m", -1, (c, t, llv) -> + expression.addTypedContextFunction("m", -1, Context.MAPDEF, (c, t, lv) -> { - List lv = new ArrayList<>(); - for (LazyValue lazyParam : llv) { - lv.add(lazyParam.evalValue(c, Context.MAPDEF)); // none type default by design - } Value ret; if (lv.size() == 1 && lv.get(0) instanceof LazyListValue) ret = new MapValue(((LazyListValue) lv.get(0)).unroll()); else ret = new MapValue(lv); - return (cc, tt) -> ret; + return ret; }); expression.addUnaryFunction("keys", v -> @@ -184,41 +182,23 @@ public class DataStructures { return Value.NULL; }); - expression.addLazyBinaryOperator(":", Operators.precedence.get("attribute~:"),true, (c, t, container_lv, key_lv) -> + expression.addBinaryContextOperator(":", Operators.precedence.get("attribute~:"),true, (c, t, container, address) -> { - Value container = container_lv.evalValue(c); if (container instanceof LContainerValue) { ContainerValueInterface outerContainer = ((LContainerValue) container).getContainer(); - if (outerContainer == null) - { - Value innerLValue = new LContainerValue(null, null); - return (cc, tt) -> innerLValue; - } + if (outerContainer == null) return LContainerValue.NULL_CONTAINER; Value innerContainer = outerContainer.get(((LContainerValue) container).getAddress()); - if (!(innerContainer instanceof ContainerValueInterface)) - { - Value innerLValue = new LContainerValue(null, null); - return (cc, tt) -> innerLValue; - } - Value innerLValue = new LContainerValue((ContainerValueInterface) innerContainer, key_lv.evalValue(c)); - return (cc, tt) -> innerLValue; + if (!(innerContainer instanceof ContainerValueInterface)) return LContainerValue.NULL_CONTAINER; + return new LContainerValue((ContainerValueInterface) innerContainer, address); } if (!(container instanceof ContainerValueInterface)) - if (t == Context.LVALUE) - return (cc, tt) -> new LContainerValue(null, null); - else - return (cc, tt) -> Value.NULL; - Value address = key_lv.evalValue(c); - if (t != Context.LVALUE) - { - Value retVal = ((ContainerValueInterface) container).get(address); - return (cc, ct) -> retVal; - } - Value retVal = new LContainerValue((ContainerValueInterface) container, address); - return (cc, ct) -> retVal; + return t == Context.LVALUE ? LContainerValue.NULL_CONTAINER : Value.NULL; + if (t != Context.LVALUE) return ((ContainerValueInterface) container).get(address); + return new LContainerValue((ContainerValueInterface) container, address); }); + // lazy cause conditional typing - questionable expression.addLazyFunction("get", -1, (c, t, lv) -> { if (lv.size() == 0) @@ -227,10 +207,10 @@ public class DataStructures { { Value v = lv.get(0).evalValue(c, Context.LVALUE); if (!(v instanceof LContainerValue)) - return (cc, tt) -> Value.NULL; + return LazyValue.NULL; ContainerValueInterface container = ((LContainerValue) v).getContainer(); if (container == null) - return (cc, tt) -> Value.NULL; + return LazyValue.NULL; Value ret = container.get(((LContainerValue) v).getAddress()); return (cc, tt) -> ret; } @@ -246,6 +226,7 @@ public class DataStructures { return (cc, tt) -> finalContainer; }); + // same as `get` expression.addLazyFunction("has", -1, (c, t, lv) -> { if (lv.size() == 0) @@ -254,25 +235,26 @@ public class DataStructures { { Value v = lv.get(0).evalValue(c, Context.LVALUE); if (!(v instanceof LContainerValue)) - return (cc, tt) -> Value.NULL; + return LazyValue.NULL; ContainerValueInterface container = ((LContainerValue) v).getContainer(); if (container == null) - return (cc, tt) -> Value.NULL; + return LazyValue.NULL; Value ret = new NumericValue(container.has(((LContainerValue) v).getAddress())); return (cc, tt) -> ret; } Value container = lv.get(0).evalValue(c); for (int i = 1; i < lv.size()-1; i++) { - if (!(container instanceof ContainerValueInterface)) return (cc, tt) -> Value.NULL; + if (!(container instanceof ContainerValueInterface)) return LazyValue.NULL; container = ((ContainerValueInterface) container).get(lv.get(i).evalValue(c)); } if (!(container instanceof ContainerValueInterface)) - return (cc, tt) -> Value.NULL; + return LazyValue.NULL; Value ret = new NumericValue(((ContainerValueInterface) container).has(lv.get(lv.size()-1).evalValue(c))); return (cc, tt) -> ret; }); + // same as `get` expression.addLazyFunction("put", -1, (c, t, lv) -> { if(lv.size()<2) @@ -285,7 +267,7 @@ public class DataStructures { ContainerValueInterface internalContainer = ((LContainerValue) container).getContainer(); if (internalContainer == null) { - return (cc, tt) -> Value.NULL; + return LazyValue.NULL; } Value address = ((LContainerValue) container).getAddress(); Value what = lv.get(1).evalValue(c); @@ -301,7 +283,7 @@ public class DataStructures { } if (!(container instanceof ContainerValueInterface)) { - return (cc, tt) -> Value.NULL; + return LazyValue.NULL; } Value where = lv.get(1).evalValue(c); Value what = lv.get(2).evalValue(c); @@ -311,6 +293,7 @@ public class DataStructures { return (cc, tt) -> retVal; }); + // same as `get` expression.addLazyFunction("delete", -1, (c, t, lv) -> { if (lv.size() == 0) @@ -319,21 +302,21 @@ public class DataStructures { { Value v = lv.get(0).evalValue(c, Context.LVALUE); if (!(v instanceof LContainerValue)) - return (cc, tt) -> Value.NULL; + return LazyValue.NULL; ContainerValueInterface container = ((LContainerValue) v).getContainer(); if (container == null) - return (cc, tt) -> Value.NULL; + return LazyValue.NULL; Value ret = new NumericValue(container.delete(((LContainerValue) v).getAddress())); return (cc, tt) -> ret; } Value container = lv.get(0).evalValue(c); for (int i = 1; i < lv.size()-1; i++) { - if (!(container instanceof ContainerValueInterface)) return (cc, tt) -> Value.NULL; + if (!(container instanceof ContainerValueInterface)) return LazyValue.NULL; container = ((ContainerValueInterface) container).get(lv.get(i).evalValue(c)); } if (!(container instanceof ContainerValueInterface)) - return (cc, tt) -> Value.NULL; + return LazyValue.NULL; Value ret = new NumericValue(((ContainerValueInterface) container).delete(lv.get(lv.size()-1).evalValue(c))); return (cc, tt) -> ret; }); diff --git a/src/main/java/carpet/script/language/Functions.java b/src/main/java/carpet/script/language/Functions.java index 5c03dd13..25fa7825 100644 --- a/src/main/java/carpet/script/language/Functions.java +++ b/src/main/java/carpet/script/language/Functions.java @@ -2,12 +2,13 @@ package carpet.script.language; import carpet.script.Context; import carpet.script.Expression; -import carpet.script.LazyValue; +import carpet.script.Fluff; import carpet.script.argument.FunctionArgument; import carpet.script.exception.InternalExpressionException; import carpet.script.exception.ReturnStatement; import carpet.script.value.AbstractListValue; import carpet.script.value.FunctionSignatureValue; +import carpet.script.value.FunctionUnpackedArgumentsValue; import carpet.script.value.FunctionValue; import carpet.script.value.FunctionAnnotationValue; import carpet.script.value.ListValue; @@ -24,20 +25,20 @@ public class Functions { public static void apply(Expression expression) // public just to get the javadoc right { // artificial construct to handle user defined functions and function definitions - expression.addLazyFunction("import", -1, (c, t, lv) -> + expression.addContextFunction("import", -1, (c, t, lv) -> { if (lv.size() < 1) throw new InternalExpressionException("'import' needs at least a module name to import, and list of values to import"); - String moduleName = lv.get(0).evalValue(c).getString(); + String moduleName = lv.get(0).getString(); c.host.importModule(c, moduleName); moduleName = moduleName.toLowerCase(Locale.ROOT); if (lv.size() > 1) - c.host.importNames(c, expression.module, moduleName, lv.subList(1, lv.size()).stream().map((l) -> l.evalValue(c).getString()).collect(Collectors.toList())); + c.host.importNames(c, expression.module, moduleName, lv.subList(1, lv.size()).stream().map(Value::getString).collect(Collectors.toList())); if (t == Context.VOID) - return LazyValue.NULL; - ListValue list = ListValue.wrap(c.host.availableImports(moduleName).map(StringValue::new).collect(Collectors.toList())); - return (cc, tt) -> list; + return Value.NULL; + return ListValue.wrap(c.host.availableImports(moduleName).map(StringValue::new).collect(Collectors.toList())); }); + // needs to be lazy because of custom context of execution of arguments as a signature expression.addLazyFunctionWithDelegation("call",-1, (c, t, expr, tok, lv) -> { // adjust based on c if (lv.size() == 0) @@ -45,7 +46,8 @@ public class Functions { //lv.remove(lv.size()-1); // aint gonna cut it // maybe it will because of the eager eval changes if (t != Context.SIGNATURE) // just call the function { - FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 0, false, true); + List args = Fluff.AbstractFunction.unpackLazy(lv, c, Context.NONE); + FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, args, 0, false, true); FunctionValue fun = functionArgument.function; return fun.callInContext(c, t, functionArgument.args); } @@ -63,7 +65,7 @@ public class Functions { } if (v instanceof FunctionAnnotationValue) { - if (((FunctionAnnotationValue) v).type == 0) + if (((FunctionAnnotationValue) v).type == FunctionAnnotationValue.Type.GLOBAL) { globals.add(v.boundVariable); } @@ -83,32 +85,37 @@ public class Functions { return (cc, tt) -> retval; }); - expression.addLazyFunction("outer", 1, (c, t, lv) -> + expression.addContextFunction("outer", 1, (c, t, lv) -> { if (t != Context.LOCALIZATION) throw new InternalExpressionException("Outer scoping of variables is only possible in function signatures."); - return (cc, tt) -> new FunctionAnnotationValue(lv.get(0).evalValue(c), 0); + return new FunctionAnnotationValue(lv.get(0), FunctionAnnotationValue.Type.GLOBAL); }); + // lazy because of typed evaluation of the argument expression.addLazyUnaryOperator("...", Operators.precedence.get("def->..."), false, (c, t, lv) -> { if (t == Context.LOCALIZATION) - return (cc, tt) -> new FunctionAnnotationValue(lv.evalValue(c), 1); - if (t == Context.CALLARGS) - { - Value params = lv.evalValue(c, Context.NONE); - if (params instanceof ListValue) - return (cc, tt) -> params; - if (!(params instanceof AbstractListValue)) - throw new InternalExpressionException("Unable to unpack a non-list"); - Value unpacked = ListValue.wrap(ImmutableList.copyOf(((AbstractListValue) params).iterator())); - return (cc, tt) -> unpacked; - } - throw new InternalExpressionException("That functionality has not been implemented yet."); + return (cc, tt) -> new FunctionAnnotationValue(lv.evalValue(c), FunctionAnnotationValue.Type.VARARG); + Value params = lv.evalValue(c, t); + FunctionUnpackedArgumentsValue fuaval; + if (params instanceof ListValue) + { + fuaval = new FunctionUnpackedArgumentsValue(((ListValue) params).getItems()); + return (cc, tt) -> fuaval; + } + if (!(params instanceof AbstractListValue)) + throw new InternalExpressionException("Unable to unpack a non-list"); + fuaval = new FunctionUnpackedArgumentsValue( + ImmutableList.copyOf(((AbstractListValue) params).iterator()) + ); + return (cc, tt) -> fuaval; + //throw new InternalExpressionException("That functionality has not been implemented yet."); }); //assigns const procedure to the lhs, returning its previous value + // must be lazy due to RHS being an expression to save to execute expression.addLazyBinaryOperatorWithDelegation("->", Operators.precedence.get("def->..."), false, (c, type, e, t, lv1, lv2) -> { if (type == Context.MAPDEF) diff --git a/src/main/java/carpet/script/language/Loops.java b/src/main/java/carpet/script/language/Loops.java index ad041cd2..4a566b07 100644 --- a/src/main/java/carpet/script/language/Loops.java +++ b/src/main/java/carpet/script/language/Loops.java @@ -35,6 +35,7 @@ public class Loops { throw new InternalExpressionException("'continue' can only be called with zero or one argument"); }); + // lazy expression.addLazyFunction("while", 3, (c, t, lv) -> { long limit = NumericValue.asNumber(lv.get(1).evalValue(c)).getLong(); diff --git a/src/main/java/carpet/script/language/Operators.java b/src/main/java/carpet/script/language/Operators.java index b3548992..389623e1 100644 --- a/src/main/java/carpet/script/language/Operators.java +++ b/src/main/java/carpet/script/language/Operators.java @@ -44,6 +44,7 @@ public class Operators { expression.addBinaryOperator("^", precedence.get("exponent^"), false, (v1, v2) -> new NumericValue(java.lang.Math.pow(NumericValue.asNumber(v1).getDouble(), NumericValue.asNumber(v2).getDouble()))); + // lazy cause RHS is only conditional expression.addLazyBinaryOperator("&&", precedence.get("and&&"), false, (c, t, lv1, lv2) -> { Value v1 = lv1.evalValue(c, Context.BOOLEAN); @@ -51,6 +52,7 @@ public class Operators { return lv2; }); + // lazy cause RHS is only conditional expression.addLazyBinaryOperator("||", precedence.get("or||"), false, (c, t, lv1, lv2) -> { Value v1 = lv1.evalValue(c, Context.BOOLEAN); @@ -73,6 +75,7 @@ public class Operators { expression.addBinaryOperator("!=", precedence.get("equal==!="), false, (v1, v2) -> v1.equals(v2) ? Value.FALSE : Value.TRUE); + // lazy cause of assignment which is non-trivial expression.addLazyBinaryOperator("=", precedence.get("assign=<>"), false, (c, t, lv1, lv2) -> { Value v1 = lv1.evalValue(c, Context.LVALUE); @@ -111,6 +114,7 @@ public class Operators { return boundedLHS; }); + // lazy due to assignment expression.addLazyBinaryOperator("+=", precedence.get("assign=<>"), false, (c, t, lv1, lv2) -> { Value v1 = lv1.evalValue(c, Context.LVALUE); @@ -171,10 +175,8 @@ public class Operators { return boundedLHS; }); - expression.addLazyBinaryOperator("<>", precedence.get("assign=<>"), false, (c, t, lv1, lv2) -> + expression.addBinaryContextOperator("<>", precedence.get("assign=<>"), false, (c, t, v1, v2) -> { - Value v1 = lv1.evalValue(c); - Value v2 = lv2.evalValue(c); if (v1 instanceof ListValue.ListConstructorValue && v2 instanceof ListValue.ListConstructorValue) { List ll = ((ListValue)v1).getItems(); @@ -196,7 +198,7 @@ public class Operators { expression.setAnyVariable(c, lname, (cc, tt) -> rval); expression.setAnyVariable(c, rname, (cc, tt) -> lval); } - return (cc, tt) -> Value.TRUE; + return Value.TRUE; } v1.assertAssignable(); v2.assertAssignable(); @@ -206,13 +208,14 @@ public class Operators { Value rval = v1.reboundedTo(rvalvar); expression.setAnyVariable(c, lvalvar, (cc, tt) -> lval); expression.setAnyVariable(c, rvalvar, (cc, tt) -> rval); - return (cc, tt) -> lval; + return lval; }); expression.addUnaryOperator("-", false, v -> NumericValue.asNumber(v).opposite()); expression.addUnaryOperator("+", false, NumericValue::asNumber); + // could be non-lazy, but who cares - its a small one. expression.addLazyUnaryOperator("!", precedence.get("unary+-!"), false, (c, t, lv)-> lv.evalValue(c, Context.BOOLEAN).getBoolean() ? (cc, tt)-> Value.FALSE : (cc, tt) -> Value.TRUE); // might need context boolean } diff --git a/src/main/java/carpet/script/language/Sys.java b/src/main/java/carpet/script/language/Sys.java index dc2a75df..c9481537 100644 --- a/src/main/java/carpet/script/language/Sys.java +++ b/src/main/java/carpet/script/language/Sys.java @@ -7,6 +7,7 @@ import carpet.script.ScriptHost; import carpet.script.exception.InternalExpressionException; import carpet.script.utils.PerlinNoiseSampler; import carpet.script.utils.SimplexNoiseSampler; +import carpet.script.value.BooleanValue; import carpet.script.value.FunctionValue; import carpet.script.value.ListValue; import carpet.script.value.NullValue; @@ -37,19 +38,15 @@ public class Sys { expression.addUnaryFunction("copy", Value::deepcopy); - expression.addLazyFunction("bool", 1, (c, t, lv) -> + expression.addTypedContextFunction("bool", 1, Context.BOOLEAN, (c, t, lv) -> { - Value v = lv.get(0).evalValue(c, Context.BOOLEAN); + Value v = lv.get(0); if (v instanceof StringValue) { - String str = v.getString(); - if ("false".equalsIgnoreCase(str) || "null".equalsIgnoreCase(str)) - { - return (cc, tt) -> Value.FALSE; - } + String str = v.getString().toLowerCase(Locale.ROOT); + if ("false".equals(str) || "null".equals(str)) return Value.FALSE; } - Value retval = v.getBoolean()?Value.TRUE:Value.FALSE; - return (cc, tt) -> retval; + return BooleanValue.of(v.getBoolean()); }); expression.addUnaryFunction("number", v -> @@ -187,45 +184,40 @@ public class Sys { expression.addUnaryFunction("type", v -> new StringValue(v.getTypeString())); expression.addUnaryFunction("length", v -> new NumericValue(v.length())); - expression.addLazyFunction("rand", -1, (c, t, lv) -> + expression.addContextFunction("rand", -1, (c, t, lv) -> { int argsize = lv.size(); Random randomizer = Sys.randomizer; if (argsize != 1 && argsize != 2) throw new InternalExpressionException("'rand' takes one (range) or two arguments (range and seed)"); - if (argsize == 2) randomizer = c.host.getRandom(NumericValue.asNumber(lv.get(1).evalValue(c)).getLong()); - Value argument = lv.get(0).evalValue(c); + if (argsize == 2) randomizer = c.host.getRandom(NumericValue.asNumber(lv.get(1)).getLong()); + Value argument = lv.get(0); if (argument instanceof ListValue) { List list = ((ListValue) argument).getItems(); - Value retval = list.get(randomizer.nextInt(list.size())); - return (cc, tt) -> retval; + return list.get(randomizer.nextInt(list.size())); } + double value = NumericValue.asNumber(argument).getDouble()*randomizer.nextDouble(); if (t == Context.BOOLEAN) - { - double rv = NumericValue.asNumber(argument).getDouble()*randomizer.nextFloat(); - Value retval = rv<1.0D?Value.FALSE:Value.TRUE; - return (cc, tt) -> retval; - } - Value retval = new NumericValue(NumericValue.asNumber(argument).getDouble()*randomizer.nextDouble()); - return (cc, tt) -> retval; + return BooleanValue.of(value >= 1.0D); + return new NumericValue(value); }); - expression.addLazyFunction("reset_seed", 1, (c, t, lv) -> { - boolean gotIt = c.host.resetRandom(NumericValue.asNumber(lv.get(0).evalValue(c)).getLong()); - return gotIt?LazyValue.TRUE:LazyValue.FALSE; + expression.addContextFunction("reset_seed", 1, (c, t, lv) -> { + boolean gotIt = c.host.resetRandom(NumericValue.asNumber(lv.get(0)).getLong()); + return BooleanValue.of(gotIt); }); - expression.addLazyFunction("perlin", -1, (c, t, lv) -> + expression.addFunction("perlin", lv -> { PerlinNoiseSampler sampler; Value x, y, z; if (lv.size() >= 4) { - x = lv.get(0).evalValue(c); - y = lv.get(1).evalValue(c); - z = lv.get(2).evalValue(c); - sampler = PerlinNoiseSampler.getPerlin(NumericValue.asNumber(lv.get(3).evalValue(c)).getLong()); + x = lv.get(0); + y = lv.get(1); + z = lv.get(2); + sampler = PerlinNoiseSampler.getPerlin(NumericValue.asNumber(lv.get(3)).getLong()); } else { @@ -234,12 +226,12 @@ public class Sys { z = Value.NULL; if (lv.size() == 0 ) throw new InternalExpressionException("'perlin' requires at least one dimension to sample from"); - x = NumericValue.asNumber(lv.get(0).evalValue(c)); + x = NumericValue.asNumber(lv.get(0)); if (lv.size() > 1) { - y = NumericValue.asNumber(lv.get(1).evalValue(c)); + y = NumericValue.asNumber(lv.get(1)); if (lv.size() > 2) - z = NumericValue.asNumber(lv.get(2).evalValue(c)); + z = NumericValue.asNumber(lv.get(2)); } } @@ -255,21 +247,20 @@ public class Sys { NumericValue.asNumber(x).getDouble(), NumericValue.asNumber(y).getDouble(), NumericValue.asNumber(z).getDouble()); - Value ret = new NumericValue(result); - return (cc, tt) -> ret; + return new NumericValue(result); }); - expression.addLazyFunction("simplex", -1, (c, t, lv) -> + expression.addFunction("simplex", lv -> { SimplexNoiseSampler sampler; Value x, y, z; if (lv.size() >= 4) { - x = lv.get(0).evalValue(c); - y = lv.get(1).evalValue(c); - z = lv.get(2).evalValue(c); - sampler = SimplexNoiseSampler.getSimplex(NumericValue.asNumber(lv.get(3).evalValue(c)).getLong()); + x = lv.get(0); + y = lv.get(1); + z = lv.get(2); + sampler = SimplexNoiseSampler.getSimplex(NumericValue.asNumber(lv.get(3)).getLong()); } else { @@ -277,10 +268,10 @@ public class Sys { z = Value.NULL; if (lv.size() < 2 ) throw new InternalExpressionException("'simplex' requires at least two dimensions to sample from"); - x = NumericValue.asNumber(lv.get(0).evalValue(c)); - y = NumericValue.asNumber(lv.get(1).evalValue(c)); + x = NumericValue.asNumber(lv.get(0)); + y = NumericValue.asNumber(lv.get(1)); if (lv.size() > 2) - z = NumericValue.asNumber(lv.get(2).evalValue(c)); + z = NumericValue.asNumber(lv.get(2)); } double result; @@ -291,8 +282,7 @@ public class Sys { NumericValue.asNumber(x).getDouble(), NumericValue.asNumber(y).getDouble(), NumericValue.asNumber(z).getDouble()); - Value ret = new NumericValue(result); - return (cc, tt) -> ret; + return new NumericValue(result); }); expression.addUnaryFunction("print", (v) -> @@ -301,17 +291,11 @@ public class Sys { return v; // pass through for variables }); - expression.addLazyFunction("time", 0, (c, t, lv) -> - { - Value time = new NumericValue((System.nanoTime() / 1000) / 1000.0); - return (cc, tt) -> time; - }); + expression.addContextFunction("time", 0, (c, t, lv) -> + new NumericValue((System.nanoTime() / 1000.0) / 1000.0)); - expression.addLazyFunction("unix_time", 0, (c, t, lv) -> - { - Value time = new NumericValue(System.currentTimeMillis()); - return (cc, tt) -> time; - }); + expression.addContextFunction("unix_time", 0, (c, t, lv) -> + new NumericValue(System.currentTimeMillis())); expression.addFunction("convert_date", lv -> { @@ -324,7 +308,7 @@ public class Sys { cal.setTimeInMillis(NumericValue.asNumber(value, "timestamp").getLong()); int weekday = cal.get(Calendar.DAY_OF_WEEK)-1; if (weekday == 0) weekday = 7; - Value retVal = ListValue.ofNums( + return ListValue.ofNums( cal.get(Calendar.YEAR), cal.get(Calendar.MONTH)+1, cal.get(Calendar.DAY_OF_MONTH), @@ -335,7 +319,6 @@ public class Sys { cal.get(Calendar.DAY_OF_YEAR), cal.get(Calendar.WEEK_OF_YEAR) ); - return retVal; } else if(value instanceof ListValue) { @@ -367,6 +350,7 @@ public class Sys { return new NumericValue(cal.getTimeInMillis()); }); + // lazy cause evaluates expression multiple times expression.addLazyFunction("profile_expr", 1, (c, t, lv) -> { LazyValue lazy = lv.get(0); @@ -381,19 +365,16 @@ public class Sys { return (cc, tt) -> res; }); - expression.addLazyFunction("var", 1, (c, t, lv) -> - { - String varname = lv.get(0).evalValue(c).getString(); - return expression.getOrSetAnyVariable(c, varname); - }); + expression.addContextFunction("var", 1, (c, t, lv) -> + expression.getOrSetAnyVariable(c, lv.get(0).getString()).evalValue(c)); - expression.addLazyFunction("undef", 1, (c, t, lv) -> + expression.addContextFunction("undef", 1, (c, t, lv) -> { - Value remove = lv.get(0).evalValue(c); + Value remove = lv.get(0); if (remove instanceof FunctionValue) { c.host.delFunction(expression.module, remove.getString()); - return (cc, tt) -> Value.NULL; + return Value.NULL; } String varname = remove.getString(); boolean isPrefix = varname.endsWith("*"); @@ -423,13 +404,13 @@ public class Sys { c.delVariable(varname); } } - return (cc, tt) -> Value.NULL; + return Value.NULL; }); //deprecate - expression.addLazyFunction("vars", 1, (c, t, lv) -> + expression.addContextFunction("vars", 1, (c, t, lv) -> { - String prefix = lv.get(0).evalValue(c).getString(); + String prefix = lv.get(0).getString(); List values = new ArrayList<>(); if (prefix.startsWith("global")) { @@ -439,30 +420,25 @@ public class Sys { { c.getAllVariableNames().stream().filter(s -> s.startsWith(prefix)).forEach(s -> values.add(new StringValue(s))); } - Value retval = ListValue.wrap(values); - return (cc, tt) -> retval; + return ListValue.wrap(values); }); + // lazy cause default expression may not be executed if not needed expression.addLazyFunction("system_variable_get", -1, (c, t, lv) -> { if (lv.size() == 0) throw new InternalExpressionException("'system_variable_get' expects at least a key to be fetched"); Value key = lv.get(0).evalValue(c); - if (lv.size() > 1) - { - ScriptHost.systemGlobals.computeIfAbsent(key, k -> lv.get(1).evalValue(c)); - } + if (lv.size() > 1) ScriptHost.systemGlobals.computeIfAbsent(key, k -> lv.get(1).evalValue(c)); Value res = ScriptHost.systemGlobals.get(key); if (res!=null) return (cc, tt) -> res; - return (cc, tt) -> Value.NULL; + return LazyValue.NULL; }); - expression.addLazyFunction("system_variable_set", 2, (c, t, lv) -> + expression.addBinaryFunction("system_variable_set", (key, value) -> { - Value key = lv.get(0).evalValue(c); - Value value = lv.get(1).evalValue(c); Value res = ScriptHost.systemGlobals.put(key, value); - if (res!=null) return (cc, tt) -> res; - return (cc, tt) -> Value.NULL; + if (res!=null) return res; + return Value.NULL; }); } } diff --git a/src/main/java/carpet/script/language/Threading.java b/src/main/java/carpet/script/language/Threading.java index f7dd0389..ed2691eb 100644 --- a/src/main/java/carpet/script/language/Threading.java +++ b/src/main/java/carpet/script/language/Threading.java @@ -1,11 +1,9 @@ package carpet.script.language; import carpet.script.Expression; -import carpet.script.LazyValue; import carpet.script.argument.FunctionArgument; import carpet.script.exception.ExitStatement; import carpet.script.exception.InternalExpressionException; -import carpet.script.value.FunctionValue; import carpet.script.value.NumericValue; import carpet.script.value.ThreadValue; import carpet.script.value.Value; @@ -14,35 +12,30 @@ public class Threading { public static void apply(Expression expression) { - expression.addLazyFunctionWithDelegation("task", -1, (c, t, expr, tok, lv) -> + expression.addFunctionWithDelegation("task", -1, (c, t, expr, tok, lv) -> { if (lv.size() == 0) throw new InternalExpressionException("'task' requires at least function to call as a parameter"); - FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 0, false, true); - ThreadValue thread = new ThreadValue(Value.NULL, functionArgument.function, expr, tok, c, functionArgument.unpackArgs(c)); + FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 0, false, true); + ThreadValue thread = new ThreadValue(Value.NULL, functionArgument.function, expr, tok, c, functionArgument.checkedArgs()); Thread.yield(); - return (cc, tt) -> thread; + return thread; }); - expression.addLazyFunctionWithDelegation("task_thread", -1, (c, t, expr, tok, lv) -> + expression.addFunctionWithDelegation("task_thread", -1, (c, t, expr, tok, lv) -> { if (lv.size() < 2) throw new InternalExpressionException("'task' requires at least function to call as a parameter"); - Value queue = lv.get(0).evalValue(c); - FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 1, false, true); - ThreadValue thread = new ThreadValue(queue, functionArgument.function, expr, tok, c, functionArgument.unpackArgs(c)); + Value queue = lv.get(0); + FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 1, false, true); + ThreadValue thread = new ThreadValue(queue, functionArgument.function, expr, tok, c, functionArgument.checkedArgs()); Thread.yield(); - return (cc, tt) -> thread; + return thread; }); - expression.addLazyFunction("task_count", -1, (c, t, lv) -> - { - Value ret = (lv.size() > 0)? - new NumericValue(c.host.taskCount(lv.get(0).evalValue(c))): - new NumericValue(c.host.taskCount()); - return (cc, tt) -> ret; - }); + expression.addContextFunction("task_count", -1, (c, t, lv) -> + (lv.size() > 0)? new NumericValue(c.host.taskCount(lv.get(0))):new NumericValue(c.host.taskCount())); expression.addUnaryFunction("task_value", (v) -> { @@ -72,6 +65,7 @@ public class Threading return new NumericValue(((ThreadValue) v).isFinished()); }); + // lazy cause expr is evaluated in the same type expression.addLazyFunction("synchronize", -1, (c, t, lv) -> { if (lv.size() == 0) throw new InternalExpressionException("'synchronize' require at least an expression to synchronize"); @@ -89,6 +83,7 @@ public class Threading } }); + // lazy since exception expression is very conditional expression.addLazyFunction("sleep", -1, (c, t, lv) -> { long time = lv.isEmpty()?0L:NumericValue.asNumber(lv.get(0).evalValue(c)).getLong(); diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index d2882c2e..3968d3a0 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -1208,7 +1208,7 @@ public class EntityValue extends Value else if (v instanceof ListValue) { List lv = ((ListValue) v).getItems(); - Vector3Argument locator = Vector3Argument.findIn(lv, 0, false); + Vector3Argument locator = Vector3Argument.findIn(lv, 0, false, false); pos = new BlockPos(locator.vec.x, locator.vec.y, locator.vec.z); if (lv.size() > locator.offset) { @@ -1237,7 +1237,7 @@ public class EntityValue extends Value else if (a instanceof ListValue) { List params= ((ListValue) a).getItems(); - Vector3Argument blockLocator = Vector3Argument.findIn(params, 0, false); + Vector3Argument blockLocator = Vector3Argument.findIn(params, 0, false, false); BlockPos pos = new BlockPos(blockLocator.vec); RegistryKey world = spe.getEntityWorld().getRegistryKey(); float angle = spe.getHeadYaw(); diff --git a/src/main/java/carpet/script/value/FunctionAnnotationValue.java b/src/main/java/carpet/script/value/FunctionAnnotationValue.java index c15ab396..41ba7914 100644 --- a/src/main/java/carpet/script/value/FunctionAnnotationValue.java +++ b/src/main/java/carpet/script/value/FunctionAnnotationValue.java @@ -5,10 +5,12 @@ import net.minecraft.nbt.Tag; public class FunctionAnnotationValue extends Value { - // 0 global - // 1 vararg - public int type; - public FunctionAnnotationValue(Value variable, int type) + public enum Type + { + GLOBAL, VARARG + } + public Type type; + public FunctionAnnotationValue(Value variable, Type type) { if (variable.boundVariable == null) throw new InternalExpressionException("You can only borrow variables from the outer scope"); diff --git a/src/main/java/carpet/script/value/FunctionValue.java b/src/main/java/carpet/script/value/FunctionValue.java index a05e87b1..b67a4211 100644 --- a/src/main/java/carpet/script/value/FunctionValue.java +++ b/src/main/java/carpet/script/value/FunctionValue.java @@ -1,5 +1,6 @@ package carpet.script.value; +import carpet.CarpetSettings; import carpet.script.Context; import carpet.script.Expression; import carpet.script.Fluff; @@ -149,11 +150,11 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction return varArgs != null; } - public LazyValue callInContext(Context c, Integer type, List lazyParams) + public LazyValue callInContext(Context c, Integer type, List args) { try { - return lazyEval(c, type, expression, token, lazyParams); + return execute(c, type, expression, token, args); } catch (ExpressionException exc) { @@ -182,10 +183,34 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction throw new InternalExpressionException("Function " + getPrettyString() + " requires " + actual + " arguments"); } + public static List unpackArgs(List lzargs, Context c) + { + // TODO we shoudn't need that if all fuctions are not lazy really + List args = new ArrayList<>(); + for (LazyValue lv : lzargs) + { + Value arg = lv.evalValue(c, Context.NONE); + if (arg instanceof FunctionUnpackedArgumentsValue) + { + CarpetSettings.LOG.error("How did we get here?"); + args.addAll(((ListValue) arg).getItems()); + } + else + { + args.add(arg); + } + } + return args; + } + @Override - public LazyValue lazyEval(Context c, Integer type, Expression e, Tokenizer.Token t, List lazyPrams) + public LazyValue lazyEval(Context c, Integer type, Expression e, Tokenizer.Token t, List lazyParams) { + List resolvedArgs = unpackArgs(lazyParams, c); + return execute(c, type, e, t, resolvedArgs); + } + + public LazyValue execute(Context c, Integer type, Expression e, Tokenizer.Token t, List resolvedArgs) { - List resolvedArgs = Fluff.AbstractFunction.unpackArgs(lazyPrams, c); assertArgsOk(resolvedArgs, (fixedArgs) ->{ if (fixedArgs) // wrong number of args for fixed args { @@ -275,12 +300,6 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction feedback.accept(false); } } - public static List resolveArgs(List lzargs, Context c, Integer t) - { - List args = new ArrayList<>(lzargs.size()); - lzargs.forEach( v -> args.add( v.evalValue(c, t))); - return args; - } public static List lazify(List args) { diff --git a/src/main/java/carpet/script/value/LContainerValue.java b/src/main/java/carpet/script/value/LContainerValue.java index b95ae723..2c46ee55 100644 --- a/src/main/java/carpet/script/value/LContainerValue.java +++ b/src/main/java/carpet/script/value/LContainerValue.java @@ -4,6 +4,7 @@ public class LContainerValue extends FrameworkValue { private ContainerValueInterface container; private Value address; + public static final LContainerValue NULL_CONTAINER = new LContainerValue(null, null); public LContainerValue(ContainerValueInterface c, Value v) { diff --git a/src/main/java/carpet/script/value/NBTSerializableValue.java b/src/main/java/carpet/script/value/NBTSerializableValue.java index 9c26f252..568cb7c8 100644 --- a/src/main/java/carpet/script/value/NBTSerializableValue.java +++ b/src/main/java/carpet/script/value/NBTSerializableValue.java @@ -81,6 +81,12 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa owned = true; } + public static Value of(Tag tag) + { + if (tag == null) return Value.NULL; + return new NBTSerializableValue(tag); + } + public NBTSerializableValue(Supplier tagSupplier) { nbtSupplier = tagSupplier; @@ -178,29 +184,29 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa return inventory; } - public static InventoryLocator locateInventory(CarpetContext c, List params, int offset) + public static InventoryLocator locateInventory(CarpetContext c, List params, int offset) { try { - Value v1 = params.get(offset).evalValue(c); + Value v1 = params.get(offset); if (v1.isNull()) { offset ++; - v1 = params.get(offset).evalValue(c); + v1 = params.get(offset); } else if (v1 instanceof StringValue) { String strVal = v1.getString().toLowerCase(Locale.ROOT); if (strVal.equals("enderchest")) { - Value v2 = params.get(1 + offset).evalValue(c); + Value v2 = params.get(1 + offset); ServerPlayerEntity player = EntityValue.getPlayerByValue(c.s.getMinecraftServer(), v2); if (player == null) throw new InternalExpressionException("enderchest inventory requires player argument"); return new InventoryLocator(player, player.getBlockPos(), player.getEnderChestInventory(), offset + 2, true); } if (strVal.equals("equipment")) { - Value v2 = params.get(1 + offset).evalValue(c); + Value v2 = params.get(1 + offset); if (!(v2 instanceof EntityValue)) throw new InternalExpressionException("Equipment inventory requires a living entity argument"); Entity e = ((EntityValue) v2).getEntity(); if (!(e instanceof LivingEntity)) throw new InternalExpressionException("Equipment inventory requires a living entity argument"); @@ -256,8 +262,8 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa } BlockPos pos = new BlockPos( NumericValue.asNumber(v1).getDouble(), - NumericValue.asNumber(params.get(1 + offset).evalValue(c)).getDouble(), - NumericValue.asNumber(params.get(2 + offset).evalValue(c)).getDouble()); + NumericValue.asNumber(params.get(1 + offset)).getDouble(), + NumericValue.asNumber(params.get(2 + offset)).getDouble()); Inventory inv = getInventoryAt(c.s.getWorld(), pos); if (inv == null) return null; diff --git a/src/main/java/carpet/script/value/ThreadValue.java b/src/main/java/carpet/script/value/ThreadValue.java index fd833bec..d3494ea1 100644 --- a/src/main/java/carpet/script/value/ThreadValue.java +++ b/src/main/java/carpet/script/value/ThreadValue.java @@ -35,7 +35,7 @@ public class ThreadValue extends Value { try { - return function.lazyEval(ctx, Context.NONE, expr, token, FunctionValue.lazify(args)).evalValue(ctx); + return function.execute(ctx, Context.NONE, expr, token, args).evalValue(ctx); } catch (ExitStatement exit) { From 5edbbe3fe2213c5fccd4c2ff1546e2321ea72d0b Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 22 Apr 2021 22:25:46 -0300 Subject: [PATCH 3/7] remane --- .../carpet/script/value/FunctionValue.java | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/main/java/carpet/script/value/FunctionValue.java b/src/main/java/carpet/script/value/FunctionValue.java index b67a4211..588b755c 100644 --- a/src/main/java/carpet/script/value/FunctionValue.java +++ b/src/main/java/carpet/script/value/FunctionValue.java @@ -150,11 +150,11 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction return varArgs != null; } - public LazyValue callInContext(Context c, Integer type, List args) + public LazyValue callInContext(Context c, Integer type, List params) { try { - return execute(c, type, expression, token, args); + return execute(c, type, expression, token, params); } catch (ExpressionException exc) { @@ -183,40 +183,40 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction throw new InternalExpressionException("Function " + getPrettyString() + " requires " + actual + " arguments"); } - public static List unpackArgs(List lzargs, Context c) + public static List unpackArgs(List lazyParams, Context c) { // TODO we shoudn't need that if all fuctions are not lazy really - List args = new ArrayList<>(); - for (LazyValue lv : lzargs) + List params = new ArrayList<>(); + for (LazyValue lv : lazyParams) { - Value arg = lv.evalValue(c, Context.NONE); - if (arg instanceof FunctionUnpackedArgumentsValue) + Value param = lv.evalValue(c, Context.NONE); + if (param instanceof FunctionUnpackedArgumentsValue) { CarpetSettings.LOG.error("How did we get here?"); - args.addAll(((ListValue) arg).getItems()); + params.addAll(((ListValue) param).getItems()); } else { - args.add(arg); + params.add(param); } } - return args; + return params; } @Override public LazyValue lazyEval(Context c, Integer type, Expression e, Tokenizer.Token t, List lazyParams) { - List resolvedArgs = unpackArgs(lazyParams, c); - return execute(c, type, e, t, resolvedArgs); + List resolvedParams = unpackArgs(lazyParams, c); + return execute(c, type, e, t, resolvedParams); } - public LazyValue execute(Context c, Integer type, Expression e, Tokenizer.Token t, List resolvedArgs) + public LazyValue execute(Context c, Integer type, Expression e, Tokenizer.Token t, List params) { - assertArgsOk(resolvedArgs, (fixedArgs) ->{ + assertArgsOk(params, (fixedArgs) ->{ if (fixedArgs) // wrong number of args for fixed args { throw new ExpressionException(c, e, t, "Incorrect number of arguments for function "+name+ - ". Should be "+args.size()+", not "+resolvedArgs.size()+" like "+args + ". Should be "+args.size()+", not "+params.size()+" like "+args ); } else // too few args for varargs @@ -225,7 +225,7 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction argList.add("... "+varArgs); throw new ExpressionException(c, e, t, "Incorrect number of arguments for function "+name+ - ". Should be at least "+args.size()+", not "+resolvedArgs.size()+" like "+argList + ". Should be at least "+args.size()+", not "+params.size()+" like "+argList ); } }); @@ -235,15 +235,15 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction for (int i=0; i val); } if (varArgs != null) { List extraParams = new ArrayList<>(); - for (int i = args.size(), mx = resolvedArgs.size(); i < mx; i++) + for (int i = args.size(), mx = params.size(); i < mx; i++) { - extraParams.add(resolvedArgs.get(i).reboundedTo(null)); // copy by value I guess + extraParams.add(params.get(i).reboundedTo(null)); // copy by value I guess } Value rest = ListValue.wrap(extraParams).bindTo(varArgs); // didn't we just copied that? newFrame.setVariable(varArgs, (cc, tt) -> rest); From a6f39e2d22d5ee327e0d1d5725318cc107228975 Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 22 Apr 2021 22:26:07 -0300 Subject: [PATCH 4/7] scarpet LOG --- src/main/java/carpet/CarpetServer.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/carpet/CarpetServer.java b/src/main/java/carpet/CarpetServer.java index ae9e4dce..f175e1a2 100644 --- a/src/main/java/carpet/CarpetServer.java +++ b/src/main/java/carpet/CarpetServer.java @@ -36,10 +36,13 @@ import net.fabricmc.loader.api.FabricLoader; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayerEntity; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; public class CarpetServer implements ClientModInitializer,DedicatedServerModInitializer // static for now - easier to handle all around the code, its one anyways { public static final Random rand = new Random(); + public static final Logger LOG = LogManager.getLogger("scarpet"); public static MinecraftServer minecraft_server; private static CommandDispatcher currentCommandDispatcher; public static CarpetScriptServer scriptServer; From d072ec90c3e0ab6c30dbc34604f3fe319d06d3bc Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 22 Apr 2021 22:26:35 -0300 Subject: [PATCH 5/7] hold your horses --- .../java/carpet/script/value/EntityValue.java | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index 3968d3a0..e8e55c3f 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -1,5 +1,6 @@ package carpet.script.value; +import carpet.CarpetServer; import carpet.fakes.BrainInterface; import carpet.fakes.EntityInterface; import carpet.fakes.ItemEntityInterface; @@ -917,9 +918,11 @@ public class EntityValue extends Value } } - private static void updateVelocity(Entity e) + private static void updateVelocity(Entity e, double scale) { e.velocityModified = true; + if (Math.abs(scale) > 10000) + CarpetServer.LOG.warn("Moved entity "+e.getEntityName()+" "+e.getName()+" at " +e.getPos()+" extremly fast: "+e.getVelocity()); //((ServerWorld)e.getEntityWorld()).method_14178().sendToNearbyPlayers(e, new EntityVelocityUpdateS2CPacket(e)); } @@ -1051,30 +1054,32 @@ public class EntityValue extends Value throw new InternalExpressionException("Expected a list of 3 parameters as a second argument"); } List coords = ((ListValue) v).getItems(); - e.setVelocity( - NumericValue.asNumber(coords.get(0)).getDouble(), - NumericValue.asNumber(coords.get(1)).getDouble(), - NumericValue.asNumber(coords.get(2)).getDouble() - ); - updateVelocity(e); + double dx = NumericValue.asNumber(coords.get(0)).getDouble(); + double dy = NumericValue.asNumber(coords.get(0)).getDouble(); + double dz = NumericValue.asNumber(coords.get(2)).getDouble(); + e.setVelocity(dx, dy, dz); + updateVelocity(e, MathHelper.absMax(MathHelper.absMax(dx, dy), dz)); }); put("motion_x", (e, v) -> { Vec3d velocity = e.getVelocity(); - e.setVelocity(NumericValue.asNumber(v).getDouble(), velocity.y, velocity.z); - updateVelocity(e); + double dv = NumericValue.asNumber(v).getDouble(); + e.setVelocity(dv, velocity.y, velocity.z); + updateVelocity(e, dv); }); put("motion_y", (e, v) -> { Vec3d velocity = e.getVelocity(); - e.setVelocity(velocity.x, NumericValue.asNumber(v).getDouble(), velocity.z); - updateVelocity(e); + double dv = NumericValue.asNumber(v).getDouble(); + e.setVelocity(velocity.x, dv, velocity.z); + updateVelocity(e, dv); }); put("motion_z", (e, v) -> { Vec3d velocity = e.getVelocity(); - e.setVelocity(velocity.x, velocity.y, NumericValue.asNumber(v).getDouble()); - updateVelocity(e); + double dv = NumericValue.asNumber(v).getDouble(); + e.setVelocity(velocity.x, velocity.y, dv); + updateVelocity(e, dv); }); put("accelerate", (e, v) -> @@ -1089,7 +1094,7 @@ public class EntityValue extends Value NumericValue.asNumber(coords.get(1)).getDouble(), NumericValue.asNumber(coords.get(2)).getDouble() ); - updateVelocity(e); + updateVelocity(e, e.getVelocity().length()); }); put("custom_name", (e, v) -> { From edca3fb131ce3b14630471d3994fc031e4e47932 Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 22 Apr 2021 22:30:45 -0300 Subject: [PATCH 6/7] using proper logger now --- src/main/java/carpet/CarpetServer.java | 3 --- .../java/carpet/script/CarpetScriptServer.java | 3 +++ src/main/java/carpet/script/api/Auxiliary.java | 16 +++++++--------- .../java/carpet/script/value/EntityValue.java | 3 ++- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/main/java/carpet/CarpetServer.java b/src/main/java/carpet/CarpetServer.java index f175e1a2..ae9e4dce 100644 --- a/src/main/java/carpet/CarpetServer.java +++ b/src/main/java/carpet/CarpetServer.java @@ -36,13 +36,10 @@ import net.fabricmc.loader.api.FabricLoader; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayerEntity; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; public class CarpetServer implements ClientModInitializer,DedicatedServerModInitializer // static for now - easier to handle all around the code, its one anyways { public static final Random rand = new Random(); - public static final Logger LOG = LogManager.getLogger("scarpet"); public static MinecraftServer minecraft_server; private static CommandDispatcher currentCommandDispatcher; public static CarpetScriptServer scriptServer; diff --git a/src/main/java/carpet/script/CarpetScriptServer.java b/src/main/java/carpet/script/CarpetScriptServer.java index 10faab8f..01048258 100644 --- a/src/main/java/carpet/script/CarpetScriptServer.java +++ b/src/main/java/carpet/script/CarpetScriptServer.java @@ -20,6 +20,8 @@ import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.WorldSavePath; import net.minecraft.util.math.BlockPos; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import java.io.IOException; import java.nio.file.FileVisitOption; @@ -43,6 +45,7 @@ import static net.minecraft.server.command.CommandManager.literal; public class CarpetScriptServer { //make static for now, but will change that later: + public static final Logger LOG = LogManager.getLogger("scarpet"); public final MinecraftServer server; public CarpetScriptHost globalHost; public Map modules; diff --git a/src/main/java/carpet/script/api/Auxiliary.java b/src/main/java/carpet/script/api/Auxiliary.java index 0db652ca..f3b02aac 100644 --- a/src/main/java/carpet/script/api/Auxiliary.java +++ b/src/main/java/carpet/script/api/Auxiliary.java @@ -1,7 +1,6 @@ package carpet.script.api; import carpet.CarpetServer; -import carpet.CarpetSettings; import carpet.fakes.MinecraftServerInterface; import carpet.fakes.ServerWorldInterface; import carpet.fakes.StatTypeInterface; @@ -628,7 +627,7 @@ public class Auxiliary { s.getMinecraftServer().getPlayerManager().saveAllPlayerData(); s.getMinecraftServer().save(true,true,true); s.getWorld().getChunkManager().tick(() -> true); - CarpetSettings.LOG.warn("Saved chunks"); + CarpetScriptServer.LOG.warn("Saved chunks"); return Value.TRUE; }); @@ -797,24 +796,23 @@ public class Auxiliary { expression.addFunction("logger", lv -> { - //CarpetSettings.LOG.error(Registry.ENTITY_TYPE.getIds().stream().sorted().map(ValueConversions::simplify).collect(Collectors.joining("`, `"))); Value res; if(lv.size()==1) { res = lv.get(0); - CarpetSettings.LOG.info(res.getString()); + CarpetScriptServer.LOG.info(res.getString()); } else if(lv.size()==2) { String level = lv.get(0).getString().toLowerCase(Locale.ROOT); res = lv.get(1); switch(level){ - case "error": CarpetSettings.LOG.error(res.getString()); break; - case "warn": CarpetSettings.LOG.warn(res.getString()); break; - case "debug": CarpetSettings.LOG.debug(res.getString()); break; - case "fatal": CarpetSettings.LOG.fatal(res.getString()); break; - case "info": CarpetSettings.LOG.info(res.getString()); break; + case "error": CarpetScriptServer.LOG.error(res.getString()); break; + case "warn": CarpetScriptServer.LOG.warn(res.getString()); break; + case "debug": CarpetScriptServer.LOG.debug(res.getString()); break; + case "fatal": CarpetScriptServer.LOG.fatal(res.getString()); break; + case "info": CarpetScriptServer.LOG.info(res.getString()); break; default: throw new InternalExpressionException("Unknown log level for 'logger': "+level); } } diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index e8e55c3f..500a1017 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -14,6 +14,7 @@ import carpet.helpers.Tracer; import carpet.network.ServerNetworkHandler; import carpet.patches.EntityPlayerMPFake; import carpet.script.CarpetContext; +import carpet.script.CarpetScriptServer; import carpet.script.EntityEventsGroup; import carpet.script.argument.Vector3Argument; import carpet.script.exception.InternalExpressionException; @@ -922,7 +923,7 @@ public class EntityValue extends Value { e.velocityModified = true; if (Math.abs(scale) > 10000) - CarpetServer.LOG.warn("Moved entity "+e.getEntityName()+" "+e.getName()+" at " +e.getPos()+" extremly fast: "+e.getVelocity()); + CarpetScriptServer.LOG.warn("Moved entity "+e.getEntityName()+" "+e.getName()+" at " +e.getPos()+" extremly fast: "+e.getVelocity()); //((ServerWorld)e.getEntityWorld()).method_14178().sendToNearbyPlayers(e, new EntityVelocityUpdateS2CPacket(e)); } From bed9e2c60a22dad3654bf03b1f56aa24e28b08de Mon Sep 17 00:00:00 2001 From: gnembon Date: Fri, 23 Apr 2021 01:20:42 -0300 Subject: [PATCH 7/7] docs --- docs/scarpet/language/Operators.md | 25 +++++++++++++++++-- src/main/java/carpet/script/Expression.java | 18 ++++++------- src/main/java/carpet/script/Fluff.java | 9 +++---- .../carpet/script/language/Functions.java | 4 +-- .../carpet/script/language/Operators.java | 8 +++--- .../value/FunctionUnpackedArgumentsValue.java | 13 ++++++++++ 6 files changed, 56 insertions(+), 21 deletions(-) diff --git a/docs/scarpet/language/Operators.md b/docs/scarpet/language/Operators.md index 0024c4c1..ea59aa6e 100644 --- a/docs/scarpet/language/Operators.md +++ b/docs/scarpet/language/Operators.md @@ -29,11 +29,12 @@ Here is the complete list of operators in `scarpet` including control flow opera are not technically operators, but part of the language, even if they look like them: * Match, Get `~ :` -* Unary `+ - !` +* Unary `+ - ! ...` * Exponent `^` * Multiplication `* / %` * Addition `+ -` -* Comparison `== != > >= <= <` +* Comparison `> >= <= <` +* Equality `== !=` * Logical And`&&` * Logical Or `||` * Assignment `= += <>` @@ -234,3 +235,23 @@ flips boolean condition of the expression. Equivalent of `bool(expr)==false` !l() => true !l(null) => false + +### `Unpacking Operator ...` + +Unpacks elements of a list of an iterator into a sequence of arguments in a function making so that `fun(...[1, 2, 3])` is +identical with `fun(1, 2, 3)`. + +In function signatures it identifies a vararg parameter. + +`fun(a, b, ... rest) -> [a, b, rest]; fun(1, 2, 3, 4)` => `[1, 2, [3, 4]]` + +Effects of `...` can be surprisingly lasting. It is kept through the use of variables and function calls. + +`fun(a, b, ... rest) -> [a, b, ... rest]; fun(1, 2, 3, 4)` => `[1, 2, 3, 4]` +`args() -> ... [1, 2, 3]; sum(a, b, c) -> a+b+c; sum(args())` => `6` +`a = ... [1, 2, 3]; sum(a, b, c) -> a+b+c; sum(a)` => `6` + +Unpacking mechanics can be used for list and map constriction, not just for function calls. + +`[...range(5), pi, ...range(5,-1,-1)]` => `[0, 1, 2, 3, 4, 3.14159265359, 5, 4, 3, 2, 1, 0]` +`{ ... map(range(5), _ -> _*_ )}` => `{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}` diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index 28b6a2fa..770b64d2 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -188,7 +188,7 @@ public class Expression public void addLazyFunctionWithDelegation(String name, int numpar, QuinnFunction, LazyValue> lazyfun) { - functions.put(name, new AbstractLazyFunction(numpar) + functions.put(name, new AbstractLazyFunction(numpar, name) { @Override public LazyValue lazyEval(Context c, Integer type, Expression e, Tokenizer.Token t, List lv) @@ -208,7 +208,7 @@ public class Expression public void addFunctionWithDelegation(String name, int numpar, QuinnFunction, Value> fun) { - functions.put(name, new AbstractLazyFunction(numpar) + functions.put(name, new AbstractLazyFunction(numpar, name) { @Override public LazyValue lazyEval(Context c, Integer type, Expression e, Tokenizer.Token t, List lv) @@ -286,7 +286,7 @@ public class Expression public void addUnaryOperator(String surface, boolean leftAssoc, Function fun) { - operators.put(surface+"u", new AbstractUnaryOperator(Operators.precedence.get("unary+-!"), leftAssoc) + operators.put(surface+"u", new AbstractUnaryOperator(Operators.precedence.get("unary+-!..."), leftAssoc) { @Override public Value evalUnary(Value v1) @@ -312,7 +312,7 @@ public class Expression public void addUnaryFunction(String name, Function fun) { - functions.put(name, new AbstractFunction(1) + functions.put(name, new AbstractFunction(1, name) { @Override public Value eval(List parameters) @@ -324,7 +324,7 @@ public class Expression public void addBinaryFunction(String name, BiFunction fun) { - functions.put(name, new AbstractFunction(2) + functions.put(name, new AbstractFunction(2, name) { @Override public Value eval(List parameters) @@ -339,7 +339,7 @@ public class Expression public void addFunction(String name, Function, Value> fun) { - functions.put(name, new AbstractFunction(-1) + functions.put(name, new AbstractFunction(-1, name) { @Override public Value eval(List parameters) @@ -370,7 +370,7 @@ public class Expression public void addLazyFunction(String name, int num_params, TriFunction, LazyValue> fun) { - functions.put(name, new AbstractLazyFunction(num_params) + functions.put(name, new AbstractLazyFunction(num_params, name) { @Override public LazyValue lazyEval(Context c, Integer i, Expression e, Tokenizer.Token t, List lazyParams) @@ -389,7 +389,7 @@ public class Expression public void addContextFunction(String name, int num_params, TriFunction, Value> fun) { - functions.put(name, new AbstractLazyFunction(num_params) + functions.put(name, new AbstractLazyFunction(num_params, name) { @Override public LazyValue lazyEval(Context c, Integer i, Expression e, Tokenizer.Token t, List lazyParams) @@ -409,7 +409,7 @@ public class Expression public void addTypedContextFunction(String name, int num_params, int reqType, TriFunction, Value> fun) { - functions.put(name, new AbstractLazyFunction(num_params) + functions.put(name, new AbstractLazyFunction(num_params, name) { @Override public LazyValue lazyEval(Context c, Integer i, Expression e, Tokenizer.Token t, List lazyParams) diff --git a/src/main/java/carpet/script/Fluff.java b/src/main/java/carpet/script/Fluff.java index dc41d936..122d75c5 100644 --- a/src/main/java/carpet/script/Fluff.java +++ b/src/main/java/carpet/script/Fluff.java @@ -64,9 +64,10 @@ public abstract class Fluff protected String name; int numParams; - AbstractLazyFunction(int numParams) + AbstractLazyFunction(int numParams, String name) { this.numParams = numParams; + this.name = name; } @@ -115,12 +116,10 @@ public abstract class Fluff public abstract static class AbstractFunction extends AbstractLazyFunction implements IFunction { - AbstractFunction(int numParams) { - super(numParams); + AbstractFunction(int numParams, String name) { + super(numParams, name); } - - @Override public LazyValue lazyEval(Context cc, Integer type, Expression e, Tokenizer.Token t, final List lazyParams) { diff --git a/src/main/java/carpet/script/language/Functions.java b/src/main/java/carpet/script/language/Functions.java index 25fa7825..54d43629 100644 --- a/src/main/java/carpet/script/language/Functions.java +++ b/src/main/java/carpet/script/language/Functions.java @@ -93,7 +93,7 @@ public class Functions { }); // lazy because of typed evaluation of the argument - expression.addLazyUnaryOperator("...", Operators.precedence.get("def->..."), false, (c, t, lv) -> + expression.addLazyUnaryOperator("...", Operators.precedence.get("unary+-!..."), false, (c, t, lv) -> { if (t == Context.LOCALIZATION) return (cc, tt) -> new FunctionAnnotationValue(lv.evalValue(c), FunctionAnnotationValue.Type.VARARG); @@ -116,7 +116,7 @@ public class Functions { //assigns const procedure to the lhs, returning its previous value // must be lazy due to RHS being an expression to save to execute - expression.addLazyBinaryOperatorWithDelegation("->", Operators.precedence.get("def->..."), false, (c, type, e, t, lv1, lv2) -> + expression.addLazyBinaryOperatorWithDelegation("->", Operators.precedence.get("def->"), false, (c, type, e, t, lv1, lv2) -> { if (type == Context.MAPDEF) { diff --git a/src/main/java/carpet/script/language/Operators.java b/src/main/java/carpet/script/language/Operators.java index 389623e1..56a92184 100644 --- a/src/main/java/carpet/script/language/Operators.java +++ b/src/main/java/carpet/script/language/Operators.java @@ -20,7 +20,7 @@ import java.util.Map; public class Operators { public static final Map precedence = new HashMap() {{ put("attribute~:", 80); - put("unary+-!", 60); + put("unary+-!...", 60); put("exponent^", 40); put("multiplication*/%", 30); put("addition+-", 20); @@ -29,7 +29,7 @@ public class Operators { put("and&&", 5); put("or||", 4); put("assign=<>", 3); - put("def->...", 2); + put("def->", 2); put("nextop;", 1); }}; @@ -216,7 +216,9 @@ public class Operators { expression.addUnaryOperator("+", false, NumericValue::asNumber); // could be non-lazy, but who cares - its a small one. - expression.addLazyUnaryOperator("!", precedence.get("unary+-!"), false, (c, t, lv)-> lv.evalValue(c, Context.BOOLEAN).getBoolean() ? (cc, tt)-> Value.FALSE : (cc, tt) -> Value.TRUE); // might need context boolean + expression.addLazyUnaryOperator("!", precedence.get("unary+-!..."), false, (c, t, lv) -> + lv.evalValue(c, Context.BOOLEAN).getBoolean() ? (cc, tt)-> Value.FALSE : (cc, tt) -> Value.TRUE + ); // might need context boolean } } diff --git a/src/main/java/carpet/script/value/FunctionUnpackedArgumentsValue.java b/src/main/java/carpet/script/value/FunctionUnpackedArgumentsValue.java index 8c053e7b..e33a64eb 100644 --- a/src/main/java/carpet/script/value/FunctionUnpackedArgumentsValue.java +++ b/src/main/java/carpet/script/value/FunctionUnpackedArgumentsValue.java @@ -7,4 +7,17 @@ public class FunctionUnpackedArgumentsValue extends ListValue public FunctionUnpackedArgumentsValue(List list) { super(list); } + + @Override + public Value clone() + { + return new FunctionUnpackedArgumentsValue(items); + } + + @Override + public Value deepcopy() + { + ListValue copy = (ListValue)super.deepcopy(); + return new FunctionUnpackedArgumentsValue(copy.items); + } }