From 76d596fb778bede40d83df0907008cd2c7f21086 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 24 Jun 2023 22:32:47 +0200 Subject: [PATCH] fixes + timeout --- src/main/java/leekscript/compiler/AIFile.java | 1 + .../java/leekscript/compiler/IACompiler.java | 10 +++ .../leekscript/compiler/LexicalParser.java | 73 ++++++++--------- .../compiler/LexicalParserTokenStream.java | 3 +- .../java/leekscript/compiler/Location.java | 5 ++ .../leekscript/compiler/WordCompiler.java | 78 +++++++++++++++---- .../compiler/bloc/AbstractLeekBlock.java | 1 + .../compiler/expression/LeekArrayAccess.java | 40 +++++----- .../compiler/expression/LeekObjectAccess.java | 38 ++++----- src/test/java/test/TestArray.java | 5 ++ 10 files changed, 160 insertions(+), 94 deletions(-) diff --git a/src/main/java/leekscript/compiler/AIFile.java b/src/main/java/leekscript/compiler/AIFile.java index e8515053..47d9bd86 100644 --- a/src/main/java/leekscript/compiler/AIFile.java +++ b/src/main/java/leekscript/compiler/AIFile.java @@ -53,6 +53,7 @@ public String getCode() { } public void setCode(String code) { this.code = code; + this.tokens = null; } public Folder getFolder() { return folder; diff --git a/src/main/java/leekscript/compiler/IACompiler.java b/src/main/java/leekscript/compiler/IACompiler.java index 3c0a2c42..bcd6dd30 100644 --- a/src/main/java/leekscript/compiler/IACompiler.java +++ b/src/main/java/leekscript/compiler/IACompiler.java @@ -22,8 +22,11 @@ public static class AnalyzeResult { public Throwable tooMuchErrors; } + public static final long TIMEOUT_MS = 30 * 1000; // 30 seconds + private final JSONArray informations = new JSONArray(); private AIFile mCurrentAI; + private long analyzeStart; public IACompiler() {} @@ -43,6 +46,7 @@ public void addError(Location location, Error errorType, String[] parameters) { public AnalyzeResult analyze(AIFile ai) throws LeekCompilerException { AnalyzeResult result = new AnalyzeResult(); + this.analyzeStart = System.currentTimeMillis(); // For timeout try { ai.clearErrors(); // On lance la compilation du code de l'IA @@ -80,6 +84,7 @@ public AnalyzeResult analyze(AIFile ai) throws LeekCompilerException { } public AICode compile(AIFile ai, String AIClass, boolean enableOperations) throws LeekCompilerException { + this.analyzeStart = System.currentTimeMillis(); // For timeout JavaWriter writer = new JavaWriter(true, ai.getJavaClass(), enableOperations); try { ai.clearErrors(); @@ -111,6 +116,7 @@ public AICode compile(AIFile ai, String AIClass, boolean enableOperations) throw public String merge(AIFile ai) throws LeekCompilerException { // System.out.println("Merge ai " + ai); + this.analyzeStart = System.currentTimeMillis(); // For timeout WordCompiler compiler = new WordCompiler(ai, ai.getVersion()); MainLeekBlock main = new MainLeekBlock(this, compiler, ai); main.setWordCompiler(compiler); @@ -127,4 +133,8 @@ public AIFile getCurrentAI() { public void setCurrentAI(AIFile ai) { mCurrentAI = ai; } + + public long getAnalyzeStart() { + return analyzeStart; + } } diff --git a/src/main/java/leekscript/compiler/LexicalParser.java b/src/main/java/leekscript/compiler/LexicalParser.java index 49372eb5..d9d93f66 100644 --- a/src/main/java/leekscript/compiler/LexicalParser.java +++ b/src/main/java/leekscript/compiler/LexicalParser.java @@ -73,7 +73,7 @@ private boolean tryParseOperator() { "===", "==", "=", "!=", "!", "<<<=", "<<<", "<<=", "<<", "<=", "<", - ">>>=", ">>>", ">>=", ">>", ">=", ">", + ">>>=", /* ">>>", ">>=", ">>", */ ">=", ">", "^=", "^", "~", "@", "?", "\\" @@ -98,7 +98,7 @@ private boolean tryParseOperator() { } private boolean tryParseIdentifier() { - var startingPoint = stream.getRestorePoint(); + var startingPoint = stream.index; for (char c = stream.peek(); stream.hasMore(); c = stream.next()) { if (c >= '0' && c <= '9') continue; if (c >= 'A' && c <= 'Z') continue; @@ -113,7 +113,7 @@ private boolean tryParseIdentifier() { break; } - if (startingPoint.equals(stream.getRestorePoint())) { + if (startingPoint == stream.index) { return false; } @@ -135,12 +135,13 @@ private boolean tryParseIdentifier() { } private boolean tryParseNumber(ErrorReporter error) throws LeekCompilerException { - var startingPoint = stream.getRestorePoint(); if (stream.peek() < '0' || stream.peek() > '9') { return false; } + var startingPoint = stream.index; + stream.next(); for (char c = stream.peek(); stream.hasMore(); c = stream.next()) { @@ -177,13 +178,14 @@ private boolean tryParseNumber(ErrorReporter error) throws LeekCompilerException } private boolean tryParseString() { - var startingPoint = stream.getRestorePoint(); var openQuote = stream.peek(); if (openQuote != '"' && openQuote != '\'') { return false; } + var startingPoint = stream.index; + stream.next(); var escaped = false; @@ -204,7 +206,8 @@ private boolean tryParseString() { } private boolean tryParseWhiteSpaces() { - if ("\r\n\t ".contains("" + stream.peek()) || stream.peek() == 160) { + var c = stream.peek(); + if (c == ' ' || c == '\r' || c == '\n' || c == '\t' || c == 160) { stream.next(); return true; } @@ -237,30 +240,32 @@ private boolean tryParseComments() { } private boolean tryParseExact(String expected, TokenType type) { - var startingPoint = stream.getRestorePoint(); - - for (int i = 0; i < expected.length(); i++) stream.next(); - var streamWord = stream.getSubStringSince(startingPoint); - if (wordEquals(streamWord, expected)) { - addToken(expected, type); - return true; + if (stream.index + expected.length() <= stream.content.length()) { + var streamWord = stream.content.substring(stream.index, stream.index + expected.length()); + if (wordEquals(streamWord, expected)) { + stream.index += expected.length(); + if (stream.index < stream.content.length()) { + stream.c = stream.content.charAt(stream.index); + } + addToken(expected, type); + return true; + } } - - stream.restore(startingPoint); return false; } private boolean tryParseExact(char expected, TokenType type) { if (stream.peek() == expected) { - addToken("" + expected, type); stream.next(); + addToken("" + expected, type); return true; } return false; } private void addToken(String word, TokenType type) { + // System.out.println("addToken " + word + " " + type + " " + stream.getLineCounter() + " " + stream.getCharCounter()); tokens.add(new Token(type, word, aiFile, stream.getLineCounter(), stream.getCharCounter())); } @@ -271,17 +276,16 @@ private boolean wordEquals(String word, String expected) { return word.equals(expected); } - private record CharStreamRestorePoint(int index, int lineCounter, int charCounter) { - } - private class CharStream { private int lineCounter = 1; - private int charCounter = 1; + private int charCounter = 0; private int index = 0; private String content; + private char c; public CharStream(String content) { this.content = content; + this.c = content.charAt(0); } public int getLineCounter() { @@ -299,40 +303,31 @@ public boolean hasMore() { public char next() { if (index >= content.length()) return 0; - if (peek() == '\n') { + if (c == '\n') { lineCounter++; - charCounter = 1; + charCounter = 0; } else { charCounter++; } index++; - - return peek(); + if (index < content.length()) { + c = content.charAt(index); + } + return c; } public char peek(int offset) { - if (index + offset >= content.length() || index + offset < 0) return 0; + if (index + offset >= content.length()) return 0; return content.charAt(index + offset); } public char peek() { - return peek(0); + return c; } - public CharStreamRestorePoint getRestorePoint() { - return new CharStreamRestorePoint(index, lineCounter, charCounter); - } - - public void restore(CharStreamRestorePoint restorePoint) { - index = restorePoint.index; - lineCounter = restorePoint.lineCounter; - charCounter = restorePoint.charCounter; - } - - public String getSubStringSince(CharStreamRestorePoint restorePoint) { - return content.substring(restorePoint.index, index); + public String getSubStringSince(int start) { + return content.substring(start, index); } } - } diff --git a/src/main/java/leekscript/compiler/LexicalParserTokenStream.java b/src/main/java/leekscript/compiler/LexicalParserTokenStream.java index ee5c4f7d..04c18835 100644 --- a/src/main/java/leekscript/compiler/LexicalParserTokenStream.java +++ b/src/main/java/leekscript/compiler/LexicalParserTokenStream.java @@ -130,6 +130,5 @@ public void setPosition(LexicalParserTokenStreamPosition position) { cursor = position.cursor; } - public record LexicalParserTokenStreamPosition(int cursor) { - } + public record LexicalParserTokenStreamPosition(int cursor) {} } \ No newline at end of file diff --git a/src/main/java/leekscript/compiler/Location.java b/src/main/java/leekscript/compiler/Location.java index ff1e964b..7fb60dea 100644 --- a/src/main/java/leekscript/compiler/Location.java +++ b/src/main/java/leekscript/compiler/Location.java @@ -86,4 +86,9 @@ public Object toJSON() { a.add(this.endColumn); return a; } + + @Override + public String toString() { + return file + " [" + this.startLine + ", " + this.startColumn + ", " + this.endLine + ", " + this.endColumn + "]"; + } } diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index da3d46fc..a69c1e03 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -68,10 +68,13 @@ private void parse() throws LeekCompilerException { var parser = new LexicalParser(mAI, version); mAI.setTokenStream(parser.parse(error -> addError(error))); } - mTokens = mAI.getTokenStream(); } + public boolean isInterrupted() { + return System.currentTimeMillis() - mMain.getCompiler().getAnalyzeStart() > IACompiler.TIMEOUT_MS; + } + public void readCode() throws LeekCompilerException { firstPass(); @@ -88,9 +91,12 @@ public void readCode() throws LeekCompilerException { public void firstPass() throws LeekCompilerException { try { parse(); + mTokens.reset(); while (mTokens.hasMoreTokens()) { + if (isInterrupted()) throw new LeekCompilerException(mTokens.get(), Error.AI_TIMEOUT); + if (mTokens.get().getWord().equals("include")) { var token = mTokens.eat(); // On vérifie qu'on est dans le bloc principal @@ -152,6 +158,9 @@ public void firstPass() throws LeekCompilerException { int param_count = 0; var parameters = new HashSet(); while (mTokens.hasMoreTokens() && mTokens.get().getType() != TokenType.PAR_RIGHT) { + + if (isInterrupted()) throw new LeekCompilerException(mTokens.get(), Error.AI_TIMEOUT); + if (mTokens.get().getType() == TokenType.OPERATOR && mTokens.get().getWord().equals("@")) { mTokens.skip(); } @@ -204,11 +213,15 @@ public void firstPass() throws LeekCompilerException { } public void secondPass() throws LeekCompilerException { + mTokens = this.mAI.getTokenStream(); + assert mTokens != null : "tokens are null"; mTokens.reset(); try { // Vraie compilation while (mTokens.hasMoreTokens()) { + if (isInterrupted()) throw new LeekCompilerException(mTokens.get(), Error.AI_TIMEOUT); + // On vérifie les instructions en cours if (mCurentBlock instanceof DoWhileBlock && !((DoWhileBlock) mCurentBlock).hasAccolade() && mCurentBlock.isFull()) { DoWhileBlock do_block = (DoWhileBlock) mCurentBlock; @@ -222,6 +235,9 @@ public void secondPass() throws LeekCompilerException { compileWord(); } while (mCurentBlock.getParent() != null && !mCurentBlock.hasAccolade()) { + + if (isInterrupted()) throw new LeekCompilerException(mTokens.get(), Error.AI_TIMEOUT); + if (mCurentBlock instanceof DoWhileBlock) { DoWhileBlock do_block = (DoWhileBlock) mCurentBlock; mCurentBlock = mCurentBlock.endInstruction(); @@ -420,6 +436,8 @@ private void functionBlock() throws LeekCompilerException { setCurrentFunction(block); while (mTokens.hasMoreTokens() && mTokens.get().getType() != TokenType.PAR_RIGHT) { + if (isInterrupted()) throw new LeekCompilerException(mTokens.get(), Error.AI_TIMEOUT); + var type = eatType(false, false); boolean is_reference = false; @@ -468,7 +486,9 @@ private void functionBlock() throws LeekCompilerException { } // On regarde s'il y a des accolades - if (mTokens.eat().getType() != TokenType.ACCOLADE_LEFT) throw new LeekCompilerException(mTokens.get(), Error.OPENING_CURLY_BRACKET_EXPECTED); + if (mTokens.eat().getType() != TokenType.ACCOLADE_LEFT) { + throw new LeekCompilerException(mTokens.get(), Error.OPENING_CURLY_BRACKET_EXPECTED); + } mMain.addFunction(block); setCurrentFunction(previousFunction); } @@ -479,6 +499,9 @@ private LeekType eatType(boolean first, boolean mandatory) throws LeekCompilerEx if (type == null) return null; while (mTokens.get().getWord().equals("|")) { + + if (isInterrupted()) throw new LeekCompilerException(mTokens.get(), Error.AI_TIMEOUT); + var pipe = mTokens.eat(); var type2 = eatOptionalType(false, true); @@ -573,6 +596,9 @@ private LeekType eatPrimaryType(boolean first, boolean mandatory) throws LeekCom if (value != null) function.add_argument(value.getType(), false); while (mTokens.get().getWord().equals(",")) { + + if (isInterrupted()) throw new LeekCompilerException(mTokens.get(), Error.AI_TIMEOUT); + mTokens.eat().setExpression(functionType); var parameter = eatType(false, true); @@ -711,18 +737,18 @@ private void forBlock() throws LeekCompilerException { // On récupère la valeur de base du compteur var initValue = readExpression(); if (mTokens.eat().getType() != TokenType.END_INSTRUCTION) { - // errors.add(new AnalyzeError(mCompiler.getWord(), AnalyzeErrorLevel.ERROR, Error.END_OF_INSTRUCTION_EXPECTED)); + // errors.add(new AnalyzeError(mTokens.getWord(), AnalyzeErrorLevel.ERROR, Error.END_OF_INSTRUCTION_EXPECTED)); throw new LeekCompilerException(mTokens.get(), Error.END_OF_INSTRUCTION_EXPECTED); // return; } var condition = readExpression(); if (mTokens.eat().getType() != TokenType.END_INSTRUCTION) { - // errors.add(new AnalyzeError(mCompiler.getWord(), AnalyzeErrorLevel.ERROR, Error.END_OF_INSTRUCTION_EXPECTED)); + // errors.add(new AnalyzeError(mTokens.getWord(), AnalyzeErrorLevel.ERROR, Error.END_OF_INSTRUCTION_EXPECTED)); throw new LeekCompilerException(mTokens.get(), Error.END_OF_INSTRUCTION_EXPECTED); // return; } - // if (mCompiler.getWord().getType() == TokenType.END_INSTRUCTION) { - // mCompiler.skipWord(); + // if (mTokens.getWord().getType() == TokenType.END_INSTRUCTION) { + // mTokens.skipWord(); // } var incrementation = readExpression(); @@ -791,8 +817,8 @@ private void dowhileendBlock(DoWhileBlock bloc) throws LeekCompilerException { if (mTokens.eat().getType() != TokenType.PAR_RIGHT) { throw new LeekCompilerException(mTokens.get(), Error.CLOSING_PARENTHESIS_EXPECTED); } - // if (mCompiler.getWord().getType() != TokenType.END_INSTRUCTION) - // throw new LeekCompilerException(mCompiler.lastWord(), Error.END_OF_INSTRUCTION_EXPECTED); + // if (mTokens.getWord().getType() != TokenType.END_INSTRUCTION) + // throw new LeekCompilerException(mTokens.lastWord(), Error.END_OF_INSTRUCTION_EXPECTED); } private void elseBlock() throws LeekCompilerException { @@ -870,6 +896,9 @@ private void globalDeclaration() throws LeekCompilerException { mMain.addGlobalDeclaration(variable); mCurentBlock.addInstruction(this, variable); while (mTokens.hasMoreTokens() && mTokens.get().getType() == TokenType.VIRG) { + + if (isInterrupted()) throw new LeekCompilerException(mTokens.get(), Error.AI_TIMEOUT); + // On regarde si y'en a d'autres mTokens.skip();// On passe la virgule word = mTokens.eat(); @@ -885,7 +914,7 @@ private void globalDeclaration() throws LeekCompilerException { mMain.addGlobalDeclaration(variable); mCurentBlock.addInstruction(this, variable); } - // word = mCompiler.readWord(); + // word = mTokens.readWord(); // if (word.getType() != TokenType.END_INSTRUCTION) // throw new LeekCompilerException(word, Error.END_OF_INSTRUCTION_EXPECTED); if (mTokens.hasMoreTokens() && mTokens.get().getType() == TokenType.END_INSTRUCTION) mTokens.skip(); @@ -917,6 +946,9 @@ private void variableDeclaration(LeekType type) throws LeekCompilerException { mCurentBlock.addInstruction(this, variable); while (mTokens.hasMoreTokens() && mTokens.get().getType() == TokenType.VIRG) { + + if (isInterrupted()) throw new LeekCompilerException(mTokens.get(), Error.AI_TIMEOUT); + // On regarde si y'en a d'autres mTokens.skip();// On passe la virgule word = mTokens.eat(); @@ -948,7 +980,8 @@ public void classDeclaration() throws LeekCompilerException { if (isKeyword(word)) { addError(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, Error.VARIABLE_NAME_UNAVAILABLE, new String[] { word.getWord() })); } - ClassDeclarationInstruction classDeclaration = mMain.getUserClass(word.getWord()); + ClassDeclarationInstruction classDeclaration = mMain.getDefinedClass(word.getWord()); + assert classDeclaration != null : "Class " + word.getWord() + " not declared (" + mMain.getDefinedClasses().size() + " classes)"; mMain.addClassList(classDeclaration); mCurrentClass = classDeclaration; @@ -958,11 +991,12 @@ public void classDeclaration() throws LeekCompilerException { classDeclaration.setParent(parent); } if (mTokens.get().getType() != TokenType.ACCOLADE_LEFT) { - throw new LeekCompilerException(mTokens.get(), Error.OPENING_CURLY_BRACKET_EXPECTED); + throw new LeekCompilerException(mTokens.get(), Error.OPENING_CURLY_BRACKET_EXPECTED); } mTokens.skip(); while (mTokens.hasMoreTokens() && mTokens.get().getType() != TokenType.ACCOLADE_RIGHT) { + if (isInterrupted()) throw new LeekCompilerException(mTokens.get(), Error.AI_TIMEOUT); word = mTokens.get(); switch (word.getWord()) { case "public": @@ -1071,6 +1105,8 @@ public void endClassMember(ClassDeclarationInstruction classDeclaration, AccessL } if (isStatic) { + // System.out.println(classDeclaration); + assert classDeclaration != null; classDeclaration.addStaticField(this, name, expr, accessLevel, isFinal, typeExpression != null ? typeExpression.getType() : Type.ANY); } else { classDeclaration.addField(this, name, expr, accessLevel, isFinal, typeExpression != null ? typeExpression.getType() : Type.ANY); @@ -1094,6 +1130,7 @@ public ClassMethodBlock classMethod(ClassDeclarationInstruction classDeclaration } int param_count = 0; while (mTokens.hasMoreTokens() && mTokens.get().getType() != TokenType.PAR_RIGHT) { + if (isInterrupted()) throw new LeekCompilerException(mTokens.get(), Error.AI_TIMEOUT); if (mTokens.get().getType() == TokenType.OPERATOR && mTokens.get().getWord().equals("@")) { addError(new AnalyzeError(mTokens.get(), AnalyzeErrorLevel.WARNING, Error.REFERENCE_DEPRECATED)); mTokens.skip(); @@ -1134,10 +1171,13 @@ public ClassMethodBlock classMethod(ClassDeclarationInstruction classDeclaration mCurentBlock = method; // Ouverture des accolades - if (mTokens.eat().getType() != TokenType.ACCOLADE_LEFT) throw new LeekCompilerException(mTokens.get(), Error.OPENING_CURLY_BRACKET_EXPECTED); + if (mTokens.eat().getType() != TokenType.ACCOLADE_LEFT) { + throw new LeekCompilerException(mTokens.get(), Error.OPENING_CURLY_BRACKET_EXPECTED); + } // Lecture du corps de la fonction while (mTokens.hasMoreTokens()) { + if (isInterrupted()) throw new LeekCompilerException(mTokens.get(), Error.AI_TIMEOUT); // Fermeture des blocs ouverts if (mCurentBlock instanceof DoWhileBlock && !((DoWhileBlock) mCurentBlock).hasAccolade() && mCurentBlock.isFull()) { DoWhileBlock do_block = (DoWhileBlock) mCurentBlock; @@ -1199,6 +1239,7 @@ public Expression readExpression(boolean inList) throws LeekCompilerException { boolean first = true; while (mTokens.hasMoreTokens() && mTokens.get().getType() != TokenType.PAR_RIGHT && mTokens.get().getType() != TokenType.ARROW) { + if (isInterrupted()) throw new LeekCompilerException(mTokens.get(), Error.AI_TIMEOUT); if (mTokens.get().getType() != TokenType.STRING) { addError(new AnalyzeError(mTokens.get(), AnalyzeErrorLevel.ERROR, Error.PARAMETER_NAME_EXPECTED)); @@ -1235,7 +1276,7 @@ public Expression readExpression(boolean inList) throws LeekCompilerException { pos = mTokens.getPosition(); var returnType = eatType(false, false); if (returnType != null) { - if (mTokens.get().getWord() == ".") { + if (mTokens.get().getWord().equals(".")) { mTokens.setPosition(pos); // On prend pas le type si "Type.[...]" } else { block.setReturnType(returnType.getType()); @@ -1249,6 +1290,7 @@ public Expression readExpression(boolean inList) throws LeekCompilerException { // Lecture du corps de la fonction while (mTokens.hasMoreTokens()) { + if (isInterrupted()) throw new LeekCompilerException(mTokens.get(), Error.AI_TIMEOUT); // Fermeture des blocs ouverts if (mCurentBlock instanceof DoWhileBlock && !((DoWhileBlock) mCurentBlock).hasAccolade() && mCurentBlock.isFull()) { DoWhileBlock do_block = (DoWhileBlock) mCurentBlock; @@ -1288,6 +1330,7 @@ public Expression readExpression(boolean inList) throws LeekCompilerException { } while (mTokens.hasMoreTokens()) { + if (isInterrupted()) throw new LeekCompilerException(mTokens.get(), Error.AI_TIMEOUT); Token word = mTokens.get(); if (word.getType() == TokenType.PAR_RIGHT || word.getType() == TokenType.ACCOLADE_RIGHT || word.getType() == TokenType.END_INSTRUCTION) { break; @@ -1354,6 +1397,7 @@ public Expression readExpression(boolean inList) throws LeekCompilerException { mTokens.skip(); // On avance le curseur pour être au début de l'expression while (mTokens.hasMoreTokens() && mTokens.get().getType() != TokenType.PAR_RIGHT) { + if (isInterrupted()) throw new LeekCompilerException(mTokens.get(), Error.AI_TIMEOUT); function.addParameter(readExpression(true)); if (mTokens.get().getType() == TokenType.VIRG) mTokens.skip(); } @@ -1477,6 +1521,7 @@ public Expression readExpression(boolean inList) throws LeekCompilerException { int type = 0;// 0 => A déterminer, 1 => Simple, 2 => Clé:valeur while (mTokens.hasMoreTokens() && mTokens.get().getType() != TokenType.BRACKET_RIGHT) { + if (isInterrupted()) throw new LeekCompilerException(mTokens.get(), Error.AI_TIMEOUT); var exp = readExpression(true); if (mTokens.get().getWord().equals(":")) { if (type == 0) type = 2; @@ -1506,6 +1551,7 @@ public Expression readExpression(boolean inList) throws LeekCompilerException { var object = new LeekObject(token); while (mTokens.hasMoreTokens() && mTokens.get().getType() != TokenType.ACCOLADE_RIGHT) { + if (isInterrupted()) throw new LeekCompilerException(mTokens.get(), Error.AI_TIMEOUT); if (mTokens.get().getType() != TokenType.STRING) { addError(new AnalyzeError(mTokens.get(), AnalyzeErrorLevel.ERROR, Error.PARENTHESIS_EXPECTED_AFTER_PARAMETERS)); } @@ -1639,6 +1685,7 @@ private LeekAnonymousFunction readAnonymousFunction() throws LeekCompilerExcepti // Lecture des paramètres while (mTokens.hasMoreTokens() && mTokens.get().getType() != TokenType.PAR_RIGHT) { + if (isInterrupted()) throw new LeekCompilerException(mTokens.get(), Error.AI_TIMEOUT); boolean is_reference = false; if (mTokens.get().getType() == TokenType.OPERATOR && mTokens.get().getWord().equals("@")) { is_reference = true; @@ -1686,10 +1733,13 @@ private LeekAnonymousFunction readAnonymousFunction() throws LeekCompilerExcepti } // Ouverture des accolades - if (mTokens.eat().getType() != TokenType.ACCOLADE_LEFT) throw new LeekCompilerException(mTokens.get(), Error.OPENING_CURLY_BRACKET_EXPECTED); + if (mTokens.eat().getType() != TokenType.ACCOLADE_LEFT) { + throw new LeekCompilerException(mTokens.get(), Error.OPENING_CURLY_BRACKET_EXPECTED); + } // Lecture du corp de la fonction while (mTokens.hasMoreTokens()) { + if (isInterrupted()) throw new LeekCompilerException(mTokens.get(), Error.AI_TIMEOUT); // Fermeture des blocs ouverts if (mCurentBlock instanceof DoWhileBlock && !((DoWhileBlock) mCurentBlock).hasAccolade() && mCurentBlock.isFull()) { diff --git a/src/main/java/leekscript/compiler/bloc/AbstractLeekBlock.java b/src/main/java/leekscript/compiler/bloc/AbstractLeekBlock.java index 3ef267fb..1600e820 100644 --- a/src/main/java/leekscript/compiler/bloc/AbstractLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/AbstractLeekBlock.java @@ -5,6 +5,7 @@ import leekscript.compiler.Token; import leekscript.compiler.AnalyzeError; +import leekscript.compiler.IACompiler; import leekscript.compiler.JavaWriter; import leekscript.compiler.WordCompiler; import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; diff --git a/src/main/java/leekscript/compiler/expression/LeekArrayAccess.java b/src/main/java/leekscript/compiler/expression/LeekArrayAccess.java index 421ada56..517eb20d 100644 --- a/src/main/java/leekscript/compiler/expression/LeekArrayAccess.java +++ b/src/main/java/leekscript/compiler/expression/LeekArrayAccess.java @@ -271,7 +271,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { @Override public void compileL(MainLeekBlock mainblock, JavaWriter writer) { - assert(mLeftValue && !mTabular.nullable()); + // assert(mLeftValue && !mTabular.nullable()); writer.addCode("getBox("); mTabular.writeJavaCode(mainblock, writer); writer.addCode(", "); @@ -281,7 +281,7 @@ public void compileL(MainLeekBlock mainblock, JavaWriter writer) { @Override public void compileSet(MainLeekBlock mainblock, JavaWriter writer, Expression expr) { - assert(mLeftValue && !mTabular.nullable()); + // assert(mLeftValue && !mTabular.nullable()); if (expr.getType() != Type.ANY && mainblock.isStrict()) { if (expr.getType().isPrimitive()) { @@ -324,7 +324,7 @@ public void compileSet(MainLeekBlock mainblock, JavaWriter writer, Expression ex @Override public void compileSetCopy(MainLeekBlock mainblock, JavaWriter writer, Expression expr) { - assert(mLeftValue && !mTabular.nullable()); + // assert(mLeftValue && !mTabular.nullable()); if (expr.getType() != Type.ANY) { writer.addCode("(" + expr.getType().getJavaName(mainblock.getVersion()) + ") "); @@ -366,7 +366,7 @@ public void compileSetCopy(MainLeekBlock mainblock, JavaWriter writer, Expressio @Override public void compileIncrement(MainLeekBlock mainblock, JavaWriter writer) { - assert(mLeftValue && !mTabular.nullable()); + // assert(mLeftValue && !mTabular.nullable()); writer.addCode("put_inc("); mTabular.writeJavaCode(mainblock, writer); @@ -378,7 +378,7 @@ public void compileIncrement(MainLeekBlock mainblock, JavaWriter writer) { @Override public void compilePreIncrement(MainLeekBlock mainblock, JavaWriter writer) { - assert(mLeftValue && !mTabular.nullable()); + // assert(mLeftValue && !mTabular.nullable()); writer.addCode("put_pre_inc("); mTabular.writeJavaCode(mainblock, writer); @@ -389,7 +389,7 @@ public void compilePreIncrement(MainLeekBlock mainblock, JavaWriter writer) { @Override public void compileDecrement(MainLeekBlock mainblock, JavaWriter writer) { - assert(mLeftValue && !mTabular.nullable()); + // assert(mLeftValue && !mTabular.nullable()); writer.addCode("put_dec("); mTabular.writeJavaCode(mainblock, writer); @@ -400,7 +400,7 @@ public void compileDecrement(MainLeekBlock mainblock, JavaWriter writer) { @Override public void compilePreDecrement(MainLeekBlock mainblock, JavaWriter writer) { - assert(mLeftValue && !mTabular.nullable()); + // assert(mLeftValue && !mTabular.nullable()); writer.addCode("put_pre_dec("); mTabular.writeJavaCode(mainblock, writer); @@ -411,7 +411,7 @@ public void compilePreDecrement(MainLeekBlock mainblock, JavaWriter writer) { @Override public void compileAddEq(MainLeekBlock mainblock, JavaWriter writer, Expression expr, Type t) { - assert(mLeftValue && !mTabular.nullable()); + // assert(mLeftValue && !mTabular.nullable()); writer.addCode("put_add_eq("); mTabular.writeJavaCode(mainblock, writer); @@ -424,7 +424,7 @@ public void compileAddEq(MainLeekBlock mainblock, JavaWriter writer, Expression @Override public void compileSubEq(MainLeekBlock mainblock, JavaWriter writer, Expression expr) { - assert(mLeftValue && !mTabular.nullable()); + // assert(mLeftValue && !mTabular.nullable()); writer.addCode("put_sub_eq("); mTabular.writeJavaCode(mainblock, writer); @@ -437,7 +437,7 @@ public void compileSubEq(MainLeekBlock mainblock, JavaWriter writer, Expression @Override public void compileMulEq(MainLeekBlock mainblock, JavaWriter writer, Expression expr, Type type) { - assert(mLeftValue && !mTabular.nullable()); + // assert(mLeftValue && !mTabular.nullable()); writer.addCode("put_mul_eq("); mTabular.writeJavaCode(mainblock, writer); @@ -450,7 +450,7 @@ public void compileMulEq(MainLeekBlock mainblock, JavaWriter writer, Expression @Override public void compileModEq(MainLeekBlock mainblock, JavaWriter writer, Expression expr) { - assert(mLeftValue && !mTabular.nullable()); + // assert(mLeftValue && !mTabular.nullable()); writer.addCode("put_mod_eq("); mTabular.writeJavaCode(mainblock, writer); @@ -463,7 +463,7 @@ public void compileModEq(MainLeekBlock mainblock, JavaWriter writer, Expression @Override public void compileDivEq(MainLeekBlock mainblock, JavaWriter writer, Expression expr) { - assert(mLeftValue && !mTabular.nullable()); + // assert(mLeftValue && !mTabular.nullable()); writer.addCode("put_div_eq("); mTabular.writeJavaCode(mainblock, writer); @@ -476,7 +476,7 @@ public void compileDivEq(MainLeekBlock mainblock, JavaWriter writer, Expression @Override public void compileIntDivEq(MainLeekBlock mainblock, JavaWriter writer, Expression expr) { - assert(mLeftValue && !mTabular.nullable()); + // assert(mLeftValue && !mTabular.nullable()); writer.addCode("put_intdiv_eq("); mTabular.writeJavaCode(mainblock, writer); @@ -489,7 +489,7 @@ public void compileIntDivEq(MainLeekBlock mainblock, JavaWriter writer, Expressi @Override public void compilePowEq(MainLeekBlock mainblock, JavaWriter writer, Expression expr, Type t) { - assert(mLeftValue && !mTabular.nullable()); + // assert(mLeftValue && !mTabular.nullable()); writer.addCode("put_pow_eq("); mTabular.writeJavaCode(mainblock, writer); @@ -502,7 +502,7 @@ public void compilePowEq(MainLeekBlock mainblock, JavaWriter writer, Expression @Override public void compileBitOrEq(MainLeekBlock mainblock, JavaWriter writer, Expression expr) { - assert(mLeftValue && !mTabular.nullable()); + // assert(mLeftValue && !mTabular.nullable()); writer.addCode("put_bor_eq("); mTabular.writeJavaCode(mainblock, writer); @@ -515,7 +515,7 @@ public void compileBitOrEq(MainLeekBlock mainblock, JavaWriter writer, Expressio @Override public void compileBitAndEq(MainLeekBlock mainblock, JavaWriter writer, Expression expr) { - assert(mLeftValue && !mTabular.nullable()); + // assert(mLeftValue && !mTabular.nullable()); writer.addCode("put_band_eq("); mTabular.writeJavaCode(mainblock, writer); @@ -528,7 +528,7 @@ public void compileBitAndEq(MainLeekBlock mainblock, JavaWriter writer, Expressi @Override public void compileBitXorEq(MainLeekBlock mainblock, JavaWriter writer, Expression expr) { - assert(mLeftValue && !mTabular.nullable()); + // assert(mLeftValue && !mTabular.nullable()); writer.addCode("put_bxor_eq("); mTabular.writeJavaCode(mainblock, writer); @@ -541,7 +541,7 @@ public void compileBitXorEq(MainLeekBlock mainblock, JavaWriter writer, Expressi @Override public void compileShiftLeftEq(MainLeekBlock mainblock, JavaWriter writer, Expression expr) { - assert(mLeftValue && !mTabular.nullable()); + // assert(mLeftValue && !mTabular.nullable()); writer.addCode("put_shl_eq("); mTabular.writeJavaCode(mainblock, writer); @@ -554,7 +554,7 @@ public void compileShiftLeftEq(MainLeekBlock mainblock, JavaWriter writer, Expre @Override public void compileShiftRightEq(MainLeekBlock mainblock, JavaWriter writer, Expression expr) { - assert(mLeftValue && !mTabular.nullable()); + // assert(mLeftValue && !mTabular.nullable()); writer.addCode("put_shr_eq("); mTabular.writeJavaCode(mainblock, writer); @@ -567,7 +567,7 @@ public void compileShiftRightEq(MainLeekBlock mainblock, JavaWriter writer, Expr @Override public void compileShiftUnsignedRightEq(MainLeekBlock mainblock, JavaWriter writer, Expression expr) { - assert(mLeftValue && !mTabular.nullable()); + // assert(mLeftValue && !mTabular.nullable()); writer.addCode("put_ushr_eq("); mTabular.writeJavaCode(mainblock, writer); diff --git a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java index c03910d1..45f7eb1b 100644 --- a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java +++ b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java @@ -225,7 +225,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { @Override public void compileL(MainLeekBlock mainblock, JavaWriter writer) { - assert (object.isLeftValue() && !object.nullable()); + // assert (object.isLeftValue() && !object.nullable()); if (mainblock.getWordCompiler().getVersion() >= 2 && field.getWord().equals("class")) { writer.addCode("classOf("); @@ -248,7 +248,7 @@ public void compileL(MainLeekBlock mainblock, JavaWriter writer) { @Override public void compileSet(MainLeekBlock mainblock, JavaWriter writer, Expression expr) { - assert (object.isLeftValue() && !object.nullable()); + // assert (object.isLeftValue() && !object.nullable()); if (object instanceof LeekVariable && ((LeekVariable) object).getVariableType() == VariableType.THIS) { writer.addCode(field.getWord() + " = "); @@ -269,7 +269,7 @@ public void compileSet(MainLeekBlock mainblock, JavaWriter writer, Expression ex @Override public void compileIncrement(MainLeekBlock mainblock, JavaWriter writer) { - assert (object.isLeftValue() && !object.nullable()); + // assert (object.isLeftValue() && !object.nullable()); if (this.type != Type.ANY) { writer.addCode("(" + this.type.getJavaName(mainblock.getVersion()) + ") "); @@ -281,7 +281,7 @@ public void compileIncrement(MainLeekBlock mainblock, JavaWriter writer) { @Override public void compilePreIncrement(MainLeekBlock mainblock, JavaWriter writer) { - assert (object.isLeftValue() && !object.nullable()); + // assert (object.isLeftValue() && !object.nullable()); writer.addCode("field_pre_inc("); object.writeJavaCode(mainblock, writer); @@ -290,7 +290,7 @@ public void compilePreIncrement(MainLeekBlock mainblock, JavaWriter writer) { @Override public void compileDecrement(MainLeekBlock mainblock, JavaWriter writer) { - assert (object.isLeftValue() && !object.nullable()); + // assert (object.isLeftValue() && !object.nullable()); writer.addCode("field_dec("); object.writeJavaCode(mainblock, writer); @@ -299,7 +299,7 @@ public void compileDecrement(MainLeekBlock mainblock, JavaWriter writer) { @Override public void compilePreDecrement(MainLeekBlock mainblock, JavaWriter writer) { - assert (object.isLeftValue() && !object.nullable()); + // assert (object.isLeftValue() && !object.nullable()); writer.addCode("field_pre_dec("); object.writeJavaCode(mainblock, writer); @@ -308,7 +308,7 @@ public void compilePreDecrement(MainLeekBlock mainblock, JavaWriter writer) { @Override public void compileAddEq(MainLeekBlock mainblock, JavaWriter writer, Expression expr, Type t) { - assert (object.isLeftValue() && !object.nullable()); + // assert (object.isLeftValue() && !object.nullable()); writer.addCode("field_add_eq("); object.writeJavaCode(mainblock, writer); @@ -320,7 +320,7 @@ public void compileAddEq(MainLeekBlock mainblock, JavaWriter writer, Expression @Override public void compileSubEq(MainLeekBlock mainblock, JavaWriter writer, Expression expr) { - assert (object.isLeftValue() && !object.nullable()); + // assert (object.isLeftValue() && !object.nullable()); writer.addCode("field_sub_eq("); object.writeJavaCode(mainblock, writer); @@ -332,7 +332,7 @@ public void compileSubEq(MainLeekBlock mainblock, JavaWriter writer, Expression @Override public void compileMulEq(MainLeekBlock mainblock, JavaWriter writer, Expression expr, Type t) { - assert (object.isLeftValue() && !object.nullable()); + // assert (object.isLeftValue() && !object.nullable()); writer.addCode("field_mul_eq("); object.writeJavaCode(mainblock, writer); @@ -344,7 +344,7 @@ public void compileMulEq(MainLeekBlock mainblock, JavaWriter writer, Expression @Override public void compilePowEq(MainLeekBlock mainblock, JavaWriter writer, Expression expr, Type t) { - assert (object.isLeftValue() && !object.nullable()); + // assert (object.isLeftValue() && !object.nullable()); writer.addCode("field_pow_eq("); object.writeJavaCode(mainblock, writer); @@ -356,7 +356,7 @@ public void compilePowEq(MainLeekBlock mainblock, JavaWriter writer, Expression @Override public void compileDivEq(MainLeekBlock mainblock, JavaWriter writer, Expression expr) { - assert (object.isLeftValue() && !object.nullable()); + // assert (object.isLeftValue() && !object.nullable()); writer.addCode("field_div_eq("); object.writeJavaCode(mainblock, writer); @@ -368,7 +368,7 @@ public void compileDivEq(MainLeekBlock mainblock, JavaWriter writer, Expression @Override public void compileIntDivEq(MainLeekBlock mainblock, JavaWriter writer, Expression expr) { - assert (object.isLeftValue() && !object.nullable()); + // assert (object.isLeftValue() && !object.nullable()); writer.addCode("field_intdiv_eq("); object.writeJavaCode(mainblock, writer); @@ -380,7 +380,7 @@ public void compileIntDivEq(MainLeekBlock mainblock, JavaWriter writer, Expressi @Override public void compileModEq(MainLeekBlock mainblock, JavaWriter writer, Expression expr) { - assert (object.isLeftValue() && !object.nullable()); + // assert (object.isLeftValue() && !object.nullable()); writer.addCode("field_mod_eq("); object.writeJavaCode(mainblock, writer); @@ -392,7 +392,7 @@ public void compileModEq(MainLeekBlock mainblock, JavaWriter writer, Expression @Override public void compileBitOrEq(MainLeekBlock mainblock, JavaWriter writer, Expression expr) { - assert (object.isLeftValue() && !object.nullable()); + // assert (object.isLeftValue() && !object.nullable()); writer.addCode("field_bor_eq("); object.writeJavaCode(mainblock, writer); @@ -404,7 +404,7 @@ public void compileBitOrEq(MainLeekBlock mainblock, JavaWriter writer, Expressio @Override public void compileBitAndEq(MainLeekBlock mainblock, JavaWriter writer, Expression expr) { - assert (object.isLeftValue() && !object.nullable()); + // assert (object.isLeftValue() && !object.nullable()); writer.addCode("field_band_eq("); object.writeJavaCode(mainblock, writer); @@ -416,7 +416,7 @@ public void compileBitAndEq(MainLeekBlock mainblock, JavaWriter writer, Expressi @Override public void compileBitXorEq(MainLeekBlock mainblock, JavaWriter writer, Expression expr) { - assert (object.isLeftValue() && !object.nullable()); + // assert (object.isLeftValue() && !object.nullable()); writer.addCode("field_bxor_eq("); object.writeJavaCode(mainblock, writer); @@ -428,7 +428,7 @@ public void compileBitXorEq(MainLeekBlock mainblock, JavaWriter writer, Expressi @Override public void compileShiftLeftEq(MainLeekBlock mainblock, JavaWriter writer, Expression expr) { - assert (object.isLeftValue() && !object.nullable()); + // assert (object.isLeftValue() && !object.nullable()); writer.addCode("field_shl_eq("); object.writeJavaCode(mainblock, writer); @@ -440,7 +440,7 @@ public void compileShiftLeftEq(MainLeekBlock mainblock, JavaWriter writer, Expre @Override public void compileShiftRightEq(MainLeekBlock mainblock, JavaWriter writer, Expression expr) { - assert (object.isLeftValue() && !object.nullable()); + // assert (object.isLeftValue() && !object.nullable()); writer.addCode("field_shr_eq("); object.writeJavaCode(mainblock, writer); @@ -452,7 +452,7 @@ public void compileShiftRightEq(MainLeekBlock mainblock, JavaWriter writer, Expr @Override public void compileShiftUnsignedRightEq(MainLeekBlock mainblock, JavaWriter writer, Expression expr) { - assert (object.isLeftValue() && !object.nullable()); + // assert (object.isLeftValue() && !object.nullable()); writer.addCode("field_ushr_eq("); object.writeJavaCode(mainblock, writer); diff --git a/src/test/java/test/TestArray.java b/src/test/java/test/TestArray.java index 07eee7a4..3138f38c 100644 --- a/src/test/java/test/TestArray.java +++ b/src/test/java/test/TestArray.java @@ -731,5 +731,10 @@ public void run() throws Exception { code_v4_("var a = [1, 1, 1, 2, 2, 2] return arrayUnique(a)").equals("[1, 2]"); code_v4_("var a = [1, 2, 3, 4, 5, 6] return arrayUnique(a)").equals("[1, 2, 3, 4, 5, 6]"); code_v4_("var a = [1, 2, 3, 4, 3, 2, 1] return arrayUnique(a)").equals("[1, 2, 3, 4]"); + + section("Array types"); + code_v4_("Array array = [1, 2, 3] return array").equals("[1, 2, 3]"); + code_v4_("Array> array = [[1], [2], [3]] return array").equals("[[1], [2], [3]]"); + code_v4_("Array>> array = [[[1]], [[2]], [[3]]] return array").equals("[[[1]], [[2]], [[3]]]"); } }