rework StackSizeAnalyzer

This commit is contained in:
ChUrl
2021-01-31 16:40:20 +01:00
parent 228a0221ac
commit bdf1376675
2 changed files with 25 additions and 17 deletions

View File

@ -1,14 +1,20 @@
package codegen.analysis; package codegen.analysis;
import parser.ast.ASTNode; import parser.ast.ASTNode;
import util.Logger;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.Deque; import java.util.Deque;
/**
* Simuliert den Laufzeit-Stack während einer Programmausführung.
*/
public class StackModel { public class StackModel {
private final Deque<ASTNode> stack; private final Deque<ASTNode> stack;
/**
* Speichert die maximale Stacktiefe während der Ausführung.
*/
private int max; private int max;
public StackModel() { public StackModel() {
@ -16,22 +22,16 @@ public class StackModel {
} }
public void push(ASTNode root) { public void push(ASTNode root) {
Logger.log("PUSH " + root.getName() + ": " + root.getValue());
this.stack.push(root); this.stack.push(root);
this.updateMax(); this.updateMax();
} }
public ASTNode pop() { public void pop() {
if (this.stack.isEmpty()) { if (this.stack.isEmpty()) {
throw new IllegalStateException("Can't pop empty stack"); throw new IllegalStateException("Can't pop empty stack");
} }
Logger.log("POP " + this.stack.peek().getName() + ": " + this.stack.peek().getValue()); this.stack.pop();
return this.stack.pop();
}
public ASTNode peek() {
return this.stack.peek();
} }
private void updateMax() { private void updateMax() {

View File

@ -7,14 +7,18 @@ import java.util.Set;
import static util.Logger.log; import static util.Logger.log;
/**
* Ermittelt die maximal benötigte Stacktiefe für ein Programm.
* Das Programm wird übergeben als {@link AST}.
*/
public final class StackSizeAnalyzer { public final class StackSizeAnalyzer {
private static final Set<String> mod; private static final Set<String> mod;
private static final Set<String> bin; private static final Set<String> binaryOperators;
static { static {
mod = Set.of("assignment", "expr", "INTEGER_LIT", "BOOLEAN_LIT", "STRING_LIT", "IDENTIFIER", "print"); mod = Set.of("assignment", "expr", "INTEGER_LIT", "BOOLEAN_LIT", "STRING_LIT", "IDENTIFIER", "print");
bin = Set.of("AND", "OR", "ADD", "SUB", "MUL", "DIV", "MOD", "LESS", "LESS_EQUAL", "GREATER", "GREATER_EQUAL", "EQUAL", "NOT_EQUAL"); binaryOperators = Set.of("AND", "OR", "ADD", "SUB", "MUL", "DIV", "MOD", "LESS", "LESS_EQUAL", "GREATER", "GREATER_EQUAL", "EQUAL", "NOT_EQUAL");
} }
private StackSizeAnalyzer() {} private StackSizeAnalyzer() {}
@ -23,6 +27,7 @@ public final class StackSizeAnalyzer {
log("\nDetermining required stack depth:"); log("\nDetermining required stack depth:");
final StackModel stack = new StackModel(); final StackModel stack = new StackModel();
runStackModel(tree.getRoot().getChildren().get(3).getChildren().get(11), stack); runStackModel(tree.getRoot().getChildren().get(3).getChildren().get(11), stack);
return stack.getMax(); return stack.getMax();
@ -44,15 +49,15 @@ public final class StackSizeAnalyzer {
} }
} }
// Simulate instructions
private static void literal(ASTNode root, StackModel stack) { private static void literal(ASTNode root, StackModel stack) {
log("literal():");
stack.push(root); stack.push(root);
} }
private static void assignment(ASTNode root, StackModel stack) { private static void assignment(ASTNode root, StackModel stack) {
runStackModel(root.getChildren().get(0), stack); runStackModel(root.getChildren().get(0), stack);
log("assignment():");
stack.pop(); stack.pop();
} }
@ -61,29 +66,32 @@ public final class StackSizeAnalyzer {
runStackModel(root.getChildren().get(1).getChildren().get(1), stack); runStackModel(root.getChildren().get(1).getChildren().get(1), stack);
log("println():");
stack.pop(); // Objectref stack.pop(); // Objectref
stack.pop(); // Argument stack.pop(); // Argument
} }
private static void expr(ASTNode root, StackModel stack) { private static void expr(ASTNode root, StackModel stack) {
if (root.getChildren().size() == 2 && bin.contains(root.getValue())) { if (root.getChildren().size() == 2 && binaryOperators.contains(root.getValue())) {
// Expression with binary operator
runStackModel(root.getChildren().get(0), stack); runStackModel(root.getChildren().get(0), stack);
runStackModel(root.getChildren().get(1), stack); runStackModel(root.getChildren().get(1), stack);
log("expr():");
stack.pop(); // Argument stack.pop(); // Argument
stack.pop(); // Argument stack.pop(); // Argument
stack.push(root); // Result stack.push(root); // Result
} else if (root.getChildren().size() == 1 && "NOT".equals(root.getValue())) { } else if (root.getChildren().size() == 1 && "NOT".equals(root.getValue())) {
// Expression with NOT
runStackModel(root.getChildren().get(0), stack); runStackModel(root.getChildren().get(0), stack);
log("expr():");
stack.push(new ASTNode("1 (XOR)", 0)); // 1 for xor stack.push(new ASTNode("1 (XOR)", 0)); // 1 for xor
stack.pop(); // xor stack.pop(); // xor
stack.pop(); // xor stack.pop(); // xor
stack.push(root); // result stack.push(root); // result
} else if (root.getChildren().size() == 1) { } else if (root.getChildren().size() == 1) {
// Expression with other unary operators
runStackModel(root.getChildren().get(0), stack); runStackModel(root.getChildren().get(0), stack);
} }
} }