java-commons/muscript/src/main/java/io/gitlab/jfronny/muscript/data/dynamic/additional/DEnum.java

136 lines
4.3 KiB
Java

package io.gitlab.jfronny.muscript.data.dynamic.additional;
import io.gitlab.jfronny.commons.StringFormatter;
import io.gitlab.jfronny.commons.data.ImmCollection;
import io.gitlab.jfronny.muscript.ast.DynamicExpr;
import io.gitlab.jfronny.muscript.ast.dynamic.Call;
import io.gitlab.jfronny.muscript.ast.dynamic.Variable;
import io.gitlab.jfronny.muscript.ast.literal.StringLiteral;
import io.gitlab.jfronny.muscript.compiler.CodeLocation;
import io.gitlab.jfronny.muscript.data.dynamic.*;
import io.gitlab.jfronny.muscript.data.dynamic.lens.*;
import io.gitlab.jfronny.muscript.data.dynamic.type.*;
import org.jetbrains.annotations.Nullable;
import java.util.*;
/**
* An enum represented as an OObject.
* May also have a selected value with automatic conversions to a number (index) and string
*/
public record DEnum(Map<String, ? extends Dynamic> values, @Nullable DEnumEntry value, @Nullable DType valueSignature) implements DObject {
public DEnum(Map<String, ? extends Dynamic> values) {
this(null, values);
}
public DEnum(DType valueSignature, Map<String, ? extends Dynamic> values) {
this(values, null, valueSignature);
}
public DEnum(Map<String, ? extends Dynamic> values, @Nullable String value) {
this(null, values, value);
}
public DEnum(DType valueSignature, Map<String, ? extends Dynamic> values, @Nullable String value) {
this(values, value == null ? null : new DEnumEntry(value, values.keySet().stream().toList().indexOf(value), true), valueSignature);
}
public DEnum(List<String> values, String value) {
this(createMap(values, value), value == null ? null : new DEnumEntry(value, values.indexOf(value), true), DTypePrimitive.STRING);
}
public DEnum(List<String> values) {
this(values, null);
}
@Override
public Map<String, ? extends Dynamic> getValue() {
return values;
}
@Override
public boolean isList() {
return true;
}
@Override
public DList asList() {
return new DListLens(this, () -> List.copyOf(values.values()));
}
@Override
public boolean isString() {
return true;
}
@Override
public DString asString() {
return value != null ? value : new DStringLens(this, () -> StringFormatter.toString(values));
}
@Override
public boolean isNumber() {
return value != null;
}
@Override
public DNumber asNumber() {
return value != null ? new DNumberLens(this, value::index) : DObject.super.asNumber();
}
@Override
public DynamicExpr toExpr() {
List<Call.Arg> args = new LinkedList<>();
args.add(new Call.Arg(DObject.super.toExpr(), false));
if (value != null) args.add(new Call.Arg(new StringLiteral(CodeLocation.NONE, value.value).asDynamicExpr(), false));
return new Call(CodeLocation.NONE, new Variable(CodeLocation.NONE, "enum"), args);
}
@Override
public DType getSignature() {
Set<DType> types = new HashSet<>();
types.add(new DTypeObject(valueSignature));
types.add(new DTypeList(valueSignature));
types.add(DTypePrimitive.STRING);
if (value != null) types.add(DTypePrimitive.NUMBER);
return new DTypeAnd(types);
}
private static Map<String, Dynamic> createMap(List<String> values, String value) {
Map<String, Dynamic> result = new LinkedHashMap<>();
DEnumEntry v = new DEnumEntry(value, values.indexOf(value), true);
result.put("value", v);
for (int i = 0; i < values.size(); i++) {
result.put(values.get(i), new DEnumEntry(values.get(i), i, values.get(i).equals(value)));
}
return ImmCollection.of(result);
}
public record DEnumEntry(String value, int index, boolean selected) implements DString {
@Override
public String getValue() {
return value;
}
@Override
public boolean isNumber() {
return true;
}
@Override
public DNumber asNumber() {
return new DNumberLens(this, this::index);
}
@Override
public boolean isBool() {
return true;
}
@Override
public DBool asBool() {
return new DBoolLens(this, this::selected);
}
}
}