true and false represent now proper boolean values, not just 0 and 1. All other previous arithmetic holds.

This commit is contained in:
gnembon committed 2021-03-02 23:33:51 -04:00
1 parent 8f592735ca
commit 1ae358909b
9 files changed
+137 -74

No files matched your search

+13 -13
View File
@@ -23,12 +23,12 @@ In case to simplify the access with nested objects, you can add chain of address
than calling it multiple times. `get(get(foo,a),b)` is equivalent to `get(foo, a, b)`, or `foo:a:b`.
<pre>
get(l(range(10)), 5) => 5
get(l(range(10)), -1) => 9
get(l(range(10)), 10) => 0
l(range(10)):93 => 3
get([range(10)], 5) => 5
get([range(10)], -1) => 9
get([range(10)], 10) => 0
[range(10)]:93 => 3
get(player() ~ 'nbt', 'Health') => 20 // inefficient way to get player health, use player() ~ 'health' instead
get(m( l('foo',2), l('bar',3), l('baz',4) ), 'bar') => 3
get({ 'foo' -> 2, 'bar' -> 3, 'baz' -> 4 }, 'bar') => 3
</pre>
### `has(container, address, ...), has(lvalue)`
@@ -100,13 +100,13 @@ of the existing elements. Use `replace` to remove and replace existing element.
and merges keys from `value` with the compound tag under the path
<pre>
a = l(1, 2, 3); put(a, 1, 4); a => [1, 4, 3]
a = l(1, 2, 3); put(a, null, 4); a => [1, 2, 3, 4]
a = l(1, 2, 3); put(a, 1, 4, 'insert'); a => [1, 4, 2, 3]
a = l(1, 2, 3); put(a, null, l(4, 5, 6), 'extend'); a => [1, 2, 3, 4, 5, 6]
a = l(1, 2, 3); put(a, 1, l(4, 5, 6), 'extend'); a => [1, 4, 5, 6, 2, 3]
a = l(l(0,0,0),l(0,0,0),l(0,0,0)); put(a.1, 1, 1); a => [[0, 0, 0], [0, 1, 0], [0, 0, 0]]
a = m(1,2,3,4); put(a, 5, null); a => {1: null, 2: null, 3: null, 4: null, 5: null}
a = [1, 2, 3]; put(a, 1, 4); a => [1, 4, 3]
a = [1, 2, 3]; put(a, null, 4); a => [1, 2, 3, 4]
a = [1, 2, 3]; put(a, 1, 4, 'insert'); a => [1, 4, 2, 3]
a = [1, 2, 3]; put(a, null, [4, 5, 6], 'extend'); a => [1, 2, 3, 4, 5, 6]
a = [1, 2, 3]; put(a, 1, [4, 5, 6], 'extend'); a => [1, 4, 5, 6, 2, 3]
a = [[0,0,0],[0,0,0],[0,0,0]]; put(a:1, 1, 1); a => [[0, 0, 0], [0, 1, 0], [0, 0, 0]]
a = {1,2,3,4}; put(a, 5, null); a => {1: null, 2: null, 3: null, 4: null, 5: null}
tag = nbt('{}'); put(tag, 'BlockData.Properties', '[1,2,3,4]'); tag => {BlockData:{Properties:[1,2,3,4]}}
tag = nbt('{a:[{lvl:3},{lvl:5},{lvl:2}]}'); put(tag, 'a[].lvl', 1); tag => {a:[{lvl:1},{lvl:1},{lvl:1}]}
tag = nbt('{a:[{lvl:[1,2,3]},{lvl:[3,2,1]},{lvl:[4,5,6]}]}'); put(tag, 'a[].lvl', 1, 2); tag
@@ -225,7 +225,7 @@ Primarily to be used in higher order functions
<pre>
range(10) => [...]
l(range(10)) => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[range(10)] => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
map(range(10),_*_) => [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
reduce(range(10),_a+_, 0) => 45
range(5,10) => [5, 6, 7, 8, 9]
@@ -124,12 +124,12 @@ to `all(list,expr) <=> for(list,expr)==length(list)`. `expr` also receives bound
and `continue` have no sense and cannot be used inside of `expr` body.
<pre>
all([1,2,3], check_prime(_)) => 1
all(neighbours(x,y,z), _=='stone') => 1 // if all neighbours of [x, y, z] are stone
map(filter(rect(0,4,0,1000,0,1000), l(x,y,z)=pos(_); all(rect(x,y,z,1,0,1),_=='bedrock') ), pos(_) )
all([1,2,3], check_prime(_)) => true
all(neighbours(x,y,z), _=='stone') => true // if all neighbours of [x, y, z] are stone
map(filter(rect(0,4,0,1000,0,1000), [x,y,z]=pos(_); all(rect(x,y,z,1,0,1),_=='bedrock') ), pos(_) )
=> [[-298, 4, -703], [-287, 4, -156], [-269, 4, 104], [242, 4, 250], [-159, 4, 335], [-208, 4, 416], [-510, 4, 546], [376, 4, 806]]
// find all 3x3 bedrock structures in the top bedrock layer
map( filter( rect(0,4,0,1000,1,1000,1000,0,1000), l(x,y,z)=pos(_);
map( filter( rect(0,4,0,1000,1,1000,1000,0,1000), [x,y,z]=pos(_);
all(rect(x,y,z,1,0,1),_=='bedrock') && for(rect(x,y-1,z,1,1,1,1,0,1),_=='bedrock')<8),
pos(_) ) => [[343, 3, -642], [153, 3, -285], [674, 3, 167], [-710, 3, 398]]
// ditto, but requiring at most 7 bedrock block in the 18 blocks below them
+24 -23
View File
@@ -16,7 +16,7 @@ in [User Defined Functions and Program Control Flow](docs/scarpet/language/Funct
1357-5 => 1352
1357-'5' => 137
3*'foo'-'o' => 'fff'
l(1,3,5)+7 => l(8,10,12)
[1,3,5]+7 => [8,10,12]
</pre>
As you can see, values can behave differently when mixed with other types in the same expression.
@@ -76,8 +76,8 @@ In Minecraft API portion `entity ~ feature` is a shortcode for `query(entity,fea
any extra arguments.
<pre>
l(1,2,3) ~ 2 => 1
l(1,2,3) ~ 4 => null
[1,2,3] ~ 2 => 1
[1,2,3] ~ 4 => null
'foobar' ~ 'baz' => null
'foobar' ~ '.b' => 'ob'
@@ -103,10 +103,10 @@ Or an example to find if a player has specific enchantment on a held axe (either
<pre>
global_get_enchantment(p, ench) -> (
$ for(l('main','offhand'),
$ for(['main','offhand'],
$ holds = query(p, 'holds', _);
$ if( holds,
$ l(what, count, nbt) = holds;
$ [what, count, nbt] = holds;
$ if( what ~ '_axe' && nbt ~ ench,
$ lvl = max(lvl, number(nbt ~ '(?<=lvl:)\\d') )
$ )
@@ -143,8 +143,8 @@ Examples:
'foo'*3 => 'foofoofoo'
'foofoofoo' / 3 => 'foo'
'foofoofoo'-'o' => 'fff'
l(1,2,3)+1 => l(2,3,4)
b = l(100,63,100); b+l(10,0,10) => l(110,63,110)
[1,2,3]+1 => [2,3,4]
b = [100,63,100]; b+[10,0,10] => [110,63,110]
{'a' -> 1} + {'b' -> 2} => {'a' -> 1, 'b' -> 2}
</pre>
@@ -186,11 +186,12 @@ second operand is not necessary, it won't be evaluated, which means one can use
case of success returns first positive operand (`||`) or last one (`&&`).
<pre>
true || false => 1
null || false => 0
null != false || run('kill gnembon') => 1 // gnembon survives
null != false && run('kill gnembon') => 0 // when cheats not allowed
null != false && run('kill gnembon') => 1 // gnembon dies, cheats allowed
true || false => true
null || false => false
false || null => null
null != false || run('kill gnembon') // gnembon survives
null != false && run('kill gnembon') // when cheats not allowed
null != false && run('kill gnembon') // gnembon dies, cheats allowed
</pre>
### `Assignment Operators = <> +=`
@@ -204,11 +205,11 @@ require rewriting of the array anyways.
<pre>
a = 5 => a == 5
l(a,b,c) = l(3,4,5) => a==3, b==4, c==5
l(minx,maxx) = sort(xi,xj); // minx assumes min(xi, xj) and maxx, max(xi, xj)
l(a,b,c,d,e,f) = l(range(6)); l(a,b,c) <> l(d,e,f); l(a,b,c,d,e,f) => [3,4,5,0,1,2]
a = l(1,2,3); a += 4 => [1,2,3,4]
a = l(1,2,3,4); a = filter(a,_!=2) => [1,3,4]
[a,b,c] = [3,4,5] => a==3, b==4, c==5
[minx,maxx] = sort(xi,xj); // minx assumes min(xi, xj) and maxx, max(xi, xj)
[a,b,c,d,e,f] = [range(6)]; [a,b,c] <> [d,e,f]; [a,b,c,d,e,f] => [3,4,5,0,1,2]
a = [1,2,3]; a += 4 => [1,2,3,4]
a = [1,2,3,4]; a = filter(a,_!=2) => [1,3,4]
</pre>
### `Unary Operators - +`
@@ -226,10 +227,10 @@ Require a number, flips the sign. One way to assert it's a number is by crashing
flips boolean condition of the expression. Equivalent of `bool(expr)==false`
<pre>
!true => 0
!false => 1
!null => 1
!5 => 0
!l() => 1
!l(null) => 0
!true => false
!false => true
!null => true
!5 => false
!l() => true
!l(null) => false
</pre>
+25 -24
View File
@@ -14,30 +14,31 @@ as well as minecraft related concepts like `block`, `entity`, `nbt`, `text`.
### `bool(expr)`
Returns a boolean context of the expression. Note that there are no true/false values in scarpet. `true` is
alias of 1, and `false` is 0\. Bool is also interpreting string values as boolean, which is different from other
Returns a boolean context of the expression.
Bool is also interpreting string values as boolean, which is different from other
places where boolean context can be used. This can be used in places where API functions return string values to
represent binary values
represent binary values.
<pre>
bool(pi) => 1
bool(false) => 0
bool('') => 0
bool(l()) => 0
bool(l('')) => 1
bool('foo') => 1
bool('false') => 0
bool('nulL') => 0
if('false',1,0) => 1
bool(pi) => true
bool(false) => false
bool('') => false
bool(l()) => false
bool(l('')) => true
bool('foo') => true
bool('false') => false
bool('nulL') => false
if('false',1,0) => true
</pre>
### `number(expr)`
Returns a numeric context of the expression. Can be used to read numbers from strings
Returns a numeric context of the expression. Can be used to read numbers from strings, or other types
<pre>
number(null) => null
number(null) => 0
number(false) => 0
number(true) => 1
number('') => null
number('3.14') => 3.14
number(l()) => 0
@@ -65,15 +66,15 @@ Supported types (with `"%<?>"` syntax):
* `%%`: '%' character
<pre>
str(null) => null
str(false) => 0
str('') => null
str('3.14') => 3.14
str(l()) => 0
str(l('')) => 1
str('foo') => null
str('3bar') => null
str(2)+str(2) => 22
str(null) => 'null'
str(false) => 'false'
str('') => ''
str('3.14') => '3.14'
str([]) => '[]'
str(['']) => '[]'
str('foo') => 'foo'
str('3bar') => '3bar'
str(2)+str(2) => '22'
str('pi: %.2f',pi) => 'pi: 3.14'
str('player at: %d %d %d',pos(player())) => 'player at: 567, -2423, 124'
</pre>
@@ -234,7 +235,7 @@ same random object. Scarpet keeps track of up to 1024 custom random number gener
<pre>
map(range(10), floor(rand(10))) => [5, 8, 0, 6, 9, 3, 9, 9, 1, 8]
map(range(10), bool(rand(2))) => [1, 1, 1, 0, 0, 1, 1, 0, 0, 0]
map(range(10), bool(rand(2))) => [false, false, true, false, false, false, true, false, true, false]
map(range(10), str('%.1f',rand(_))) => [0.0, 0.4, 0.6, 1.9, 2.8, 3.8, 5.3, 2.2, 1.6, 5.6]
</pre>
@@ -3,8 +3,8 @@
`scarpet` provides a number of constants that can be used literally in scripts
* `null`: nothing, zilch, not even false
* `true`: pure true, or just 1 (one)
* `false`: false truth, or true falsth, 0 (zero) actually
* `true`: pure true, can act as `1`
* `false`: false truth, or true falsth, equals to `0`
* `pi`: for the fans of perimeters, its a perimeter of an apple pi of diameter 1\. About 3.14
* `euler`: clever guy. Derivative of its exponent is goto 1\. About 2.72
@@ -48,7 +48,7 @@ public class Sys {
return (cc, tt) -> Value.FALSE;
}
}
Value retval = new NumericValue(v.getBoolean());
Value retval = v.getBoolean()?Value.TRUE:Value.FALSE;
return (cc, tt) -> retval;
});
@@ -56,7 +56,9 @@ public class Sys {
{
if (v instanceof NumericValue)
{
return v;
NumericValue num = (NumericValue)v;
if (num.isInteger()) return new NumericValue(num.getLong());
return new NumericValue(num.getDouble());
}
try
{
@@ -0,0 +1,58 @@
package carpet.script.value;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import net.minecraft.nbt.ByteTag;
import net.minecraft.nbt.Tag;
public class BooleanValue extends NumericValue
{
public static final BooleanValue FALSE = new BooleanValue(false);
public static final BooleanValue TRUE = new BooleanValue(true);
boolean boolValue;
private BooleanValue(boolean boolval) {
super(boolval);
boolValue = boolval;
}
@Override
public String getString() {
return boolValue?"true":"false";
}
@Override
public String getPrettyString() {
return getString();
}
@Override
public String getTypeString() {
return "bool";
}
@Override
public Value clone() {
return new BooleanValue(boolValue);
}
@Override
public int hashCode() {
return Boolean.hashCode(boolValue);
}
@Override
public Tag toTag(boolean force) {
return ByteTag.of(boolValue);
}
@Override
public JsonElement toJson() {
return new JsonPrimitive(boolValue);
}
@Override
public boolean isInteger() {
return true;
}
}
@@ -9,6 +9,7 @@ import net.minecraft.nbt.Tag;
public class NullValue extends NumericValue // TODO check nonsingleton code
{
public static final NullValue NULL = new NullValue();
@Override
public String getString()
{
@@ -32,7 +33,7 @@ public class NullValue extends NumericValue // TODO check nonsingleton code
{
return new NullValue();
}
public NullValue() {super(0.0D);}
private NullValue() {super(false);}
@Override
public boolean equals(final Object o)
+5 -5
View File
@@ -15,12 +15,12 @@ import java.util.stream.Collectors;
public abstract class Value implements Comparable<Value>, Cloneable
{
public static NumericValue FALSE = new NumericValue(0);
public static NumericValue TRUE = new NumericValue(1);
public static NumericValue ZERO = FALSE;
public static NumericValue ONE = TRUE;
public static NumericValue FALSE = BooleanValue.FALSE;
public static NumericValue TRUE = BooleanValue.TRUE;
public static NumericValue ZERO = new NumericValue(0);
public static NumericValue ONE = new NumericValue(1);
public static NullValue NULL = new NullValue();
public static NullValue NULL = NullValue.NULL;
public String boundVariable;