Enums: Make EnumDefinition use EnumValues instead of Strings as children.
This allows us to store the index of the enum value along the name. The index can be used to compare two enum values in assembler. Later on this might be used to enable users of KLang to set arbitrary values as the index of an enum value.
This commit is contained in:
@@ -355,7 +355,7 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var enumValueName = path.get(0);
|
var enumValueName = path.get(0);
|
||||||
if (Arrays.stream(enumDef.enums).noneMatch(e -> e.equals(enumValueName))) {
|
if (Arrays.stream(enumDef.enums).noneMatch(e -> e.value.equals(enumValueName))) {
|
||||||
var error = "Unknown enum value " + enumValueName + " of enum " + enumDef.name + ".";
|
var error = "Unknown enum value " + enumValueName + " of enum " + enumDef.name + ".";
|
||||||
throw new RuntimeException(Helper.getErrorPrefix(line, col) + error);
|
throw new RuntimeException(Helper.getErrorPrefix(line, col) + error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,20 +107,26 @@ public class GetDefinitions extends KlangBaseVisitor<Node> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IDENT() includes the enumName as the first entry, which we skip
|
// IDENT() includes the enumName as the first entry, which we skip
|
||||||
var enumFields = new LinkedHashSet<String>();
|
var enumValues = new LinkedHashMap<String, EnumValue>();
|
||||||
for (int i = 1; i < ctx.IDENT().size(); i++) {
|
for (int i = 1; i < ctx.IDENT().size(); i++) {
|
||||||
var currentEnumField = ctx.IDENT(i);
|
var currentEnumField = ctx.IDENT(i);
|
||||||
var currentEnumFieldName = currentEnumField.getText();
|
var currentEnumFieldName = currentEnumField.getText();
|
||||||
if (enumFields.contains(currentEnumFieldName)) {
|
var line = currentEnumField.getSymbol().getLine();
|
||||||
var line = currentEnumField.getSymbol().getLine();
|
var col = currentEnumField.getSymbol().getCharPositionInLine();
|
||||||
var col = currentEnumField.getSymbol().getCharPositionInLine();
|
|
||||||
|
if (enumValues.containsKey(currentEnumFieldName)) {
|
||||||
var error = " Duplicate enum value " + currentEnumFieldName + " in enum " + enumName + ".";
|
var error = " Duplicate enum value " + currentEnumFieldName + " in enum " + enumName + ".";
|
||||||
throw new RuntimeException(Helper.getErrorPrefix(line, col) + error);
|
throw new RuntimeException(Helper.getErrorPrefix(line, col) + error);
|
||||||
}
|
}
|
||||||
enumFields.add(currentEnumFieldName);
|
|
||||||
|
var enumValue = new EnumValue(currentEnumFieldName, i - 1);
|
||||||
|
enumValue.line = line;
|
||||||
|
enumValue.col = col;
|
||||||
|
|
||||||
|
enumValues.put(currentEnumFieldName, enumValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
var enumDef = new EnumDefinition(enumName, enumFields.toArray(new String[0]));
|
var enumDef = new EnumDefinition(enumName, enumValues.values().toArray(new EnumValue[0]));
|
||||||
enumDef.line = ctx.start.getLine();
|
enumDef.line = ctx.start.getLine();
|
||||||
enumDef.col = ctx.start.getCharPositionInLine();
|
enumDef.col = ctx.start.getCharPositionInLine();
|
||||||
enumDef.type = new NamedType(enumName);
|
enumDef.type = new NamedType(enumName);
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import de.hsrm.compiler.Klang.visitors.Visitor;
|
|||||||
public class EnumDefinition extends Node {
|
public class EnumDefinition extends Node {
|
||||||
|
|
||||||
public String name;
|
public String name;
|
||||||
public String[] enums;
|
public EnumValue[] enums;
|
||||||
|
|
||||||
public EnumDefinition(String name, String[] enums) {
|
public EnumDefinition(String name, EnumValue[] enums) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.enums = enums;
|
this.enums = enums;
|
||||||
}
|
}
|
||||||
|
|||||||
18
src/main/java/de/hsrm/compiler/Klang/nodes/EnumValue.java
Normal file
18
src/main/java/de/hsrm/compiler/Klang/nodes/EnumValue.java
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package de.hsrm.compiler.Klang.nodes;
|
||||||
|
|
||||||
|
import de.hsrm.compiler.Klang.visitors.Visitor;
|
||||||
|
|
||||||
|
public class EnumValue extends Node {
|
||||||
|
public String value;
|
||||||
|
public int index;
|
||||||
|
|
||||||
|
public EnumValue(String value, int index) {
|
||||||
|
this.value = value;
|
||||||
|
this.index = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <R> R welcome(Visitor<R> v) {
|
||||||
|
return v.visit(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -457,6 +457,11 @@ public class EvalVisitor implements Visitor<Value> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Value visit(EnumValue e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value visit(StructDefinition e) {
|
public Value visit(StructDefinition e) {
|
||||||
// We get these from a previous visitor
|
// We get these from a previous visitor
|
||||||
|
|||||||
@@ -779,6 +779,11 @@ public class GenASM implements Visitor<Void> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visit(EnumValue e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(StructDefinition e) {
|
public Void visit(StructDefinition e) {
|
||||||
// We get these from a previous visitor
|
// We get these from a previous visitor
|
||||||
|
|||||||
@@ -239,6 +239,11 @@ class GetVars implements Visitor<Void> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visit(EnumValue e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(StructDefinition e) {
|
public Void visit(StructDefinition e) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -387,18 +387,24 @@ public class PrettyPrintVisitor implements Visitor<Void> {
|
|||||||
public Void visit(EnumDefinition e) {
|
public Void visit(EnumDefinition e) {
|
||||||
ex.write("enum " + e.name + " { ");
|
ex.write("enum " + e.name + " { ");
|
||||||
var first = true;
|
var first = true;
|
||||||
for(var enumName: e.enums) {
|
for(var enumValue: e.enums) {
|
||||||
if (!first) {
|
if (!first) {
|
||||||
ex.write(", ");
|
ex.write(", ");
|
||||||
} else {
|
} else {
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
ex.write(enumName);
|
enumValue.welcome(this);
|
||||||
}
|
}
|
||||||
ex.write(" }");
|
ex.write(" }");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visit(EnumValue e) {
|
||||||
|
ex.write(e.value);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(StructDefinition e) {
|
public Void visit(StructDefinition e) {
|
||||||
ex.write("struct " + e.name + " {");
|
ex.write("struct " + e.name + " {");
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ public interface Visitor<R> {
|
|||||||
R visit(Program e);
|
R visit(Program e);
|
||||||
R visit(Parameter e);
|
R visit(Parameter e);
|
||||||
R visit(EnumDefinition e);
|
R visit(EnumDefinition e);
|
||||||
|
R visit(EnumValue e);
|
||||||
R visit(StructDefinition e);
|
R visit(StructDefinition e);
|
||||||
R visit(StructField e);
|
R visit(StructField e);
|
||||||
R visit(MemberAccessExpression e);
|
R visit(MemberAccessExpression e);
|
||||||
|
|||||||
Reference in New Issue
Block a user