Skip to content

Commit 6f0b233

Browse files
committed
Refactor validateGhostInvocations
1 parent ea9d845 commit 6f0b233

File tree

1 file changed

+49
-57
lines changed
  • liquidjava-verifier/src/main/java/liquidjava/rj_language/ast

1 file changed

+49
-57
lines changed

liquidjava-verifier/src/main/java/liquidjava/rj_language/ast/Expression.java

Lines changed: 49 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -269,76 +269,68 @@ private void auxChangeAlias(Map<String, AliasDTO> alias, Context ctx, Factory f)
269269
*/
270270
public void validateGhostInvocations(Context ctx, Factory f) throws LJError {
271271
if (this instanceof FunctionInvocation fi) {
272-
273272
// get all ghosts with the matching name
274273
List<GhostFunction> candidates = ctx.getGhosts().stream().filter(g -> g.matches(fi.name)).toList();
274+
if (candidates.isEmpty())
275+
return;
275276

276-
if (!candidates.isEmpty()) {
277-
// search for a matching overload
278-
for (GhostFunction g : candidates) {
279-
280-
// check argument count
281-
if (fi.children.size() != g.getParametersTypes().size())
282-
continue;
283-
284-
// check argument types
285-
boolean argsMatch = true;
286-
for (int i = 0; i < fi.children.size(); i++) {
287-
Expression arg = fi.children.get(i);
288-
CtTypeReference<?> expected = g.getParametersTypes().get(i);
289-
Optional<CtTypeReference<?>> actualOpt = TypeInfer.getType(ctx, f, arg);
290-
291-
if (actualOpt.isPresent()) {
292-
CtTypeReference<?> actual = actualOpt.get();
293-
if (!actual.equals(expected) && !actual.isSubtypeOf(expected)) {
294-
argsMatch = false;
295-
break;
296-
}
297-
}
298-
}
299-
300-
// found match
301-
if (argsMatch) {
302-
if (hasChildren()) {
303-
for (Expression child : children)
304-
child.validateGhostInvocations(ctx, f);
305-
}
306-
return;
307-
}
308-
}
309-
277+
// find matching overload
278+
Optional<GhostFunction> match = candidates.stream().filter(g -> argumentsMatch(fi, g, ctx, f)).findFirst();
279+
if (match.isEmpty()) {
310280
// no overload matched, use the first candidate to throw the error
311-
GhostFunction g = candidates.get(0);
312-
313-
if (fi.children.size() != g.getParametersTypes().size()) {
314-
throw new ArgumentMismatchError(
315-
String.format("Wrong number of arguments in ghost invocation '%s': expected %d, got %d",
316-
fi.name, g.getParametersTypes().size(), fi.children.size()));
317-
318-
}
319-
320-
for (int i = 0; i < fi.children.size(); i++) {
321-
CtTypeReference<?> expected = g.getParametersTypes().get(i);
322-
Optional<CtTypeReference<?>> actualOpt = TypeInfer.getType(ctx, f, fi.children.get(i));
323-
if (actualOpt.isPresent()) {
324-
CtTypeReference<?> actual = actualOpt.get();
325-
if (!actual.equals(expected) && !actual.isSubtypeOf(expected)) {
326-
Expression arg = fi.children.get(i);
327-
throw new ArgumentMismatchError(String.format(
328-
"Argument '%s' and its respective parameter of ghost '%s' types are incompatible: expected %s, got %s",
329-
arg, fi.name, expected.getSimpleName(), actual.getSimpleName()));
330-
}
331-
}
332-
}
281+
throwArgumentMismatchError(fi, candidates.get(0), ctx, f);
333282
}
334283
}
284+
335285
// recurse children
336286
if (hasChildren()) {
337287
for (Expression child : children) {
338288
child.validateGhostInvocations(ctx, f);
339289
}
290+
}
291+
}
340292

293+
private boolean argumentsMatch(FunctionInvocation fi, GhostFunction g, Context ctx, Factory f) {
294+
// check argument count
295+
if (fi.children.size() != g.getParametersTypes().size())
296+
return false;
297+
298+
// check argument types
299+
for (int i = 0; i < fi.children.size(); i++) {
300+
Expression arg = fi.children.get(i);
301+
CtTypeReference<?> expected = g.getParametersTypes().get(i);
302+
Optional<CtTypeReference<?>> actualOpt = TypeInfer.getType(ctx, f, arg);
303+
304+
if (actualOpt.isPresent()) {
305+
CtTypeReference<?> actual = actualOpt.get();
306+
if (!actual.equals(expected) && !actual.isSubtypeOf(expected)) {
307+
return false;
308+
}
309+
}
341310
}
311+
return true;
342312
}
343313

314+
private void throwArgumentMismatchError(FunctionInvocation fi, GhostFunction g, Context ctx, Factory f)
315+
throws LJError {
316+
if (fi.children.size() != g.getParametersTypes().size()) {
317+
throw new ArgumentMismatchError(
318+
String.format("Wrong number of arguments in ghost invocation '%s': expected %d, got %d", fi.name,
319+
g.getParametersTypes().size(), fi.children.size()));
320+
}
321+
322+
for (int i = 0; i < fi.children.size(); i++) {
323+
CtTypeReference<?> expected = g.getParametersTypes().get(i);
324+
Optional<CtTypeReference<?>> actualOpt = TypeInfer.getType(ctx, f, fi.children.get(i));
325+
if (actualOpt.isPresent()) {
326+
CtTypeReference<?> actual = actualOpt.get();
327+
if (!actual.equals(expected) && !actual.isSubtypeOf(expected)) {
328+
Expression arg = fi.children.get(i);
329+
throw new ArgumentMismatchError(String.format(
330+
"Argument '%s' and its respective parameter of ghost '%s' types are incompatible: expected %s, got %s",
331+
arg, fi.name, expected.getSimpleName(), actual.getSimpleName()));
332+
}
333+
}
334+
}
335+
}
344336
}

0 commit comments

Comments
 (0)