dhh1128 / intent

the intent formal language
https://intentlang.org
2 stars 1 forks source link

Provide a way to shrink repetitive, verbose code where generics aren't enough #63

Open dhh1128 opened 10 years ago

dhh1128 commented 10 years ago

One way that generics are inadequate is that they can't be templatized by a variable, only by a constant. Another is that generics are verbose -- they don't offer a way to decrease repetitive text unless there's significant code being abstracted away. Another is that they sometimes require a different invocation for each different type (DoSomething, DoSomething).

Use cases:

  1. Loop over a set of fields of a struct (can use compile-time reflection, but if fields have different types, I want to use a compile-time variable to invoke the right variant of the generic template)
  2. Turn a very verbose, repetitive line into a short, simple one.

Requirements:

a. Must still be debuggable/obvious. (This may suggest that expanded form is present but just hidden by default in the code.) b. Can't break syntax. c. Must support variadic args with compile-time reflection of them so I can get variadic arg 1, 2, ... N

dhh1128 commented 10 years ago

Consider the following scenario:

uint64_t n;
#define WRITE_TREE(tree) \
    if (ok) { \
        n = tree.insert_offset; \
        ok = ok && WriteToReport(file, (uint8_t*)&n, sizeof(n)); \
        ok = ok && WriteToReport(file, (uint8_t*)&n, sizeof(n)); \
        n = tree.item_count; \
        ok = ok && WriteToReport(file, (uint8_t*)&n, sizeof(n)); \
        ok = ok && WriteToReport(file, (uint8_t*)ds->tree.buffer, n); \
    }

WRITE_TREE(planetTree);
WRITE_TREE(starTree);
WRITE_TREE(asteroidTree);
WRITE_TREE(cometTree);

This code doesn't compile because the data type of cityBag and stateBag is different from the data type of the others--and cityBag lacks an _itemCount member, so the line that assigns ds->bag._itemCount to n won't compile.

We could write template functions and specialize them for the two different bag datatypes, but this would require two new function declarations and two function impls, and lots of parameter mgmt, all to "reduce" code size.

A cleaner solution might be to say, "WRITE_BAG(cityBag) is like WRITE_BAG(streetBag) except omit two lines". The question is whether we could do that in a way that is A) terse enough to save significant effort; B) easy to debug; C) obvious.

dhh1128 commented 10 years ago

Here's another example of code that uses macros to be less verbose. We want something like this.

#define SAVE_TREE(tree) if (bSuccess) bSuccess = SaveTree(ds->tree, pFile)
SAVE_TREE(planetTree);
SAVE_TREE(starTree);
SAVE_TREE(asteroidTree);
SAVE_TREE(cometTree);
#undef SAVE_TREE