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
6dbc045b93
commit
357813ee76
@ -2,6 +2,7 @@ package com.annimon.ownlang.parser;
|
|||||||
|
|
||||||
import com.annimon.ownlang.parser.ast.Statement;
|
import com.annimon.ownlang.parser.ast.Statement;
|
||||||
import com.annimon.ownlang.parser.visitors.ConstantFolding;
|
import com.annimon.ownlang.parser.visitors.ConstantFolding;
|
||||||
|
import com.annimon.ownlang.parser.visitors.ConstantPropagation;
|
||||||
import com.annimon.ownlang.parser.visitors.DeadCodeElimination;
|
import com.annimon.ownlang.parser.visitors.DeadCodeElimination;
|
||||||
import com.annimon.ownlang.parser.visitors.ExpressionSimplification;
|
import com.annimon.ownlang.parser.visitors.ExpressionSimplification;
|
||||||
|
|
||||||
@ -18,16 +19,19 @@ public final class Optimizer {
|
|||||||
if (level == 0) return statement;
|
if (level == 0) return statement;
|
||||||
|
|
||||||
final ConstantFolding constantFolding = new ConstantFolding();
|
final ConstantFolding constantFolding = new ConstantFolding();
|
||||||
|
final ConstantPropagation constantPropagation = new ConstantPropagation();
|
||||||
final DeadCodeElimination deadCodeElimination = new DeadCodeElimination();
|
final DeadCodeElimination deadCodeElimination = new DeadCodeElimination();
|
||||||
final ExpressionSimplification expressionSimplification = new ExpressionSimplification();
|
final ExpressionSimplification expressionSimplification = new ExpressionSimplification();
|
||||||
|
|
||||||
Statement result = statement;
|
Statement result = statement;
|
||||||
for (int i = 0; i < level; i++) {
|
for (int i = 0; i < level; i++) {
|
||||||
result = (Statement) result.accept(constantFolding, null);
|
result = (Statement) result.accept(constantFolding, null);
|
||||||
|
result = (Statement) constantPropagation.visit(result);
|
||||||
result = (Statement) result.accept(deadCodeElimination, null);
|
result = (Statement) result.accept(deadCodeElimination, null);
|
||||||
result = (Statement) result.accept(expressionSimplification, null);
|
result = (Statement) result.accept(expressionSimplification, null);
|
||||||
}
|
}
|
||||||
System.out.print(constantFolding.summaryInfo());
|
System.out.print(constantFolding.summaryInfo());
|
||||||
|
System.out.print(constantPropagation.summaryInfo());
|
||||||
System.out.print(deadCodeElimination.summaryInfo());
|
System.out.print(deadCodeElimination.summaryInfo());
|
||||||
System.out.print(expressionSimplification.summaryInfo());
|
System.out.print(expressionSimplification.summaryInfo());
|
||||||
System.out.println();
|
System.out.println();
|
||||||
|
162
src/com/annimon/ownlang/parser/visitors/ConstantPropagation.java
Normal file
162
src/com/annimon/ownlang/parser/visitors/ConstantPropagation.java
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
package com.annimon.ownlang.parser.visitors;
|
||||||
|
|
||||||
|
import com.annimon.ownlang.lib.Types;
|
||||||
|
import com.annimon.ownlang.lib.Value;
|
||||||
|
import com.annimon.ownlang.parser.Optimizer;
|
||||||
|
import com.annimon.ownlang.parser.ast.Argument;
|
||||||
|
import com.annimon.ownlang.parser.ast.AssignmentExpression;
|
||||||
|
import com.annimon.ownlang.parser.ast.DestructuringAssignmentStatement;
|
||||||
|
import com.annimon.ownlang.parser.ast.FunctionDefineStatement;
|
||||||
|
import com.annimon.ownlang.parser.ast.MatchExpression;
|
||||||
|
import com.annimon.ownlang.parser.ast.Node;
|
||||||
|
import com.annimon.ownlang.parser.ast.Statement;
|
||||||
|
import com.annimon.ownlang.parser.ast.ValueExpression;
|
||||||
|
import com.annimon.ownlang.parser.ast.VariableExpression;
|
||||||
|
import static com.annimon.ownlang.parser.visitors.VisitorUtils.isValue;
|
||||||
|
import static com.annimon.ownlang.parser.visitors.VisitorUtils.isVariable;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs constant propagation.
|
||||||
|
*/
|
||||||
|
public class ConstantPropagation implements Optimizer.Info {
|
||||||
|
|
||||||
|
private final Map<String, Integer> propagatedVariables;
|
||||||
|
|
||||||
|
public ConstantPropagation() {
|
||||||
|
propagatedVariables = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int optimizationsCount() {
|
||||||
|
return propagatedVariables.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String summaryInfo() {
|
||||||
|
if (optimizationsCount() == 0) return "";
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
if (propagatedVariables.size() > 0) {
|
||||||
|
sb.append("\nConstant propagations: ").append(propagatedVariables.size());
|
||||||
|
for (Map.Entry<String, Integer> e : propagatedVariables.entrySet()) {
|
||||||
|
sb.append("\n ").append(e.getKey()).append(": ").append(e.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node visit(Statement s) {
|
||||||
|
final Map<String, VariableInfo> variables = new HashMap<>();
|
||||||
|
// Find variables
|
||||||
|
s.accept(new VariablesGrabber(), variables);
|
||||||
|
// Filter only string/number values with 1 modification
|
||||||
|
final Map<String, Value> candidates = new HashMap<>();
|
||||||
|
for (Map.Entry<String, VariableInfo> e : variables.entrySet()) {
|
||||||
|
final VariableInfo info = e.getValue();
|
||||||
|
if (info.modifications != 1) continue;
|
||||||
|
if (info.value == null) continue;
|
||||||
|
switch (info.value.type()) {
|
||||||
|
case Types.NUMBER:
|
||||||
|
case Types.STRING:
|
||||||
|
candidates.put(e.getKey(), info.value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Replace VariableExpression with ValueExpression
|
||||||
|
return s.accept(new VariablesPropagator(), candidates);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class VariablesGrabber extends OptimizationVisitor<Map<String, VariableInfo>> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node visit(AssignmentExpression s, Map<String, VariableInfo> t) {
|
||||||
|
if (!isVariable((Node)s.target)) {
|
||||||
|
return super.visit(s, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
final String variableName = ((VariableExpression) s.target).name;
|
||||||
|
final VariableInfo var;
|
||||||
|
if (t.containsKey(variableName)) {
|
||||||
|
var = t.get(variableName);
|
||||||
|
var.modifications++;
|
||||||
|
} else {
|
||||||
|
var = new VariableInfo();
|
||||||
|
var.modifications = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s.operation == null && isValue(s.expression)) {
|
||||||
|
var.value = ((ValueExpression) s.expression).value;
|
||||||
|
}
|
||||||
|
t.put(variableName, var);
|
||||||
|
return super.visit(s, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node visit(DestructuringAssignmentStatement s, Map<String, VariableInfo> t) {
|
||||||
|
for (String variableName : s.variables) {
|
||||||
|
if (variableName == null) continue;
|
||||||
|
|
||||||
|
final VariableInfo var;
|
||||||
|
if (t.containsKey(variableName)) {
|
||||||
|
var = t.get(variableName);
|
||||||
|
var.modifications++;
|
||||||
|
} else {
|
||||||
|
var = new VariableInfo();
|
||||||
|
var.modifications = 1;
|
||||||
|
}
|
||||||
|
t.put(variableName, var);
|
||||||
|
}
|
||||||
|
return super.visit(s, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node visit(FunctionDefineStatement s, Map<String, VariableInfo> t) {
|
||||||
|
for (Argument argument : s.arguments) {
|
||||||
|
final String variableName = argument.getName();
|
||||||
|
final VariableInfo var;
|
||||||
|
if (t.containsKey(variableName)) {
|
||||||
|
var = t.get(variableName);
|
||||||
|
var.modifications++;
|
||||||
|
} else {
|
||||||
|
var = new VariableInfo();
|
||||||
|
var.modifications = 1;
|
||||||
|
}
|
||||||
|
t.put(variableName, var);
|
||||||
|
}
|
||||||
|
return super.visit(s, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node visit(MatchExpression s, Map<String, VariableInfo> t) {
|
||||||
|
// no visit match expression
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class VariablesPropagator extends OptimizationVisitor<Map<String, Value>> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node visit(VariableExpression s, Map<String, Value> t) {
|
||||||
|
if (t.containsKey(s.name)) {
|
||||||
|
if (!propagatedVariables.containsKey(s.name)) {
|
||||||
|
propagatedVariables.put(s.name, 1);
|
||||||
|
} else {
|
||||||
|
propagatedVariables.put(s.name, 1 + propagatedVariables.get(s.name));
|
||||||
|
}
|
||||||
|
return new ValueExpression(t.get(s.name));
|
||||||
|
}
|
||||||
|
return super.visit(s, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class VariableInfo {
|
||||||
|
Value value;
|
||||||
|
int modifications;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return (value == null ? "?" : value) + " (" + modifications + " mods)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -17,8 +17,16 @@ import java.util.Set;
|
|||||||
|
|
||||||
public final class VisitorUtils {
|
public final class VisitorUtils {
|
||||||
|
|
||||||
|
public static boolean isValue(Node node) {
|
||||||
|
return (node instanceof ValueExpression);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isVariable(Node node) {
|
||||||
|
return (node instanceof VariableExpression);
|
||||||
|
}
|
||||||
|
|
||||||
public static Statement includeProgram(IncludeStatement s) {
|
public static Statement includeProgram(IncludeStatement s) {
|
||||||
if (!(s.expression instanceof ValueExpression)) return null;
|
if (!isValue(s)) return null;
|
||||||
try {
|
try {
|
||||||
return s.loadProgram(s.expression.eval().asString());
|
return s.loadProgram(s.expression.eval().asString());
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
@ -27,7 +35,7 @@ public final class VisitorUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isIntegerValue(Node node, int valueToCheck) {
|
public static boolean isIntegerValue(Node node, int valueToCheck) {
|
||||||
if (!(node instanceof ValueExpression)) return false;
|
if (!isValue(node)) return false;
|
||||||
|
|
||||||
final Value value = ((ValueExpression) node).value;
|
final Value value = ((ValueExpression) node).value;
|
||||||
if (value.type() != Types.NUMBER) return false;
|
if (value.type() != Types.NUMBER) return false;
|
||||||
@ -40,7 +48,7 @@ public final class VisitorUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isSameVariables(Node n1, Node n2) {
|
public static boolean isSameVariables(Node n1, Node n2) {
|
||||||
if ( (n1 instanceof VariableExpression) && (n2 instanceof VariableExpression) ) {
|
if (isVariable(n1) && isVariable(n2)) {
|
||||||
final VariableExpression v1 = (VariableExpression) n1;
|
final VariableExpression v1 = (VariableExpression) n1;
|
||||||
final VariableExpression v2 = (VariableExpression) n2;
|
final VariableExpression v2 = (VariableExpression) n2;
|
||||||
return v1.name.equals(v2.name);
|
return v1.name.equals(v2.name);
|
||||||
|
Loading…
Reference in New Issue
Block a user