Skip to content

Commit

Permalink
umbau für trennung decl/instances (zwischenstand)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jens-G committed Jan 24, 2025
1 parent 2a019a9 commit f304880
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 46 deletions.
10 changes: 10 additions & 0 deletions compiler/cpp/src/thrift/parse/t_program.h
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,16 @@ class t_program : public t_doc {

bool get_recursive() const { return recursive_; }

virtual t_typedef* instantiate_template_type(std::string symbolic, std::vector<t_type*>* tmpl_type) {
if ((tmpl_type == nullptr) || (tmpl_type->size() == 0)) {
return nullptr;
}

t_typedef* instance = new t_typedef(this, symbolic, tmpl_type);
scope()->add_type( instance->get_symbolic(), instance);
return instance;
}

private:
// File path
std::string path_;
Expand Down
1 change: 1 addition & 0 deletions compiler/cpp/src/thrift/parse/t_scope.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ class t_scope {
}
}


private:
// Map of names to types
std::map<std::string, t_type*> types_;
Expand Down
49 changes: 15 additions & 34 deletions compiler/cpp/src/thrift/parse/t_struct.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,50 +84,31 @@ class t_struct : public t_type {

void set_template_decl_type(std::vector<std::string>* tmpl_type) { tmpl_decl_type_ = tmpl_type; }

std::vector<std::string>* get_template_decl_type() const { return tmpl_decl_type_; }

void validate_template_instantiation() const {
if ((tmpl_decl_type_ == nullptr) || (get_template_instance_type() == nullptr)) {
if (tmpl_decl_type_ != nullptr) {
printf("Type %s is not generic and expects no type parameters\n", name_.c_str());
exit(1);
}
if (get_template_instance_type() != nullptr) {
printf("Missing type parameter for generic type %s\n", name_.c_str());
exit(1);
}
} else {
if (tmpl_decl_type_->size() != get_template_instance_type()->size()) {
printf("Generic type %s expects %d type parameters, but %d were specified\n",
name_.c_str(), tmpl_decl_type_->size(), get_template_instance_type()->size());
exit(1);
}
}
}

std::map<std::string, t_type*>* map_template_types() {
validate_template_instantiation();
virtual std::vector<std::string>* get_template_decl_type() const { return tmpl_decl_type_; }

virtual std::map<std::string, t_type*>* map_template_types() {
// generic?
if (tmpl_decl_type_ == nullptr) {
return nullptr;
}

if (tmpl_decl_type_->size() != tmpl_mapped_types_.size()) {
// already cached?
if (tmpl_mapped_decls_.size() > 0) {
return &tmpl_mapped_decls_;
}

// generic type = no instance types available
if (tmpl_decl_type_->size() != tmpl_mapped_decls_.size()) {
int expected_count = 0;
std::vector<std::string>::iterator itKey = tmpl_decl_type_->begin();
std::vector<t_type*>::iterator itVal = get_template_instance_type()->begin();
while ((tmpl_decl_type_->end() != itKey) && (get_template_instance_type()->end() != itVal)) {
tmpl_mapped_types_[*itKey] = *itVal;
if (++expected_count != tmpl_mapped_types_.size()) {
for( std::vector<std::string>::iterator itKey = tmpl_decl_type_->begin(); tmpl_decl_type_->end() != itKey; ++itKey) {
tmpl_mapped_decls_[*itKey] = nullptr; // no type yet, just generic
if (++expected_count != tmpl_mapped_decls_.size()) {
printf("Duplicate type parameter %s at %s\n", itKey->c_str(), name_.c_str());
exit(1);
}
++itKey;
++itVal;
}
}

return &tmpl_mapped_types_;
return &tmpl_mapped_decls_;
}

void set_xsd_all(bool xsd_all) { xsd_all_ = xsd_all; }
Expand Down Expand Up @@ -213,7 +194,7 @@ class t_struct : public t_type {
bool xcepts_validated_;
int members_with_value_;
std::vector<std::string>* tmpl_decl_type_;
std::map<std::string, t_type*> tmpl_mapped_types_;
std::map<std::string, t_type*> tmpl_mapped_decls_;

bool xsd_all_;

Expand Down
17 changes: 7 additions & 10 deletions compiler/cpp/src/thrift/parse/t_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,32 +88,29 @@ class t_type : public t_doc {

std::map<std::string, std::vector<std::string>> annotations_;

void instantiate_template_type(std::vector<t_type*>* tmpl_type) { tmpl_inst_type_ = tmpl_type; }
virtual std::vector<std::string>* get_template_decl_type() const { return nullptr; }
virtual std::vector<t_type*>* get_template_instance_type() const { return nullptr; }
virtual t_type* instantiate_template_type(std::vector<t_type*>* tmpl_type) { return nullptr; }
virtual std::map<std::string, t_type*>* map_template_types() { return nullptr; }

std::vector<t_type*>* get_template_instance_type() const { return tmpl_inst_type_; }

protected:
t_type()
: program_(nullptr),
tmpl_inst_type_(nullptr) { ; }
: program_(nullptr) { ; }

t_type(t_program* program)
: program_(program),
tmpl_inst_type_(nullptr) { ; }
: program_(program) { ; }

t_type(t_program* program, std::string name)
: program_(program),
name_(name),
tmpl_inst_type_(nullptr) { ; }
name_(name) { ; }

t_type(std::string name)
: program_(nullptr),
tmpl_inst_type_(nullptr),
name_(name) { ; }

t_program* program_;
std::string name_;
std::vector<t_type*>* tmpl_inst_type_;

};

Expand Down
74 changes: 73 additions & 1 deletion compiler/cpp/src/thrift/parse/t_typedef.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@
class t_typedef : public t_type {
public:
t_typedef(t_program* program, t_type* type, const std::string& symbolic)
: t_type(program, symbolic), type_(type), symbolic_(symbolic), forward_(false) {}
: t_type(program, symbolic),
type_(type),
tmpl_inst_type_(nullptr),
symbolic_(symbolic),
forward_(false) {}

/**
* This constructor is used to refer to a type that is lazily
Expand All @@ -43,10 +47,18 @@ class t_typedef : public t_type {
t_typedef(t_program* program, const std::string& symbolic, bool forward)
: t_type(program, symbolic),
type_(nullptr),
tmpl_inst_type_(nullptr),
symbolic_(symbolic),
forward_(forward)
{}

t_typedef(t_program* program, const std::string& symbolic, std::vector<t_type*>* tmpl_type)
: t_type(program, symbolic),
type_(nullptr),
tmpl_inst_type_(tmpl_type),
symbolic_(symbolic),
forward_(true) {}

~t_typedef() override = default;

t_type* get_type(std::map<std::string, t_type*>* generic = nullptr);
Expand All @@ -55,14 +67,74 @@ class t_typedef : public t_type {

const std::string& get_symbolic() const { return symbolic_; }

bool is_generic_instance() const { return (tmpl_inst_type_ != nullptr) && (tmpl_inst_type_->size() > 0); }

bool is_forward_typedef() const { return forward_; }

bool is_typedef() const override { return true; }

virtual std::vector<t_type*>* get_template_instance_type() const { return tmpl_inst_type_; }

virtual std::map<std::string, t_type*>* map_template_types() {
// already cached?
if (tmpl_mapped_generic_types_.size() > 0) {
return &tmpl_mapped_generic_types_;
}

// ensure all preconditions are in place
const t_type* ttype = get_type(nullptr);
const std::vector<std::string>* decls = ttype->get_template_decl_type();
validate_template_instantiation(decls);

// map generic types
std::vector<t_type*>* instance = get_template_instance_type();
if (decls->size() != tmpl_mapped_generic_types_.size()) {
int expected_count = 0;
std::vector<std::string>::const_iterator itKey = decls->begin();
std::vector<t_type*>::const_iterator itVal = instance->begin();
while ((decls->end() != itKey) && (instance->end() != itVal)) {
tmpl_mapped_generic_types_[*itKey] = *itVal;
if (++expected_count != tmpl_mapped_generic_types_.size()) {
printf("Duplicate type parameter %s at %s\n", itKey->c_str(), name_.c_str());
exit(1);
}
++itKey;
++itVal;
}
}

return &tmpl_mapped_generic_types_;
}


private:
t_type* type_;
std::string symbolic_;
bool forward_;
std::vector<t_type*>* tmpl_inst_type_;
std::map<std::string, t_type*> tmpl_mapped_generic_types_;

void validate_template_instantiation(const std::vector<std::string>* decls) const {
std::vector<t_type*>* instance = get_template_instance_type();

// both must be either null or non-null
if ((decls == nullptr) ^ (instance != nullptr)) {
if (decls == nullptr) {
printf("Type %s is not generic and expects no type parameters\n", name_.c_str());
exit(1);
} else {
printf("Missing type parameter for generic type %s\n", name_.c_str());
exit(1);
}
}

// same number of type parameters expected
if (decls->size() != instance->size()) {
printf("Generic type %s expects %d type parameters, but %d were specified\n",
name_.c_str(), decls->size(), instance->size());
exit(1);
}
}
};

#endif
7 changes: 6 additions & 1 deletion compiler/cpp/src/thrift/thrifty.yy
Original file line number Diff line number Diff line change
Expand Up @@ -1210,7 +1210,12 @@ FieldType:
*/
$$ = new t_typedef(g_program, $1, true);
}
$$->instantiate_template_type($2);

// generics instantiation
t_type* instance = $$->instantiate_template_type($2);
if( instance != nullptr) {
$$ = instance;
}
}
}
| BaseType
Expand Down

0 comments on commit f304880

Please sign in to comment.