mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
[Tolk] Nullable types T?
and null safety
This commit introduces nullable types `T?` that are distinct from non-nullable `T`. Example: `int?` (int or null) and `int` are different now. Previously, `null` could be assigned to any primitive type. Now, it can be assigned only to `T?`. A non-null assertion operator `!` was also introduced, similar to `!` in TypeScript and `!!` in Kotlin. If `int?` still occupies 1 stack slot, `(int,int)?` and other nullable tensors occupy N+1 slots, the last for "null precedence". `v == null` actually compares that slot. Assigning `(int,int)` to `(int,int)?` implicitly creates a null presence slot. Assigning `null` to `(int,int)?` widens this null value to 3 slots. This is called "type transitioning". All stdlib functions prototypes have been updated to reflect whether they return/accept a nullable or a strict value. This commit also contains refactoring from `const FunctionData*` to `FunctionPtr` and similar.
This commit is contained in:
parent
1389ff6789
commit
f3e620f48c
62 changed files with 2031 additions and 702 deletions
|
@ -57,8 +57,46 @@ struct GenericsInstantiation {
|
|||
}
|
||||
};
|
||||
|
||||
// this class helps to deduce Ts on the fly
|
||||
// purpose: having `f<T>(value: T)` and call `f(5)`, deduce T = int
|
||||
// while analyzing a call, arguments are handled one by one, by `auto_deduce_from_argument()`
|
||||
// this class also handles manually specified substitutions like `f<int>(5)`
|
||||
class GenericSubstitutionsDeduceForCall {
|
||||
FunctionPtr fun_ref;
|
||||
std::vector<TypePtr> substitutionTs;
|
||||
bool manually_specified = false;
|
||||
|
||||
void provide_deducedT(const std::string& nameT, TypePtr deduced);
|
||||
void consider_next_condition(TypePtr param_type, TypePtr arg_type);
|
||||
|
||||
public:
|
||||
explicit GenericSubstitutionsDeduceForCall(FunctionPtr fun_ref);
|
||||
|
||||
bool is_manually_specified() const {
|
||||
return manually_specified;
|
||||
}
|
||||
|
||||
void provide_manually_specified(std::vector<TypePtr>&& substitutionTs);
|
||||
TypePtr replace_by_manually_specified(TypePtr param_type) const;
|
||||
TypePtr auto_deduce_from_argument(SrcLocation loc, TypePtr param_type, TypePtr arg_type);
|
||||
int get_first_not_deduced_idx() const;
|
||||
|
||||
std::vector<TypePtr>&& flush() {
|
||||
return std::move(substitutionTs);
|
||||
}
|
||||
};
|
||||
|
||||
struct GenericDeduceError final : std::exception {
|
||||
std::string message;
|
||||
explicit GenericDeduceError(std::string message)
|
||||
: message(std::move(message)) { }
|
||||
|
||||
const char* what() const noexcept override {
|
||||
return message.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
std::string generate_instantiated_name(const std::string& orig_name, const std::vector<TypePtr>& substitutions);
|
||||
td::Result<std::vector<TypePtr>> deduce_substitutionTs_on_generic_func_call(const FunctionData* called_fun, std::vector<TypePtr>&& arg_types, TypePtr return_hint);
|
||||
const FunctionData* instantiate_generic_function(SrcLocation loc, const FunctionData* fun_ref, const std::string& inst_name, std::vector<TypePtr>&& substitutionTs);
|
||||
FunctionPtr instantiate_generic_function(SrcLocation loc, FunctionPtr fun_ref, const std::string& inst_name, std::vector<TypePtr>&& substitutionTs);
|
||||
|
||||
} // namespace tolk
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue