aboutsummaryrefslogtreecommitdiff
path: root/docs/notes/callback_parameters.txt
blob: 3fe4bfa7979ae3dd083c3b9e8436138bca07e42d (plain)
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

callback parameters
-------------------

C functions that take a callback function pointer often take a "void *user"
argument, which is passed to the callback. This could be made type safe by
making use of generic types:

    () sort[T,U](list[T]^ elems;
                 int(U^ context; const T^ a,b) compare;
                 U^ context)
    {
        // ...
    }
    
    () main()
    {
        typedef Context = (bool reverse);
        Context ctx = struct(false);
        
        list[float] numbers;
        numbers.init();
        numbers.add(@4.5, _);
        
        int compare(const Context^ ctx, const float^ a,b) {
            float x = a^, y = b^;
            
            if (ctx^.reverse) {
                swap(@x, @y, _);
            }
            
            return (if x < y then -1 else if x > y then 1 else 0);
        }
        
        sort(numbers, @compare, @ctx);
    }

If the context parameter is not used, we can use a "void" type:

    int compare(const ()^ ctx; const float ^a,b) {
    }
    
    sort(numbers, @compare, @());


This could be simplified with some syntactic sugar:

    () sort[T,U](list[T]^ elems;
                 int(U^ context; const T^ a,b) compare;
                 U^ context)
    {
        // ...
    }
    
    () main()
    {
        bool reverse = false;
        
        list[float] numbers;
        numbers.init();
        numbers.add(@4.5, _);
        
        int compare(const locals:type^ ctx, const float^ a,b) {
            float x = a^, y = b^;
            
            if (ctx^.reverse) {
                swap(@x, @y, _);
            }
            
            return (if x < y then -1 else if x > y then 1 else 0);
        }
        
        sort(numbers, @compare, @locals);
    }

where "locals" is automatically defined like this in every function:

    namespace locals {
        // a struct for all the local variables on the stack
        typedef type = union(
            (bool reverse);
            (byte[4]; list[float] numbers); // offset is determined by the compiler
        );
    }
    
    // pointer to the local variables on the stack
    locals:type^ locals;