Ivy generates incorrect C++ code (does not compile) in this example, where I was trying to implement vector clocks in the most straightforward way possible. In the C++, the max of the pid_t range type is a member of the main class but the C++ code sometimes tries to access it as it if were a global static variable. Moreover there is a constness issue caused by the memo table in hash_thunk.
#lang ivy1.8
include order
instance pid_t : iterable
instance clock_t : unbounded_sequence
object vector_clock_t = {
type this = struct {
component(P:pid_t): clock_t
}
action empty returns (vc:this)
action merge(vc1:this, vc2:this) returns (vc:this)
action incr(vc:this, p:pid_t) returns (vc:this)
implementation {
implement empty {
component(vc, P) := 0
}
implement merge {
component(vc, P) := component(vc2, P) if component(vc2,P) > component(vc1,P) else component(vc1, P)
}
implement incr {
var s := component(vc, p).next;
component(vc, P) := s if P = p else component(vc, P)
}
}
}
export vector_clock_t.empty
export vector_clock_t.merge
export vector_clock_t.incr
extract impl = this, vector_clock_t, pid_t, clock_t
$ ivyc isolate=impl struct_clock.ivy
g++ -Wno-parentheses-equality -std=c++11 -g -o struct_clock struct_clock.cpp -pthread
In file included from struct_clock.cpp:1:
struct_clock.h: In function ‘bool operator==(const struct_clock::vector_clock_t&, const struct_clock::vector_clock_t&)’:
struct_clock.h:656:27: error: ‘pid_t__max’ was not declared in this scope
656 | for (int X0 = 0; X0 < pid_t__max+1; X0++) {
| ^~~~~~~~~~
struct_clock.h:657:29: error: passing ‘const hash_thunk<int, long long unsigned int>’ as ‘this’ argument discards qualifiers [-fpermissive]
657 | if (!(s.component[X0] == t.component[X0])) __tmp3 = 0;
| ^
struct_clock.h:592:8: note: in call to ‘R& hash_thunk<D, R, HashFun>::operator[](const D&) [with D = int; R = long long unsigned int; HashFun = hash_space::hash<int>]’
592 | R &operator[](const D& arg){
| ^~~~~~~~
struct_clock.h:657:48: error: passing ‘const hash_thunk<int, long long unsigned int>’ as ‘this’ argument discards qualifiers [-fpermissive]
657 | if (!(s.component[X0] == t.component[X0])) __tmp3 = 0;
| ^
struct_clock.h:592:8: note: in call to ‘R& hash_thunk<D, R, HashFun>::operator[](const D&) [with D = int; R = long long unsigned int; HashFun = hash_space::hash<int>]’
592 | R &operator[](const D& arg){
| ^~~~~~~~
struct_clock.cpp: In function ‘std::ostream& operator<<(std::ostream&, const struct_clock::vector_clock_t&)’:
struct_clock.cpp:703:32: error: ‘pid_t__max’ was not declared in this scope
703 | for (int X__0 = 0; X__0 < (pid_t__max+1); X__0++) {
| ^~~~~~~~~~
struct_clock.cpp:705:30: error: passing ‘const hash_thunk<int, long long unsigned int>’ as ‘this’ argument discards qualifiers [-fpermissive]
705 | s << t.component[X__0];
| ^
In file included from struct_clock.cpp:1:
struct_clock.h:592:8: note: in call to ‘R& hash_thunk<D, R, HashFun>::operator[](const D&) [with D = int; R = long long unsigned int; HashFun = hash_space::hash<int>]’
592 | R &operator[](const D& arg){
| ^~~~~~~~
struct_clock.cpp: In function ‘void __ser(ivy_ser&, const T&) [with T = struct_clock::vector_clock_t]’:
struct_clock.cpp:714:32: error: ‘pid_t__max’ was not declared in this scope
714 | for (int X__0 = 0; X__0 < (pid_t__max+1); X__0++) {
| ^~~~~~~~~~
struct_clock.cpp:716:55: error: passing ‘const hash_thunk<int, long long unsigned int>’ as ‘this’ argument discards qualifiers [-fpermissive]
716 | __ser<unsigned long long>(res,t.component[X__0]);
| ^
In file included from struct_clock.cpp:1:
struct_clock.h:592:8: note: in call to ‘R& hash_thunk<D, R, HashFun>::operator[](const D&) [with D = int; R = long long unsigned int; HashFun = hash_space::hash<int>]’
592 | R &operator[](const D& arg){
| ^~~~~~~~
struct_clock.cpp: In function ‘T _arg(std::vector<ivy_value>&, unsigned int, long long int) [with T = struct_clock::vector_clock_t]’:
struct_clock.cpp:898:32: error: ‘pid_t__max’ was not declared in this scope
898 | for (int X__0 = 0; X__0 < (pid_t__max+1); X__0++) {
| ^~~~~~~~~~
struct_clock.cpp:910:48: error: ‘pid_t__max’ was not declared in this scope
910 | for (int X__0 = 0; X__0 < (pid_t__max+1); X__0++) {
| ^~~~~~~~~~
struct_clock.cpp: In function ‘void __deser(ivy_deser&, T&) [with T = struct_clock::vector_clock_t]’:
struct_clock.cpp:933:32: error: ‘pid_t__max’ was not declared in this scope
933 | for (int X__0 = 0; X__0 < (pid_t__max+1); X__0++) {
| ^~~~~~~~~~
At global scope:
cc1plus: note: unrecognized command-line option ‘-Wno-parentheses-equality’ may have been intended to silence earlier diagnostics
Ivy generates incorrect C++ code (does not compile) in this example, where I was trying to implement vector clocks in the most straightforward way possible. In the C++, the max of the pid_t range type is a member of the main class but the C++ code sometimes tries to access it as it if were a global static variable. Moreover there is a constness issue caused by the memo table in hash_thunk.