From bcff4fbbc489ed3daad1565aa9f0d2d782af0a50 Mon Sep 17 00:00:00 2001 From: gnembon Date: Sat, 9 Nov 2019 23:12:05 -0400 Subject: [PATCH] clarify laziness of blocks and added more care to context execution --- .../java/carpet/script/CarpetExpression.java | 28 ++++++++++++++-- src/main/java/carpet/script/Expression.java | 32 ++++++++++--------- src/main/java/carpet/script/LazyValue.java | 2 +- .../java/carpet/script/value/BlockValue.java | 4 +-- src/main/java/carpet/script/value/Value.java | 1 + 5 files changed, 45 insertions(+), 22 deletions(-) diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 8083c2d7..6af69768 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -365,6 +365,23 @@ public class CarpetExpression * block(0,0,0) == block('bedrock') => 1 * block('hopper[facing=north]{Items:[{Slot:1b,id:"minecraft:slime_ball",Count:16b}]}') => hopper * + *

Retrieving a block with block function has also a side-effect of evaluating its current state and data. + * so if you use it later it will reflect block state and data of the block that was when block was called, rather than + * when it was used. Block values passed in various places like scan functions, etc, are not fully evaluated + * unless its properties are needed. This means that if the block at the location changes before its queried in the program + * this might result in getting the later state, which might not be desired. Consider the following example:

+ *
+     * set(10,10,10,'stone');
+     * scan(10,10,10,0,0,0, b = _);
+     * set(10,10,10,'air');
+     * print(b); // 'air', block was remembered 'lazily', and evaluated by `print`, when it was already set to air
+     *
+     * set(10,10,10,'stone');
+     * scan(10,10,10,0,0,0, b = block(_));
+     * set(10,10,10,'air');
+     * print(b); // 'stone', block was evaluated 'eagerly' but call to `block`
+     *
+     * 
*

World Manipulation

*

All the functions below can be used with block value, queried with coord triple, or 3-long list. * All pos in the functions referenced below refer to either method of passing block position

@@ -669,7 +686,10 @@ public class CarpetExpression { throw new InternalExpressionException("Block requires at least one parameter"); } - Value retval = BlockValue.fromParams(cc, lv, 0, true).block; + BlockValue retval = BlockValue.fromParams(cc, lv, 0, true).block; + // fixing block state and data + retval.getBlockState(); + retval.getData(); return (c_, t_) -> retval; }); @@ -2086,7 +2106,8 @@ public class CarpetExpression c.setVariable("_z", (c_, t_) -> new NumericValue(zFinal).bindTo("_z")); Value blockValue = BlockValue.fromCoords(((CarpetContext)c), xFinal,yFinal,zFinal).bindTo("_"); c.setVariable( "_", (cc_, t_c) -> blockValue); - if (expr.evalValue(c, Context.BOOLEAN).getBoolean()) + Value result = expr.evalValue(c, t); + if (t != Context.VOID && result.getBoolean()) { sCount += 1; } @@ -2138,7 +2159,8 @@ public class CarpetExpression c.setVariable("_z", (c_, t_) -> new NumericValue(zFinal).bindTo("_z")); Value blockValue = BlockValue.fromCoords(((CarpetContext)c), xFinal,yFinal,zFinal).bindTo("_"); c.setVariable( "_", (cc_, t_c) -> blockValue); - if (expr.evalValue(c, Context.BOOLEAN).getBoolean()) + Value result = expr.evalValue(c, t); + if (t != Context.VOID && result.getBoolean()) { sCount += 1; } diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index a0019457..14608707 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -994,8 +994,9 @@ public class Expression implements Cloneable addLazyBinaryOperator(";",precedence.get("nextop;"), true, (c, t, lv1, lv2) -> { - Value v1 = lv1.evalValue(c, Context.VOID); - return lv2; + lv1.evalValue(c, Context.VOID); + Value v2 = lv2.evalValue(c, t); + return (cc, tt) -> v2; }); //assigns const procedure to the lhs, returning its previous value @@ -1053,13 +1054,13 @@ public class Expression implements Cloneable if (lv.get(i).evalValue(c, Context.BOOLEAN).getBoolean()) { //int iFinal = i; - Value ret = lv.get(i+1).evalValue(c); + Value ret = lv.get(i+1).evalValue(c, t); return (cc, tt) -> ret; } } if (lv.size()%2 == 1) { - Value ret = lv.get(lv.size() - 1).evalValue(c); + Value ret = lv.get(lv.size() - 1).evalValue(c, t); return (cc, tt) -> ret; } return (cc, tt) -> Value.NULL; @@ -1746,7 +1747,7 @@ public class Expression implements Cloneable c.setVariable("_",(cc, tt) -> new NumericValue(0).bindTo("_")); while (i new NumericValue(seriously).bindTo("_")); @@ -1777,8 +1778,8 @@ public class Expression implements Cloneable { long whyYouAsk = i; c.setVariable("_", (cc, tt) -> new NumericValue(whyYouAsk).bindTo("_")); - lastOne = expr.evalValue(c); - if (cond != null && cond.evalValue(c).getBoolean()) + lastOne = expr.evalValue(c, t); + if (cond != null && cond.evalValue(c, Context.BOOLEAN).getBoolean()) break; } //revering scope @@ -1817,7 +1818,7 @@ public class Expression implements Cloneable c.setVariable("_", (cc, tt) -> next); c.setVariable("_i", (cc, tt) -> new NumericValue(doYouReally).bindTo("_i")); result.add(expr.evalValue(c)); - if (cond != null && cond.evalValue(c).getBoolean()) + if (cond != null && cond.evalValue(c, Context.BOOLEAN).getBoolean()) { next.boundVariable = var; break; @@ -1861,9 +1862,9 @@ public class Expression implements Cloneable int seriously = i; c.setVariable("_", (cc, tt) -> next); c.setVariable("_i", (cc, tt) -> new NumericValue(seriously).bindTo("_i")); - if(expr.evalValue(c).getBoolean()) + if(expr.evalValue(c, Context.BOOLEAN).getBoolean()) result.add(next); - if (cond != null && cond.evalValue(c).getBoolean()) + if (cond != null && cond.evalValue(c, Context.BOOLEAN).getBoolean()) { next.boundVariable = var; break; @@ -1901,7 +1902,7 @@ public class Expression implements Cloneable int seriously = i; c.setVariable("_", (cc, tt) -> next); c.setVariable("_i", (cc, tt) -> new NumericValue(seriously).bindTo("_i")); - if(expr.evalValue(c).getBoolean()) + if(expr.evalValue(c, Context.BOOLEAN).getBoolean()) { result = next; next.boundVariable = var; @@ -1939,7 +1940,7 @@ public class Expression implements Cloneable int seriously = i; c.setVariable("_", (cc, tt) -> next); c.setVariable("_i", (cc, tt) -> new NumericValue(seriously).bindTo("_i")); - if(!expr.evalValue(c).getBoolean()) + if(!expr.evalValue(c, Context.BOOLEAN).getBoolean()) { result = LazyValue.FALSE; next.boundVariable = var; @@ -1983,9 +1984,10 @@ public class Expression implements Cloneable int seriously = i; c.setVariable("_", (cc, tt) -> next); c.setVariable("_i", (cc, tt) -> new NumericValue(seriously).bindTo("_i")); - if(expr.evalValue(c).getBoolean()) + Value result = expr.evalValue(c, t); + if(t != Context.VOID && result.getBoolean()) successCount++; - if (cond != null && cond.evalValue(c).getBoolean()) + if (cond != null && cond.evalValue(c, Context.BOOLEAN).getBoolean()) { next.boundVariable = var; break; @@ -2033,7 +2035,7 @@ public class Expression implements Cloneable Value promiseWontChangeYou = acc; c.setVariable("_a", (cc, tt) -> promiseWontChangeYou.bindTo("_a")); c.setVariable("_", (cc, tt) -> next); - acc = expr.evalValue(c); + acc = expr.evalValue(c, t); next.boundVariable = var; } //reverting scope diff --git a/src/main/java/carpet/script/LazyValue.java b/src/main/java/carpet/script/LazyValue.java index 8a7d8f43..1cfb32a3 100644 --- a/src/main/java/carpet/script/LazyValue.java +++ b/src/main/java/carpet/script/LazyValue.java @@ -19,6 +19,6 @@ public interface LazyValue Value evalValue(Context c, Integer type); default Value evalValue(Context c){ - return evalValue(c, 0); + return evalValue(c, Context.NONE); } } diff --git a/src/main/java/carpet/script/value/BlockValue.java b/src/main/java/carpet/script/value/BlockValue.java index 6c32aebc..5a193f41 100644 --- a/src/main/java/carpet/script/value/BlockValue.java +++ b/src/main/java/carpet/script/value/BlockValue.java @@ -144,8 +144,6 @@ public class BlockValue extends Value } if (v1 instanceof BlockValue) { - ((BlockValue) v1).getBlockState(); - ((BlockValue) v1).getData(); return new LocatorResult(((BlockValue) v1), 1+offset); } if (v1 instanceof ListValue) @@ -256,7 +254,7 @@ public class BlockValue extends Value @Override public Value clone() { - return new BlockValue(blockState, world, pos); + return new BlockValue(blockState, world, pos, data); } @Override diff --git a/src/main/java/carpet/script/value/Value.java b/src/main/java/carpet/script/value/Value.java index 4b529c6a..8faf4c15 100644 --- a/src/main/java/carpet/script/value/Value.java +++ b/src/main/java/carpet/script/value/Value.java @@ -48,6 +48,7 @@ public abstract class Value implements Comparable, Cloneable { // should not happen e.printStackTrace(); + throw new InternalExpressionException("Variable of type "+getTypeString()+" is not cloneable. Tell gnembon about it, this shoudn't happen"); } copy.boundVariable = var; return copy;