Skip to content

Commit

Permalink
integer and opened intervals
Browse files Browse the repository at this point in the history
  • Loading branch information
5pilow committed Sep 4, 2023
1 parent 022ad3c commit b5eb661
Show file tree
Hide file tree
Showing 29 changed files with 1,089 additions and 475 deletions.
2 changes: 2 additions & 0 deletions src/main/java/leekscript/common/Error.java
Original file line number Diff line number Diff line change
Expand Up @@ -143,4 +143,6 @@ public enum Error {
OPERATOR_IN_ON_INVALID_CONTAINER, // 139
CANNOT_ITERATE_UNBOUNDED_INTERVAL, // 140
UNARY_OPERATOR_INCOMPATIBLE_TYPE, // 141
INTERVAL_INFINITE_CLOSED, // 142
DOT_DOT_EXPECTED, // 143
}
44 changes: 41 additions & 3 deletions src/main/java/leekscript/common/IntervalType.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,60 @@
package leekscript.common;

import leekscript.compiler.JavaWriter;

public class IntervalType extends Type {

private final Type type;

public IntervalType(Type type) {
this(type, false);
}

public IntervalType() {
super("interval", "t", "IntervalLeekValue", "IntervalLeekValue", "new IntervalLeekValue()");
public IntervalType(Type type, boolean infinite) {
super(infinite ? "Interval<infinite>" : type == Type.VOID ? "Interval<empty>" : type == Type.ANY ? "Interval" : "Interval<" + type.toString() + ">", "t", "IntervalLeekValue", "IntervalLeekValue", type == Type.INT ? "new IntegerIntervalLeekValue()" : "new RealIntervalLeekValue()");
this.type = type;
}

@Override
public Type element() {
public CastType accepts(Type type) {
if (type instanceof IntervalType at) {
var cast = this.type.accepts(at.type);
if (cast.ordinal() >= CastType.SAFE_DOWNCAST.ordinal()) return CastType.UNSAFE_DOWNCAST;
return cast;
}
return super.accepts(type);
}

@Override
public Type key() {
return Type.INT;
}

@Override
public Type element() {
return type;
}

public boolean canBeIterable() {
return true;
}

public boolean isIterable() {
return true;
}

@Override
public String getJavaPrimitiveName(int version) {
return type == Type.ANY ? "IntervalLeekValue" : type == Type.INT ? "IntegerIntervalLeekValue" : "RealIntervalLeekValue";
}

@Override
public String getJavaName(int version) {
return type == Type.ANY ? "IntervalLeekValue" : type == Type.INT ? "IntegerIntervalLeekValue" : "RealIntervalLeekValue";
}

@Override
public String getDefaultValue(JavaWriter writer, int version) {
return type == Type.INT ? "new IntegerIntervalLeekValue(" + writer.getAIThis() + ")" : "new RealIntervalLeekValue(" + writer.getAIThis() + ")";
}
}
5 changes: 4 additions & 1 deletion src/main/java/leekscript/common/Type.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ public class Type {
// public static final Type LEGACY_ARRAY = new LegacyArrayType();
public static final Type ARRAY = array(Type.ANY);
public static final Type SET = set(Type.ANY);
public static final Type INTERVAL = new IntervalType();
public static final Type INTERVAL = new IntervalType(Type.ANY);
public static final Type EMPTY_INTERVAL = new IntervalType(Type.VOID);
public static final Type REAL_INTERVAL = new IntervalType(Type.REAL);
public static final Type INTEGER_INTERVAL = new IntervalType(Type.INT);
public static final Type ARRAY_INT = array(Type.INT);
public static final Type ARRAY_REAL = array(Type.REAL);
public static final Type ARRAY_STRING = array(Type.STRING);
Expand Down
16 changes: 16 additions & 0 deletions src/main/java/leekscript/compiler/LexicalParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public LexicalParserTokenStream parse(ErrorReporter error) throws LeekCompilerEx
if (tryParseString()) continue;
if (tryParseComments()) continue;
if (tryParseNumber(error)) continue;
if (tryParseSpecialIdentifier()) continue;
if (tryParseIdentifier()) continue;
if (tryParseOperator()) continue;
if (tryParseBracketLike()) continue;
Expand Down Expand Up @@ -101,6 +102,21 @@ private boolean tryParseOperator() {
return false;
}

private boolean tryParseSpecialIdentifier() {

var c = stream.peek();
if (c == '∞') {
stream.next();
addToken("∞", TokenType.LEMNISCATE);
return true;
} else if (c == 'π') {
stream.next();
addToken("π", TokenType.PI);
return true;
}
return false;
}

private boolean tryParseIdentifier() {
var startingPoint = stream.index;
for (char c = stream.peek(); stream.hasMore(); c = stream.next()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@ public int getOffsetToNextArrow() {
}
}

@Override
public String toString() {
return "Tokens current=" + get();
}

public LexicalParserTokenStreamPosition getPosition() {
return new LexicalParserTokenStreamPosition(cursor);
}
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/leekscript/compiler/TokenType.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ public enum TokenType {
BRACKET_LEFT,
BRACKET_RIGHT,
DOUBLE_POINT,
DOT,
DOT,
DOT_DOT,
ARROW,
LEMNISCATE,
PI,
END_OF_FILE,
}
52 changes: 45 additions & 7 deletions src/main/java/leekscript/compiler/WordCompiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -1214,14 +1214,18 @@ public ClassMethodBlock classMethod(ClassDeclarationInstruction classDeclaration
}

public Expression readExpression() throws LeekCompilerException {
return readExpression(false, false);
return readExpression(false, false, false);
}

public Expression readExpression(boolean inList) throws LeekCompilerException {
return readExpression(inList, false);
return readExpression(inList, false, false);
}

public Expression readExpression(boolean inList, boolean inSet) throws LeekCompilerException {
return readExpression(inList, inSet, false);
}

public Expression readExpression(boolean inList, boolean inSet, boolean inInterval) throws LeekCompilerException {

var retour = new LeekExpression();

Expand Down Expand Up @@ -1356,6 +1360,9 @@ public Expression readExpression(boolean inList, boolean inSet) throws LeekCompi
// Si on attend un opérateur mais qu'il vient pas

if (word.getType() == TokenType.BRACKET_LEFT) {

var save = mTokens.getPosition();

var bracket = mTokens.eat(); // On avance le curseur pour être au début de l'expression
Token colon = null;
Token colon2 = null;
Expand All @@ -1382,7 +1389,7 @@ public Expression readExpression(boolean inList, boolean inSet) throws LeekCompi
}
}
}
} else {
} else if (mTokens.hasMoreTokens()) {
start = readExpression();
if (getVersion() >= 4 && mTokens.get().getWord().equals(":")) {
colon = mTokens.eat();
Expand All @@ -1404,7 +1411,12 @@ public Expression readExpression(boolean inList, boolean inSet) throws LeekCompi
}

if (mTokens.get().getType() != TokenType.BRACKET_RIGHT) {
throw new LeekCompilerException(mTokens.get(), Error.CLOSING_SQUARE_BRACKET_EXPECTED);
if (inInterval) {
mTokens.setPosition(save);
break;
} else {
throw new LeekCompilerException(mTokens.get(), Error.CLOSING_SQUARE_BRACKET_EXPECTED);
}
}
retour.addBracket(bracket, start, colon, end, colon2, stride, mTokens.get());

Expand Down Expand Up @@ -1520,13 +1532,39 @@ public Expression readExpression(boolean inList, boolean inSet) throws LeekCompi
retour.addExpression(new LeekNumber(word, 0, 0, Type.INT));
}
}

} else if (word.getType() == TokenType.LEMNISCATE) {

retour.addExpression(new LeekNumber(word, Double.POSITIVE_INFINITY, 0, Type.REAL));

} else if (word.getType() == TokenType.PI) {

retour.addExpression(new LeekNumber(word, Math.PI, 0, Type.REAL));

} else if (word.getType() == TokenType.VAR_STRING) {

retour.addExpression(new LeekString(word, word.getWord()));

} else if (word.getType() == TokenType.BRACKET_LEFT) {
retour.addExpression(readArrayOrMapOrInterval(mTokens.eat()));

} else if (word.getType() == TokenType.BRACKET_RIGHT) {

var token = mTokens.eat();
if (mTokens.get().getType() == TokenType.DOT_DOT) {
// interval `]..`
mTokens.skip();
retour.addExpression(readInterval(token, null));
} else {
// interval `]x..`
var expression = readExpression(true);
var dot_dot = mTokens.eat();
if (dot_dot.getType() != TokenType.DOT_DOT) {
addError(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, Error.DOT_DOT_EXPECTED));
}
retour.addExpression(readInterval(token, expression));
}

} else if (getVersion() >= 4 && word.getType() == TokenType.OPERATOR && word.getWord().equals("<")) {
retour.addExpression(readSet(mTokens.eat()));

Expand Down Expand Up @@ -1836,21 +1874,21 @@ private Expression readLegacyArray(Token openingBracket) throws LeekCompilerExce
}

private Expression readInterval(Token openingBracket, Expression fromExpression) throws LeekCompilerException {
if (mTokens.get().getType() == TokenType.BRACKET_RIGHT) {
if (mTokens.get().getType() == TokenType.BRACKET_RIGHT || mTokens.get().getType() == TokenType.BRACKET_LEFT) {
return new LeekInterval(openingBracket, fromExpression, null, mTokens.get());
}

// Although an interval is not comma separated, we still parse the second
// expression as if we did. This is in order to be more consitent as the first
// expression is parsed as if it was comma separated
var toExpression = readExpression(true);
var toExpression = readExpression(true, false, true);

var nextToken = mTokens.get();
if (nextToken.getWord().equals(":")) {
throw new LeekCompilerException(mTokens.get(), Error.ASSOCIATIVE_ARRAY);
} else if (nextToken.getType() == TokenType.VIRG) {
throw new LeekCompilerException(mTokens.get(), Error.SIMPLE_ARRAY);
} else if (nextToken.getType() != TokenType.BRACKET_RIGHT) {
} else if (nextToken.getType() != TokenType.BRACKET_RIGHT && nextToken.getType() != TokenType.BRACKET_LEFT) {
throw new LeekCompilerException(mTokens.get(), Error.PARENTHESIS_EXPECTED_AFTER_PARAMETERS);
}

Expand Down
4 changes: 4 additions & 0 deletions src/main/java/leekscript/compiler/expression/Expression.java
Original file line number Diff line number Diff line change
Expand Up @@ -187,4 +187,8 @@ public boolean isFinal() {
public LeekVariable getVariable() {
return null;
}

public boolean isInfinity() {
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ public Type getType() {
return type;
}

public boolean isInfinity() {
return mOperator == Operators.UNARY_MINUS && mExpression2 != null && mExpression2.isInfinity();
}

public boolean complete(int operator) {
return complete();
}
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 || mainblock.getVersion() <= 3) {
if ((unsafe && callable_versions.size() > 1) || mainblock.getVersion() <= 3) {
if (callable_versions != null) {
var key = writer.generateGenericFunction(callable_versions);
writer.addCode(system_function.getStandardClass() + "_" + key + "(");
Expand Down Expand Up @@ -682,7 +682,6 @@ public void verifyVersions(WordCompiler compiler, CallableVersion[] versions) th
else if (cast_type == CastType.UNSAFE_DOWNCAST) distance += 1000;
else if (cast_type == CastType.INCOMPATIBLE) distance += 10000;
}
if (distance >= 1000) distance = 1000;
// System.out.println("version = " + version + " distance = " + distance);
if (distance == best_distance) {
best_versions.add(version);
Expand All @@ -692,8 +691,6 @@ public void verifyVersions(WordCompiler compiler, CallableVersion[] versions) th
best_versions.add(version);
unsafe = version_unsafe;
errors = version_errors;
} else {
errors = version_errors;
}
}
if (errors != null) {
Expand Down

0 comments on commit b5eb661

Please sign in to comment.