- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 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
// https://github.com/seanbaxter/circle/blob/master/examples/README.md#tldr
// ...
// Circle's primary syntactic element is the @meta keyword, which runs the prefixed statement
// during source translation (or during template instantiation in dependent contexts).
// https://github.com/seanbaxter/circle/blob/master/examples/README.md#same-language-reflection
// duff1.cxx
void duff_copy1(char* dest, const char* source, size_t count) {
const char* end = source + count;
while(size_t count = end - source) {
switch(count % 8) {
case 0: *dest++ = *source++; // Fall-through to case 7
case 7: *dest++ = *source++; // Fall-through to case 6...
case 6: *dest++ = *source++;
case 5: *dest++ = *source++;
case 4: *dest++ = *source++;
case 3: *dest++ = *source++;
case 2: *dest++ = *source++;
case 1: *dest++ = *source++;
break;
}
}
}
// Reproduced above is a simplified version of Duff's device, an infamous memcpy function designed
// to reduce the amount of branching in the operation. (The loop is optimally interleaved with the switch,
// but I'm trying to illustrate some other points and don't want to add to the confusion.) Once we enter the
// switch, perform an assignment and unconditionally progress to the next case statement. This algorithm
// cries out for automation. The case statements have indices that run from 8 down to 1, modulo 8. Can we give it the Circle treatment?
// duff2.cxx
void duff_copy2(char* dest, const char* source, size_t count) {
const char* end = source + count;
while(size_t count = end - source) {
switch(count % 8) {
@meta for(int i = 8; i > 0; --i)
case i % 8: *dest++ = *source++;
break;
}
}
Но гомоиконности таким подкостыливанием вы естественно не добавите!