| CARVIEW |
Navigation Menu
-
Notifications
You must be signed in to change notification settings - Fork 72
Stringifying Your Types
The function packToken::str() have default implementations of how to print all the built-in types.
But you might not like it and want to change it.
Another reason for changing it is when you create new type and want packToken::str() to work with it.
This also improves how errors will look, since this function is also used when generating error messages.
To make this possible packToken::str() will first execute the function packToken::str_custom() if it is defined
and if the return value is a non empty string it will return it, if not it will fallback to the built-in
implemented behavior.
The framework comes already with an implementation of the packToken::str_custom() in builtin-features/functions.h,
which is easy to extend: It checks if there is a type-specific function implemented for this type with the
name __str__, and if there is it will use it.
Thus, if you just want to change the stringify behavior you can just implement that function for the desired type.
For example suppose you prefer the boolean type to be printed as lowercased "carview.php?tsp=true" and "false" instead of the default "True" and "False":
packToken Boolean_str(TokenMap scope) {
const packToken& token = scope["this"].asBool();
if (token) {
return "true";
} else {
return "false";
}
}
struct Startup {
Startup() {
TokenMap& base_bool = calculator::type_attribute_map()[BOOL];
base_bool["__str__"] = CppFunction(&Boolean_str, "__str__");
}
} Startup;For a more in-depth understanding of how to use type-specific functions read Type-specific functions.
This method is not very clean, so it will probably be changed or deprecated in future. Use it only if you really need it.
The default implementation of packToken::str_custom() comes with one side effect that might not be desired:
the users of your language will be able to access this stringify function like this, e.g.:
calculator::calculate("my_string_stringify_function = ''.__str__");
// or
calculator::calculate("my_int_stringify_function = 0.__str__");Or if the type is a MAP and the user can write his own functions, he might be able to overwrite how his MAP will be stringified, e.g.:
packToken myMap = calculator::calculate(
"myMap = { __str__: function() { return 'foo'; } }");
std::cout << myMap << std::endl; // fooIf you don't like this behavior you might want to reimplement the packToken::str_custom() function.
To do that you may follow an example available on file builtin-features/functions.h, it goes like this:
std::string packToken_str(const TokenBase* base, uint32_t nest) {
if (base->type == MY_TYPE) {
// ... build the str representation ...
return str_representation;
} else {
// return an empty string to make `packToken::str()`
// resume its normal behavior:
return "";
}
}
struct Startup {
Startup() {
packToken::str_custom() = packToken_str;
}
} Startup;In this case, since we are dealing with global variables, there is one caveat: You can't declare this function twice or it might have unexpected results, see Static Initialization Order Fiasco.
So if you want to change the default behavior of the built-in function, please copy the builtin-features.cpp file and respective directory to your project and modify the original declaration there, so that you may be sure it is only being declared once.