Skip to content

Feature/type attributes #136

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public boolean init(Expression<?>[] expressions, int matchedPattern, ParseContex

@Override
public boolean check(TriggerContext ctx) {
return getPerformer().check(
return getOwner().check(
ctx,
performer -> divider.getSingle(ctx)
.filter(__ -> BigDecimalMath.isIntValue(BigDecimalMath.getBigDecimal(performer)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@
public class CondExprIsPrime extends PropertyConditional<Number> {
static {
Parser.getMainRegistration().newPropertyConditional(CondExprIsPrime.class, "numbers", ConditionalType.BE, "[a] prime [number[s]]")
.addData(PROPERTY_IDENTIFIER, "prime")
.setPropertyName("prime")
.register();
}

@Override
public boolean check(Number performer) {
var bd = BigDecimalMath.getBigDecimal(performer);
public boolean check(Number owner) {
var bd = BigDecimalMath.getBigDecimal(owner);
return bd.signum() != -1
&& BigDecimalMath.isIntValue(bd)
&& NumberMath.isPrime(BigDecimalMath.getBigInteger(bd));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class CondExprIsSet extends PropertyConditional<Object> {
}

@Override
public boolean check(Object performer) {
public boolean check(Object owner) {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,16 @@

import io.github.syst3ms.skriptparser.Parser;
import io.github.syst3ms.skriptparser.lang.Expression;
import io.github.syst3ms.skriptparser.lang.Literal;
import io.github.syst3ms.skriptparser.lang.TriggerContext;
import io.github.syst3ms.skriptparser.lang.Variable;
import io.github.syst3ms.skriptparser.log.ErrorType;
import io.github.syst3ms.skriptparser.log.SkriptLogger;
import io.github.syst3ms.skriptparser.parsing.ParseContext;
import io.github.syst3ms.skriptparser.types.Type;
import io.github.syst3ms.skriptparser.types.TypeManager;
import io.github.syst3ms.skriptparser.types.changers.Arithmetic;
import io.github.syst3ms.skriptparser.util.ClassUtils;
import io.github.syst3ms.skriptparser.types.attributes.Arithmetic;
import io.github.syst3ms.skriptparser.util.DoubleOptional;
import org.jetbrains.annotations.Nullable;

import java.util.Optional;

/**
* The difference between two values.
* Note that only values that can be checked for difference are allowed
Expand All @@ -37,74 +33,29 @@ public class ExprDifference implements Expression<Object> {
}

private Expression<?> first, second;
private boolean variablePresent;
@SuppressWarnings("rawtypes")
@Nullable
private Arithmetic arithmetic;
private TypeManager.IntersectionType intersectionType;

@Override
public boolean init(Expression<?>[] expressions, int matchedPattern, ParseContext parseContext) {
first = expressions[0];
second = expressions[1];
Optional<? extends Type<?>> type;

if (first instanceof Literal<?> && second instanceof Literal<?>) {
type = TypeManager.getByClass(
ClassUtils.getCommonSuperclass(first.getReturnType(), second.getReturnType())
);
} else if (first instanceof Variable<?> && second instanceof Variable<?>) {
variablePresent = true;
type = TypeManager.getByClassExact(Object.class);
} else {
// If the values are Literals, we want to use that to convert them as much as possible.
if (first instanceof Literal<?>) {
var firstConverted = first.convertExpression(second.getReturnType());
if (firstConverted.isEmpty())
return false;
first = firstConverted.get();
} else if (second instanceof Literal<?>) {
var secondConverted = second.convertExpression(first.getReturnType());
if (secondConverted.isEmpty())
return false;
second = secondConverted.get();
}
if (first instanceof Variable<?> || second instanceof Variable<?>)
return true;

// If one value is a Variable, we do not know its type at parse-time.
if (first instanceof Variable<?>) {
variablePresent = true;
first = first.convertExpression(second.getReturnType()).orElseThrow();
type = TypeManager.getByClass(second.getReturnType());
} else if (second instanceof Variable<?>) {
variablePresent = true;
second = second.convertExpression(first.getReturnType()).orElseThrow();
type = TypeManager.getByClass(first.getReturnType());
} else {
type = TypeManager.getByClass(
ClassUtils.getCommonSuperclass(first.getReturnType(), second.getReturnType())
);
}
}

assert type.isPresent();
if (!variablePresent && type.get().getArithmetic().isEmpty()) {
var firstType = TypeManager.getByClass(first.getReturnType());
var secondType = TypeManager.getByClass(second.getReturnType());
assert firstType.isPresent() && secondType.isPresent();
var info = TypeManager.getByIntersection(Arithmetic.class, first.getReturnType(), second.getReturnType());
if (info.isEmpty()) {
SkriptLogger logger = parseContext.getLogger();
parseContext.getLogger().error(
"Cannot compare these two values"
+ " (types '"
+ firstType.get().getBaseName()
+ "' and '"
+ secondType.get().getBaseName()
+ "' are inconvertible)",
"Cannot get the difference between "
+ first.toString(TriggerContext.DUMMY, logger.isDebug())
+ " and "
+ second.toString(TriggerContext.DUMMY, logger.isDebug()),
ErrorType.SEMANTIC_ERROR
);
return false;
}
if (!variablePresent) {
assert type.get().getArithmetic().isPresent();
arithmetic = type.get().getArithmetic().get();
}
intersectionType = info.get();
return true;
}

Expand All @@ -113,27 +64,31 @@ public boolean init(Expression<?>[] expressions, int matchedPattern, ParseContex
public Object[] getValues(TriggerContext ctx) {
return DoubleOptional.ofOptional(first.getSingle(ctx), second.getSingle(ctx))
.mapToOptional((f, s) -> {
// The arithmetic field isn't initialized here.
if (variablePresent) {
assert f.getClass() == s.getClass();
var type = TypeManager.getByClass(f.getClass()).orElseThrow();
var variableMath = type.getArithmetic();
if (variableMath.isEmpty())
// If variables are used, the arithmetic field is not initialised.
if (intersectionType == null) {
var info = TypeManager.getByIntersection(Arithmetic.class, f.getClass(), s.getClass());
// If it's still null, then no difference can be found sadly...
if (info.isEmpty())
return null;
arithmetic = variableMath.get();
intersectionType = info.get();
}

assert arithmetic != null;
return new Object[] {arithmetic.difference(f, s)};
// Convert the expressions to the intersection type
var firstConverted = intersectionType.convert(f);
var secondConverted = intersectionType.convert(s);
if (firstConverted.isEmpty() || secondConverted.isEmpty())
return null;
Arithmetic arithmetic = intersectionType.getType().getArithmetic().orElseThrow();
return new Object[] {arithmetic.difference(firstConverted.get(), secondConverted.get())};
})
.orElse(new Object[0]);
}

@Override
public Class<?> getReturnType() {
return arithmetic != null
? arithmetic.getRelativeType()
: ClassUtils.getCommonSuperclass(false, first.getReturnType(), second.getReturnType());
return intersectionType != null
? intersectionType.getType().getArithmetic().orElseThrow().getRelativeType()
: Object.class;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,22 @@
import io.github.syst3ms.skriptparser.Parser;
import io.github.syst3ms.skriptparser.lang.Expression;
import io.github.syst3ms.skriptparser.lang.TriggerContext;
import io.github.syst3ms.skriptparser.lang.Variable;
import io.github.syst3ms.skriptparser.log.ErrorType;
import io.github.syst3ms.skriptparser.log.SkriptLogger;
import io.github.syst3ms.skriptparser.parsing.ParseContext;
import io.github.syst3ms.skriptparser.types.TypeManager;
import io.github.syst3ms.skriptparser.types.attributes.Range;
import io.github.syst3ms.skriptparser.types.comparisons.Comparators;
import io.github.syst3ms.skriptparser.types.comparisons.Relation;
import io.github.syst3ms.skriptparser.types.ranges.RangeInfo;
import io.github.syst3ms.skriptparser.types.ranges.Ranges;
import io.github.syst3ms.skriptparser.util.ClassUtils;
import io.github.syst3ms.skriptparser.util.CollectionUtils;
import io.github.syst3ms.skriptparser.util.DoubleOptional;

import java.util.function.BiFunction;

/**
* Returns a range of values between two endpoints. Types supported by default are integers and characters (length 1 strings).
*
* @name Range
* @pattern [the] range from %object% to %object%
* @pattern [the] range from %object% [up|down]([ ]to| until) %object%
* @since ALPHA
* @author Syst3ms
*/
Expand All @@ -30,19 +28,22 @@ public class ExprRange implements Expression<Object> {
ExprRange.class,
Object.class,
false,
"[the] range from %object% to %object%"
"[the] range from %object% [up|down]([ ]to| until) %object%"
);
}

private Expression<?> from, to;
private RangeInfo<?, ?> range;
private TypeManager.IntersectionType intersectionType;

@Override
public boolean init(Expression<?>[] expressions, int matchedPattern, ParseContext parseContext) {
from = expressions[0];
to = expressions[1];
range = Ranges.getRange(ClassUtils.getCommonSuperclass(from.getReturnType(), to.getReturnType())).orElse(null);
if (range == null) {
if (from instanceof Variable<?> || to instanceof Variable<?>)
return true;

var info = TypeManager.getByIntersection(Range.class, from.getReturnType(), to.getReturnType());
if (info.isEmpty()) {
SkriptLogger logger = parseContext.getLogger();
logger.error(
"Cannot get a range between "
Expand All @@ -52,6 +53,7 @@ public boolean init(Expression<?>[] expressions, int matchedPattern, ParseContex
ErrorType.SEMANTIC_ERROR);
return false;
}
intersectionType = info.get();
return true;
}

Expand All @@ -60,21 +62,36 @@ public boolean init(Expression<?>[] expressions, int matchedPattern, ParseContex
public Object[] getValues(TriggerContext ctx) {
return DoubleOptional.ofOptional(from.getSingle(ctx), to.getSingle(ctx))
.mapToOptional((f, t) -> {
if (intersectionType == null) {
var info = TypeManager.getByIntersection(Range.class, f.getClass(), t.getClass());
// If it's still null, then no range can be found sadly...
if (info.isEmpty())
return null;
intersectionType = info.get();
}

// Convert the expressions to the intersection type
var fromConverted = intersectionType.convert(f);
var toConverted = intersectionType.convert(t);
if (fromConverted.isEmpty() || toConverted.isEmpty())
return null;
Range range = intersectionType.getType().getRange().orElseThrow();

// This is safe... right?
if (Comparators.compare(f, t) == Relation.GREATER) {
return CollectionUtils.reverseArray(
(Object[]) ((BiFunction<? super Object, ? super Object, ?>) this.range.getFunction()).apply(t, f)
);
return CollectionUtils.reverseArray(range.apply(toConverted.get(), fromConverted.get()));
} else {
return (Object[]) ((BiFunction<? super Object, ? super Object, ?>) this.range.getFunction()).apply(f, t);
return range.apply(fromConverted.get(), toConverted.get());
}
})
.orElse(new Object[0]);
}

@Override
public Class<?> getReturnType() {
return range.getTo();
return intersectionType != null
? intersectionType.getType().getRange().orElseThrow().getRelativeType()
: Object.class;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import io.github.syst3ms.skriptparser.parsing.SkriptRuntimeException;
import io.github.syst3ms.skriptparser.types.Type;
import io.github.syst3ms.skriptparser.types.TypeManager;
import io.github.syst3ms.skriptparser.types.changers.Arithmetic;
import io.github.syst3ms.skriptparser.types.attributes.Arithmetic;
import io.github.syst3ms.skriptparser.types.changers.ChangeMode;
import io.github.syst3ms.skriptparser.types.changers.Changer;
import io.github.syst3ms.skriptparser.types.comparisons.Comparators;
Expand Down
Loading