From 56f8f17aaae0f89cd01258961af11706f9c88cea Mon Sep 17 00:00:00 2001 From: gnembon Date: Sun, 10 May 2020 13:11:58 -0300 Subject: [PATCH 1/2] tighten up function args for non-linear calls --- .../java/carpet/script/CarpetExpression.java | 2 +- src/main/java/carpet/script/Expression.java | 4 ++-- .../script/argument/FunctionArgument.java | 18 +++++++++++------- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 99dd9628..76c19de9 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -2967,7 +2967,7 @@ public class CarpetExpression 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, this.expr.module, lv, 1, true); + FunctionArgument functionArgument = FunctionArgument.findIn(c, this.expr.module, lv, 1, true, true); CarpetServer.scriptServer.events.scheduleCall( (CarpetContext) c, diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index 6d5174c5..17e5d331 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -440,7 +440,7 @@ public class Expression //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, module, lv, 0, true); + FunctionArgument functionArgument = FunctionArgument.findIn(c, module, lv, 0, false, true); FunctionValue fun = functionArgument.function; Value retval = fun.callInContext(expr, c, t, fun.getExpression(), fun.getToken(), functionArgument.args).evalValue(c); return (cc, tt) -> retval; ///!!!! dono might need to store expr and token in statics? (e? t?) @@ -1878,7 +1878,7 @@ public class Expression addLazyFunctionWithDelegation("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, module, lv, 0); + FunctionArgument functionArgument = FunctionArgument.findIn(c, module, lv, 0, true, false); Value queue = Value.NULL; if (lv.size() > functionArgument.offset) queue = lv.get(functionArgument.offset).evalValue(c); ThreadValue thread = new ThreadValue(queue, functionArgument.function, expr, tok, c, functionArgument.args); diff --git a/src/main/java/carpet/script/argument/FunctionArgument.java b/src/main/java/carpet/script/argument/FunctionArgument.java index 4f3ba735..7838a518 100644 --- a/src/main/java/carpet/script/argument/FunctionArgument.java +++ b/src/main/java/carpet/script/argument/FunctionArgument.java @@ -22,11 +22,7 @@ public class FunctionArgument extends Argument this.function = function; this.args = args; } - public static FunctionArgument findIn(Context c, Module module, List params, int offset) - { - return findIn(c, module, params, offset, false); - } - public static FunctionArgument findIn(Context c, Module module, List params, int offset, boolean strict) + public static FunctionArgument findIn(Context c, Module module, List params, int offset, boolean prematureEvaluation, boolean strict) { Value functionValue = params.get(offset).evalValue(c); if (!(functionValue instanceof FunctionValue)) @@ -40,9 +36,17 @@ public class FunctionArgument extends Argument if (extraargs < 0 || (extraargs > 0 && strict)) throw new InternalExpressionException("Function "+fun.getPrettyString()+" requires "+fun.getArguments().size()+" arguments"); List lvargs = new ArrayList<>(); - for (int i=0; i< argsize; i++) + if (prematureEvaluation) { - lvargs.add(params.get(offset+1+i)); + for (int i = 0; i < argsize; i++) + { + Value arg = params.get(offset + 1 + i).evalValue(c); + lvargs.add((cc, tt) -> arg); + } + } + else + { + for (int i = 0; i < argsize; i++) lvargs.add(params.get(offset + 1 + i)); } return new FunctionArgument(fun, offset+1+argsize, lvargs); } From 52cf599375c83217ab9168baef6aca654cce8087 Mon Sep 17 00:00:00 2001 From: gnembon Date: Sun, 10 May 2020 17:24:35 -0300 Subject: [PATCH 2/2] added task_dock --- docs/scarpet/Full.md | 12 +++++ docs/scarpet/language/SystemFunctions.md | 12 +++++ docs/scarpet/resources/editors/idea/1.txt | 1 + .../scarpet/resources/editors/npp/scarpet.xml | 2 +- .../java/carpet/script/CarpetExpression.java | 35 +++++--------- src/main/java/carpet/script/Expression.java | 46 +++---------------- 6 files changed, 44 insertions(+), 64 deletions(-) diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index 97fccb91..c07aaba4 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -790,6 +790,18 @@ Returns true if task has completed, or false otherwise. Evaluates `expression` synchronized with respect to the lock `lock`. Returns the value of the expression. +### `task_dock(expr)` + +In a not-task (running regular code on the main game thread) it is a pass-through command. In tasks - it docks +the current thread on the main server thread and executes expression as one server offline server task. +This is especially helpful in case a task has several docking operations to perform, such as setting a block, and +it would be much more efficient to do them all at once rather then packing each block access in each own call. + +Be mindful, that docking the task means that the tick execution will be delayed until the expression is evaluated. +This will synchronize your task with other tasks using `task_dock`, but if you should be using `synchronize` to +synchronize tasks without locking the main thread. + + * * * ## Auxiliary functions diff --git a/docs/scarpet/language/SystemFunctions.md b/docs/scarpet/language/SystemFunctions.md index 611057d2..7c506921 100644 --- a/docs/scarpet/language/SystemFunctions.md +++ b/docs/scarpet/language/SystemFunctions.md @@ -147,6 +147,18 @@ Returns true if task has completed, or false otherwise. Evaluates `expression` synchronized with respect to the lock `lock`. Returns the value of the expression. +### `task_dock(expr)` + +In a not-task (running regular code on the main game thread) it is a pass-through command. In tasks - it docks +the current thread on the main server thread and executes expression as one server offline server task. +This is especially helpful in case a task has several docking operations to perform, such as setting a block, and +it would be much more efficient to do them all at once rather then packing each block access in each own call. + +Be mindful, that docking the task means that the tick execution will be delayed until the expression is evaluated. +This will synchronize your task with other tasks using `task_dock`, but if you should be using `synchronize` to +synchronize tasks without locking the main thread. + + * * * ## Auxiliary functions diff --git a/docs/scarpet/resources/editors/idea/1.txt b/docs/scarpet/resources/editors/idea/1.txt index fcab9dfb..8780d3f9 100644 --- a/docs/scarpet/resources/editors/idea/1.txt +++ b/docs/scarpet/resources/editors/idea/1.txt @@ -85,6 +85,7 @@ tanh task task_completed task_count +task_dock task_join task_value throw diff --git a/docs/scarpet/resources/editors/npp/scarpet.xml b/docs/scarpet/resources/editors/npp/scarpet.xml index 3994ced4..cfcde776 100644 --- a/docs/scarpet/resources/editors/npp/scarpet.xml +++ b/docs/scarpet/resources/editors/npp/scarpet.xml @@ -36,7 +36,7 @@ print return exit throw try - task task_count task_value task_join task_completed synchronize + task task_count task_value task_join task_completed synchronize task_dock system_variable_get system_variable_set diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 76c19de9..06bded9a 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -2791,6 +2791,18 @@ public class CarpetExpression return (_c, _t) -> ret; }); + this.expr.addLazyFunction("task_dock", 1, (c, t, lv) -> { + CarpetContext cc = (CarpetContext)c; + MinecraftServer server = cc.s.getMinecraftServer(); + if (server.isOnThread()) return lv.get(1); // pass through for on thread tasks + Value[] result = new Value[]{Value.NULL}; + ((CarpetContext) c).s.getMinecraftServer().submitAndJoin(() -> result[0] = lv.get(0).evalValue(c, t)); + Value ret = result[0]; // preventing from lazy evaluating of the result in case a future completes later + return (_c, _t) -> ret; + // pass through placeholder + // implmenetation should dock the task on the main thread. + }); + this.expr.addLazyFunction("logger", 1, (c, t, lv) -> { Value res = lv.get(0).evalValue(c); @@ -2976,29 +2988,6 @@ public class CarpetExpression delay ); return (c_, t_) -> Value.TRUE; - /* - Value functionValue = lv.get(1).evalValue(c); - if (!(functionValue instanceof FunctionValue)) - { - String name = functionValue.getString(); - functionValue = c.host.getAssertFunction(this.expr.module, name); - } - FunctionValue function = (FunctionValue)functionValue; - - CarpetContext cc = (CarpetContext)c; - List args = new ArrayList<>(); - for (int i=2; i < lv.size(); i++) - { - Value arg = lv.get(i).evalValue(cc); - args.add(arg); - } - if (function.getArguments().size() != args.size()) - throw new InternalExpressionException("Function "+function.getString()+" takes "+ - function.getArguments().size()+" arguments, "+args.size()+" provided."); - CarpetServer.scriptServer.events.scheduleCall(cc, function, args, delay); - return (c_, t_) -> Value.TRUE; - */ - }); this.expr.addLazyFunction("load_app_data", -1, (c, t, lv) -> diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index 17e5d331..83e607fe 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -444,23 +444,6 @@ public class Expression FunctionValue fun = functionArgument.function; Value retval = fun.callInContext(expr, c, t, fun.getExpression(), fun.getToken(), functionArgument.args).evalValue(c); return (cc, tt) -> retval; ///!!!! dono might need to store expr and token in statics? (e? t?) - - /* - Value functionValue = lv.get(0).evalValue(c); - if (!(functionValue instanceof FunctionValue)) - { - String name = functionValue.getString(); - functionValue = c.host.getAssertFunction(module, name); - } - List lvargs = new ArrayList<>(lv.size()-1); - for (int i=1; i< lv.size(); i++) - { - lvargs.add(lv.get(i)); - } - FunctionValue fun = (FunctionValue)functionValue; - Value retval = fun.callInContext(expr, c, t, fun.getExpression(), fun.getToken(), lvargs).evalValue(c); - return (cc, tt) -> retval; ///!!!! dono might need to store expr and token in statics? (e? t?) - */ } // gimme signature String name = lv.get(0).evalValue(c).getString(); @@ -1884,29 +1867,6 @@ public class Expression ThreadValue thread = new ThreadValue(queue, functionArgument.function, expr, tok, c, functionArgument.args); Thread.yield(); return (cc, tt) -> thread; - /* - Value funcDesc = lv.get(0).evalValue(c); - if (!(funcDesc instanceof FunctionValue)) - { - String name = funcDesc.getString(); - funcDesc = c.host.getAssertFunction(module, name); - } - FunctionValue fun = (FunctionValue)funcDesc; - int extraargs = lv.size() - fun.getArguments().size(); - if (extraargs != 1 && extraargs != 2) - { - throw new InternalExpressionException("Function takes "+fun.getArguments().size()+" arguments."); - } - List lvargs = new ArrayList<>(); - for (int i=0; i< fun.getArguments().size(); i++) - { - lvargs.add(lv.get(i+1)); - } - Value queue = Value.NULL; - if (extraargs == 2) queue = lv.get(lv.size()-1).evalValue(c); - ThreadValue thread = new ThreadValue(queue, fun, expr, tok, c, lvargs); - Thread.yield(); - return (cc, tt) -> thread;*/ }); addFunction("task_count", (lv) -> @@ -1930,6 +1890,12 @@ public class Expression return ((ThreadValue) v).join(); }); + addLazyFunction("task_dock", 1, (c, t, lv) -> { + // pass through placeholder + // implmenetation should dock the task on the main thread. + return lv.get(0); + }); + addUnaryFunction("task_completed", (v) -> { if (!(v instanceof ThreadValue)) throw new InternalExpressionException("'task_completed' could only be used with a task value");