From be013ef7f1cf63b3868c41e7e14963a77a4deca1 Mon Sep 17 00:00:00 2001 From: "Justin R. Wilson" Date: Sun, 21 Feb 2016 23:09:55 -0600 Subject: [PATCH] Implement are_identical for Struct types References #73 --- src/Makefile.am | 1 + src/Makefile.in | 1 + src/executor_base.cpp | 120 ++++++++++++------------ src/executor_base.hpp | 90 +++++++++++------- src/field.hpp | 12 ++- src/generate_code.cpp | 18 ++-- src/instance_scheduler.cpp | 36 +++---- src/main.cpp | 187 ++++++++++++++++++++----------------- src/package.hpp | 9 ++ src/process_type_spec.cpp | 4 +- src/symbol_table.hpp | 5 + src/type.cpp | 75 +++++++++++++-- src/type.hpp | 26 ++++-- src/types.hpp | 5 +- src/util.hpp | 5 + utest/type.cpp | 61 ++++++++++-- 16 files changed, 422 insertions(+), 233 deletions(-) create mode 100644 src/package.hpp diff --git a/src/Makefile.am b/src/Makefile.am index e8b2e05..e4861e4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -26,6 +26,7 @@ executor_base.hpp executor_base.cpp \ field.hpp \ generate_code.hpp generate_code.cpp \ instance_scheduler.hpp instance_scheduler.cpp \ +package.hpp \ parser.hpp parser.cpp \ partitioned_scheduler.hpp partitioned_scheduler.cpp \ process_definitions.cpp \ diff --git a/src/Makefile.in b/src/Makefile.in index 13f1578..68506b9 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -349,6 +349,7 @@ executor_base.hpp executor_base.cpp \ field.hpp \ generate_code.hpp generate_code.cpp \ instance_scheduler.hpp instance_scheduler.cpp \ +package.hpp \ parser.hpp parser.cpp \ partitioned_scheduler.hpp partitioned_scheduler.cpp \ process_definitions.cpp \ diff --git a/src/executor_base.cpp b/src/executor_base.cpp index f4d53ff..db1b1a7 100644 --- a/src/executor_base.cpp +++ b/src/executor_base.cpp @@ -2,76 +2,80 @@ #include "runtime.hpp" #include "composition.hpp" -namespace runtime { +namespace runtime +{ - bool ExecutorBase::execute (const composition::Action* action) - { - Event* e = begin_event (); - bool enabled = runtime::enabled (*this, action->instance->component, action->action, action->iota); - end_event (e, enabled ? Event::Precondition_True : Event::Precondition_False, action); +bool ExecutorBase::execute (const composition::Action* action) +{ + Event* e = begin_event (); + bool enabled = runtime::enabled (*this, action->instance->component, action->action, action->iota); + end_event (e, enabled ? Event::Precondition_True : Event::Precondition_False, action); - if (enabled) - { - e = begin_event (); - runtime::execute_no_check (*this, action->instance->component, action->action, action->iota); - end_event (e, Event::Action, action); - } + if (enabled) + { + e = begin_event (); + runtime::execute_no_check (*this, action->instance->component, action->action, action->iota); + end_event (e, Event::Action, action); + } - return enabled; - } + return enabled; +} - void ExecutorBase::execute_no_check (const composition::Action* action) - { - Event* e = begin_event (); - runtime::execute_no_check (*this, action->instance->component, action->action, action->iota); - end_event (e, Event::Action, action); - } +void ExecutorBase::execute_no_check (const composition::Action* action) +{ + Event* e = begin_event (); + runtime::execute_no_check (*this, action->instance->component, action->action, action->iota); + end_event (e, Event::Action, action); +} - bool ExecutorBase::collect_garbage (ComponentInfoBase* info) - { - this->current_info (info); - Event* e = begin_event (); - bool gc = this->heap ()->collect_garbage (); - end_event (e, gc ? Event::Garbage_Collection_True : Event::Garbage_Collection_False, info); - return gc; - } +bool ExecutorBase::collect_garbage (ComponentInfoBase* info) +{ + this->current_info (info); + Event* e = begin_event (); + bool gc = this->heap ()->collect_garbage (); + end_event (e, gc ? Event::Garbage_Collection_True : Event::Garbage_Collection_False, info); + return gc; +} - void ExecutorBase::fini (FILE* profile_out, size_t thread) - { - if (!events_.empty ()) { +void ExecutorBase::fini (FILE* profile_out, size_t thread) +{ + if (!events_.empty ()) + { fprintf (profile_out, "BEGIN thread %zd%s\n", thread, event_full_ ? " OVERFLOW" : ""); for (EventsType::const_iterator pos = events_.begin (), - limit = event_full_ ? events_.end () : events_.begin () + event_idx_; + limit = event_full_ ? events_.end () : events_.begin () + event_idx_; pos != limit; - ++pos) { - switch (pos->type) { - case Event::Precondition_True: - fprintf (profile_out, "PRECONDITION_TRUE %s %ld.%.09ld %ld.%.09ld\n", pos->action->name.c_str (), pos->begin.tv_sec, pos->begin.tv_nsec, pos->end.tv_sec, pos->end.tv_nsec); - break; - case Event::Precondition_False: - fprintf (profile_out, "PRECONDITION_FALSE %s %ld.%.09ld %ld.%.09ld\n", pos->action->name.c_str (), pos->begin.tv_sec, pos->begin.tv_nsec, pos->end.tv_sec, pos->end.tv_nsec); - break; - case Event::Action: - fprintf (profile_out, "ACTION %s %ld.%.09ld %ld.%.09ld\n", pos->action->name.c_str (), pos->begin.tv_sec, pos->begin.tv_nsec, pos->end.tv_sec, pos->end.tv_nsec); - break; - case Event::Garbage_Collection_True: - fprintf (profile_out, "GARBAGE_COLLECTION_TRUE %s %ld.%.09ld %ld.%.09ld\n", pos->info->instance ()->name.c_str (), pos->begin.tv_sec, pos->begin.tv_nsec, pos->end.tv_sec, pos->end.tv_nsec); - break; - case Event::Garbage_Collection_False: - fprintf (profile_out, "GARBAGE_COLLECTION_FALSE %s %ld.%.09ld %ld.%.09ld\n", pos->info->instance ()->name.c_str (), pos->begin.tv_sec, pos->begin.tv_nsec, pos->end.tv_sec, pos->end.tv_nsec); - break; + ++pos) + { + switch (pos->type) + { + case Event::Precondition_True: + fprintf (profile_out, "PRECONDITION_TRUE %s %ld.%.09ld %ld.%.09ld\n", pos->action->name.c_str (), pos->begin.tv_sec, pos->begin.tv_nsec, pos->end.tv_sec, pos->end.tv_nsec); + break; + case Event::Precondition_False: + fprintf (profile_out, "PRECONDITION_FALSE %s %ld.%.09ld %ld.%.09ld\n", pos->action->name.c_str (), pos->begin.tv_sec, pos->begin.tv_nsec, pos->end.tv_sec, pos->end.tv_nsec); + break; + case Event::Action: + fprintf (profile_out, "ACTION %s %ld.%.09ld %ld.%.09ld\n", pos->action->name.c_str (), pos->begin.tv_sec, pos->begin.tv_nsec, pos->end.tv_sec, pos->end.tv_nsec); + break; + case Event::Garbage_Collection_True: + fprintf (profile_out, "GARBAGE_COLLECTION_TRUE %s %ld.%.09ld %ld.%.09ld\n", pos->info->instance ()->name.c_str (), pos->begin.tv_sec, pos->begin.tv_nsec, pos->end.tv_sec, pos->end.tv_nsec); + break; + case Event::Garbage_Collection_False: + fprintf (profile_out, "GARBAGE_COLLECTION_FALSE %s %ld.%.09ld %ld.%.09ld\n", pos->info->instance ()->name.c_str (), pos->begin.tv_sec, pos->begin.tv_nsec, pos->end.tv_sec, pos->end.tv_nsec); + break; + } } - } fprintf (profile_out, "END thread %zd\n", thread); } - } +} - ComponentInfoBase::ComponentInfoBase (composition::Instance* instance) - : instance_ (instance) - , heap_ (new Heap (instance->component, instance->type->Size ())) - { - // Link the instance to its scheduling information. - *reinterpret_cast (instance->component) = this; - } +ComponentInfoBase::ComponentInfoBase (composition::Instance* instance) + : instance_ (instance) + , heap_ (new Heap (instance->component, instance->type->Size ())) +{ + // Link the instance to its scheduling information. + *reinterpret_cast (instance->component) = this; +} } diff --git a/src/executor_base.hpp b/src/executor_base.hpp index 48f59ee..5e7cba7 100644 --- a/src/executor_base.hpp +++ b/src/executor_base.hpp @@ -24,15 +24,25 @@ class FileDescriptor friend class ExecutorBase; }; - struct ComponentInfoBase { - ComponentInfoBase (composition::Instance* instance); - composition::Instance* instance () const { return instance_; } - Heap* heap () const { return heap_; } - void heap (Heap* h) { heap_ = h; } - private: - composition::Instance* instance_; - Heap* heap_; - }; +struct ComponentInfoBase +{ + ComponentInfoBase (composition::Instance* instance); + composition::Instance* instance () const + { + return instance_; + } + Heap* heap () const + { + return heap_; + } + void heap (Heap* h) + { + heap_ = h; + } +private: + composition::Instance* instance_; + Heap* heap_; +}; class ExecutorBase { @@ -53,8 +63,14 @@ class ExecutorBase { return stack_; } - runtime::Heap* heap () const { return current_info_->heap (); } - void heap (runtime::Heap* heap) { current_info_->heap (heap); } + runtime::Heap* heap () const + { + return current_info_->heap (); + } + void heap (runtime::Heap* heap) + { + current_info_->heap (heap); + } ComponentInfoBase* current_info () const { return current_info_; @@ -103,15 +119,18 @@ class ExecutorBase void fini (FILE* profile_out, size_t thread); private: - struct Event { - enum Type { + struct Event + { + enum Type + { Precondition_True, Precondition_False, Action, Garbage_Collection_True, Garbage_Collection_False, } type; - union { + union + { const composition::Action* action; ComponentInfoBase* info; }; @@ -122,31 +141,34 @@ class ExecutorBase Event* begin_event () { Event* e = NULL; - if (!events_.empty ()) { - e = &events_[event_idx_]; - event_idx_ = (event_idx_ + 1) & (events_.size () - 1); - event_full_ = event_full_ || (event_idx_ == 0); - clock_gettime (CLOCK_MONOTONIC, &e->begin); - } + if (!events_.empty ()) + { + e = &events_[event_idx_]; + event_idx_ = (event_idx_ + 1) & (events_.size () - 1); + event_full_ = event_full_ || (event_idx_ == 0); + clock_gettime (CLOCK_MONOTONIC, &e->begin); + } return e; } void end_event (Event* e, Event::Type type, const composition::Action* action) { - if (e) { - clock_gettime (CLOCK_MONOTONIC, &e->end); - e->type = type; - e->action = action; - } + if (e) + { + clock_gettime (CLOCK_MONOTONIC, &e->end); + e->type = type; + e->action = action; + } } void end_event (Event* e, Event::Type type, ComponentInfoBase* info) { - if (e) { - clock_gettime (CLOCK_MONOTONIC, &e->end); - e->type = type; - e->info = info; - } + if (e) + { + clock_gettime (CLOCK_MONOTONIC, &e->end); + e->type = type; + e->info = info; + } } runtime::Stack stack_; @@ -159,10 +181,10 @@ class ExecutorBase bool event_full_; }; - inline ComponentInfoBase* component_to_info (component_t* component) - { - return *reinterpret_cast (component); - } +inline ComponentInfoBase* component_to_info (component_t* component) +{ + return *reinterpret_cast (component); +} } diff --git a/src/field.hpp b/src/field.hpp index 7aa86a4..54cca81 100644 --- a/src/field.hpp +++ b/src/field.hpp @@ -1,6 +1,8 @@ #ifndef RC_SRC_FIELD_HPP #define RC_SRC_FIELD_HPP +#include + #include "types.hpp" namespace type @@ -8,13 +10,19 @@ namespace type struct Field { + decl::Package* const package; + bool const is_anonymous; std::string const name; const type::Type* const type; + TagSet const tags; ptrdiff_t const offset; - Field (const std::string& n, const type::Type* t, ptrdiff_t o) - : name (n) + Field (decl::Package* p, bool a, const std::string& n, const type::Type* t, const TagSet& tgs, ptrdiff_t o) + : package (p) + , is_anonymous (a) + , name (n) , type (t) + , tags (tgs) , offset (o) { } }; diff --git a/src/generate_code.cpp b/src/generate_code.cpp index 4670d46..e061a90 100644 --- a/src/generate_code.cpp +++ b/src/generate_code.cpp @@ -19,15 +19,15 @@ using namespace type; using namespace semantic; using namespace decl; - static Operation* load (Node* node, Operation* op) - { - assert (node->expression_kind != kUnknown); - if (node->expression_kind == kVariable) - { - return new Load (op, node->type); - } - return op; - } +static Operation* load (Node* node, Operation* op) +{ + assert (node->expression_kind != kUnknown); + if (node->expression_kind == kVariable) + { + return new Load (op, node->type); + } + return op; +} struct CodeGenVisitor : public ast::DefaultVisitor { diff --git a/src/instance_scheduler.cpp b/src/instance_scheduler.cpp index e27dea9..f40d5e4 100644 --- a/src/instance_scheduler.cpp +++ b/src/instance_scheduler.cpp @@ -116,7 +116,7 @@ instance_scheduler_t::instance_executor_t::run_i () // Try all the actions. for (composition::ActionsType::const_iterator pos = record->instance ()->actions.begin (), - limit = record->instance ()->actions.end (); + limit = record->instance ()->actions.end (); pos != limit; ++pos) { @@ -162,7 +162,7 @@ instance_scheduler_t::init (Composer& instance_table, // Initialize. instance_executor_t exec (*this, stack_size, 0); for (InfoMapType::const_iterator pos = info_map_.begin (), - limit = info_map_.end (); + limit = info_map_.end (); pos != limit; ++pos) { @@ -177,27 +177,27 @@ instance_scheduler_t::init (Composer& instance_table, } } - void instance_scheduler_t::run () - { - for (size_t idx = 0; idx != executors_.size (); ++idx) - { - executors_[idx]->spawn (); - } +void instance_scheduler_t::run () +{ + for (size_t idx = 0; idx != executors_.size (); ++idx) + { + executors_[idx]->spawn (); + } - for (size_t idx = 0; idx != executors_.size (); ++idx) - { - executors_[idx]->join (); - } - } + for (size_t idx = 0; idx != executors_.size (); ++idx) + { + executors_[idx]->join (); + } +} - void - instance_scheduler_t::fini (FILE* profile_out) - { - for (size_t idx = 0; idx != executors_.size (); ++idx) +void +instance_scheduler_t::fini (FILE* profile_out) +{ + for (size_t idx = 0; idx != executors_.size (); ++idx) { executors_[idx]->fini (profile_out, idx); delete executors_[idx]; } - } +} } diff --git a/src/main.cpp b/src/main.cpp index 7c598a1..4841d19 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -124,17 +124,21 @@ main (int argc, char **argv) srand (atoi (optarg)); break; case PROFILE_OPTION: - if (optarg) { - profile = atoi (optarg); - } else { - profile = 4096; - } + if (optarg) + { + profile = atoi (optarg); + } + else + { + profile = 4096; + } break; case PROFILE_OUT_OPTION: profile_out = fopen (optarg, "w"); - if (profile_out == NULL) { - error (EXIT_FAILURE, errno, "Could not open %s for writing", optarg); - } + if (profile_out == NULL) + { + error (EXIT_FAILURE, errno, "Could not open %s for writing", optarg); + } break; default: @@ -154,27 +158,30 @@ main (int argc, char **argv) error (EXIT_FAILURE, 0, "Illegal thread count: %d", thread_count); } - if (profile) { - fprintf (profile_out, "BEGIN profile\n"); - fprintf (profile_out, "scheduler %s\n", scheduler_type.c_str ()); + if (profile) + { + fprintf (profile_out, "BEGIN profile\n"); + fprintf (profile_out, "scheduler %s\n", scheduler_type.c_str ()); - int e = 1; - while ((1 << e) < profile && e < 31) { - ++e; - } - profile = 1 << e; - fprintf (profile_out, "points_per_thread %zd\n", profile); + int e = 1; + while ((1 << e) < profile && e < 31) + { + ++e; + } + profile = 1 << e; + fprintf (profile_out, "points_per_thread %zd\n", profile); - struct timespec res; - clock_getres (CLOCK_MONOTONIC, &res); - fprintf (profile_out, "resolution %ld.%.09ld\n", res.tv_sec, res.tv_nsec); - } + struct timespec res; + clock_getres (CLOCK_MONOTONIC, &res); + fprintf (profile_out, "resolution %ld.%.09ld\n", res.tv_sec, res.tv_nsec); + } - if (profile) { - struct timespec res; - clock_gettime (CLOCK_MONOTONIC, &res); - fprintf (profile_out, "BEGIN parse %ld.%.09ld\n", res.tv_sec, res.tv_nsec); - } + if (profile) + { + struct timespec res; + clock_gettime (CLOCK_MONOTONIC, &res); + fprintf (profile_out, "BEGIN parse %ld.%.09ld\n", res.tv_sec, res.tv_nsec); + } util::Location::StaticFile = argv[optind]; @@ -192,17 +199,19 @@ main (int argc, char **argv) } assert (root != NULL); - if (profile) { - struct timespec res; - clock_gettime (CLOCK_MONOTONIC, &res); - fprintf (profile_out, "END parse %ld.%.09ld\n", res.tv_sec, res.tv_nsec); - } + if (profile) + { + struct timespec res; + clock_gettime (CLOCK_MONOTONIC, &res); + fprintf (profile_out, "END parse %ld.%.09ld\n", res.tv_sec, res.tv_nsec); + } - if (profile) { - struct timespec res; - clock_gettime (CLOCK_MONOTONIC, &res); - fprintf (profile_out, "BEGIN semantic_analysis %ld.%.09ld\n", res.tv_sec, res.tv_nsec); - } + if (profile) + { + struct timespec res; + clock_gettime (CLOCK_MONOTONIC, &res); + fprintf (profile_out, "BEGIN semantic_analysis %ld.%.09ld\n", res.tv_sec, res.tv_nsec); + } arch::set_stack_alignment (sizeof (void*)); @@ -215,17 +224,19 @@ main (int argc, char **argv) semantic::check_types (root, er, symtab); semantic::compute_receiver_access (root); - if (profile) { - struct timespec res; - clock_gettime (CLOCK_MONOTONIC, &res); - fprintf (profile_out, "END semantic_analysis %ld.%.09ld\n", res.tv_sec, res.tv_nsec); - } + if (profile) + { + struct timespec res; + clock_gettime (CLOCK_MONOTONIC, &res); + fprintf (profile_out, "END semantic_analysis %ld.%.09ld\n", res.tv_sec, res.tv_nsec); + } - if (profile) { - struct timespec res; - clock_gettime (CLOCK_MONOTONIC, &res); - fprintf (profile_out, "BEGIN code_generation %ld.%.09ld\n", res.tv_sec, res.tv_nsec); - } + if (profile) + { + struct timespec res; + clock_gettime (CLOCK_MONOTONIC, &res); + fprintf (profile_out, "BEGIN code_generation %ld.%.09ld\n", res.tv_sec, res.tv_nsec); + } // Calculate the offsets of all stack variables. // Do this so we can execute some code statically when checking composition. @@ -234,17 +245,19 @@ main (int argc, char **argv) // Generate code. code::generate_code (root); - if (profile) { - struct timespec res; - clock_gettime (CLOCK_MONOTONIC, &res); - fprintf (profile_out, "END code_generation %ld.%.09ld\n", res.tv_sec, res.tv_nsec); - } + if (profile) + { + struct timespec res; + clock_gettime (CLOCK_MONOTONIC, &res); + fprintf (profile_out, "END code_generation %ld.%.09ld\n", res.tv_sec, res.tv_nsec); + } - if (profile) { - struct timespec res; - clock_gettime (CLOCK_MONOTONIC, &res); - fprintf (profile_out, "BEGIN composition_check %ld.%.09ld\n", res.tv_sec, res.tv_nsec); - } + if (profile) + { + struct timespec res; + clock_gettime (CLOCK_MONOTONIC, &res); + fprintf (profile_out, "BEGIN composition_check %ld.%.09ld\n", res.tv_sec, res.tv_nsec); + } // Check composition. composition::Composer instance_table; @@ -257,17 +270,19 @@ main (int argc, char **argv) } instance_table.analyze (); - if (profile) { - struct timespec res; - clock_gettime (CLOCK_MONOTONIC, &res); - fprintf (profile_out, "END composition_check %ld.%.09ld\n", res.tv_sec, res.tv_nsec); - } + if (profile) + { + struct timespec res; + clock_gettime (CLOCK_MONOTONIC, &res); + fprintf (profile_out, "END composition_check %ld.%.09ld\n", res.tv_sec, res.tv_nsec); + } - if (profile) { - struct timespec res; - clock_gettime (CLOCK_MONOTONIC, &res); - fprintf (profile_out, "BEGIN scheduler_init %ld.%.09ld\n", res.tv_sec, res.tv_nsec); - } + if (profile) + { + struct timespec res; + clock_gettime (CLOCK_MONOTONIC, &res); + fprintf (profile_out, "BEGIN scheduler_init %ld.%.09ld\n", res.tv_sec, res.tv_nsec); + } runtime::allocate_instances (instance_table); runtime::create_bindings (instance_table); @@ -288,31 +303,35 @@ main (int argc, char **argv) scheduler->init (instance_table, 8 * 1024, thread_count, profile); - if (profile) { - struct timespec res; - clock_gettime (CLOCK_MONOTONIC, &res); - fprintf (profile_out, "END scheduler_init %ld.%.09ld\n", res.tv_sec, res.tv_nsec); - } + if (profile) + { + struct timespec res; + clock_gettime (CLOCK_MONOTONIC, &res); + fprintf (profile_out, "END scheduler_init %ld.%.09ld\n", res.tv_sec, res.tv_nsec); + } - if (profile) { - struct timespec res; - clock_gettime (CLOCK_MONOTONIC, &res); - fprintf (profile_out, "BEGIN scheduler_run %ld.%.09ld\n", res.tv_sec, res.tv_nsec); - } + if (profile) + { + struct timespec res; + clock_gettime (CLOCK_MONOTONIC, &res); + fprintf (profile_out, "BEGIN scheduler_run %ld.%.09ld\n", res.tv_sec, res.tv_nsec); + } scheduler->run (); - if (profile) { - struct timespec res; - clock_gettime (CLOCK_MONOTONIC, &res); - fprintf (profile_out, "END scheduler_run %ld.%.09ld\n", res.tv_sec, res.tv_nsec); - } + if (profile) + { + struct timespec res; + clock_gettime (CLOCK_MONOTONIC, &res); + fprintf (profile_out, "END scheduler_run %ld.%.09ld\n", res.tv_sec, res.tv_nsec); + } scheduler->fini (profile_out); - if (profile) { - fprintf (profile_out, "END profile\n"); - } + if (profile) + { + fprintf (profile_out, "END profile\n"); + } return 0; } diff --git a/src/package.hpp b/src/package.hpp new file mode 100644 index 0000000..8bdc90c --- /dev/null +++ b/src/package.hpp @@ -0,0 +1,9 @@ +#ifndef RC_SRC_PACKAGE_HPP +#define RC_SRC_PACKAGE_HPP + +namespace decl +{ +struct Package { }; +} + +#endif // RC_SRC_PACKAGE_HPP diff --git a/src/process_type_spec.cpp b/src/process_type_spec.cpp index 7ee6108..8993bed 100644 --- a/src/process_type_spec.cpp +++ b/src/process_type_spec.cpp @@ -107,7 +107,7 @@ process_type (Node* node, ErrorReporter& er, decl::SymbolTable& symtab, bool for Struct* field_list; if (node.is_component) { - field_list = new Component (); + field_list = new Component (symtab.package ()); } else { @@ -133,7 +133,7 @@ process_type (Node* node, ErrorReporter& er, decl::SymbolTable& symtab, bool for const type::Type *field = field_list->select (identifier); if (field == NULL) { - field_list->append_field (identifier, type); + field_list->append_field (symtab.package (), false, identifier, type, TagSet ()); } else { diff --git a/src/symbol_table.hpp b/src/symbol_table.hpp index 0c6debf..b6b8c4f 100644 --- a/src/symbol_table.hpp +++ b/src/symbol_table.hpp @@ -25,6 +25,11 @@ struct SymbolTable Symbol* find_global_symbol (const std::string& identifier) const; Symbol* find_local_symbol (const std::string& identifier) const; + Package* package () const + { + return NULL; + } + private: struct Scope; Scope* current_scope_; diff --git a/src/type.cpp b/src/type.cpp index 556ebd5..83d03e8 100644 --- a/src/type.cpp +++ b/src/type.cpp @@ -183,13 +183,29 @@ NamedType::get_bind (const std::string& identifier) const return NULL; } +std::string +Struct::to_string () const +{ + std::stringstream ss; + ss << '{'; + for (FieldsType::const_iterator pos = fields_.begin (), limit = fields_.end (); + pos != limit; + ++pos) + { + Field* f = *pos; + ss << f->name << ' ' << *(f->type) << ';'; + } + ss << '}'; + return ss.str (); +} + Struct* -Struct::append_field (const std::string& field_name, const Type* field_type) +Struct::append_field (Package* package, bool is_anonymous, const std::string& field_name, const Type* field_type, const TagSet& tags) { size_t alignment = field_type->Alignment (); offset_ = util::align_up (offset_, alignment); - Field *field = new Field (field_name, field_type, offset_); + Field *field = new Field (package, is_anonymous, field_name, field_type, tags, offset_); fields_.push_back (field); offset_ += field_type->Size (); @@ -379,7 +395,44 @@ struct IdenticalImpl void operator() (const Struct& type1, const Struct& type2) { - UNIMPLEMENTED; + retval = false; + if (type1.field_count () != type2.field_count ()) + { + return; + } + + Struct::const_iterator pos1 = type1.Begin (); + Struct::const_iterator limit1 = type1.End (); + Struct::const_iterator pos2 = type2.Begin (); + Struct::const_iterator limit2 = type2.End (); + + for (; pos1 != limit1 && pos2 != limit2; ++pos1, ++pos2) + { + Field* f1 = *pos1; + Field* f2 = *pos2; + if (f1->is_anonymous != f2->is_anonymous) + { + return; + } + if (!f1->is_anonymous && f1->name != f2->name) + { + return; + } + if (!f1->is_anonymous && util::is_lowercase (f1->name) && f1->package != f2->package) + { + return; + } + if (!are_identical (f1->type, f2->type)) + { + return; + } + if (f1->tags != f2->tags) + { + return; + } + } + + retval = true; } void operator() (const Pointer& type1, const Pointer& type2) @@ -503,13 +556,15 @@ INSTANCE(Float) INSTANCE(Complex) INSTANCE(String) -Struct::Struct (bool insert_runtime) : offset_ (0), alignment_ (0) +Struct::Struct () : offset_ (0), alignment_ (0) { - if (insert_runtime) - { - /* Prepend the field list with a pointer for the runtime. */ - append_field ("0runtime", Void::Instance ()->get_pointer ()); - } +} + +Component::Component (Package* package) + : Struct () +{ + /* Prepend the field list with a pointer for the runtime. */ + append_field (package, true, "0runtime", Void::Instance ()->get_pointer (), TagSet ()); } const Type* type_dereference (const Type* type) @@ -1461,6 +1516,6 @@ NamedType named_uintptr ("uintptr", Uintptr::Instance ()); NamedType named_string ("string", StringU::Instance ()); NamedType named_file_descriptor ("FileDescriptor", FileDescriptor::Instance ()); -NamedType named_timespec ("timespec", (new Struct ())->append_field ("tv_sec", &named_uint64)->append_field ("tv_nsec", &named_uint64)); +NamedType named_timespec ("timespec", (new Struct ())->append_field (NULL, false, "tv_sec", &named_uint64, TagSet ())->append_field (NULL, false, "tv_nsec", &named_uint64, TagSet ())); } diff --git a/src/type.hpp b/src/type.hpp index 98b8d54..bf8bcb3 100644 --- a/src/type.hpp +++ b/src/type.hpp @@ -764,16 +764,13 @@ class Struct : public Type public: typedef std::vector FieldsType; typedef FieldsType::const_iterator const_iterator; - Struct (bool insert_runtime = false); + Struct (); void Accept (Visitor& visitor) const; virtual Kind kind () const { return kStruct; } - std::string to_string () const - { - UNIMPLEMENTED; - } + std::string to_string () const; size_t Alignment () const { return alignment_; @@ -794,9 +791,13 @@ class Struct : public Type { return fields_.end (); } - Struct* append_field (const std::string& field_name, const Type* field_type); + Struct* append_field (decl::Package* package, bool is_anonymous, const std::string& field_name, const Type* field_type, const TagSet& tags); Field* get_field_i (const std::string& name) const; virtual Field* select_field (const std::string& name) const; + size_t field_count () const + { + return fields_.size (); + } private: FieldsType fields_; ptrdiff_t offset_; @@ -805,7 +806,8 @@ class Struct : public Type struct Component : public Struct { - Component () : Struct (true) { } + Component (decl::Package* package); + virtual Kind kind () const { return kComponent; @@ -2331,6 +2333,11 @@ struct visitor2 : public DefaultVisitor t (type1, type2); } + void visit (const Struct& type2) + { + t (type1, type2); + } + void visit (const Boolean& type2) { t (type1, type2); @@ -2472,6 +2479,11 @@ struct visitor1 : public DefaultVisitor doubleDispatchHelper (type, type2, t); } + void visit (const Struct& type) + { + doubleDispatchHelper (type, type2, t); + } + void visit (const Boolean& type) { doubleDispatchHelper (type, type2, t); diff --git a/src/types.hpp b/src/types.hpp index aeea97c..b84d510 100644 --- a/src/types.hpp +++ b/src/types.hpp @@ -4,8 +4,9 @@ #include #include -#include #include +#include +#include #include "debug.hpp" @@ -100,6 +101,7 @@ class Type; class NamedType; class Signature; class Field; +typedef std::set TagSet; } namespace decl @@ -120,6 +122,7 @@ class Getter; class Initializer; class Method; class Bind; +class Package; } namespace composition diff --git a/src/util.hpp b/src/util.hpp index b00e064..6850988 100644 --- a/src/util.hpp +++ b/src/util.hpp @@ -12,6 +12,11 @@ inline ptrdiff_t align_up (ptrdiff_t value, size_t alignment) return (value + (alignment - 1)) & ~(alignment - 1); } +inline bool is_lowercase (const std::string& s) +{ + return !s.empty () && islower (s[0]); +} + } #endif // RC_SRC_UTIL_HPP diff --git a/utest/type.cpp b/utest/type.cpp index fea0289..eaea42b 100644 --- a/utest/type.cpp +++ b/utest/type.cpp @@ -4,6 +4,7 @@ #include "action.hpp" #include "reaction.hpp" #include "bind.hpp" +#include "package.hpp" using namespace type; using namespace decl; @@ -50,7 +51,7 @@ main (int argc, char** argv) } { - NamedType foo ("foo", new Component ()); + NamedType foo ("foo", new Component (NULL)); Action* r1 = foo.get_action ("r"); Action* r = new Action (NULL, NULL, "r"); foo.insert_action (r); @@ -59,7 +60,7 @@ main (int argc, char** argv) } { - NamedType foo ("foo", new Component ()); + NamedType foo ("foo", new Component (NULL)); Reaction* r1 = foo.get_reaction ("r"); Reaction* r = new Reaction (NULL, NULL, "r", NULL); foo.insert_reaction (r); @@ -68,7 +69,7 @@ main (int argc, char** argv) } { - NamedType foo ("foo", new Component ()); + NamedType foo ("foo", new Component (NULL)); Bind* r1 = foo.get_bind ("r"); Bind* r = new Bind (NULL, "r", NULL); foo.insert_bind (r); @@ -78,7 +79,7 @@ main (int argc, char** argv) { util::Location loc; - NamedType foo ("foo", new Component ()); + NamedType foo ("foo", new Component (NULL)); decl::Method* r1 = foo.get_method ("r"); decl::Method* r = new decl::Method (NULL, "r", new type::Method (type::Method::METHOD, &foo, ParameterSymbol::makeReceiver (loc, "", &type::named_int, Mutable, Mutable), new Signature (), ParameterSymbol::makeReturn (loc, "", &type::named_int, Immutable))); foo.insert_method (r); @@ -88,7 +89,7 @@ main (int argc, char** argv) { util::Location loc; - NamedType foo ("foo", new Component ()); + NamedType foo ("foo", new Component (NULL)); Initializer* r1 = foo.get_initializer ("r"); Initializer* r = new Initializer (NULL, "r", new type::Method (type::Method::INITIALIZER, &foo, ParameterSymbol::makeReceiver (loc, "", &type::named_int, Mutable, Mutable), new Signature (), ParameterSymbol::makeReturn (loc, "", &type::named_int, Immutable))); foo.insert_initializer (r); @@ -98,7 +99,7 @@ main (int argc, char** argv) { util::Location loc; - NamedType foo ("foo", new Component ()); + NamedType foo ("foo", new Component (NULL)); Getter* r1 = foo.get_getter ("r"); Getter* r = new Getter (NULL, "r", new type::Method (type::Method::GETTER, &foo, ParameterSymbol::makeReceiver (loc, "", &type::named_int, Mutable, Mutable), new Signature (), ParameterSymbol::makeReturn (loc, "", &type::named_int, Immutable))); foo.insert_getter (r); @@ -106,10 +107,16 @@ main (int argc, char** argv) tap.tassert ("NamedType::get_getter", r1 == NULL && r2 == r); } + { + Struct s; + s.append_field (NULL, false, "r", &named_int, TagSet ()); + tap.tassert ("Struct::to_string", s.to_string () == "{r int;}"); + } + { Struct s; Field* f1 = s.get_field ("r"); - s.append_field ("r", &named_int); + s.append_field (NULL, false, "r", &named_int, TagSet ()); Field* f2 = s.get_field ("r"); tap.tassert ("Struct::get_field", f1 == NULL && f2 != NULL); } @@ -118,7 +125,7 @@ main (int argc, char** argv) util::Location loc; Struct s; - s.append_field ("field", &named_int); + s.append_field (NULL, false, "field", &named_int, TagSet ()); NamedType nt ("foo", &s); @@ -218,6 +225,44 @@ main (int argc, char** argv) tap.tassert ("type::are_identical - slice different type", !are_identical (named_int.get_slice (), named_float32.get_slice ())); } + { + Struct* s1 = (new Struct ())->append_field (NULL, false, "x", &named_int, TagSet ()); + Struct* s2 = (new Struct ())->append_field (NULL, false, "x", &named_int, TagSet ()); + tap.tassert ("type::are_identical - struct same", are_identical (s1, s2)); + } + { + Struct* s1 = (new Struct ())->append_field (NULL, true, "T", &named_int, TagSet ()); + Struct* s2 = (new Struct ())->append_field (NULL, true, "T", &named_int, TagSet ()); + tap.tassert ("type::are_identical - struct same anonymous field", are_identical (s1, s2)); + } + { + Struct* s1 = (new Struct ())->append_field (NULL, false, "T", &named_int, TagSet ()); + Struct* s2 = (new Struct ())->append_field (NULL, true, "T", &named_int, TagSet ()); + tap.tassert ("type::are_identical - struct different anonymous field", !are_identical (s1, s2)); + } + { + Struct* s1 = (new Struct ())->append_field (NULL, false, "x", &named_int, TagSet ()); + Struct* s2 = (new Struct ())->append_field (NULL, false, "y", &named_int, TagSet ()); + tap.tassert ("type::are_identical - struct different field name", !are_identical (s1, s2)); + } + { + Struct* s1 = (new Struct ())->append_field (NULL, false, "x", &named_int, TagSet ()); + Struct* s2 = (new Struct ())->append_field (NULL, false, "x", &named_float32, TagSet ()); + tap.tassert ("type::are_identical - struct different field type", !are_identical (s1, s2)); + } + { + TagSet ts; + ts.insert ("some tag"); + Struct* s1 = (new Struct ())->append_field (NULL, false, "x", &named_int, ts); + Struct* s2 = (new Struct ())->append_field (NULL, false, "x", &named_int, TagSet ()); + tap.tassert ("type::are_identical - struct different field tags", !are_identical (s1, s2)); + } + { + Struct* s1 = (new Struct ())->append_field (new Package (), false, "x", &named_int, TagSet ()); + Struct* s2 = (new Struct ())->append_field (new Package (), false, "x", &named_int, TagSet ()); + tap.tassert ("type::are_identical - struct different package with private field", !are_identical (s1, s2)); + } + tap.print_plan (); return 0;