mirror of
https://github.com/aNNiMON/Own-Programming-Language-Tutorial.git
synced 2024-09-20 00:34:20 +03:00
Добавлен оптимизация: объединение инструкций
This commit is contained in:
parent
1b9c5187f6
commit
692370eb4b
@ -7,6 +7,7 @@ import com.annimon.ownlang.parser.optimization.ConstantFolding;
|
||||
import com.annimon.ownlang.parser.optimization.ConstantPropagation;
|
||||
import com.annimon.ownlang.parser.optimization.DeadCodeElimination;
|
||||
import com.annimon.ownlang.parser.optimization.ExpressionSimplification;
|
||||
import com.annimon.ownlang.parser.optimization.InstructionCombining;
|
||||
import com.annimon.ownlang.parser.optimization.Optimizable;
|
||||
import com.annimon.ownlang.parser.optimization.SummaryOptimization;
|
||||
|
||||
@ -19,11 +20,12 @@ public final class Optimizer {
|
||||
new ConstantFolding(),
|
||||
new ConstantPropagation(),
|
||||
new DeadCodeElimination(),
|
||||
new ExpressionSimplification()
|
||||
new ExpressionSimplification(),
|
||||
new InstructionCombining()
|
||||
});
|
||||
|
||||
Node result = statement;
|
||||
if (true || level >= 9) {
|
||||
if (level >= 9) {
|
||||
int iteration = 0, lastModifications = 0;
|
||||
do {
|
||||
lastModifications = optimization.optimizationsCount();
|
||||
|
@ -0,0 +1,110 @@
|
||||
package com.annimon.ownlang.parser.optimization;
|
||||
|
||||
import com.annimon.ownlang.parser.ast.BlockStatement;
|
||||
import com.annimon.ownlang.parser.ast.Expression;
|
||||
import com.annimon.ownlang.parser.ast.Node;
|
||||
import com.annimon.ownlang.parser.ast.PrintStatement;
|
||||
import com.annimon.ownlang.parser.ast.PrintlnStatement;
|
||||
import com.annimon.ownlang.parser.ast.Statement;
|
||||
import com.annimon.ownlang.parser.ast.ValueExpression;
|
||||
import static com.annimon.ownlang.parser.visitors.VisitorUtils.isConstantValue;
|
||||
|
||||
/**
|
||||
* Performs instruction combining.
|
||||
*/
|
||||
public class InstructionCombining extends OptimizationVisitor<Void> implements Optimizable {
|
||||
|
||||
private int printCombinedCount;
|
||||
|
||||
@Override
|
||||
public Node optimize(Node node) {
|
||||
return node.accept(this, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int optimizationsCount() {
|
||||
return printCombinedCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String summaryInfo() {
|
||||
if (optimizationsCount() == 0) return "";
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
if (printCombinedCount > 0) {
|
||||
sb.append("\nPrint statement combined: ").append(printCombinedCount);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visit(BlockStatement s, Void t) {
|
||||
final int size = s.statements.size();
|
||||
if (size <= 1) {
|
||||
return super.visit(s, t);
|
||||
}
|
||||
|
||||
boolean changed = false;
|
||||
final BlockStatement result = new BlockStatement();
|
||||
int i;
|
||||
for (i = 1; i < size; i++) {
|
||||
Statement s1 = s.statements.get(i - 1);
|
||||
Statement s2 = s.statements.get(i);
|
||||
Node n1 = s1.accept(this, t);
|
||||
Node n2 = s2.accept(this, t);
|
||||
if (n1 != s1 || n2 != s2) {
|
||||
changed = true;
|
||||
}
|
||||
final Node combined = tryCombine(n1, n2);
|
||||
if (combined == null) {
|
||||
result.add((Statement) n1);
|
||||
} else {
|
||||
changed = true;
|
||||
result.add(consumeStatement(combined));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (i == size) {
|
||||
// Last node
|
||||
Statement s2 = s.statements.get(size - 1);
|
||||
Node n2 = s2.accept(this, t);
|
||||
if (n2 != s2) {
|
||||
changed = true;
|
||||
}
|
||||
result.add((Statement) n2);
|
||||
}
|
||||
if (changed) {
|
||||
return result;
|
||||
}
|
||||
return super.visit(s, t);
|
||||
}
|
||||
|
||||
private Node tryCombine(Node n1, Node n2) {
|
||||
final int n1Type;
|
||||
if (n1 instanceof PrintStatement) n1Type = 1;
|
||||
else if (n1 instanceof PrintlnStatement) n1Type = 2;
|
||||
else n1Type = 0;
|
||||
|
||||
final int n2Type;
|
||||
if (n2 instanceof PrintStatement) n2Type = 1;
|
||||
else if (n2 instanceof PrintlnStatement) n2Type = 2;
|
||||
else n2Type = 0;
|
||||
|
||||
if (n1Type != 0 && n2Type != 0) {
|
||||
final Expression e1 = (n1Type == 1)
|
||||
? ((PrintStatement) n1).expression
|
||||
: ((PrintlnStatement) n1).expression;
|
||||
final Expression e2 = (n2Type == 1)
|
||||
? ((PrintStatement) n2).expression
|
||||
: ((PrintlnStatement) n2).expression;
|
||||
if (isConstantValue(e1) && isConstantValue(e2)) {
|
||||
String s1 = e1.eval().asString();
|
||||
if (n1Type == 2) s1 += System.lineSeparator();
|
||||
String s2 = e2.eval().asString();
|
||||
if (n2Type == 2) s2 += System.lineSeparator();
|
||||
printCombinedCount++;
|
||||
return new PrintStatement(new ValueExpression(s1 + s2));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -56,6 +56,13 @@ public final class VisitorUtils {
|
||||
return value.asInt() == valueToCheck;
|
||||
}
|
||||
|
||||
public static boolean isConstantValue(Node node) {
|
||||
if (!isValue(node)) return false;
|
||||
|
||||
final int type = ((ValueExpression) node).value.type();
|
||||
return ( (type == Types.NUMBER) || (type == Types.STRING) );
|
||||
}
|
||||
|
||||
public static boolean isSameVariables(Node n1, Node n2) {
|
||||
if (isVariable(n1) && isVariable(n2)) {
|
||||
final VariableExpression v1 = (VariableExpression) n1;
|
||||
|
Loading…
Reference in New Issue
Block a user