Files
fabric-carpet/src/main/java/carpet/script/value/Value.java
T
2021-01-11 19:46:39 +01:00

259 lines
6.9 KiB
Java

package carpet.script.value;
import carpet.script.exception.InternalExpressionException;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import net.minecraft.nbt.Tag;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
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 NullValue NULL = new NullValue();
public String boundVariable;
public static <T> T assertNotNull(T t)
{
if (t == null)
throw new InternalExpressionException("Operand may not be null");
return t;
}
public static <T> void assertNotNull(T t1, T t2)
{
if (t1 == null)
throw new InternalExpressionException("First operand may not be null");
if (t2 == null)
throw new InternalExpressionException("Second operand may not be null");
}
public boolean isBound()
{
return boundVariable != null;
}
public String getVariable()
{
return boundVariable;
}
public Value reboundedTo(String var)
{
Value copy;
try
{
copy = (Value)clone();
}
catch (CloneNotSupportedException e)
{
// 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;
}
public Value bindTo(String var)
{
this.boundVariable = var;
return this;
}
public abstract String getString();
public String getPrettyString()
{
return getString();
}
public abstract boolean getBoolean();
public Value add(Value o) {
String lstr = this.getString();
if (o instanceof FormattedTextValue)
{
return FormattedTextValue.combine(this, o);
}
if (lstr == null) // null
return new StringValue(o.getString());
String rstr = o.getString();
if (rstr == null)
{
return new StringValue(lstr);
}
return new StringValue(lstr+rstr);
}
public Value subtract(Value v)
{
return new StringValue(this.getString().replace(v.getString(),""));
}
public Value multiply(Value v)
{
if (v instanceof NumericValue || v instanceof ListValue)
{
return v.multiply(this);
}
return new StringValue(this.getString()+"."+v.getString());
}
public Value divide(Value v)
{
if (v instanceof NumericValue)
{
String lstr = getString();
return new StringValue(lstr.substring(0, (int)(lstr.length()/ ((NumericValue) v).getDouble())));
}
return new StringValue(getString()+"/"+v.getString());
}
public Value()
{
this.boundVariable = null;
}
@Override
public int compareTo(final Value o)
{
if (o instanceof NumericValue || o instanceof ListValue || o instanceof ThreadValue)
{
return -o.compareTo(this);
}
return getString().compareTo(o.getString());
}
@Override // for hashmap key access, and == operator
public boolean equals(final Object o)
{
if (o instanceof Value)
return this.compareTo((Value) o)==0;
return false;
}
public void assertAssignable()
{
if (boundVariable == null || boundVariable.startsWith("_"))
{
if (boundVariable != null)
{
throw new InternalExpressionException(boundVariable+ " cannot be assigned a new value");
}
throw new InternalExpressionException(getString()+ " is not a variable");
}
}
public Value in(Value value1)
{
final Pattern p;
try
{
p = Pattern.compile(value1.getString());
}
catch (PatternSyntaxException pse)
{
throw new InternalExpressionException("Incorrect matching pattern: "+pse.getMessage());
}
final Matcher m = p.matcher(this.getString());
if (!m.find()) return Value.NULL;
int gc = m.groupCount();
if (gc == 0) return new StringValue(m.group());
if (gc == 1) return new StringValue(m.group(1));
List<Value> groups = new ArrayList<>(gc);
for (int i = 1; i <= gc; i++)
{
groups.add(new StringValue(m.group(i)));
}
return ListValue.wrap(groups);
}
public int length()
{
return getString().length();
}
public Value slice(long fromDesc, Long toDesc)
{
String value = this.getString();
int size = value.length();
int from = ListValue.normalizeIndex(fromDesc, size);
if (toDesc == null) return new StringValue(value.substring(from));
int to = ListValue.normalizeIndex(toDesc, size);
if (from > to) return StringValue.EMPTY;
return new StringValue(value.substring(from, to));
}
public Value split(Value delimiter)
{
try
{
return ListValue.wrap(Arrays.stream(getString().split(delimiter.getString())).map(StringValue::new).collect(Collectors.toList()));
}
catch (PatternSyntaxException pse)
{
throw new InternalExpressionException("Incorrect pattern for 'split': "+pse.getMessage());
}
}
public double readDoubleNumber()
{
String s = getString();
try
{
return Double.valueOf(s);
}
catch (NumberFormatException e)
{
return Double.NaN;
}
}
public long readInteger()
{
return (long) readDoubleNumber();
}
public String getTypeString()
{
throw new InternalExpressionException("How did you get here? Cannot get type of an intenal type.");
}
@Override
public int hashCode()
{
String stringVal = getString();
if (stringVal.isEmpty()) return 0;
return ("s"+stringVal).hashCode();
}
public Value deepcopy()
{
try
{
return (Value)this.clone();
}
catch (CloneNotSupportedException e)
{
// should never happen
throw new InternalExpressionException("Cannot make a copy of value: "+this);
}
}
public abstract Tag toTag(boolean force);
public JsonElement toJson()
{
return new JsonPrimitive(getString());
}
public boolean isNull() { return false; }
}