File: vcalls.c

package info (click to toggle)
interface99 1.0.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 324 kB
  • sloc: ansic: 951; sh: 48; makefile: 6
file content (110 lines) | stat: -rw-r--r-- 5,490 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include <interface99.h>

#include <assert.h>

#define METHODS(prefix, T)                                                                         \
    vfunc(int, prefix##_vcall, VSelf)                                                              \
    vfunc(int, prefix##_vcall_args, const VSelf, int x, const char *y)                             \
                                                                                                   \
    vfunc(int, prefix##_vcall_obj, T self)                                                         \
    vfunc(int, prefix##_vcall_obj_args, T self, int x, const char *y)

#define TestSuper_IFACE METHODS(test_super, TestSuper)
#define Test_IFACE      METHODS(test, Test)
#define Test_EXTENDS    (TestSuper)

interface(TestSuper);
interface(Test);

static const int n = 7;
static const char *str = "abc";

typedef enum {
    TEST_VCALL,
    TEST_VCALL_ARGS,
    TEST_VCALL_OBJ,
    TEST_VCALL_OBJ_ARGS,
} RetVal;

typedef struct {
    char dummy;
} Impl;

static Impl obj = {0};

#define IMPL_METHODS(prefix, T)                                                                    \
    static int Impl_##prefix##_vcall(VSelf) {                                                      \
        VSELF(Impl);                                                                               \
        assert(&obj == self);                                                                      \
                                                                                                   \
        return TEST_VCALL;                                                                         \
    }                                                                                              \
                                                                                                   \
    static int Impl_##prefix##_vcall_args(const VSelf, int x, const char *y) {                     \
        VSELF(const Impl);                                                                         \
        assert(&obj == self);                                                                      \
        assert(n == x);                                                                            \
        assert(str == y);                                                                          \
                                                                                                   \
        return TEST_VCALL_ARGS;                                                                    \
    }                                                                                              \
                                                                                                   \
    static int Impl_##prefix##_vcall_obj(T test) {                                                 \
        assert(&obj == test.self);                                                                 \
        assert(&VTABLE(Impl, T) == test.vptr);                                                     \
                                                                                                   \
        return TEST_VCALL_OBJ;                                                                     \
    }                                                                                              \
                                                                                                   \
    static int Impl_##prefix##_vcall_obj_args(T test, int x, const char *y) {                      \
        assert(&obj == test.self);                                                                 \
        assert(&VTABLE(Impl, T) == test.vptr);                                                     \
        assert(n == x);                                                                            \
        assert(str == y);                                                                          \
                                                                                                   \
        return TEST_VCALL_OBJ_ARGS;                                                                \
    }

declImpl(TestSuper, Impl);
declImpl(Test, Impl);

// clang-format off
IMPL_METHODS(test_super, TestSuper)
IMPL_METHODS(test, Test)
// clang-format on

impl(TestSuper, Impl);
impl(Test, Impl);

int main(void) {
#define RVALUE DYN(Impl, Test, &obj)

    // Test that VCALL_* can accept lvalues.
    {
        Test lvalue = RVALUE;

        assert(TEST_VCALL == VCALL(lvalue, test_vcall));
        assert(TEST_VCALL_ARGS == VCALL(lvalue, test_vcall_args, n, str));
        assert(TEST_VCALL_OBJ == VCALL_OBJ(lvalue, test_vcall_obj));
        assert(TEST_VCALL_OBJ_ARGS == VCALL_OBJ(lvalue, test_vcall_obj_args, n, str));

        assert(TEST_VCALL == VCALL_SUPER(lvalue, TestSuper, test_super_vcall));
        assert(TEST_VCALL_ARGS == VCALL_SUPER(lvalue, TestSuper, test_super_vcall_args, n, str));
        assert(TEST_VCALL_OBJ == VCALL_SUPER_OBJ(lvalue, TestSuper, test_super_vcall_obj));
        assert(
            TEST_VCALL_OBJ_ARGS ==
            VCALL_SUPER_OBJ(lvalue, TestSuper, test_super_vcall_obj_args, n, str));
    }

    // Test rvalues.
    {
        (void)VCALL(RVALUE, test_vcall);
        (void)VCALL_OBJ(RVALUE, test_vcall_obj);
        (void)VCALL_SUPER(RVALUE, TestSuper, test_super_vcall);
        (void)VCALL_SUPER_OBJ(RVALUE, TestSuper, test_super_vcall_obj);
    }

#undef RVALUE

    return 0;
}