Skip to content

Commit

Permalink
for loop tuples now work
Browse files Browse the repository at this point in the history
  • Loading branch information
davydotcom committed Feb 13, 2024
1 parent f9aed6c commit c143855
Show file tree
Hide file tree
Showing 7 changed files with 308 additions and 51 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ Using gradle one can include the hcl4j dependency like so:

```groovy
dependencies {
compile "com.bertramlabs.plugins:hcl4j:0.7.7"
compile "com.bertramlabs.plugins:hcl4j:0.8.0"
}
```

## What's New

* **0.8.0** HCL For Loop Tuples now evaluated.
* **0.7.7** HCL Periods in attribute names referenced from Unicodes ID_Continue, fixed.
* **0.7.6** SLF4j 1.7.36 upgrade to reduce CVE's
* **0.7.5** For Tuple with boolean conditionals as value expression did not work before
Expand Down Expand Up @@ -62,6 +63,6 @@ For More Information on the HCL Syntax Please see the project page:

## Things to be Done

* for tuples and objects are processed but not evaluated
* for loop objects are processed but not evaluated
* add more method definitions for base terraform functions
* add handlers for data lookup modules
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ ext {


group = 'com.bertramlabs.plugins'
version = '0.7.7'
version = '0.8.0'

ext.isReleaseVersion = !version.endsWith("SNAPSHOT")
sourceCompatibility = "1.8"
Expand Down
200 changes: 188 additions & 12 deletions src/main/java/com/bertramlabs/plugins/hcl4j/HCLParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,9 @@ private Object processSymbolPass2(Object val, Map<String,Object> mapPosition) th
}

private Object processSymbol(Symbol symbol, Map<String,Object> mapPosition) throws HCLParserException {
return processSymbol(symbol,mapPosition,null);
}
private Object processSymbol(Symbol symbol, Map<String,Object> mapPosition, Map<String,Object> stackVars) throws HCLParserException {

if(symbol instanceof HCLBlock) {
HCLBlock block = (HCLBlock)symbol;
Expand Down Expand Up @@ -736,7 +739,7 @@ private Object processSymbol(Symbol symbol, Map<String,Object> mapPosition) thro
}
if(symbol.getChildren() != null) {
for(Symbol child : block.getChildren()) {
processSymbol(child,mapPosition);
processSymbol(child,mapPosition,stackVars);
}
}
return mapPosition;
Expand Down Expand Up @@ -765,8 +768,8 @@ private Object processSymbol(Symbol symbol, Map<String,Object> mapPosition) thro
} else if(symbol instanceof PrimitiveType) {
return symbol;
} else if(symbol instanceof EvalSymbol) {
return processEvaluation((EvalSymbol) symbol,null);
} else if(symbol instanceof HCLAttribute || symbol instanceof GroupedExpression) {
return processEvaluation((EvalSymbol) symbol,null,stackVars);
} else if(symbol instanceof HCLAttribute || symbol instanceof GroupedExpression || symbol instanceof StringInterpolatedExpression) {
Map<String,Object> nestedMap = new LinkedHashMap<>();
if(symbol.getChildren().size() > 0) {
Object results = null;
Expand All @@ -776,14 +779,14 @@ private Object processSymbol(Symbol symbol, Map<String,Object> mapPosition) thro
switch(child.getName()) {
case "+":
if(results instanceof String) {
Object rightResult = processSymbol(symbol.getChildren().get(++x),nestedMap);
Object rightResult = processSymbol(symbol.getChildren().get(++x),nestedMap,stackVars);
if(rightResult != null) {
results = (String)results + rightResult.toString();
} else {
//TODO: Exception?
}
} else if(results instanceof Double) {
Object rightResult = processSymbol(symbol.getChildren().get(++x),nestedMap);
Object rightResult = processSymbol(symbol.getChildren().get(++x),nestedMap,stackVars);
if(rightResult != null && rightResult instanceof Double) {
results = (Double)results + (Double)rightResult;
} else {
Expand All @@ -794,7 +797,7 @@ private Object processSymbol(Symbol symbol, Map<String,Object> mapPosition) thro
break;
case "-":
if(results instanceof Double) {
Object rightResult = processSymbol(symbol.getChildren().get(++x),nestedMap);
Object rightResult = processSymbol(symbol.getChildren().get(++x),nestedMap,stackVars);
if(rightResult != null && rightResult instanceof Double) {
results = (Double)results - (Double)rightResult;
} else {
Expand All @@ -804,7 +807,7 @@ private Object processSymbol(Symbol symbol, Map<String,Object> mapPosition) thro
break;
case "/":
if(results instanceof Double) {
Object rightResult = processSymbol(symbol.getChildren().get(++x),nestedMap);
Object rightResult = processSymbol(symbol.getChildren().get(++x),nestedMap,stackVars);
if(rightResult != null && rightResult instanceof Double) {
results = (Double)results / (Double)rightResult;
} else {
Expand All @@ -814,21 +817,91 @@ private Object processSymbol(Symbol symbol, Map<String,Object> mapPosition) thro
break;
case "*":
if(results instanceof Double) {
Object rightResult = processSymbol(symbol.getChildren().get(++x),nestedMap);
Object rightResult = processSymbol(symbol.getChildren().get(++x),nestedMap,stackVars);
if(rightResult != null && rightResult instanceof Double) {
results = (Double)results * (Double)rightResult;
} else {
//TODO: Exception?
}
}
break;
case "?":
//if left side of result is false we need to skip between the ? and the :
if(results instanceof Boolean && !((Boolean) results) || results == null ) {
//skip children until ":" operator
Symbol nextElement = symbol.getChildren().get(++x);
while(!(nextElement instanceof Operator) && nextElement.getName() != ":") {
nextElement = symbol.getChildren().get(++x);
}
}
break;
case ":":
//if we got to a colon operator then we need to skip everything after it as its processed with the ? operator above
x = symbol.getChildren().size();
break;
case "!=":
Object compareResult2 = processSymbol(symbol.getChildren().get(++x),nestedMap,stackVars);
if(compareResult2 != results && (compareResult2 == null || !compareResult2.equals(results))) {
results = true;
} else {
results = false;
}
break;
case "==":
Object compareResult = processSymbol(symbol.getChildren().get(++x),nestedMap,stackVars);
if(compareResult == results || (compareResult != null && compareResult.equals(results))) {
results = true;
} else {
results = false;
}
break;
case ">":
if(results instanceof Double) {
Object rightResult = processSymbol(symbol.getChildren().get(++x),nestedMap,stackVars);
if(rightResult != null && rightResult instanceof Double) {
results = ((Double)results > (Double)rightResult);
} else {
//TODO: Exception?
}
}
break;
case ">=":
if(results instanceof Double) {
Object rightResult = processSymbol(symbol.getChildren().get(++x),nestedMap,stackVars);
if(rightResult != null && rightResult instanceof Double) {
results = ((Double)results >= (Double)rightResult);
} else {
//TODO: Exception?
}
}
break;
case "<":
if(results instanceof Double) {
Object rightResult = processSymbol(symbol.getChildren().get(++x),nestedMap,stackVars);
if(rightResult != null && rightResult instanceof Double) {
results = ((Double)results < (Double)rightResult);
} else {
//TODO: Exception?
}
}
break;
case "<=":
if(results instanceof Double) {
Object rightResult = processSymbol(symbol.getChildren().get(++x),nestedMap,stackVars);
if(rightResult != null && rightResult instanceof Double) {
results = ((Double)results <= (Double)rightResult);
} else {
//TODO: Exception?
}
}
break;
}
} else {
results = processSymbol(symbol.getChildren().get(0),nestedMap);
results = processSymbol(symbol.getChildren().get(0),nestedMap,stackVars);
}
}

if(symbol instanceof GroupedExpression) {
if(symbol instanceof GroupedExpression || symbol instanceof StringInterpolatedExpression) {
return results;
} else {
mapPosition.put(symbol.getName(),results);
Expand Down Expand Up @@ -894,6 +967,80 @@ protected Object evaluateFunctionCall(String functionName,Function functionSymbo
}
}


protected Object evaluateComputedTuple(ComputedTuple thisTuple) throws HCLParserException {
// System.out.println("Evaluating Tuple");
ArrayList computedResult = new ArrayList();
Variable indexVariable = null;
Variable valueVariable = null;
if(thisTuple.getVariables().size() == 2) {
//variables with index

indexVariable = thisTuple.getVariables().get(0);
valueVariable = thisTuple.getVariables().get(1);
} else if(thisTuple.getVariables().size() == 1) {
valueVariable = thisTuple.getVariables().get(0);
} else {
log.warn("Computed Tuple loop found with too many variables at line {}",thisTuple.getLine());
return null;
}
ForConditional tupleConditional = null;
for(Symbol child : thisTuple.getChildren()) {
if(child instanceof ForConditional) {
tupleConditional = (ForConditional) child;
thisTuple.getChildren().remove(child);
break;
}
}
Object elementResult = null;
Boolean forSourceFound=false;
GroupedExpression sourceExpression = new GroupedExpression(0,0,0);
GroupedExpression iteratorExpression = new GroupedExpression(0,0,0);
for(Symbol child : thisTuple.getChildren()) {
if(child instanceof ForSource) {
forSourceFound = true;
continue;
}
if(forSourceFound) {
iteratorExpression.appendChild(child);
} else {
sourceExpression.appendChild(child);
}

}
if(sourceExpression.getChildren().size() > 0 && iteratorExpression.getChildren().size() > 0) {
elementResult = processSymbol(sourceExpression,result);
if(elementResult instanceof List) {
List elementResultList = (List)elementResult;
System.out.println("Iterating over list");
for(int counter=0;counter < elementResultList.size();counter++){
Map<String,Object> stackVars = new LinkedHashMap<>();
if(indexVariable != null) {
stackVars.put(indexVariable.getName(),counter);
}
stackVars.put(valueVariable.getName(),elementResultList.get(counter));
if(tupleConditional != null) {
System.out.println("Conditional Tuple Found");
Object conditionalResult = processSymbol(tupleConditional ,null,stackVars);
System.out.println("Conditional Result: " + conditionalResult);
if(conditionalResult == null || ((conditionalResult instanceof Boolean) && (Boolean) conditionalResult == false)) {
System.out.println("Does not match");
continue;
} else {
System.out.println("Matches");
}
}
computedResult.add(processSymbol(iteratorExpression,null,stackVars));
System.out.println("Computed Result: " + computedResult);
}
} else {
log.error("Error Processing Tuple from source not a List");
return computedResult;
}
}
return computedResult;
}

protected Map<String,Object> evaluateDataLookup(String lookupName,String name,Map<String,Object> properties) throws HCLParserException {
if(dataLookupRegistry.get(lookupName) != null) {
try {
Expand All @@ -917,8 +1064,14 @@ protected Map<String,Object> evaluateDataLookup(String lookupName,String name,Ma
//TODO: DO we throw a method missing exception at some point
return null;
}


}

protected Object processEvaluation(EvalSymbol evalSymbol, Object context) throws HCLParserException{
return processEvaluation(evalSymbol,context,null);
}
protected Object processEvaluation(EvalSymbol evalSymbol, Object context,Map<String,Object> stackVars) throws HCLParserException{
Boolean variableLookup = false;
Boolean dataLookup = false;
String dataLookupName = null;
Expand All @@ -945,7 +1098,14 @@ protected Object processEvaluation(EvalSymbol evalSymbol, Object context) throws
context = dataLookups;
break;
default:
context = result.get(child.getName());
if(stackVars != null) {
context = stackVars.get(child.getName());
if(context == null) {
context = result.get(child.getName());
}
} else {
context = result.get(child.getName());
}
}

} else if(context != null){
Expand Down Expand Up @@ -1054,8 +1214,24 @@ else if(evalSymbol instanceof Function) {
} else {
return null;
}
} else if(evalSymbol instanceof ComputedTuple) {
//time to actually implemented a tuple loop
ComputedTuple thisTuple = (ComputedTuple) evalSymbol;
return evaluateComputedTuple(thisTuple);
}
else if(evalSymbol instanceof Variable) {
System.out.println("Evaluating Variable: " + evalSymbol.getName());
if(stackVars != null) {
context = stackVars.get(evalSymbol.getName());
if(context == null) {
context = result.get(evalSymbol.getName());
}
} else {
context = result.get(evalSymbol.getName());
}
return context;
}
else if(evalSymbol instanceof Variable || evalSymbol instanceof ComputedTuple || evalSymbol instanceof ComputedObject) {
else if(evalSymbol instanceof ComputedObject) {
return evalSymbol;
} else {
return null;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.bertramlabs.plugins.hcl4j.RuntimeSymbols;

public class ForConditional extends EvalSymbol{
public class ForConditional extends GroupedExpression{
public ForConditional(Integer line, Integer column,Integer position) {
super(null,line,column,position);
super(line,column,position);
}

public String getSymbolName() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.bertramlabs.plugins.hcl4j.RuntimeSymbols;

public class ForSource extends EvalSymbol{
public ForSource(Integer line, Integer column,Integer position) {
super(null,line,column,position);
}

public String getSymbolName() {
return "ForSource";
}
}
Loading

0 comments on commit c143855

Please sign in to comment.