|
7 | 7 |
|
8 | 8 | import liquidjava.rj_language.ast.BinaryExpression; |
9 | 9 | import liquidjava.rj_language.ast.Expression; |
| 10 | +import liquidjava.rj_language.ast.FunctionInvocation; |
10 | 11 | import liquidjava.rj_language.ast.Var; |
11 | 12 |
|
12 | 13 | public class VariableResolver { |
@@ -45,33 +46,50 @@ private static void resolveRecursive(Expression exp, Map<String, Expression> map |
45 | 46 | if ("&&".equals(op)) { |
46 | 47 | resolveRecursive(be.getFirstOperand(), map); |
47 | 48 | resolveRecursive(be.getSecondOperand(), map); |
48 | | - } else if ("==".equals(op)) { |
49 | | - Expression left = be.getFirstOperand(); |
50 | | - Expression right = be.getSecondOperand(); |
51 | | - if (left instanceof Var var && right.isLiteral()) { |
52 | | - map.put(var.getName(), right.clone()); |
53 | | - } else if (right instanceof Var var && left.isLiteral()) { |
54 | | - map.put(var.getName(), left.clone()); |
55 | | - } else if (left instanceof Var leftVar && right instanceof Var rightVar) { |
56 | | - // to substitute internal variable with user-facing variable |
57 | | - if (isInternal(leftVar) && !isInternal(rightVar) && !isReturnVar(leftVar)) { |
58 | | - map.put(leftVar.getName(), right.clone()); |
59 | | - } else if (isInternal(rightVar) && !isInternal(leftVar) && !isReturnVar(rightVar)) { |
60 | | - map.put(rightVar.getName(), left.clone()); |
61 | | - } else if (isInternal(leftVar) && isInternal(rightVar)) { |
62 | | - // to substitute the lower-counter variable with the higher-counter one |
63 | | - boolean isLeftCounterLower = getCounter(leftVar) <= getCounter(rightVar); |
64 | | - Var lowerVar = isLeftCounterLower ? leftVar : rightVar; |
65 | | - Var higherVar = isLeftCounterLower ? rightVar : leftVar; |
66 | | - if (!isReturnVar(lowerVar) && !isFreshVar(higherVar)) |
67 | | - map.putIfAbsent(lowerVar.getName(), higherVar.clone()); |
68 | | - } |
69 | | - } else if (left instanceof Var var && !(right instanceof Var) && canSubstitute(var, right)) { |
70 | | - map.put(var.getName(), right.clone()); |
| 49 | + return; |
| 50 | + } |
| 51 | + if (!"==".equals(op)) |
| 52 | + return; |
| 53 | + |
| 54 | + Expression left = be.getFirstOperand(); |
| 55 | + Expression right = be.getSecondOperand(); |
| 56 | + String leftKey = substitutionKey(left); |
| 57 | + String rightKey = substitutionKey(right); |
| 58 | + |
| 59 | + if (leftKey != null && right.isLiteral()) { |
| 60 | + map.put(leftKey, right.clone()); |
| 61 | + } else if (rightKey != null && left.isLiteral()) { |
| 62 | + map.put(rightKey, left.clone()); |
| 63 | + } else if (left instanceof Var leftVar && right instanceof Var rightVar) { |
| 64 | + // to substitute internal variable with user-facing variable |
| 65 | + if (isInternal(leftVar) && !isInternal(rightVar) && !isReturnVar(leftVar)) { |
| 66 | + map.put(leftVar.getName(), right.clone()); |
| 67 | + } else if (isInternal(rightVar) && !isInternal(leftVar) && !isReturnVar(rightVar)) { |
| 68 | + map.put(rightVar.getName(), left.clone()); |
| 69 | + } else if (isInternal(leftVar) && isInternal(rightVar)) { |
| 70 | + // to substitute the lower-counter variable with the higher-counter one |
| 71 | + boolean isLeftCounterLower = getCounter(leftVar) <= getCounter(rightVar); |
| 72 | + Var lowerVar = isLeftCounterLower ? leftVar : rightVar; |
| 73 | + Var higherVar = isLeftCounterLower ? rightVar : leftVar; |
| 74 | + if (!isReturnVar(lowerVar) && !isFreshVar(higherVar)) |
| 75 | + map.putIfAbsent(lowerVar.getName(), higherVar.clone()); |
71 | 76 | } |
| 77 | + } else if (left instanceof Var var && !(right instanceof Var) && canSubstitute(var, right)) { |
| 78 | + map.put(var.getName(), right.clone()); |
| 79 | + } else if (left instanceof FunctionInvocation && !(right instanceof Var) |
| 80 | + && !right.toString().contains(leftKey)) { |
| 81 | + map.put(leftKey, right.clone()); |
72 | 82 | } |
73 | 83 | } |
74 | 84 |
|
| 85 | + private static String substitutionKey(Expression exp) { |
| 86 | + if (exp instanceof Var var) |
| 87 | + return var.getName(); |
| 88 | + if (exp instanceof FunctionInvocation) |
| 89 | + return exp.toString(); |
| 90 | + return null; |
| 91 | + } |
| 92 | + |
75 | 93 | /** |
76 | 94 | * Handles transitive variable equalities in the map (e.g. map: x -> y, y -> 1 => map: x -> 1, y -> 1) |
77 | 95 | * |
@@ -129,14 +147,22 @@ private static boolean hasUsage(Expression exp, String name) { |
129 | 147 | if (left instanceof Var v && v.getName().equals(name) |
130 | 148 | && (right.isLiteral() || (!(right instanceof Var) && canSubstitute(v, right)))) |
131 | 149 | return false; |
| 150 | + if (left instanceof FunctionInvocation && left.toString().equals(name) |
| 151 | + && (right.isLiteral() || (!(right instanceof Var) && !right.toString().contains(name)))) |
| 152 | + return false; |
132 | 153 | if (right instanceof Var v && v.getName().equals(name) && left.isLiteral()) |
133 | 154 | return false; |
| 155 | + if (right instanceof FunctionInvocation && right.toString().equals(name) && left.isLiteral()) |
| 156 | + return false; |
134 | 157 | } |
135 | 158 |
|
136 | 159 | // usage found |
137 | 160 | if (exp instanceof Var var && var.getName().equals(name)) { |
138 | 161 | return true; |
139 | 162 | } |
| 163 | + if (exp instanceof FunctionInvocation && exp.toString().equals(name)) { |
| 164 | + return true; |
| 165 | + } |
140 | 166 |
|
141 | 167 | // recurse children |
142 | 168 | if (exp.hasChildren()) { |
|
0 commit comments