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
8077b643bf
commit
1842c4c387
@ -31,6 +31,7 @@ task runOptimizing(dependsOn: classes, type: JavaExec) {
|
|||||||
main = project.mainClass
|
main = project.mainClass
|
||||||
classpath = sourceSets.main.runtimeClasspath
|
classpath = sourceSets.main.runtimeClasspath
|
||||||
ignoreExitValue = true
|
ignoreExitValue = true
|
||||||
|
// args '-o 9 -m -a -f examples/game/minesweeper.own'.split(' ')
|
||||||
args '-o 9 -m -a -f program.own'.split(' ')
|
args '-o 9 -m -a -f program.own'.split(' ')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,59 +0,0 @@
|
|||||||
package com.annimon.ownlang.annotations;
|
|
||||||
|
|
||||||
import java.lang.reflect.Modifier;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Set;
|
|
||||||
import javax.annotation.processing.AbstractProcessor;
|
|
||||||
import javax.annotation.processing.RoundEnvironment;
|
|
||||||
import javax.annotation.processing.SupportedAnnotationTypes;
|
|
||||||
import javax.annotation.processing.SupportedSourceVersion;
|
|
||||||
import javax.lang.model.SourceVersion;
|
|
||||||
import javax.lang.model.element.Element;
|
|
||||||
import javax.lang.model.element.ElementKind;
|
|
||||||
import javax.lang.model.element.TypeElement;
|
|
||||||
import javax.lang.model.type.ExecutableType;
|
|
||||||
import javax.lang.model.type.TypeKind;
|
|
||||||
import javax.lang.model.util.SimpleTypeVisitor6;
|
|
||||||
import javax.tools.Diagnostic.Kind;
|
|
||||||
|
|
||||||
@SupportedAnnotationTypes("com.annimon.ownlang.annotations.ConstantInitializer")
|
|
||||||
@SupportedSourceVersion(SourceVersion.RELEASE_6)
|
|
||||||
public class ConstantInitializerAnnotationProcessor extends AbstractProcessor {
|
|
||||||
|
|
||||||
// https://github.com/corgrath/abandoned-Requires-Static-Method-Annotation
|
|
||||||
private static final String METHOD_NAME = "initConstants";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
|
||||||
Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(ConstantInitializer.class);
|
|
||||||
for (Element element : elements) {
|
|
||||||
final Optional<? extends Element> result = element.getEnclosedElements().stream()
|
|
||||||
.filter(e -> e.getKind() == ElementKind.METHOD)
|
|
||||||
.filter(m -> m.getSimpleName().contentEquals(METHOD_NAME))
|
|
||||||
.filter(m -> m.getModifiers().containsAll(Arrays.asList(Modifier.PUBLIC, Modifier.STATIC)))
|
|
||||||
.filter(m -> m.asType().accept(visitor, null))
|
|
||||||
.findFirst();
|
|
||||||
if (result.isPresent()) {
|
|
||||||
showError(element);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showError(Element element) {
|
|
||||||
final String message = String.format("Class %s requires a method"
|
|
||||||
+ " `public static void %s() {}`", element.getSimpleName(), METHOD_NAME);
|
|
||||||
processingEnv.getMessager().printMessage(Kind.ERROR, message, element);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final SimpleTypeVisitor6<Boolean, Void> visitor = new SimpleTypeVisitor6<Boolean, Void>() {
|
|
||||||
@Override
|
|
||||||
public Boolean visitExecutable(ExecutableType t, Void v) {
|
|
||||||
if (t.getReturnType().getKind() != TypeKind.VOID) return false;
|
|
||||||
if (!t.getParameterTypes().isEmpty()) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,6 +1,7 @@
|
|||||||
package com.annimon.ownlang.parser.ast;
|
package com.annimon.ownlang.parser.ast;
|
||||||
|
|
||||||
import com.annimon.ownlang.lib.modules.Module;
|
import com.annimon.ownlang.lib.modules.Module;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -9,6 +10,7 @@ import com.annimon.ownlang.lib.modules.Module;
|
|||||||
public final class UseStatement extends InterruptableNode implements Statement {
|
public final class UseStatement extends InterruptableNode implements Statement {
|
||||||
|
|
||||||
private static final String PACKAGE = "com.annimon.ownlang.lib.modules.";
|
private static final String PACKAGE = "com.annimon.ownlang.lib.modules.";
|
||||||
|
private static final String INIT_CONSTANTS_METHOD = "initConstants";
|
||||||
|
|
||||||
public final Expression expression;
|
public final Expression expression;
|
||||||
|
|
||||||
@ -28,6 +30,18 @@ public final class UseStatement extends InterruptableNode implements Statement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void loadConstants() {
|
||||||
|
try {
|
||||||
|
final String moduleName = expression.eval().asString();
|
||||||
|
final Class<?> moduleClass = Class.forName(PACKAGE + moduleName);
|
||||||
|
final Method method = moduleClass.getMethod(INIT_CONSTANTS_METHOD);
|
||||||
|
if (method != null) {
|
||||||
|
method.invoke(this);
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accept(Visitor visitor) {
|
public void accept(Visitor visitor) {
|
||||||
visitor.visit(this);
|
visitor.visit(this);
|
||||||
|
@ -23,7 +23,7 @@ public class ConstantPropagation extends OptimizationVisitor<Map<String, Value>>
|
|||||||
public Node optimize(Node node) {
|
public Node optimize(Node node) {
|
||||||
final Map<String, VariableInfo> variables = new HashMap<>();
|
final Map<String, VariableInfo> variables = new HashMap<>();
|
||||||
// Find variables
|
// Find variables
|
||||||
node.accept(new VariablesGrabber(), variables);
|
node.accept(new VariablesGrabber(true), variables);
|
||||||
// Filter only string/number values with 1 modification
|
// Filter only string/number values with 1 modification
|
||||||
final Map<String, Value> candidates = new HashMap<>();
|
final Map<String, Value> candidates = new HashMap<>();
|
||||||
for (Map.Entry<String, VariableInfo> e : variables.entrySet()) {
|
for (Map.Entry<String, VariableInfo> e : variables.entrySet()) {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package com.annimon.ownlang.parser.optimization;
|
package com.annimon.ownlang.parser.optimization;
|
||||||
|
|
||||||
|
import com.annimon.ownlang.lib.Value;
|
||||||
|
import com.annimon.ownlang.lib.Variables;
|
||||||
import com.annimon.ownlang.parser.ast.Accessible;
|
import com.annimon.ownlang.parser.ast.Accessible;
|
||||||
import com.annimon.ownlang.parser.ast.Argument;
|
import com.annimon.ownlang.parser.ast.Argument;
|
||||||
import com.annimon.ownlang.parser.ast.AssignmentExpression;
|
import com.annimon.ownlang.parser.ast.AssignmentExpression;
|
||||||
@ -11,6 +13,7 @@ import com.annimon.ownlang.parser.ast.FunctionDefineStatement;
|
|||||||
import com.annimon.ownlang.parser.ast.MatchExpression;
|
import com.annimon.ownlang.parser.ast.MatchExpression;
|
||||||
import com.annimon.ownlang.parser.ast.Node;
|
import com.annimon.ownlang.parser.ast.Node;
|
||||||
import com.annimon.ownlang.parser.ast.UnaryExpression;
|
import com.annimon.ownlang.parser.ast.UnaryExpression;
|
||||||
|
import com.annimon.ownlang.parser.ast.UseStatement;
|
||||||
import com.annimon.ownlang.parser.ast.ValueExpression;
|
import com.annimon.ownlang.parser.ast.ValueExpression;
|
||||||
import com.annimon.ownlang.parser.ast.VariableExpression;
|
import com.annimon.ownlang.parser.ast.VariableExpression;
|
||||||
import static com.annimon.ownlang.parser.visitors.VisitorUtils.isValue;
|
import static com.annimon.ownlang.parser.visitors.VisitorUtils.isValue;
|
||||||
@ -21,11 +24,25 @@ import java.util.Map;
|
|||||||
public class VariablesGrabber extends OptimizationVisitor<Map<String, VariableInfo>> {
|
public class VariablesGrabber extends OptimizationVisitor<Map<String, VariableInfo>> {
|
||||||
|
|
||||||
public static Map<String, VariableInfo> getInfo(Node node) {
|
public static Map<String, VariableInfo> getInfo(Node node) {
|
||||||
|
return getInfo(node, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<String, VariableInfo> getInfo(Node node, boolean grabModuleConstants) {
|
||||||
Map<String, VariableInfo> variableInfos = new HashMap<>();
|
Map<String, VariableInfo> variableInfos = new HashMap<>();
|
||||||
node.accept(new VariablesGrabber(), variableInfos);
|
node.accept(new VariablesGrabber(grabModuleConstants), variableInfos);
|
||||||
return variableInfos;
|
return variableInfos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final boolean grabModuleConstants;
|
||||||
|
|
||||||
|
public VariablesGrabber() {
|
||||||
|
this(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public VariablesGrabber(boolean grabModuleConstants) {
|
||||||
|
this.grabModuleConstants = grabModuleConstants;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Node visit(AssignmentExpression s, Map<String, VariableInfo> t) {
|
public Node visit(AssignmentExpression s, Map<String, VariableInfo> t) {
|
||||||
if (!isVariable((Node)s.target)) {
|
if (!isVariable((Node)s.target)) {
|
||||||
@ -99,6 +116,27 @@ public class VariablesGrabber extends OptimizationVisitor<Map<String, VariableIn
|
|||||||
return super.visit(s, t);
|
return super.visit(s, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node visit(UseStatement s, Map<String, VariableInfo> t) {
|
||||||
|
if (grabModuleConstants) {
|
||||||
|
// To get module variables we need to store current variables, clear all, then load module.
|
||||||
|
final Map<String, Value> currentVariables = new HashMap<>(Variables.variables());
|
||||||
|
Variables.variables().clear();
|
||||||
|
if (isValue(s.expression)) {
|
||||||
|
s.loadConstants();
|
||||||
|
}
|
||||||
|
// Grab module variables
|
||||||
|
for (Map.Entry<String, Value> entry : Variables.variables().entrySet()) {
|
||||||
|
final VariableInfo var = variableInfo(t, entry.getKey());
|
||||||
|
var.value = entry.getValue();
|
||||||
|
t.put(entry.getKey(), var);
|
||||||
|
}
|
||||||
|
// Restore previous variables
|
||||||
|
Variables.variables().putAll(currentVariables);
|
||||||
|
}
|
||||||
|
return super.visit(s, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private VariableInfo variableInfo(Map<String, VariableInfo> t, final String variableName) {
|
private VariableInfo variableInfo(Map<String, VariableInfo> t, final String variableName) {
|
||||||
|
Loading…
Reference in New Issue
Block a user