nbt support WIP and proper container API
This commit is contained in:
1 parent
8b7b285503
commit
718a619128
8 files changed
+393
-49
No files matched your search
@@ -13,10 +13,12 @@ import carpet.script.Fluff.TriFunction;
|
||||
import carpet.script.exception.ExpressionException;
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
import carpet.script.value.AbstractListValue;
|
||||
import carpet.script.value.ContainerValueInterface;
|
||||
import carpet.script.value.FunctionSignatureValue;
|
||||
import carpet.script.value.GlobalValue;
|
||||
import carpet.script.value.LazyListValue;
|
||||
import carpet.script.value.ListValue;
|
||||
import carpet.script.value.MapValue;
|
||||
import carpet.script.value.NumericValue;
|
||||
import carpet.script.value.StringValue;
|
||||
import carpet.script.value.Value;
|
||||
@@ -1227,7 +1229,12 @@ public class Expression implements Cloneable
|
||||
*/
|
||||
public void Operators()
|
||||
{
|
||||
addBinaryOperator(".", precedence.get("attribute~."),true, Value::getElementAt);
|
||||
addBinaryOperator(".", precedence.get("attribute~."),true, (container, key) ->
|
||||
{
|
||||
if (container instanceof ContainerValueInterface)
|
||||
return ((ContainerValueInterface) container).get(key);
|
||||
throw new InternalExpressionException("Cannot access elements of a non-container");
|
||||
});
|
||||
addBinaryOperator("+", precedence.get("addition+-"), true, Value::add);
|
||||
addBinaryOperator("-", precedence.get("addition+-"), true, Value::subtract);
|
||||
addBinaryOperator("*", precedence.get("multiplication*/%"), true, Value::multiply);
|
||||
@@ -1322,7 +1329,7 @@ public class Expression implements Cloneable
|
||||
v1.assertAssignable();
|
||||
String varname = v1.getVariable();
|
||||
LazyValue boundedLHS;
|
||||
if (v1 instanceof ListValue)
|
||||
if (v1 instanceof ListValue || v1 instanceof MapValue)
|
||||
{
|
||||
((ListValue) v1).append(v2);
|
||||
boundedLHS = (cc, tt)-> v1;
|
||||
@@ -1872,7 +1879,46 @@ public class Expression implements Cloneable
|
||||
return LazyListValue.range(from, to, step);
|
||||
});
|
||||
|
||||
addBinaryFunction("get", Value::getElementAt);
|
||||
addFunction("m", lv ->
|
||||
{
|
||||
if (lv.size() == 1 && lv.get(0) instanceof LazyListValue)
|
||||
return new MapValue(((LazyListValue) lv.get(0)).unroll());
|
||||
return new MapValue(lv);
|
||||
});
|
||||
|
||||
addUnaryFunction("keys", v -> {
|
||||
if (v instanceof MapValue)
|
||||
return new ListValue(((MapValue) v).getMap().keySet());
|
||||
throw new InternalExpressionException("keys applies only to maps");
|
||||
});
|
||||
|
||||
addUnaryFunction("values", v -> {
|
||||
if (v instanceof MapValue)
|
||||
return new ListValue(((MapValue) v).getMap().values());
|
||||
throw new InternalExpressionException("keys applies only to maps");
|
||||
});
|
||||
|
||||
addUnaryFunction("pairs", v -> {
|
||||
if (v instanceof MapValue)
|
||||
return new ListValue(((MapValue) v).getMap().entrySet().stream().map(
|
||||
(p) -> ListValue.of(p.getKey(), p.getValue())
|
||||
).collect(Collectors.toList()));
|
||||
throw new InternalExpressionException("pairs applies only to maps");
|
||||
});
|
||||
|
||||
addBinaryFunction("get", (container, key) ->
|
||||
{
|
||||
if (container instanceof ContainerValueInterface)
|
||||
return ((ContainerValueInterface) container).get(key);
|
||||
throw new InternalExpressionException("Cannot access elements of a non-container");
|
||||
});
|
||||
|
||||
addBinaryFunction("has", (container, key) ->
|
||||
{
|
||||
if (container instanceof ContainerValueInterface)
|
||||
return new NumericValue(((ContainerValueInterface) container).has(key));
|
||||
throw new InternalExpressionException("Cannot access elements of a non-container");
|
||||
});
|
||||
|
||||
//Deprecated, use "get" instead
|
||||
addBinaryFunction("element", (v1, v2) ->
|
||||
@@ -1892,27 +1938,36 @@ public class Expression implements Cloneable
|
||||
{
|
||||
if(lv.size()<3)
|
||||
{
|
||||
throw new InternalExpressionException("put takes at least three arguments, a list, index, and values to insert at that index");
|
||||
throw new InternalExpressionException("put takes at least three arguments, a container, address, and values to insert at that index");
|
||||
}
|
||||
Value list = lv.get(0);
|
||||
if (!(list instanceof ListValue))
|
||||
Value container = lv.get(0);
|
||||
if (!(container instanceof ContainerValueInterface))
|
||||
{
|
||||
throw new InternalExpressionException("First argument of element should be a list");
|
||||
throw new InternalExpressionException("First argument of put should be a container: list, map or nbt");
|
||||
}
|
||||
int size = lv.size();
|
||||
//List<Value> items = ((ListValue)lv.get(0)).getItems();
|
||||
Value index = lv.get(1);
|
||||
if (index == Value.NULL)
|
||||
Value where = lv.get(1);
|
||||
Value what = lv.get(2);
|
||||
Value ret;
|
||||
if (lv.size()>3)
|
||||
{
|
||||
((ListValue) list).extend(lv.subList(2,size));
|
||||
return ((ContainerValueInterface) container).put(where, what, lv.get(3));
|
||||
}
|
||||
else
|
||||
{
|
||||
((ListValue) list).addAtIndex((int) NumericValue.asNumber(index).getLong(), lv.subList(2,size));
|
||||
return ((ContainerValueInterface) container).put(where, what);
|
||||
}
|
||||
return new NumericValue(size-2);
|
||||
});
|
||||
|
||||
addBinaryFunction("delete", (container, address) ->
|
||||
{
|
||||
if (container instanceof ContainerValueInterface)
|
||||
{
|
||||
return ((ContainerValueInterface) container).remove(address);
|
||||
}
|
||||
throw new InternalExpressionException("First argument of remove should be a container: list, map or nbt");
|
||||
});
|
||||
|
||||
|
||||
//condition and expression will get a bound 'i'
|
||||
//returns last successful expression or false
|
||||
// while(cond, limit, expr) => ??
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
package carpet.script.value;
|
||||
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
public abstract class AbstractListValue extends Value
|
||||
{
|
||||
public abstract Iterator<Value> iterator();
|
||||
public void fatality() { }
|
||||
public void append(Value v)
|
||||
{
|
||||
throw new InternalExpressionException("Cannot append a value to abstract list");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package carpet.script.value;
|
||||
|
||||
public interface ContainerValueInterface
|
||||
{
|
||||
public Value put(Value where, Value value);
|
||||
default Value put(Value where, Value value, Value conditions)
|
||||
{
|
||||
return put(where, value);
|
||||
}
|
||||
public Value get(Value where);
|
||||
public boolean has(Value where);
|
||||
public Value remove(Value where);
|
||||
}
|
||||
@@ -126,11 +126,6 @@ public abstract class LazyListValue extends AbstractListValue implements Iterato
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value getElementAt(Value v2)
|
||||
{
|
||||
throw new InternalExpressionException("get element can only be obtained for regular lists");
|
||||
}
|
||||
@Override
|
||||
public String getTypeString()
|
||||
{
|
||||
|
||||
@@ -9,7 +9,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
import static java.lang.Math.abs;
|
||||
|
||||
public class ListValue extends AbstractListValue
|
||||
public class ListValue extends AbstractListValue implements ContainerValueInterface
|
||||
{
|
||||
protected List<Value> items;
|
||||
@Override
|
||||
@@ -98,6 +98,7 @@ public class ListValue extends AbstractListValue
|
||||
}
|
||||
return output;
|
||||
}
|
||||
@Override
|
||||
public void append(Value v)
|
||||
{
|
||||
items.add(v);
|
||||
@@ -271,6 +272,8 @@ public class ListValue extends AbstractListValue
|
||||
super(list);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length()
|
||||
{
|
||||
return items.size();
|
||||
@@ -309,7 +312,30 @@ public class ListValue extends AbstractListValue
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value getElementAt(Value value)
|
||||
public Value put(Value ind, Value value)
|
||||
{
|
||||
if (ind == Value.NULL)
|
||||
{
|
||||
items.add(value);
|
||||
return items.get(items.size()-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
int numitems = items.size();
|
||||
int index = (int) NumericValue.asNumber(ind).getLong();
|
||||
if (index < 0)
|
||||
{
|
||||
long range = abs(index) / numitems;
|
||||
index += (range + 2) * numitems;
|
||||
index = index % numitems;
|
||||
}
|
||||
while (index >= items.size()) items.add(Value.NULL);
|
||||
return items.set(index, value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value get(Value value)
|
||||
{
|
||||
long index = NumericValue.asNumber(value).getLong();
|
||||
int numitems = items.size();
|
||||
@@ -319,6 +345,24 @@ public class ListValue extends AbstractListValue
|
||||
return items.get((int)index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean has(Value where)
|
||||
{
|
||||
long index = NumericValue.asNumber(where).getLong();
|
||||
return index >= 0 && index < items.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value remove(Value where)
|
||||
{
|
||||
long index = NumericValue.asNumber(where).getLong();
|
||||
int numitems = items.size();
|
||||
long range = abs(index)/numitems;
|
||||
index += (range+2)*numitems;
|
||||
index = index % numitems;
|
||||
return items.remove((int)index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeString()
|
||||
{
|
||||
|
||||
@@ -1,18 +1,32 @@
|
||||
package carpet.script.value;
|
||||
|
||||
import java.util.Arrays;
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MapValue extends AbstractListValue
|
||||
public class MapValue extends AbstractListValue implements ContainerValueInterface
|
||||
{
|
||||
private Map<Value, Value> map;
|
||||
public MapValue()
|
||||
|
||||
private MapValue()
|
||||
{
|
||||
map = new HashMap<>();
|
||||
}
|
||||
|
||||
public MapValue(List<Value> kvPairs)
|
||||
{
|
||||
this();
|
||||
for (Value v : kvPairs)
|
||||
{
|
||||
put(v);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Value> iterator()
|
||||
{
|
||||
@@ -22,7 +36,20 @@ public class MapValue extends AbstractListValue
|
||||
@Override
|
||||
public String getString()
|
||||
{
|
||||
return Arrays.toString(map.entrySet().toArray());
|
||||
return "{"+map.entrySet().stream().map((p) -> p.getKey().getString()+": "+p.getValue().getString()).collect(Collectors.joining(", "))+"}";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrettyString()
|
||||
{
|
||||
if (map.size()<6)
|
||||
return "{"+map.entrySet().stream().map((p) -> p.getKey().getPrettyString()+": "+p.getValue().getPrettyString()).collect(Collectors.joining(", "))+"}";
|
||||
List<Value> keys = new ArrayList<>(map.keySet());
|
||||
int max = keys.size();
|
||||
return "{"+keys.get(0).getPrettyString()+": "+map.get(keys.get(0)).getPrettyString()+", "+
|
||||
keys.get(1).getPrettyString()+": "+map.get(keys.get(1)).getPrettyString()+", ..., "+
|
||||
keys.get(max-2).getPrettyString()+": "+map.get(keys.get(max-2)).getPrettyString()+", "+
|
||||
keys.get(max-1).getPrettyString()+": "+map.get(keys.get(max-1)).getPrettyString()+"}";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -31,4 +58,150 @@ public class MapValue extends AbstractListValue
|
||||
return !map.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value clone()
|
||||
{
|
||||
return new MapValue(map);
|
||||
}
|
||||
public MapValue(Map<Value,Value> other)
|
||||
{
|
||||
map = new HashMap<>(other);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value add(Value o)
|
||||
{
|
||||
throw new InternalExpressionException("cannot add to a map value");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value subtract(Value v)
|
||||
{
|
||||
throw new InternalExpressionException("cannot subtract to a map value");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value multiply(Value v)
|
||||
{
|
||||
throw new InternalExpressionException("cannot multiply to a map value");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value divide(Value v)
|
||||
{
|
||||
throw new InternalExpressionException("cannot divide to a map value");
|
||||
}
|
||||
|
||||
public void put(Value v)
|
||||
{
|
||||
if (!(v instanceof ListValue))
|
||||
{
|
||||
map.put(v, Value.NULL);
|
||||
return;
|
||||
}
|
||||
ListValue pair = (ListValue)v;
|
||||
if (pair.getItems().size() != 2)
|
||||
{
|
||||
throw new InternalExpressionException("map constructor requires elements that have two elements");
|
||||
}
|
||||
map.put(pair.getItems().get(0), pair.getItems().get(1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void append(Value v)
|
||||
{
|
||||
put(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Value o)
|
||||
{
|
||||
throw new InternalExpressionException("cannot compare to a map value");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Value o)
|
||||
{
|
||||
if (o instanceof MapValue)
|
||||
{
|
||||
MapValue ol = (MapValue)o;
|
||||
int this_size = this.map.keySet().size();
|
||||
int o_size = ol.map.keySet().size();
|
||||
if (this_size != o_size) return false;
|
||||
if (this_size == 0) return true;
|
||||
return this.map.keySet().equals(ol.map.keySet());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Map<Value, Value> getMap()
|
||||
{
|
||||
return map;
|
||||
}
|
||||
|
||||
public void extend(List<Value> subList)
|
||||
{
|
||||
for (Value v: subList) put(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length()
|
||||
{
|
||||
return map.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value in(Value value1)
|
||||
{
|
||||
if (map.containsKey(value1)) return value1;
|
||||
return Value.NULL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value slice(long from, long to)
|
||||
{
|
||||
throw new InternalExpressionException("cannot slice a map value");
|
||||
}
|
||||
|
||||
@Override
|
||||
public double readNumber()
|
||||
{
|
||||
return (double)map.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value get(Value v2)
|
||||
{
|
||||
return map.getOrDefault(v2, Value.NULL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean has(Value where)
|
||||
{
|
||||
return map.containsKey(where);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value remove(Value where)
|
||||
{
|
||||
return map.remove(where);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value put(Value key, Value value)
|
||||
{
|
||||
return map.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeString()
|
||||
{
|
||||
return "map";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return map.hashCode();
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package carpet.script.value;
|
||||
import carpet.script.CarpetContext;
|
||||
import carpet.script.LazyValue;
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
import carpet.settings.CarpetSettings;
|
||||
import com.mojang.brigadier.StringReader;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.minecraft.block.entity.HopperBlockEntity;
|
||||
@@ -20,17 +21,18 @@ import net.minecraft.nbt.StringNbtReader;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class NBTSerializableValue extends Value
|
||||
public class NBTSerializableValue extends Value implements ContainerValueInterface
|
||||
{
|
||||
private String nbtString = null;
|
||||
private Tag nbtTag = null;
|
||||
private Supplier<CompoundTag> nbtSupplier = null;
|
||||
private Supplier<Tag> nbtSupplier = null;
|
||||
|
||||
public NBTSerializableValue(ItemStack stack)
|
||||
{
|
||||
@@ -43,7 +45,7 @@ public class NBTSerializableValue extends Value
|
||||
{
|
||||
try
|
||||
{
|
||||
return (new StringNbtReader(new StringReader(nbtString))).parseCompoundTag();
|
||||
return (new StringNbtReader(new StringReader(nbtString))).parseTag();
|
||||
}
|
||||
catch (CommandSyntaxException e)
|
||||
{
|
||||
@@ -207,6 +209,82 @@ public class NBTSerializableValue extends Value
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value put(Value where, Value value)
|
||||
{
|
||||
/// WIP
|
||||
|
||||
NbtPathArgumentType.NbtPath path = cachePath(where.getString());
|
||||
Tag tagToInsert = value instanceof NBTSerializableValue ?
|
||||
((NBTSerializableValue) value).getTag() :
|
||||
new NBTSerializableValue(value.getString()).getTag();
|
||||
CarpetSettings.LOG.error("Inserting tag of class: "+tagToInsert.getClass().getSimpleName());
|
||||
|
||||
Tag tag = getTag().copy();
|
||||
try
|
||||
{
|
||||
Collection<Tag> collection_1 = path.get(tag); //, CompoundTag::new);
|
||||
for(Tag t: collection_1)
|
||||
{
|
||||
((CompoundTag)t).copyFrom((CompoundTag) tagToInsert);
|
||||
}
|
||||
if (collection_1.size() > 0)
|
||||
{
|
||||
nbtSupplier = () -> tag;
|
||||
nbtTag = tag;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
catch (CommandSyntaxException e)
|
||||
{
|
||||
return Value.NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value put(Value where, Value value, Value conditions)
|
||||
{
|
||||
throw new InternalExpressionException("not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value get(Value value)
|
||||
{
|
||||
NbtPathArgumentType.NbtPath path = cachePath(value.getString());
|
||||
try
|
||||
{
|
||||
List<Tag> tags = path.get(getTag());
|
||||
if (tags.size()==0)
|
||||
return Value.NULL;
|
||||
if (tags.size()==1)
|
||||
return NBTSerializableValue.decodeTag(tags.get(0));
|
||||
return ListValue.wrap(tags.stream().map(NBTSerializableValue::decodeTag).collect(Collectors.toList()));
|
||||
}
|
||||
catch (CommandSyntaxException ignored) { }
|
||||
return Value.NULL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean has(Value where)
|
||||
{
|
||||
return cachePath(where.getString()).count(getTag()) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value remove(Value where)
|
||||
{
|
||||
NbtPathArgumentType.NbtPath path = cachePath(where.getString());
|
||||
Tag tag = getTag().copy();
|
||||
int removed = path.remove(tag);
|
||||
if (removed > 0)
|
||||
{
|
||||
nbtSupplier = null;
|
||||
nbtTag = tag;
|
||||
return Value.TRUE;
|
||||
}
|
||||
return Value.FALSE;
|
||||
}
|
||||
|
||||
public static class InventoryLocator
|
||||
{
|
||||
public Object owner;
|
||||
@@ -242,22 +320,7 @@ public class NBTSerializableValue extends Value
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value getElementAt(Value value)
|
||||
{
|
||||
NbtPathArgumentType.NbtPath path = cachePath(value.getString());
|
||||
try
|
||||
{
|
||||
List<Tag> tags = path.get(getTag());
|
||||
if (tags.size()==0)
|
||||
return Value.NULL;
|
||||
if (tags.size()==1)
|
||||
return NBTSerializableValue.decodeTag(tags.get(0));
|
||||
return ListValue.wrap(tags.stream().map(NBTSerializableValue::decodeTag).collect(Collectors.toList()));
|
||||
}
|
||||
catch (CommandSyntaxException ignored) { }
|
||||
return Value.NULL;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getTypeString()
|
||||
|
||||
@@ -173,11 +173,6 @@ public abstract class Value implements Comparable<Value>, Cloneable
|
||||
return (long)readNumber();
|
||||
}
|
||||
|
||||
public Value getElementAt(Value v2)
|
||||
{
|
||||
throw new InternalExpressionException("get element can only be obtained for lists and nbt values");
|
||||
}
|
||||
|
||||
public String getTypeString()
|
||||
{
|
||||
throw new InternalExpressionException("How did you get here? Cannot get type of an intenal type.");
|
||||
|
||||
Reference in new issue
Block a user