From 6b98f9050d342ea6f7a5cc613dd401f7c0cd9827 Mon Sep 17 00:00:00 2001 From: olegtymko Date: Wed, 12 Oct 2022 21:11:44 +0700 Subject: [PATCH] =?UTF-8?q?feat(compiler):=20#140=20=D0=BA=D0=BE=D0=BD?= =?UTF-8?q?=D1=86=D0=B5=D0=BF=D1=82=20=D0=B2=D1=8B=D0=BF=D0=BE=D0=BB=D0=BD?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B1=D0=B0=D0=B9=D1=82=D0=BA=D0=BE?= =?UTF-8?q?=D0=B4=D0=B0=20=D0=B1=D0=B5=D0=B7=20LINE=5FNUM?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../github/otymko/jos/compiler/Compiler.java | 53 ++++++++++++++----- .../otymko/jos/compiler/ScriptCompiler.java | 1 + .../github/otymko/jos/module/ModuleImage.java | 4 ++ .../otymko/jos/module/ModuleImageCache.java | 2 + .../jos/runtime/machine/ExecutionFrame.java | 25 +++++++++ .../jos/runtime/machine/MachineInstance.java | 5 +- 6 files changed, 76 insertions(+), 14 deletions(-) diff --git a/engine/src/main/java/com/github/otymko/jos/compiler/Compiler.java b/engine/src/main/java/com/github/otymko/jos/compiler/Compiler.java index 39890d68..8359339e 100644 --- a/engine/src/main/java/com/github/otymko/jos/compiler/Compiler.java +++ b/engine/src/main/java/com/github/otymko/jos/compiler/Compiler.java @@ -21,6 +21,7 @@ import com.github.otymko.jos.util.StringLineCleaner; import lombok.Data; import org.antlr.v4.runtime.tree.ParseTree; +import org.apache.commons.lang3.tuple.Pair; import java.math.BigDecimal; import java.util.ArrayDeque; @@ -49,6 +50,8 @@ public class Compiler extends BSLParserBaseVisitor { private MethodDescriptor currentMethodDescriptor; private SymbolScope localScope; + private boolean skipLineNumbers; + @Data private static class NestedLoopInfo { private int startPoint = DUMMY_ADDRESS; @@ -74,6 +77,8 @@ public Compiler(ModuleImageCache imageCache, ScriptCompiler compiler) { this.imageCache = imageCache; this.compiler = compiler; this.annotationProcessing = new AnnotationProcessing(this); + + this.skipLineNumbers = false; } @Override @@ -193,10 +198,10 @@ public ParseTree visitFileCodeBlockBeforeSub(BSLParser.FileCodeBlockBeforeSubCon @Override public ParseTree visitStatement(BSLParser.StatementContext statement) { - int numberLint = statement.getStart().getLine(); - addCommand(OperationCode.LINE_NUM, numberLint); + var numberLint = statement.getStart().getLine(); + var index = addLineNumCommand(numberLint); if (currentMethodDescriptor != null && currentMethodDescriptor.getEntry() == DUMMY_ADDRESS) { - currentMethodDescriptor.setEntry(imageCache.getCode().size() - 1); + currentMethodDescriptor.setEntry(index); } return super.visitStatement(statement); } @@ -237,8 +242,8 @@ public ParseTree visitIfStatement(BSLParser.IfStatementContext ifStatement) { var alternativeBranches = false; for (var elseIfBranches : ifStatement.elsifBranch()) { - correctCommandArgument(jumpFalse, imageCache.getCode().size()); - addCommand(OperationCode.LINE_NUM, elseIfBranches.getStart().getLine()); + var index = addLineNumCommand(elseIfBranches.getStart().getLine()); + correctCommandArgument(jumpFalse, index); visitExpression(elseIfBranches.expression()); @@ -250,13 +255,13 @@ public ParseTree visitIfStatement(BSLParser.IfStatementContext ifStatement) { if (ifStatement.elseBranch() != null) { alternativeBranches = true; - correctCommandArgument(jumpFalse, imageCache.getCode().size()); - addCommand(OperationCode.LINE_NUM, ifStatement.elseBranch().getStart().getLine()); + var index = addLineNumCommand(ifStatement.elseBranch().getStart().getLine()); + correctCommandArgument(jumpFalse, index); visitCodeBlock(ifStatement.elseBranch().codeBlock()); } - var endIndex = addCommand(OperationCode.LINE_NUM, ifStatement.getStop().getLine()); + var endIndex = addLineNumCommand(ifStatement.getStop().getLine()); if (!alternativeBranches) { correctCommandArgument(jumpFalse, endIndex); } @@ -272,7 +277,13 @@ public ParseTree visitIfStatement(BSLParser.IfStatementContext ifStatement) { public ParseTree visitWhileStatement(BSLParser.WhileStatementContext whileStatement) { // прыжок наверх цикла должен попадать на опкод LineNum // поэтому указываем адрес - 1 - var conditionIndex = imageCache.getCode().size() - 1; + int conditionIndex; + if (skipLineNumbers) { + conditionIndex = imageCache.getCode().size(); + } else { + conditionIndex = imageCache.getCode().size() - 1; + } +// var conditionIndex = imageCache.getCode().size() - 1; var loopRecord = Compiler.NestedLoopInfo.create(conditionIndex); nestedLoops.push(loopRecord); @@ -303,7 +314,7 @@ public ParseTree visitForStatement(BSLParser.ForStatementContext forStatement) { addCommand(OperationCode.PUSH_TMP); var jumpIndex = addCommand(OperationCode.JMP, DUMMY_ADDRESS); - var loopStart = addCommand(OperationCode.LINE_NUM, forStatement.getStart().getLine()); + var loopStart = addLineNumCommand(forStatement.getStart().getLine()); // инкремент processIdentifier(identifier); @@ -337,7 +348,7 @@ public ParseTree visitForEachStatement(BSLParser.ForEachStatementContext forEach addCommand(OperationCode.PUSH_ITERATOR); - var loopStart = addCommand(OperationCode.LINE_NUM, forEachStatement.getStart().getLine()); + var loopStart = addLineNumCommand(forEachStatement.getStart().getLine()); addCommand(OperationCode.ITERATOR_NEXT); @@ -363,13 +374,13 @@ public ParseTree visitTryStatement(BSLParser.TryStatementContext tryStatement) { visitTryCodeBlock(tryStatement.tryCodeBlock()); var jmpIndex = addCommand(OperationCode.JMP, DUMMY_ADDRESS); - var beginHandler = addCommand(OperationCode.LINE_NUM, tryStatement.exceptCodeBlock().getStart().getLine()); + var beginHandler = addLineNumCommand(tryStatement.exceptCodeBlock().getStart().getLine()); correctCommandArgument(beginTryIndex, beginHandler); visitExceptCodeBlock(tryStatement.exceptCodeBlock()); - var endIndex = addCommand(OperationCode.LINE_NUM, tryStatement.getStop().getLine()); + var endIndex = addLineNumCommand(tryStatement.getStop().getLine()); addCommand(OperationCode.END_TRY, 0); correctCommandArgument(jmpIndex, endIndex); @@ -688,6 +699,22 @@ private int addCommand(OperationCode operationCode, int argument) { return index; } + private int addLineNumCommand(int lineNumber) { + if (skipLineNumbers) { + imageCache.getLinesOffset().add(Pair.of(imageCache.getCode().size(), lineNumber)); + + if (imageCache.getCode().isEmpty()) { + return 0; + } + return imageCache.getCode().size(); + } + + var index = imageCache.getCode().size(); + imageCache.getCode().add(new Command(OperationCode.LINE_NUM, lineNumber)); + + return index; + } + private int addCommand(OperationCode operationCode) { return addCommand(operationCode, 0); } diff --git a/engine/src/main/java/com/github/otymko/jos/compiler/ScriptCompiler.java b/engine/src/main/java/com/github/otymko/jos/compiler/ScriptCompiler.java index 2f6984d4..478d944c 100644 --- a/engine/src/main/java/com/github/otymko/jos/compiler/ScriptCompiler.java +++ b/engine/src/main/java/com/github/otymko/jos/compiler/ScriptCompiler.java @@ -108,6 +108,7 @@ private static ModuleImage buildImage(ModuleImageCache cache) { .source(cache.getSource()) .entry(cache.getEntryPoint()) .code(List.copyOf(cache.getCode())) + .linesOffset(List.copyOf(cache.getLinesOffset())) .methods(List.copyOf(cache.getMethods())) .variables(List.copyOf(cache.getVariables())) .constants(List.copyOf(cache.getConstants())) diff --git a/engine/src/main/java/com/github/otymko/jos/module/ModuleImage.java b/engine/src/main/java/com/github/otymko/jos/module/ModuleImage.java index a0077b99..98f4880d 100644 --- a/engine/src/main/java/com/github/otymko/jos/module/ModuleImage.java +++ b/engine/src/main/java/com/github/otymko/jos/module/ModuleImage.java @@ -12,7 +12,9 @@ import com.github.otymko.jos.runtime.machine.info.VariableInfo; import lombok.Builder; import lombok.Data; +import org.apache.commons.lang3.tuple.Pair; +import java.util.ArrayList; import java.util.List; /** @@ -30,6 +32,8 @@ public class ModuleImage { * Байткоды */ private List code; + + private List> linesOffset; /** * Методы */ diff --git a/engine/src/main/java/com/github/otymko/jos/module/ModuleImageCache.java b/engine/src/main/java/com/github/otymko/jos/module/ModuleImageCache.java index 540ac03a..b49e5d83 100644 --- a/engine/src/main/java/com/github/otymko/jos/module/ModuleImageCache.java +++ b/engine/src/main/java/com/github/otymko/jos/module/ModuleImageCache.java @@ -11,6 +11,7 @@ import com.github.otymko.jos.runtime.machine.Command; import com.github.otymko.jos.runtime.machine.info.VariableInfo; import lombok.Data; +import org.apache.commons.lang3.tuple.Pair; import java.util.ArrayList; import java.util.List; @@ -23,6 +24,7 @@ public class ModuleImageCache { private ModuleSource source; private int entryPoint = -1; private List code = new ArrayList<>(); + private List> linesOffset = new ArrayList<>(); private List constants = new ArrayList<>(); private List variables = new ArrayList<>(); private List methods = new ArrayList<>(); diff --git a/engine/src/main/java/com/github/otymko/jos/runtime/machine/ExecutionFrame.java b/engine/src/main/java/com/github/otymko/jos/runtime/machine/ExecutionFrame.java index 6b9f4ce9..19e84cfe 100644 --- a/engine/src/main/java/com/github/otymko/jos/runtime/machine/ExecutionFrame.java +++ b/engine/src/main/java/com/github/otymko/jos/runtime/machine/ExecutionFrame.java @@ -12,7 +12,9 @@ import lombok.Data; import java.util.ArrayDeque; +import java.util.Comparator; import java.util.Deque; +import java.util.NoSuchElementException; @Data public class ExecutionFrame { @@ -31,4 +33,27 @@ public class ExecutionFrame { private boolean discardReturnValue; private boolean oneTimeCall; + + public int getLineNumber() { + if (lineNumber == 0) { + return findLineNumberByInstructionPointer(instructionPointer); + } + + return lineNumber; + } + + private int findLineNumberByInstructionPointer(int instruction) { + if (instruction < 0) { + return 1; + } + + try { + return image.getLinesOffset().stream() + .filter(pair -> pair.getLeft() <= instruction) + .max(Comparator.naturalOrder()) + .stream().findAny().get().getRight(); + } catch (NoSuchElementException e) { + throw e; + } + } } diff --git a/engine/src/main/java/com/github/otymko/jos/runtime/machine/MachineInstance.java b/engine/src/main/java/com/github/otymko/jos/runtime/machine/MachineInstance.java index b3c2ac19..a99e51fb 100644 --- a/engine/src/main/java/com/github/otymko/jos/runtime/machine/MachineInstance.java +++ b/engine/src/main/java/com/github/otymko/jos/runtime/machine/MachineInstance.java @@ -167,6 +167,9 @@ private void executeCode() { var errorInfo = exception.getErrorInfo(); if (errorInfo.getLine() < 0) { + + nextInstruction(); + errorInfo.setLine(currentFrame.getLineNumber()); errorInfo.setSource(Common.getAbsolutPath(currentImage.getSource().getPath())); Common.fillCodePositionInErrorInfo(errorInfo, currentImage, currentFrame.getLineNumber()); @@ -232,7 +235,7 @@ private void mainCommandLoop() { runCommand(command.getCode(), command.getArgument()); } } catch (EngineException exception) { - throw exception; + throw exception; } catch (Exception exception) { throw new WrappedJavaException(exception); }