diff --git a/liquidjava-example/src/main/java/testSuite/CorrectResult.java b/liquidjava-example/src/main/java/testSuite/CorrectResult.java new file mode 100644 index 00000000..e5bf60e4 --- /dev/null +++ b/liquidjava-example/src/main/java/testSuite/CorrectResult.java @@ -0,0 +1,16 @@ +package testSuite; + +import liquidjava.specification.Refinement; + +public class CorrectResult { + + @Refinement("#result > 10") + public int getLargeNumber() { + return 15; + } + + @Refinement("#result == (a + b)") + public int sum(int a, int b) { + return a + b; + } +} \ No newline at end of file diff --git a/liquidjava-example/src/main/java/testSuite/ErrorResultVariable.java b/liquidjava-example/src/main/java/testSuite/ErrorResultVariable.java new file mode 100644 index 00000000..72d83952 --- /dev/null +++ b/liquidjava-example/src/main/java/testSuite/ErrorResultVariable.java @@ -0,0 +1,10 @@ +// Not Found Error +package testSuite; +import liquidjava.specification.Refinement; + +public class ErrorResultVariable { + public void test() { + @Refinement("#result > 0") + int x = 10; + } +} \ No newline at end of file diff --git a/liquidjava-verifier/src/main/antlr4/rj/grammar/RJ.g4 b/liquidjava-verifier/src/main/antlr4/rj/grammar/RJ.g4 index d6f7f45f..cbafa5fa 100644 --- a/liquidjava-verifier/src/main/antlr4/rj/grammar/RJ.g4 +++ b/liquidjava-verifier/src/main/antlr4/rj/grammar/RJ.g4 @@ -36,6 +36,7 @@ operand: literalExpression: '(' literalExpression ')' #litGroup | literal #lit + | RESULT #result | ID #var | functionCall #invocation ; @@ -95,7 +96,8 @@ ARITHOP : '+'|'*'|'/'|'%';//|'-'; BOOL : 'true' | 'false'; ID_UPPER: ([A-Z][a-zA-Z0-9]*); OBJECT_TYPE: - (([a-zA-Z][a-zA-Z0-9]+) ('.' [a-zA-Z][a-zA-Z0-9]*)+); + (([a-zA-Z][a-zA-Z0-9]+) ('.' [a-zA-Z][a-zA-Z0-9]*)+); +RESULT : '#result'; ID : '#'*[a-zA-Z_][a-zA-Z0-9_#]*; STRING : '"'(~["])*'"'; INT : (([0-9]+) | ([0-9]+('_'[0-9]+)*)); diff --git a/liquidjava-verifier/src/main/java/liquidjava/processor/refinement_checker/general_checkers/MethodsFunctionsChecker.java b/liquidjava-verifier/src/main/java/liquidjava/processor/refinement_checker/general_checkers/MethodsFunctionsChecker.java index c2bd580e..4c93278a 100644 --- a/liquidjava-verifier/src/main/java/liquidjava/processor/refinement_checker/general_checkers/MethodsFunctionsChecker.java +++ b/liquidjava-verifier/src/main/java/liquidjava/processor/refinement_checker/general_checkers/MethodsFunctionsChecker.java @@ -162,6 +162,7 @@ private Predicate handleFunctionRefinements(RefinedFunction f, CtElement method, Optional oret = rtc.getRefinementFromAnnotation(method); Predicate ret = oret.orElse(new Predicate()); ret = ret.substituteVariable("return", Keys.WILDCARD); + ret = ret.substituteVariable("#result", Keys.WILDCARD); f.setRefReturn(ret); rtc.getMessageFromAnnotation(method).ifPresent(f::setMessage); return Predicate.createConjunction(joint, ret); diff --git a/liquidjava-verifier/src/main/java/liquidjava/rj_language/visitors/CreateASTVisitor.java b/liquidjava-verifier/src/main/java/liquidjava/rj_language/visitors/CreateASTVisitor.java index d906772c..bdeb86bf 100644 --- a/liquidjava-verifier/src/main/java/liquidjava/rj_language/visitors/CreateASTVisitor.java +++ b/liquidjava-verifier/src/main/java/liquidjava/rj_language/visitors/CreateASTVisitor.java @@ -51,6 +51,7 @@ import rj.grammar.RJParser.PredLogicContext; import rj.grammar.RJParser.PredNegateContext; import rj.grammar.RJParser.ProgContext; +import rj.grammar.RJParser.ResultContext; import rj.grammar.RJParser.StartContext; import rj.grammar.RJParser.StartPredContext; import rj.grammar.RJParser.VarContext; @@ -158,10 +159,14 @@ else if (rc instanceof LitContext) return create(((LitContext) rc).literal()); else if (rc instanceof VarContext) { return new Var(((VarContext) rc).ID().getText()); - - } else { + } else if (rc instanceof ResultContext) { + return new Var("#result"); + } else if (rc instanceof InvocationContext) { return create(((InvocationContext) rc).functionCall()); + } else { + throw new IllegalStateException("Unknown literalExpression: " + rc.getClass()); } + } private Expression functionCallCreate(FunctionCallContext rc) throws LJError {