mirror of
https://github.com/aNNiMON/Own-Programming-Language-Tutorial.git
synced 2024-09-20 08:44: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.ConstantPropagation;
|
||||||
import com.annimon.ownlang.parser.optimization.DeadCodeElimination;
|
import com.annimon.ownlang.parser.optimization.DeadCodeElimination;
|
||||||
import com.annimon.ownlang.parser.optimization.ExpressionSimplification;
|
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.Optimizable;
|
||||||
import com.annimon.ownlang.parser.optimization.SummaryOptimization;
|
import com.annimon.ownlang.parser.optimization.SummaryOptimization;
|
||||||
|
|
||||||
@ -19,11 +20,12 @@ public final class Optimizer {
|
|||||||
new ConstantFolding(),
|
new ConstantFolding(),
|
||||||
new ConstantPropagation(),
|
new ConstantPropagation(),
|
||||||
new DeadCodeElimination(),
|
new DeadCodeElimination(),
|
||||||
new ExpressionSimplification()
|
new ExpressionSimplification(),
|
||||||
|
new InstructionCombining()
|
||||||
});
|
});
|
||||||
|
|
||||||
Node result = statement;
|
Node result = statement;
|
||||||
if (true || level >= 9) {
|
if (level >= 9) {
|
||||||
int iteration = 0, lastModifications = 0;
|
int iteration = 0, lastModifications = 0;
|
||||||
do {
|
do {
|
||||||
lastModifications = optimization.optimizationsCount();
|
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;
|
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) {
|
public static boolean isSameVariables(Node n1, Node n2) {
|
||||||
if (isVariable(n1) && isVariable(n2)) {
|
if (isVariable(n1) && isVariable(n2)) {
|
||||||
final VariableExpression v1 = (VariableExpression) n1;
|
final VariableExpression v1 = (VariableExpression) n1;
|
||||||
|
Loading…
Reference in New Issue
Block a user