ACSL Logic Struct Declarations Not Working as in Reference Manual - frama-c

I would like to have a way to describe logic/spec level structs that include abstract lists. Example 2.2.7 on page 27 of the ACSL Reference Manual suggests that there is a
way to do this and it is as follows:
//# type point = struct { real x; real y; };
//# type triangle = point[3];
//# logic point origin = { .x = 0.0 , .y = 0.0 };
/*# logic triangle t_iso = { [0] = origin,
# [1] = { .y = 2.0 , .x = 0.0 }
# [2] = { .x = 2.0 , .y = 0.0 }};
#*/
/*# logic point centroid(triangle t) = {
# .x = mean3(t[0].x,t[1].x,t[2].x);
# .y = mean3(t[0].y,t[1].y,t[2].y);
# };
#*/
//# type polygon = point[];
/*# logic perimeter(polygon p) =
# \sum(0,\length(p)-1,\lambda integer i;d(p[i],p[(i+1) % \length(p)])) ;
#*/
If I copy/paste this exact code into a text editor and try to run this code with the wp plugin with:
frama-c -wp -wp-rte -wp-prover alt-ergo shapes.c
I get an error:
[kernel:annot-error] shapes.c:1: Warning: unexpected token '{'
If I give up on trying to write logic/spec level declarations of struct types, but would still like to write logic/spec level expressions that instantiate structs defined in C as follows:
struct somestruct {
int x;
int y;
};
/*#
logic struct somestruct foo = { .x = 3, .y = 4 };
*/
I still get an error:
[kernel:annot-error] aggregate_err.c:7: Warning:
unsupported aggregated field construct. Ignoring global annotation
and not having a way to write particular values of structs as expressions in specifications leads to some fairly ugly specifications, so I am hoping that I am doing something wrong.
If I dig into the source of frama-C 20.0 to try to find the part of the parser-generator code for /*# type declarations, it looks like the syntax in Ex 2.2.7 is not really implemented. It looks like the syntax for type level declarations is line 799 of
frama-c-20.0-Calcium/src/kernel_internals/parsing/logic_parser.mly
(called type_spec)
And the parse rule for type level declarations of structs is:
| STRUCT exit_rt_type identifier_or_typename { LTstruct $3 }
which looks like it would support
//# type foo = struct c_struct;
but not something like what Ex 2.2.7 has as in:
//# type point = struct { real x; real y; };
Is there something else I should be doing to have better support for structs in ACSL/Frama-C? Thanks!

Not all ACSL constructions are supported by the current Frama-C implementation. With each Frama-C release comes an ACSL implementation manual, which describes the constructions that are not yet implemented. For Frama-C 20.0 Calcium, this can be found here. In this document, unsupported constructions appear in red in the relevant BNF rule. Note however that other parts of the manual are left untouched. Notably, the fact that an example is included in the implementation manual does not imply that it is expected to be successfully parsed by the current Frama-C version. In your case, these are the rules of figure 2.17 on page 57, which show that indeed records are not implemented.
As you have already discovered by yourselves, it is indeed possible to define a C struct (possibly ghost) and an ACSL type out of it. Of course, since the struct lives in the C world, its fields must have C types (ACSL types in ghost declarations is unsupported as well).
Similarly, you can simulate the absence of direct record definition by an update (the \with construction) of all the fields of an arbitrary record, as in the following example:
//# ghost struct c_s { float x; float y; };
//# type point = struct c_s;
//# axiomatic Arbitrary_point { logic point empty; }
//# logic point my_point = {{ empty \with .x = (float)1. } \with .y = (float)2.};

Related

How to use declarative macros to generate a self containing enum?

I want to create a declarative macro that simplifies a recursive creation of an enum structure (by hiding all the Box::new). However commas seem to cause a problem when having a deep formula that has commas in its substructures.
Here is an explanation in code:
Assume this definition for an Enum representing a subset of propositional logic
#[derive(Debug)]
enum PFormula {
True,
False,
Atom(i32),
Not(Box<PFormula>),
And(Box<PFormula>, Box<PFormula>)
}
macro_rules! pformula {
($func:tt($($($sub:tt)+),+)) => { PFormula::$func($(Box::new($sub)+),+) };
(True) => { PFormula::True };
(False) => { PFormula::False };
($e:expr) => { PFormula::Atom($e) };
}
fn main() {
let x = pformula!(And(Not(2), 3));
let y = pformula!(And(And(1, 4), And(5, And(2, 6))));
println!("{:?}", x);
println!("{:?}", y);
}
The pformula should take a simplified version of the syntax defined as the enum and create a PFormula representation by hiding all the Box<PFormula>'s required for the recursive structure. What is happening is that there seems to be an ambiguity when handling the commas.
So the x in the above code should expand to:
PFormula::And(Box::new(PFormula::Not(Box::new(PFormula::Atom(2)))), Box::new(PFormula::Atom(3)))
However this is the error returned
error: local ambiguity when calling macro `pformula`: multiple parsing options: built-in NTs tt ('sub') or 1 other option.
--> src/main.rs:18:33
|
18 | let x = pformula!(And(Not(2), 3));
| ^
error: local ambiguity when calling macro `pformula`: multiple parsing options: built-in NTs tt ('sub') or 1 other option.
--> src/main.rs:19:36
|
19 | let y = pformula!(And(And(1, 4), And(5, And(2, 6))));
| ^
error: could not compile `playground` due to 2 previous errors
Please note that this is a simplification of the syntax I am actually working on. The syntax I am using has around 8 variants of arity 1 and around 5 of arity 2, so having a match arm for each variant seemed like an overkill. Additionally I tried it and it still was not working because of the commas.
So the question, is there a way to do this in declarative macros or is this better solved using function-like proc macros?

How to use QtConcurrent::mappedReduced with lambdas or std::functions of lambdas?

I'd like to use Qt's mappedReduced with lambdas.
Answers to Make QtConcurrent::mapped work with lambdas seem to suggest that this is not possible directly, but might be achieved by use of std::function.
But while I can build a compiler-accepted call to mapped() this way, I cannot figure out how to apply the principle to mappedReduced() in a way that the compiler wants to compile. How must this be formulated?
Simple example:
int cap = 1;
std::function<int(char)> mlf = [cap](char c){ return static_cast<int>(c)+cap; };
std::function<void(double&,int const&)> rlf = [cap](double &d,int const &i){ d += static_cast<double>(i+cap); };
QVector<char> seq = {'a','b','c'};
QVector<int> v = QtConcurrent::blockingMapped( seq, mlf );
double d = QtConcurrent::blockingMappedReduced( seq, mlf, rlf );
[NB: The final code has to support captures, therefore I included captures in this example. Removing the captures won't make to compiler happy here.]
The IDE/compiler complains:
qtsupplement.cpp:291:17: error: no matching function for call to 'blockingMappedReduced'
qtconcurrentmap.h:199:12: note: candidate template ignored: couldn't infer template argument 'ResultType'
qtconcurrentmap.h:213:65: note: candidate template ignored: substitution failure [with MapFunctor = std::function<int (char)>, ReduceFunctor = std::function<void (double &, const int &)>, Sequence = QVector<char>]: implicit instantiation of undefined template 'QtPrivate::ReduceResultType<std::function<void (double &, const int &)> >'
qtconcurrentmap.h:228:12: note: candidate function template not viable: requires at least 4 arguments, but 3 were provided
qtconcurrentmap.h:243:65: note: candidate function template not viable: requires at least 4 arguments, but 3 were provided
while the 'ResultType' should be the type of variable d and the first parameter of rlf() hints to the result type, too.
used versions: qt5.5.1, g++5.4.0, qtcreator4.9.0
The following code works for me (Qt 6.0.3, C++17):
int cap = 1;
QVector<char> seq = {'a','b','c'};
QVector<int> v = QtConcurrent::blockingMapped<QVector<int>>(
seq,
[cap](char c){ return static_cast<int>(c)+cap; }
);
double d = QtConcurrent::blockingMappedReduced<double>(
seq,
[cap](char c){ return static_cast<int>(c)+cap; },
[cap](double &d,int const& i){ d += static_cast<double>(i+cap); }
);
So you should use Qt 6.0.3 and specify template arguments.

instance::class.java vs. instance.javaClass

Given Kotlin 1.1. For an instance of some class, instance::class.java and instance.javaClass seem to be nearly equivalent:
val i = 0
println(i::class.java) // int
println(i.javaClass) // int
println(i::class.java === i.javaClass) // true
There is a subtle difference, however:
val c1: Class<out Int> = i::class.java
val c2: Class<Int> = i.javaClass
instance.javaClass is negligibly shorter, but instance::class.java is more consistent with the corresponding usage on a type. While you can use .javaClass on some types, the result may not be what you would expect:
println(i::class.java === Int::class.java) // true
println(i.javaClass === Int.javaClass) // false
println(Int::class.java === Int.javaClass) // false
println(Int.javaClass) // class kotlin.jvm.internal.IntCompanionObject
So, I would argue that it is better to never use .javaClass for more consistency. Are there any arguments against that?
The difference in these two constructs is that, for an expression foo of static (declared or inferred) type Foo:
foo.javaClass is typed as Class<Foo>
foo::class.java is typed as Class<out Foo>
In fact, the latter is more precise, because the actual value that foo evaluates to can be an instance of not Foo itself but one of its subtypes (and it's exactly what's denoted by the covariant out Foo).
As #marstran correctly noted in the comment on the question, .javaClass once was considered to be deprecated (see the Kotlin 1.1 RC announcement) because it can break type safety (see below), but it was afterwards left as-is because it was widely used and replacing it with the alternative of ::class.java would require adding explicit unchecked casts in the code.
Also, see the comments under this answer: (link)
Please note that Int.javaClass does not denote the type of Int but instead is the Java class of the Int's companion object. Whereas Int::class.java is an unbound class reference and denotes the type. To get it with .javaClass, you need to call it on an Int instance, e.g. 1.javaClass.
Here's how exactly .javaClass can break type safety. This code compiles but breaks at runtime:
open class Foo
class Bar : Foo() {
val baz: Int = 0
}
fun main(args: Array<String>) {
val someFoo: Foo = Bar()
val anotherFoo: Foo = Foo()
val someFooProperty: KProperty1<in Foo, *> = // 'in Foo' is bad
someFoo.javaClass.kotlin.memberProperties.first()
val someValue = someFooProperty.get(anotherFoo)
}
This example uses kotlin-reflect.
That's because someFooProperty represents a property of Bar, not Foo, but since it was obtained from someFoo.javaClass (Class<Foo> then converted to KClass<Foo>) the compiler allows us to use it with the in Foo projection.

Why does asserting on the result of Deref::deref fail with a type mismatch?

The following is the Deref example from The Rust Programming Language except I've added another assertion.
Why does the assert_eq with the deref also equal 'a'? Why do I need a * once I've manually called deref?
use std::ops::Deref;
struct DerefExample<T> {
value: T,
}
impl<T> Deref for DerefExample<T> {
type Target = T;
fn deref(&self) -> &T {
&self.value
}
}
fn main() {
let x = DerefExample { value: 'a' };
assert_eq!('a', *x.deref()); // this is true
// assert_eq!('a', x.deref()); // this is a compile error
assert_eq!('a', *x); // this is also true
println!("ok");
}
If I uncomment the line, I get this error:
error[E0308]: mismatched types
--> src/main.rs:18:5
|
18 | assert_eq!('a', x.deref());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected char, found &char
|
= note: expected type `char`
found type `&char`
= help: here are some functions which might fulfill your needs:
- .to_ascii_lowercase()
- .to_ascii_uppercase()
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
First, let's spell out the generic types for your specific example: 'a' is char, so we have:
impl Deref for DerefExample<char> {
type Target = char;
fn deref(&self) -> &char {
&self.value
}
}
Notably, the return type of deref is a reference to a char. Thus it shouldn't be surprising that, when you use just x.deref(), the result is a &char rather than a char. Remember, at that point deref is just another normal method — it's just implicitly invoked as part of some language-provided special syntax. *x, for example, will call deref and dereference the result, when applicable. x.char_method() and fn_taking_char(&x) will also call deref some number of times and then do something further with the result.
Why does deref return a reference to begin with, you ask? Isn't that circular? Well, no, it isn't circular: it reduces library-defined smart pointers to the built-in type &T which the compiler already knows how to dereference. By returning a reference instead of a value, you avoid a copy/move (which may not always be possible!) and allow &*x (or &x when it's coerced) to refer to the actual char that DerefExample holds rather than a temporary copy.
See also:
Why is the return type of Deref::deref itself a reference?

Passing a pointer to struct as an argument in Julia

I have a type definition corresponding to a C-struct as follows:
type fakeCStruct
a::Uint8;
b::Uint32;
end
var=fakeCStruct(3,4);
How can I pass a pointer to this type as an input argument (i.e. struct CStruct *) for a c-function in ccall?
The old documentation (v0.3) suggest using &var in the input argument list of ccall. However that statement is deleted in v0.4 documentation (also, &var does not work in v0.4).
Use Ref{fakeCStruct}:
r = Ref(fakeCStruct(3, 4))
ccall((:somefunction, "lib"), Void, (Ref{fakeCStruct},), r)
From the Julia docs in the System Independent table here:
C name: | Julia base type
T* (where T represents an appropriately defined type) | Ref{T}
Allocate memory for the Julia object, then pass it by pointer:
type fakeCStruct
a::UInt8;
b::UInt32;
end
var = fakeCStruct(3,4)
var_p = Ptr{fakeCStruct}(pointer_from_objref(var))
ccall((:somefunc, "lib"), Void, (Ptr{fakeCStruct},), var_p)
(Using Ref{} doesn't work for me... using Julia 0.4.0)
Although I'm definitely no expert on this I iterated to some code which works for me. Hopefully this will help people on their way. In the example foo.c is compiled to a shared library (.dll in my case) and called from foo.jl.
foo.c
struct mystruct {
int a;
int b;
};
typedef struct mystruct mystruct_t;
int recvstruct(mystruct_t* st) {
printf("C %u, %u\n", st->a, st->b);
return 0;
}
mystruct_t* updatestruct(mystruct_t* st) {
// here we need to return the pointer, since Julia seems to
// pass a pointer to a copy of the struct
st->a = 10;
st->b = 11;
return st;
}
foo.jl
struct mystruct
a::Int32
b::Int32
end
function let_c_print_struct()
# Note that the function call automatically converts `mystruct(3, 4)` to `::Ref(..)`.
ccall((:recvstruct, libfile), Int32, (Ref{mystruct},), mystruct(3, 4))
end
function let_c_update_struct()
st = mystruct(5, 6)
ret = ccall((:updatestruct, libfile), Ref{ mystruct }, (Ref{ mystruct }, ), st)
#show st # st = mystruct(5, 6)
#show ret[] # ret[] = mystruct(10, 11)
end
Regarding lifetime of data inside the shared library: I found that objects stored in memory remain available (I would guess that they are outside of the scope of the garbage collector). Four observations support that the data remains available:
Julia keeps the library open unless it is explicitly closed.
The Julia language source code uses unsafe_string (dereferencing pointer) on values returning from a ccall. See search results for unsafe_string(ccall(.
I found that allocating data (even structs containing pointers) in C and passing references to this data around in Julia does work.
I found that sockets remain open.

Resources