composition better than inheritance

This commit is contained in:
rusefillc 2021-10-16 21:01:30 -04:00
parent e6973e2446
commit 315ae3d982
3 changed files with 67 additions and 57 deletions

View File

@ -12,6 +12,7 @@ import com.rusefi.util.LazyFile;
import com.rusefi.util.SystemOut; import com.rusefi.util.SystemOut;
import org.antlr.v4.runtime.*; import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.ParseTree; import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeListener;
import org.antlr.v4.runtime.tree.ParseTreeWalker; import org.antlr.v4.runtime.tree.ParseTreeWalker;
import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.Yaml;
@ -252,18 +253,18 @@ public class ConfigDefinition {
// Parse the input files // Parse the input files
{ {
ParseState listener = new ParseState(state.enumsReader); ParseState parseState = new ParseState(state.enumsReader);
// First process yaml files // First process yaml files
//processYamls(listener, yamlFiles); //processYamls(listener, yamlFiles);
// Process firing order enum // Process firing order enum
handleFiringOrder(firingEnumFileName, listener); handleFiringOrder(firingEnumFileName, parseState);
// Load prepend files // Load prepend files
{ {
// Ignore duplicates of definitions made during prepend phase // Ignore duplicates of definitions made during prepend phase
listener.setDefinitionPolicy(Definition.OverwritePolicy.IgnoreNew); parseState.setDefinitionPolicy(Definition.OverwritePolicy.IgnoreNew);
//for (String prependFile : prependFiles) { //for (String prependFile : prependFiles) {
// TODO: fix signature define file parsing // TODO: fix signature define file parsing
@ -274,8 +275,8 @@ public class ConfigDefinition {
// Now load the main config file // Now load the main config file
{ {
// don't allow duplicates in the main file // don't allow duplicates in the main file
listener.setDefinitionPolicy(Definition.OverwritePolicy.NotAllowed); parseState.setDefinitionPolicy(Definition.OverwritePolicy.NotAllowed);
parseFile(listener, definitionInputFile); parseFile(parseState.getListener(), definitionInputFile);
} }
// Write C structs // Write C structs
@ -635,7 +636,7 @@ public class ConfigDefinition {
} }
} }
private static void parseFile(ParseState listener, String filePath) throws IOException { private static void parseFile(ParseTreeListener listener, String filePath) throws IOException {
SystemOut.println("Parsing file (Antlr) " + filePath); SystemOut.println("Parsing file (Antlr) " + filePath);
CharStream in = new ANTLRInputStream(new FileInputStream(filePath)); CharStream in = new ANTLRInputStream(new FileInputStream(filePath));

View File

@ -6,6 +6,7 @@ import com.rusefi.generated.RusefiConfigGrammarBaseListener;
import com.rusefi.generated.RusefiConfigGrammarParser; import com.rusefi.generated.RusefiConfigGrammarParser;
import com.rusefi.newparse.parsing.*; import com.rusefi.newparse.parsing.*;
import jdk.nashorn.internal.runtime.regexp.joni.constants.StringType; import jdk.nashorn.internal.runtime.regexp.joni.constants.StringType;
import org.antlr.v4.runtime.tree.ParseTreeListener;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.io.PrintStream; import java.io.PrintStream;
@ -13,13 +14,22 @@ import java.util.*;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class ParseState extends RusefiConfigGrammarBaseListener { public class ParseState {
private final Map<String, Definition> definitions = new HashMap<>(); private final Map<String, Definition> definitions = new HashMap<>();
private final Map<String, Struct> structs = new HashMap<>(); private final Map<String, Struct> structs = new HashMap<>();
private final List<Struct> structList = new ArrayList<>(); private final List<Struct> structList = new ArrayList<>();
private final Map<String, Typedef> typedefs = new HashMap<>(); private final Map<String, Typedef> typedefs = new HashMap<>();
private static final Pattern CHAR_LITERAL = Pattern.compile("'.'");
private final EnumsReader enumsReader; private final EnumsReader enumsReader;
private Definition.OverwritePolicy definitionOverwritePolicy = Definition.OverwritePolicy.NotAllowed;
private String typedefName = null;
private final Queue<Double> evalResults = new LinkedList<>();
private Scope scope = null;
private final Stack<Scope> scopes = new Stack<>();
private Struct lastStruct = null;
public ParseState(EnumsReader enumsReader) { public ParseState(EnumsReader enumsReader) {
this.enumsReader = enumsReader; this.enumsReader = enumsReader;
@ -34,6 +44,10 @@ public class ParseState extends RusefiConfigGrammarBaseListener {
} }
} }
public Struct getLastStruct() {
return lastStruct;
}
private String[] resolveEnumValues(String enumName) { private String[] resolveEnumValues(String enumName) {
TreeMap<Integer, String> valueNameById = new TreeMap<>(); TreeMap<Integer, String> valueNameById = new TreeMap<>();
@ -67,32 +81,12 @@ public class ParseState extends RusefiConfigGrammarBaseListener {
return structList; return structList;
} }
class Scope { public Definition findDefinition(String name) {
public List<Field> structFields = new ArrayList<>(); return definitions.getOrDefault(name, null);
}
Scope scope = null;
Stack<Scope> scopes = new Stack<>();
@Override
public void exitContent(RusefiConfigGrammarParser.ContentContext ctx) {
assert(this.scopes.empty());
assert(this.scope == null);
assert(this.typedefName == null);
assert(evalResults.isEmpty());
assert(evalStack.empty());
}
private Definition.OverwritePolicy definitionOverwritePolicy = Definition.OverwritePolicy.NotAllowed;
private void addDefinition(String name, Object value) {
addDefinition(name, value, this.definitionOverwritePolicy);
} }
public void addDefinition(String name, Object value, Definition.OverwritePolicy overwritePolicy) { public void addDefinition(String name, Object value, Definition.OverwritePolicy overwritePolicy) {
Definition existingDefinition = this.definitions.getOrDefault(name, null); Definition existingDefinition = definitions.getOrDefault(name, null);
if (existingDefinition != null) { if (existingDefinition != null) {
switch (existingDefinition.overwritePolicy) { switch (existingDefinition.overwritePolicy) {
@ -109,15 +103,32 @@ public class ParseState extends RusefiConfigGrammarBaseListener {
definitions.put(name, new Definition(name, value, overwritePolicy)); definitions.put(name, new Definition(name, value, overwritePolicy));
} }
public Definition findDefinition(String name) { private void addDefinition(String name, Object value) {
return this.definitions.getOrDefault(name, null); addDefinition(name, value, definitionOverwritePolicy);
} }
public void setDefinitionPolicy(Definition.OverwritePolicy policy) { public void setDefinitionPolicy(Definition.OverwritePolicy policy) {
this.definitionOverwritePolicy = policy; this.definitionOverwritePolicy = policy;
} }
private static final Pattern CHAR_LITERAL = Pattern.compile("'.'"); public ParseTreeListener getListener() {
return new RusefiConfigGrammarBaseListener() {
@Override
public void exitContent(RusefiConfigGrammarParser.ContentContext ctx) {
if (!scopes.empty())
throw new IllegalStateException();
if (scope != null)
throw new IllegalStateException();
if (typedefName != null)
throw new IllegalStateException();
if (!evalResults.isEmpty())
throw new IllegalStateException();
if (!evalStack.empty())
throw new IllegalStateException();
}
private void handleIntDefinition(String name, int value) { private void handleIntDefinition(String name, int value) {
addDefinition(name, value); addDefinition(name, value);
@ -135,7 +146,7 @@ public class ParseState extends RusefiConfigGrammarBaseListener {
} else if (ctx.floatNum() != null) { } else if (ctx.floatNum() != null) {
addDefinition(name, Double.parseDouble(ctx.floatNum().getText())); addDefinition(name, Double.parseDouble(ctx.floatNum().getText()));
} else if (ctx.numexpr() != null) { } else if (ctx.numexpr() != null) {
double evalResult = this.evalResults.remove(); double evalResult = evalResults.remove();
double floored = Math.floor(evalResult); double floored = Math.floor(evalResult);
if (Math.abs(floored - evalResult) < 0.001) { if (Math.abs(floored - evalResult) < 0.001) {
@ -157,16 +168,14 @@ public class ParseState extends RusefiConfigGrammarBaseListener {
} }
} }
String typedefName = null;
@Override @Override
public void enterTypedef(RusefiConfigGrammarParser.TypedefContext ctx) { public void enterTypedef(RusefiConfigGrammarParser.TypedefContext ctx) {
this.typedefName = ctx.identifier().getText(); typedefName = ctx.identifier().getText();
} }
@Override @Override
public void exitTypedef(RusefiConfigGrammarParser.TypedefContext ctx) { public void exitTypedef(RusefiConfigGrammarParser.TypedefContext ctx) {
this.typedefName = null; typedefName = null;
} }
@Override @Override
@ -176,7 +185,7 @@ public class ParseState extends RusefiConfigGrammarBaseListener {
FieldOptions options = new FieldOptions(); FieldOptions options = new FieldOptions();
handleFieldOptionsList(options, ctx.fieldOptionsList()); handleFieldOptionsList(options, ctx.fieldOptionsList());
typedefs.put(this.typedefName, new ScalarTypedef(this.typedefName, datatype, options)); typedefs.put(typedefName, new ScalarTypedef(typedefName, datatype, options));
} }
@Override @Override
@ -196,7 +205,7 @@ public class ParseState extends RusefiConfigGrammarBaseListener {
defName = defName.substring(0, defName.length() - 10); defName = defName.substring(0, defName.length() - 10);
values = resolveEnumValues(defName); values = resolveEnumValues(defName);
} else { } else {
Definition def = this.definitions.get(defName); Definition def = definitions.get(defName);
if (def == null) { if (def == null) {
throw new RuntimeException("couldn't find definition for " + rhs); throw new RuntimeException("couldn't find definition for " + rhs);
@ -219,7 +228,7 @@ public class ParseState extends RusefiConfigGrammarBaseListener {
.toArray(n -> new String[n]); // Convert back to array .toArray(n -> new String[n]); // Convert back to array
} }
typedefs.put(this.typedefName, new EnumTypedef(this.typedefName, datatype, endBit, values)); typedefs.put(typedefName, new EnumTypedef(typedefName, datatype, endBit, values));
} }
@Override @Override
@ -229,14 +238,14 @@ public class ParseState extends RusefiConfigGrammarBaseListener {
FieldOptions options = new FieldOptions(); FieldOptions options = new FieldOptions();
handleFieldOptionsList(options, ctx.fieldOptionsList()); handleFieldOptionsList(options, ctx.fieldOptionsList());
typedefs.put(this.typedefName, new ArrayTypedef(this.typedefName, this.arrayDim, datatype, options)); typedefs.put(typedefName, new ArrayTypedef(ParseState.this.typedefName, this.arrayDim, datatype, options));
} }
@Override @Override
public void exitStringTypedefSuffix(RusefiConfigGrammarParser.StringTypedefSuffixContext ctx) { public void exitStringTypedefSuffix(RusefiConfigGrammarParser.StringTypedefSuffixContext ctx) {
Double stringLength = this.evalResults.remove(); Double stringLength = ParseState.this.evalResults.remove();
this.typedefs.put(this.typedefName, new StringTypedef(this.typedefName, stringLength.intValue())); ParseState.this.typedefs.put(ParseState.this.typedefName, new StringTypedef(ParseState.this.typedefName, stringLength.intValue()));
} }
@Override @Override
@ -428,14 +437,14 @@ public class ParseState extends RusefiConfigGrammarBaseListener {
// iterate required for structs // iterate required for structs
assert(iterate); assert(iterate);
scope.structFields.add(new ArrayField<StructField>(new StructField(structs.get(type), name), length, iterate)); scope.structFields.add(new ArrayField<>(new StructField(structs.get(type), name), length, iterate));
return; return;
} }
// Check first if we have a typedef for this type // Check first if we have a typedef for this type
Typedef typedef = this.typedefs.get(type); Typedef typedef = typedefs.get(type);
FieldOptions options = null; FieldOptions options;
if (typedef != null) { if (typedef != null) {
if (typedef instanceof ScalarTypedef) { if (typedef instanceof ScalarTypedef) {
ScalarTypedef scTypedef = (ScalarTypedef) typedef; ScalarTypedef scTypedef = (ScalarTypedef) typedef;
@ -501,12 +510,6 @@ public class ParseState extends RusefiConfigGrammarBaseListener {
scope.structFields.add(new UnusedField(Integer.parseInt(ctx.integer().getText()))); scope.structFields.add(new UnusedField(Integer.parseInt(ctx.integer().getText())));
} }
private Struct lastStruct = null;
public Struct getLastStruct() {
return lastStruct;
}
@Override @Override
public void exitStruct(RusefiConfigGrammarParser.StructContext ctx) { public void exitStruct(RusefiConfigGrammarParser.StructContext ctx) {
String structName = ctx.identifier().getText(); String structName = ctx.identifier().getText();
@ -559,12 +562,12 @@ public class ParseState extends RusefiConfigGrammarBaseListener {
// Strip any @@ symbols // Strip any @@ symbols
String defName = ctx.getText().replaceAll("@", ""); String defName = ctx.getText().replaceAll("@", "");
if (!this.definitions.containsKey(defName)) { if (!definitions.containsKey(defName)) {
throw new RuntimeException("Definition not found for " + ctx.getText()); throw new RuntimeException("Definition not found for " + ctx.getText());
} }
// Find the matching definition and push on to the eval stack // Find the matching definition and push on to the eval stack
Definition def = this.definitions.get(defName); Definition def = definitions.get(defName);
if (!def.isNumeric()) { if (!def.isNumeric()) {
throw new RuntimeException("Tried to use symbol " + defName + " in an expression, but it wasn't a number"); throw new RuntimeException("Tried to use symbol " + defName + " in an expression, but it wasn't a number");
@ -605,11 +608,16 @@ public class ParseState extends RusefiConfigGrammarBaseListener {
evalStack.push(left - right); evalStack.push(left - right);
} }
private Queue<Double> evalResults = new LinkedList<>();
@Override @Override
public void exitNumexpr(RusefiConfigGrammarParser.NumexprContext ctx) { public void exitNumexpr(RusefiConfigGrammarParser.NumexprContext ctx) {
assert(evalStack.size() == 1); assert(evalStack.size() == 1);
evalResults.add(evalStack.pop()); evalResults.add(evalStack.pop());
} }
};
};
static class Scope {
public List<Field> structFields = new ArrayList<>();
}
} }

View File

@ -27,6 +27,7 @@ public enum Type {
} }
public static Optional<Type> findByCtype(String cType) { public static Optional<Type> findByCtype(String cType) {
// todo: better implementation of type aliases!
String cTypeWithAlas = "floatms_t".equals(cType) ? "float" : cType; String cTypeWithAlas = "floatms_t".equals(cType) ? "float" : cType;
return Arrays.stream(Type.values()).filter(t -> t.cType.equals(cTypeWithAlas)).findFirst(); return Arrays.stream(Type.values()).filter(t -> t.cType.equals(cTypeWithAlas)).findFirst();
} }