-
Notifications
You must be signed in to change notification settings - Fork 1
Use Case Collection
Some use case examples that cannot be done with existing languages or are quite hard to maintain.
https://www.reddit.com/r/cpp/comments/5himv7/a_perfect_string_design_missed_it_by_that_much/
In C++ a constexpr
type has to be a literal. This allows no custom destructor, even if it does nothing.
Rebuild is build around the idea that the code that is executed at compile time should be as unrestricted as possible. We do not these limitations like C++. Any regular string class would be usable at compile time.
boost::hana wraps types & constants to allow normal looking C++ code.
This still falls down, you cannot iterate over a vector of types/tuples. The type in each iteration is different. Therefore many cases still require meta template programming.
In Rebuild we have a direct interface to the compiler constructs. All meta programming looks like regular code that acts on compile time constructs.
C++ does not allow us to access the names of the enum states. Therefore we have to keep a separate mapping.
A simplified example:
enum class eState { normal, hover, pressed /* many more */ };
// keep synchron to eState
constexpr const char* eStateNames[] = { "normal", "hover", "pressed" /* do not forget any! */ };
Rebuild allows us to reflect over everything.
enum
is a user or library defined method. Code might look something like this. (Syntax still up for changes)
enum eState (normal, hover, pressed)
def eStateNames = &(eState.values.map_attr(name).to_array)
C++ introduces a product type std::variant<>
next year.
This allows code like this:
struct Point { int x, y; };
struct Normal {};
struct Hover { Point position; };
struct Pressed {
Point position;
int button;
};
using State : std::variant<Normal, Hover, Pressed>;
Looks nice. We only store the data we need for each state. Let's look at the usage.
void print(const State& state) {
std::visit([](auto&& data) {
// reflink: http://en.cppreference.com/w/cpp/utility/variant/visit
using T = std::remove_cv_t<std::remove_reference_t<decltype(data)>>;
if constexpr (std::is_same_v<T, Normal>) {
std::cout << "Normal\n";
}
else if constexpr (std::is_same_v<T, Hover>) {
std::cout << "Hover: "
<< data.position.x << ' ' << data.position.y << "\n";
}
else if constexpr (std::is_same_v<T, Pressed>) {
// …
}
}, state);
}
Who is supposed to use this? You need to understand all of C++ to know what you are doing.
With rebuild this is no issue. Again enum_data
is user or library implemented and can be tailored to fit your needs.
enum_data State:
normal
hover (position : Point)
pressed:
attr position : Point
attr button : int
end
end
fn print (state : State):
match state:
normal:
print "Normal\n"
end
hover (position):
print "Hover: #{position.x} #{position.y}\n"
end
pressed (position, button):
print "Pressed: #{position.x} #{position.y} button #{button}"
end
end
end
C++ and most other system language do not allow us to reflect on complex data structures. This forces us to write separate code that adds these details. Examples:
Rebuild has all the interfaces to the compiler structures. This allows us to generate very efficient and flexible serialisation code.
Traditionally you need to use a tool with a custom domain specific language flex
, yacc
and Antlr.
In C++ we got boost spirit with a strange syntax and quite long compile times.
Rebuild is designed to make it easy to build custom DSLs.
For a lexer it might look like this:
lexer myLang:
'+' -> plus
'-' -> minus
'\d+' -> number
end