Skip to content

Commit

Permalink
Update class type rewriting
Browse files Browse the repository at this point in the history
- Move bare strings / concat class type re-parsing up to keep the re-parsing logic in one location.
- Do not handle bare string/concat types as types if they do not match the type regex (do not throw "Unexpected data after ClassType" in these cases).
- Handle deeper nested bare string concats as types (e.g. `my.custom.type.with.more.than.two.concats`).
  • Loading branch information
Pieter12345 committed Apr 4, 2024
1 parent 15b5e3e commit 552f380
Showing 1 changed file with 21 additions and 47 deletions.
68 changes: 21 additions & 47 deletions src/main/java/com/laytonsmith/core/functions/Compiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -464,39 +464,24 @@ public static ParseTree rewrite(List<ParseTree> list, boolean returnSConcat,
}

// Look for typed assignments
typedAssignmentLoop: for(int k = 0; k < list.size(); k++) {
for(int k = 0; k < list.size(); k++) {
ParseTree typeNode = list.get(k);
if(typeNode.getData().equals(CVoid.VOID) || typeNode.getData().isInstanceOf(CClassType.TYPE)
|| (typeNode.getData().getClass().equals(CBareString.class))
|| (typeNode.getData() instanceof CFunction
&& typeNode.getData().val().equals(concat.NAME))) {

// If concat, ensure only CClassType or CBareString are being concatenated.
// This can be nested once: concat(concat(ms, lang), string)
if(typeNode.getData() instanceof CFunction) {
for(ParseTree concatChild : typeNode.getChildren()) {
if(concatChild.getData() instanceof CFunction) {
if(!concatChild.getData().val().equals(concat.NAME)) {
continue typedAssignmentLoop;
}
for(ParseTree innerConcatChild : concatChild.getChildren()) {
if(!innerConcatChild.getData().isInstanceOf(CClassType.TYPE)
&& !innerConcatChild.getData().getClass().equals(CBareString.class)) {
continue typedAssignmentLoop;
}
}
} else if(!concatChild.getData().isInstanceOf(CClassType.TYPE)
&& !concatChild.getData().getClass().equals(CBareString.class)) {
continue typedAssignmentLoop;
}
}
}

// Convert bare string or concat() to type reference if used like that in syntax.
ParseTree convertedTypeNode = __type_ref__.createFromBareStringOrConcats(typeNode);
ParseTree originalTypeNode = typeNode;
if(convertedTypeNode != null) {
typeNode = convertedTypeNode;
}

if(convertedTypeNode != null
|| typeNode.getData().equals(CVoid.VOID) || typeNode.getData().isInstanceOf(CClassType.TYPE)) {
if(k == list.size() - 1) {
// This is not a typed assignment
break;
//throw new ConfigCompileException("Unexpected ClassType", list.get(k).getTarget());
}

if(list.get(k + 1).getData() instanceof CFunction) {
switch(list.get(k + 1).getData().val()) {
// closure is missing from this, because "closure" is both a ClassType and a keyword,
Expand All @@ -510,13 +495,9 @@ public static ParseTree rewrite(List<ParseTree> list, boolean returnSConcat,
throw new ConfigCompileException("Variables may not be of type void",
list.get(k + 1).getTarget());
}
typeNode = list.remove(k);

// Convert bare string or concat() to type reference as it is used like that in syntax.
ParseTree typeRefNode = __type_ref__.createFromBareStringOrConcats(typeNode);
if(typeRefNode != null) {
typeNode = typeRefNode;
}
// Remove type node.
list.remove(k);

List<ParseTree> children = list.get(k).getChildren();
children.add(0, typeNode);
Expand All @@ -531,34 +512,20 @@ public static ParseTree rewrite(List<ParseTree> list, boolean returnSConcat,
} else if(list.get(k + 1).getData() instanceof IVariable) {
// Not an assignment, a random variable declaration though.
ParseTree node = new ParseTree(new CFunction(assign.NAME, list.get(k + 1).getTarget()), typeNode.getFileOptions());

// Convert bare string or concat() to type reference as it is used like that in syntax.
ParseTree typeRefNode = __type_ref__.createFromBareStringOrConcats(typeNode);
if(typeRefNode != null) {
typeNode = typeRefNode;
}

node.addChild(typeNode);
node.addChild(list.get(k + 1));
node.addChild(new ParseTree(CNull.UNDEFINED, typeNode.getFileOptions()));
list.set(k, node);
list.remove(k + 1);
} else if(list.get(k + 1).getData() instanceof CLabel) {
ParseTree node = new ParseTree(new CFunction(assign.NAME, list.get(k + 1).getTarget()), typeNode.getFileOptions());

// Convert bare string or concat() to type reference as it is used like that in syntax.
ParseTree typeRefNode = __type_ref__.createFromBareStringOrConcats(typeNode);
if(typeRefNode != null) {
typeNode = typeRefNode;
}

ParseTree labelNode = new ParseTree(new CLabel(node.getData()), typeNode.getFileOptions());
labelNode.addChild(typeNode);
labelNode.addChild(new ParseTree(((CLabel) list.get(k + 1).getData()).cVal(), typeNode.getFileOptions()));
labelNode.addChild(new ParseTree(CNull.UNDEFINED, typeNode.getFileOptions()));
list.set(k, labelNode);
list.remove(k + 1);
} else if(typeNode.getData().getClass().equals(CBareString.class)) {
} else if(originalTypeNode.getData().getClass().equals(CBareString.class)) {
continue; // Bare string was not used as a type.
} else {
throw new ConfigCompileException("Unexpected data after ClassType", list.get(k + 1).getTarget());
Expand Down Expand Up @@ -814,6 +781,13 @@ public static ParseTree createASTNode(String typeName, Target t, FileOptions fil
return node;
}

/**
* Converts already parsed AST node to a {@link __type_ref__} {@link ParseTree} node when the used syntax
* actually implies usage of a class type reference (also when the type reference cannot be resolved).
* @param typeNode - The node to convert.
* @return A {@link ParseTree} containing the resulting {@link __type_ref__},
* or {@code null} when conversion was not possible.
*/
public static ParseTree createFromBareStringOrConcats(ParseTree typeNode) {

// Convert bare string types to __type_ref__.
Expand Down

0 comments on commit 552f380

Please sign in to comment.