Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,15 @@ public Optional<Predicate> getRefinementFromAnnotation(CtElement element) throws
}
if (ref.isPresent()) {
Predicate p = new Predicate(ref.get(), element, errorEmitter);

// check if refinement is valid
if (!p.getExpression().isBooleanExpression()) {
ErrorHandler.printCustomError(element, "Refinement predicate must be a boolean expression",
errorEmitter);
}
if (errorEmitter.foundError())
return Optional.empty();

constr = Optional.of(p);
}
return constr;
Expand Down Expand Up @@ -245,6 +252,12 @@ protected void handleAlias(String value, CtElement element) {
}
if (klass != null && path != null) {
a.parse(path);
// refinement alias must return a boolean expression
if (a.getExpression() != null && !a.getExpression().isBooleanExpression()) {
ErrorHandler.printCustomError(element, "Refinement alias must return a boolean expression",
errorEmitter);
return;
}
AliasWrapper aw = new AliasWrapper(a, factory, WILD_VAR, context, klass, path);
context.addAlias(aw);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,15 @@ private static void setConstructorStates(RefinedFunction f, List<CtAnnotation<?
Map<String, CtExpression> m = an.getAllValues();
String to = TypeCheckingUtils.getStringFromAnnotation(m.get("to"));
ObjectState state = new ObjectState();
if (to != null)
state.setTo(new Predicate(to, element, tc.getErrorEmitter()));
if (to != null) {
Predicate p = new Predicate(to, element, tc.getErrorEmitter());
if (!p.getExpression().isBooleanExpression()) {
ErrorHandler.printCustomError(element, "State refinement transition must be a boolean expression",
tc.getErrorEmitter());
return;
}
state.setTo(p);
}
l.add(state);
}
f.setAllStates(l);
Expand Down Expand Up @@ -176,6 +183,11 @@ private static ObjectState getStates(CtAnnotation<? extends Annotation> ctAnnota
private static Predicate createStatePredicate(String value, /* RefinedFunction f */ String targetClass,
TypeChecker tc, CtElement e, boolean isTo, String prefix) throws ParsingException {
Predicate p = new Predicate(value, e, tc.getErrorEmitter(), prefix);
if (!p.getExpression().isBooleanExpression()) {
ErrorHandler.printCustomError(e, "State refinement transition must be a boolean expression",
tc.getErrorEmitter());
return new Predicate();
}
String t = targetClass; // f.getTargetClass();
CtTypeReference<?> r = tc.getFactory().Type().createReference(t);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
import java.util.List;
import java.util.Map;

import com.microsoft.z3.Expr;

import liquidjava.processor.context.Context;
import liquidjava.processor.facade.AliasDTO;
import liquidjava.rj_language.ast.typing.TypeInfer;
Expand Down Expand Up @@ -53,6 +51,28 @@ public boolean isLiteral() {
return this instanceof LiteralInt || this instanceof LiteralReal || this instanceof LiteralBoolean;
}

/**
* Checks if this expression produces a boolean type based on its structure
*
* @return true if it is a boolean expression, false otherwise
*/
public boolean isBooleanExpression() {
if (this instanceof LiteralBoolean || this instanceof Ite || this instanceof AliasInvocation
|| this instanceof FunctionInvocation) {
return true;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We assume ghost and alias invocations always return boolean expressions.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but ghosts can be ints right? like size is that an issue?

Copy link
Collaborator Author

@rcosta358 rcosta358 Nov 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah in that case we can't catch it there since would need the context to check if it actually returns a boolean.

}
if (this instanceof GroupExpression ge) {
return ge.getExpression().isBooleanExpression();
}
if (this instanceof BinaryExpression be) {
return be.isBooleanOperation() || be.isLogicOperation();
}
if (this instanceof UnaryExpression ue) {
return ue.getOp().equals("!");
}
return false;
}

/**
* Substitutes the expression first given expression by the second
*
Expand Down