Skip to content

Commit

Permalink
set add union and intersection + allow v1-3
Browse files Browse the repository at this point in the history
  • Loading branch information
5pilow committed Sep 5, 2023
1 parent 296fbff commit 2573ec6
Show file tree
Hide file tree
Showing 13 changed files with 388 additions and 232 deletions.
7 changes: 7 additions & 0 deletions src/main/java/leekscript/common/SetType.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package leekscript.common;

import leekscript.compiler.JavaWriter;

public class SetType extends Type {

private Type type;
Expand Down Expand Up @@ -46,4 +48,9 @@ public boolean equals(Object object) {
}
return false;
}

@Override
public String getDefaultValue(JavaWriter writer, int version) {
return "new SetLeekValue(" + writer.getAIThis() + ")";
}
}
13 changes: 6 additions & 7 deletions src/main/java/leekscript/compiler/JavaWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,6 @@ public void writeGenericFunctions(MainLeekBlock block) {

for (var entry : genericFunctions.entrySet()) {


var signature = entry.getKey();
var versions = entry.getValue();
var first_version = versions.get(0);
Expand All @@ -321,7 +320,7 @@ public void writeGenericFunctions(MainLeekBlock block) {
addCode("if (");
for (int a = 0; a < other_version.arguments.length; ++a) {
if (a > 0) addCode(" && ");
addCode("a" + a + " instanceof " + other_version.arguments[a].getJavaName(block.getVersion()));
addCode("a" + a + " instanceof " + other_version.arguments[a].getJavaName(block.getVersion()) + " x" + a);
}
addLine(") {");
writeFunctionCall(block, other_version, true);
Expand All @@ -342,14 +341,14 @@ public void writeGenericFunctions(MainLeekBlock block) {
}

private void writeFunctionCall(MainLeekBlock block, CallableVersion version, boolean cast) {
var function_name = version.function.getName();
if ((version.return_type.isArray() || version.return_type.isArrayOrNull()) && block.getVersion() <= 3) {
function_name += "_v1_3";
}
if (version.function.isStatic()) {
var function_name = version.function.getName();
if ((version.return_type.isArray() || version.return_type.isArrayOrNull()) && block.getVersion() <= 3) {
function_name += "_v1_3";
}
addCode("return " + version.function.getStandardClass() + "Class." + function_name + "(");
} else {
addCode("return x0." + version.function.getName() + "(");
addCode("return x0." + function_name + "(");
}
ArrayList<String> args = new ArrayList<>();
args.add("this");
Expand Down
40 changes: 27 additions & 13 deletions src/main/java/leekscript/compiler/WordCompiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -1565,7 +1565,8 @@ public Expression readExpression(boolean inList, boolean inSet, boolean inInterv
retour.addExpression(readInterval(token, expression));
}

} else if (getVersion() >= 4 && word.getType() == TokenType.OPERATOR && word.getWord().equals("<")) {
} else if (word.getType() == TokenType.OPERATOR && word.getWord().equals("<")) {

retour.addExpression(readSet(mTokens.eat()));

} else if (getVersion() >= 2 && word.getType() == TokenType.ACCOLADE_LEFT) {
Expand Down Expand Up @@ -1708,9 +1709,6 @@ private Expression readSet(Token openingToken) throws LeekCompilerException {
}

private Expression readArrayOrMapOrInterval(Token openingBracket) throws LeekCompilerException {
if (version < 4) {
return readLegacyArray(openingBracket);
}

// Empty map `[:]`
if (mTokens.get().getWord().equals(":")) {
Expand All @@ -1720,9 +1718,16 @@ private Expression readArrayOrMapOrInterval(Token openingBracket) throws LeekCom
throw new LeekCompilerException(mTokens.get(), Error.PARENTHESIS_EXPECTED_AFTER_PARAMETERS);
}

var container = new LeekMap(openingBracket);
container.setClosingBracket(mTokens.get());
return container;
if (version >= 4) {
var container = new LeekMap(openingBracket);
container.setClosingBracket(mTokens.get());
return container;
} else {
var container = new LegacyLeekArray(openingBracket);
container.mIsKeyVal = true;
container.setClosingBracket(mTokens.get());
return container;
}
}

// Empty array `[]`
Expand All @@ -1732,6 +1737,7 @@ private Expression readArrayOrMapOrInterval(Token openingBracket) throws LeekCom
return container;
}

// Empty interval [..]
if (mTokens.get().getType() == TokenType.DOT_DOT) {
mTokens.skip();
return readInterval(openingBracket, null);
Expand All @@ -1740,12 +1746,20 @@ private Expression readArrayOrMapOrInterval(Token openingBracket) throws LeekCom
var firstExpression = readExpression(true);
if (mTokens.get().getWord().equals(":")) {
mTokens.skip();
return readMap(openingBracket, firstExpression);
} else if (version >= 4 && mTokens.get().getType() == TokenType.DOT_DOT) {
if (version < 4) {
return readLegacyArray(openingBracket, firstExpression);
} else {
return readMap(openingBracket, firstExpression);
}
} else if (mTokens.get().getType() == TokenType.DOT_DOT) {
mTokens.skip();
return readInterval(openingBracket, firstExpression);
} else {
return readArray(openingBracket, firstExpression);
if (version < 4) {
return readLegacyArray(openingBracket, firstExpression);
} else {
return readArray(openingBracket, firstExpression);
}
}
}

Expand Down Expand Up @@ -1807,10 +1821,10 @@ private Expression readArray(Token openingBracket, Expression firstExpression) t
return container;
}

private Expression readLegacyArray(Token openingBracket) throws LeekCompilerException {
private Expression readLegacyArray(Token openingBracket, Expression firstExpression) throws LeekCompilerException {
var container = new LegacyLeekArray(openingBracket);

// Empty map `[:]`
// Empty array `[:]`
if (mTokens.get().getWord().equals(":")) {
container.mIsKeyVal = true;
container.type = Type.MAP;
Expand All @@ -1829,7 +1843,6 @@ private Expression readLegacyArray(Token openingBracket) throws LeekCompilerExce
return container;
}

var firstExpression = readExpression(true);
boolean isKeyVal = mTokens.get().getWord().equals(":");

if (isKeyVal) {
Expand Down Expand Up @@ -1874,6 +1887,7 @@ private Expression readLegacyArray(Token openingBracket) throws LeekCompilerExce
}

private Expression readInterval(Token openingBracket, Expression fromExpression) throws LeekCompilerException {

if (mTokens.get().getType() == TokenType.BRACKET_RIGHT || mTokens.get().getType() == TokenType.BRACKET_LEFT) {
return new LeekInterval(openingBracket, fromExpression, null, mTokens.get());
}
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/leekscript/compiler/bloc/MainLeekBlock.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ public MainLeekBlock(IACompiler compiler, WordCompiler wordCompiler, AIFile ai)
addClass(new ClassDeclarationInstruction(new Token("Array"), 0, ai, true, this, Type.ARRAY));
if (ai.getVersion() >= 4) {
addClass(new ClassDeclarationInstruction(new Token("Map"), 0, ai, true, this, Type.MAP));
addClass(new ClassDeclarationInstruction(new Token("Interval"), 0, ai, true, this, Type.INTERVAL));
addClass(new ClassDeclarationInstruction(new Token("Set"), 0, ai, true, this, Type.SET));
}
addClass(new ClassDeclarationInstruction(new Token("Interval"), 0, ai, true, this, Type.INTERVAL));
addClass(new ClassDeclarationInstruction(new Token("Set"), 0, ai, true, this, Type.SET));
addClass(new ClassDeclarationInstruction(new Token("String"), 0, ai, true, this, Type.STRING));
var objectClass = new ClassDeclarationInstruction(new Token("Object"), 0, ai, true, this, Type.OBJECT);
objectClass.addMethod(wordCompiler, new Token("keys"), new ClassMethodBlock(objectClass, false, false, wordCompiler.getCurrentBlock(), this, new Token("keys"), Type.ARRAY), AccessLevel.PUBLIC);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ public void compileL(MainLeekBlock mainblock, JavaWriter writer) {
writer.addCode(".execute(");
addComma = false;
} else if (mExpression instanceof LeekVariable && ((LeekVariable) mExpression).getVariableType() == VariableType.SYSTEM_FUNCTION) {
if ((unsafe && callable_versions.size() > 1) || mainblock.getVersion() <= 3) {
if (unsafe || mainblock.getVersion() <= 3) {
if (callable_versions != null) {
var key = writer.generateGenericFunction(callable_versions);
writer.addCode(system_function.getStandardClass() + "_" + key + "(");
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/leekscript/runner/AI.java
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,7 @@ public LeekError throwableToError(Throwable throwable) {
}
} else {
// Erreur inconnue
throwable.printStackTrace(System.out);
error.parameters = throwable == null ? null : new Object[] { throwable.toString() };
}
return error;
Expand Down Expand Up @@ -1399,6 +1400,8 @@ public String export(Object value) throws LeekRunException {
return ((ArrayLeekValue) value).string(this, new HashSet<Object>());
} else if (value instanceof MapLeekValue) {
return ((MapLeekValue) value).string(this, new HashSet<Object>());
} else if (value instanceof SetLeekValue set) {
return set.string(this, new HashSet<Object>());
} else if (value instanceof IntervalLeekValue interval) {
return interval.string(this, new HashSet<Object>());
} else if (value instanceof String) {
Expand Down
38 changes: 20 additions & 18 deletions src/main/java/leekscript/runner/LeekFunctions.java
Original file line number Diff line number Diff line change
Expand Up @@ -235,53 +235,55 @@ public class LeekFunctions {
/**
* Set functions
*/
method("setPut", "Set", 3, Type.ANY, new Type[] { Type.SET, Type.ANY }).setMinVersion(4);
method("setRemove", "Set", 2, Type.ANY, new Type[] { Type.SET, Type.ANY }).setMinVersion(4);
method("setClear", "Set", 1, Type.SET, new Type[] { Type.SET }).setMinVersion(4);
method("setContains", "Set", 2, Type.BOOL, new Type[] { Type.SET, Type.ANY }).setMinVersion(4);
method("setSize", "Set", 1, Type.INT, new Type[] { Type.SET }).setMinVersion(4);
method("setIsEmpty", "Set", 2, Type.BOOL, new Type[] { Type.SET }).setMinVersion(4);
method("setIsSubsetOf", "Set", Type.BOOL, new Type[] { Type.SET, Type.SET }).setMinVersion(4);
method("setPut", "Set", 3, Type.ANY, new Type[] { Type.SET, Type.ANY });
method("setRemove", "Set", 2, Type.ANY, new Type[] { Type.SET, Type.ANY });
method("setClear", "Set", 1, Type.SET, new Type[] { Type.SET });
method("setContains", "Set", 2, Type.BOOL, new Type[] { Type.SET, Type.ANY });
method("setSize", "Set", 1, Type.INT, new Type[] { Type.SET });
method("setIsEmpty", "Set", 2, Type.BOOL, new Type[] { Type.SET });
method("setIsSubsetOf", "Set", Type.BOOL, new Type[] { Type.SET, Type.SET });
method("setUnion", "Set", Type.SET, new Type[] { Type.SET, Type.SET });
method("setIntersection", "Set", Type.SET, new Type[] { Type.SET, Type.SET });

/**
* Interval functions
*/
method("intervalMin", "Interval", 1, new CallableVersion[] {
new CallableVersion(Type.REAL, new Type[] { Type.REAL_INTERVAL}),
new CallableVersion(Type.INT, new Type[] { Type.INTEGER_INTERVAL }),
}).setMinVersion(4);
});
method("intervalMax", "Interval", 1, new CallableVersion[] {
new CallableVersion(Type.REAL, new Type[] { Type.REAL_INTERVAL}),
new CallableVersion(Type.INT, new Type[] { Type.INTEGER_INTERVAL }),
}).setMinVersion(4);
});
method("intervalSize", "Interval", 1, new CallableVersion[] {
new CallableVersion(Type.REAL, new Type[] { Type.REAL_INTERVAL}),
new CallableVersion(Type.INT, new Type[] { Type.INTEGER_INTERVAL }),
}).setMinVersion(4);
method("intervalIsEmpty", "Interval", 1, Type.BOOL, new Type[] { Type.INTERVAL }).setMinVersion(4);
method("intervalIsBounded", "Interval", 1, Type.BOOL, new Type[] { Type.INTERVAL }).setMinVersion(4);
method("intervalIsRightBounded", "Interval", 1, Type.BOOL, new Type[] { Type.INTERVAL }).setMinVersion(4);
method("intervalIsLeftBounded", "Interval", 1, Type.BOOL, new Type[] { Type.INTERVAL }).setMinVersion(4);
method("intervalAverage", "Interval", 3, Type.REAL, new Type[] { Type.INTERVAL }).setMinVersion(4);
});
method("intervalIsEmpty", "Interval", 1, Type.BOOL, new Type[] { Type.INTERVAL });
method("intervalIsBounded", "Interval", 1, Type.BOOL, new Type[] { Type.INTERVAL });
method("intervalIsRightBounded", "Interval", 1, Type.BOOL, new Type[] { Type.INTERVAL });
method("intervalIsLeftBounded", "Interval", 1, Type.BOOL, new Type[] { Type.INTERVAL });
method("intervalAverage", "Interval", 3, Type.REAL, new Type[] { Type.INTERVAL });
method("intervalIntersection", "Interval", 3, new CallableVersion[] {
new CallableVersion(Type.REAL_INTERVAL, new Type[] { Type.REAL_INTERVAL, Type.REAL_INTERVAL }),
new CallableVersion(Type.REAL_INTERVAL, new Type[] { Type.INTEGER_INTERVAL, Type.REAL_INTERVAL }),
new CallableVersion(Type.REAL_INTERVAL, new Type[] { Type.REAL_INTERVAL, Type.INTEGER_INTERVAL }),
new CallableVersion(Type.INTEGER_INTERVAL, new Type[] { Type.INTEGER_INTERVAL, Type.INTEGER_INTERVAL }),
}).setMinVersion(4);
});
method("intervalCombine", "Interval", 3, new CallableVersion[] {
new CallableVersion(Type.REAL_INTERVAL, new Type[] { Type.REAL_INTERVAL, Type.REAL_INTERVAL }),
new CallableVersion(Type.REAL_INTERVAL, new Type[] { Type.INTEGER_INTERVAL, Type.REAL_INTERVAL }),
new CallableVersion(Type.REAL_INTERVAL, new Type[] { Type.REAL_INTERVAL, Type.INTEGER_INTERVAL }),
new CallableVersion(Type.INTEGER_INTERVAL, new Type[] { Type.INTEGER_INTERVAL, Type.INTEGER_INTERVAL }),
}).setMinVersion(4);
});
method("intervalToArray", "Interval", new CallableVersion[] {
new CallableVersion(Type.ARRAY_REAL, new Type[] { Type.REAL_INTERVAL, Type.REAL }),
new CallableVersion(Type.ARRAY_REAL, new Type[] { Type.REAL_INTERVAL}),
new CallableVersion(Type.ARRAY_REAL, new Type[] { Type.INTEGER_INTERVAL, Type.REAL }),
new CallableVersion(Type.ARRAY_INT, new Type[] { Type.INTEGER_INTERVAL, Type.INT }),
new CallableVersion(Type.ARRAY_INT, new Type[] { Type.INTEGER_INTERVAL}),
}).setMinVersion(4);
});

/**
* JSON functions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ public boolean operatorIn(Object value) throws LeekRunException {
return from <= valueAsReal && valueAsReal <= to;
}

@Override
public double intervalAverage(AI ai) throws LeekRunException {
if (intervalIsEmpty(ai)) {
return Double.NaN;
Expand Down Expand Up @@ -199,18 +200,18 @@ public IntegerIntervalLeekValue intervalCombine(AI ai, IntegerIntervalLeekValue
return new IntegerIntervalLeekValue(ai, unionMinClosed, Math.min(from, interval.from), unionMaxClosed, Math.max(to, interval.to));
}

public IntegerIntervalLeekValue intervalCombine(AI ai, RealIntervalLeekValue interval) throws LeekRunException {
public RealIntervalLeekValue intervalCombine(AI ai, RealIntervalLeekValue interval) throws LeekRunException {
if (intervalIsEmpty(ai)) {
return new IntegerIntervalLeekValue(ai, interval.minClosed, interval.getFrom(), interval.maxClosed, interval.getTo());
return new RealIntervalLeekValue(ai, interval.minClosed, interval.getFrom(), interval.maxClosed, interval.getTo());
}

if (interval.intervalIsEmpty(ai)) {
return new IntegerIntervalLeekValue(ai, minClosed, from, maxClosed, to);
return new RealIntervalLeekValue(ai, minClosed, from, maxClosed, to);
}

var unionMinClosed = from < interval.getFrom() ? minClosed : interval.minClosed;
var unionMaxClosed = to < interval.getTo() ? interval.maxClosed : maxClosed;
return new IntegerIntervalLeekValue(ai, unionMinClosed, Math.min(from, interval.getFrom()), unionMaxClosed, Math.max(to, interval.getTo()));
return new RealIntervalLeekValue(ai, unionMinClosed, Math.min(from, interval.getFrom()), unionMaxClosed, Math.max(to, interval.getTo()));
}

public ArrayLeekValue intervalToArray(AI ai) throws LeekRunException {
Expand Down Expand Up @@ -240,6 +241,33 @@ public ArrayLeekValue intervalToArray(AI ai, long step) throws LeekRunException
return array;
}

public LegacyArrayLeekValue intervalToArray_v1_3(AI ai) throws LeekRunException {
return intervalToArray_v1_3(ai, 1);
}

public LegacyArrayLeekValue intervalToArray_v1_3(AI ai, long step) throws LeekRunException {
if (!intervalIsBounded(ai)) {
ai.addSystemLog(AILog.ERROR, Error.CANNOT_ITERATE_UNBOUNDED_INTERVAL, new Object[] { this });
return null;
}

var array = new LegacyArrayLeekValue(ai);

if (step >= 0) {
for (var i = from; i <= to; i += step) {
array.push(ai, i);
}
} else {
for (var i = to; i >= from; i += step) {
array.push(ai, i);
}
}

ai.ops(array.size() * 2);

return array;
}

public ArrayLeekValue intervalToArray(AI ai, double step) throws LeekRunException {
if (!intervalIsBounded(ai)) {
ai.addSystemLog(AILog.ERROR, Error.CANNOT_ITERATE_UNBOUNDED_INTERVAL, new Object[] { this });
Expand All @@ -263,6 +291,29 @@ public ArrayLeekValue intervalToArray(AI ai, double step) throws LeekRunExceptio
return array;
}

public LegacyArrayLeekValue intervalToArray_v1_3(AI ai, double step) throws LeekRunException {
if (!intervalIsBounded(ai)) {
ai.addSystemLog(AILog.ERROR, Error.CANNOT_ITERATE_UNBOUNDED_INTERVAL, new Object[] { this });
return null;
}

var array = new LegacyArrayLeekValue(ai);

if (step >= 0) {
for (double i = from; i <= to; i += step) {
array.push(ai, i);
}
} else {
for (double i = to; i >= from; i += step) {
array.push(ai, i);
}
}

ai.ops(array.size() * 2);

return array;
}

public ArrayLeekValue range(AI ai, Object start, Object end, Object strideObject) throws LeekRunException {

if (intervalIsEmpty(ai)) {
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/leekscript/runner/values/IntervalLeekValue.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ public IntervalLeekValue(AI ai, boolean minClosed, boolean maxClosed) {

public abstract boolean intervalIsEmpty(AI ai);

public abstract double intervalAverage(AI ai) throws LeekRunException;

public abstract boolean intervalIsBounded(AI ai);

public abstract boolean intervalIsRightBounded(AI ai);

public abstract boolean intervalIsLeftBounded(AI ai);

public abstract ArrayLeekValue range(AI ai, Object start, Object object, Object stride) throws LeekRunException;

}
Loading

0 comments on commit 2573ec6

Please sign in to comment.