Introspection: Extract ParseCommand method

Signed-off-by: Tomasz Michalak <tmichalak@antmicro.com>
diff --git a/design_introspection-plugin/get_cells.cc b/design_introspection-plugin/get_cells.cc
index 8e9abe7..6c4f0c9 100644
--- a/design_introspection-plugin/get_cells.cc
+++ b/design_introspection-plugin/get_cells.cc
@@ -7,17 +7,17 @@
 std::string GetCells::SelectionType() { return "c"; }
 
 void GetCells::ExtractSelection(Tcl_Obj* tcl_list, RTLIL::Module* module,
-                               Filters& filters, bool is_quiet) {
+                                const CommandArgs& args) {
     for (auto cell : module->selected_cells()) {
-	if (filters.size() > 0) {
-	    Filter filter = filters.at(0);
+	if (args.filters.size() > 0) {
+	    Filter filter = args.filters.at(0);
 	    std::string attr_value = cell->get_string_attribute(
 	        RTLIL::IdString(RTLIL::escape_id(filter.first)));
 	    if (attr_value.compare(filter.second)) {
 		continue;
 	    }
 	}
-	if (!is_quiet) {
+	if (!args.is_quiet) {
 	    log("%s ", id2cstr(cell->name));
 	}
 	Tcl_Obj* value_obj = Tcl_NewStringObj(id2cstr(cell->name), -1);
diff --git a/design_introspection-plugin/get_cells.h b/design_introspection-plugin/get_cells.h
index ae7610b..48f6b30 100644
--- a/design_introspection-plugin/get_cells.h
+++ b/design_introspection-plugin/get_cells.h
@@ -11,7 +11,7 @@
     std::string TypeName() override;
     std::string SelectionType() override;
     void ExtractSelection(Tcl_Obj* tcl_list, RTLIL::Module* module,
-                          Filters& filters, bool is_quiet) override;
+                          const CommandArgs& args) override;
 };
 
 #endif  // GET_CELLS_H_
diff --git a/design_introspection-plugin/get_cmd.cc b/design_introspection-plugin/get_cmd.cc
index b9ab13b..3341b3c 100644
--- a/design_introspection-plugin/get_cmd.cc
+++ b/design_introspection-plugin/get_cmd.cc
@@ -30,36 +30,44 @@
     log("\n");
 }
 
-void GetCmd::ExecuteSelection(RTLIL::Design* design, std::vector<std::string>& args, size_t argidx, bool is_quiet) {
+void GetCmd::ExecuteSelection(RTLIL::Design* design, std::vector<std::string>& raw_args, const CommandArgs& args) {
     std::vector<std::string> selection_args;
     // Add name of top module to selection string
-    std::transform(args.begin() + argidx, args.end(),
+    std::transform(raw_args.begin() + args.current_args_idx, raw_args.end(),
                    std::back_inserter(selection_args), [&](std::string& obj) {
 	               return RTLIL::unescape_id(design->top_module()->name) + "/" +
 	                      SelectionType() + ":" + obj;
                    });
     extra_args(selection_args, 0, design);
     if (design->selected_modules().empty()) {
-	if (!is_quiet) {
+	if (!args.is_quiet) {
 	    log_warning("Specified %s not found in design\n", TypeName().c_str());
 	}
     }
 }
 
-void GetCmd::execute(std::vector<std::string> args, RTLIL::Design* design) {
-    if (design->top_module() == nullptr) {
-	log_cmd_error("No top module detected\n");
+void GetCmd::PackSelectionToTcl(RTLIL::Design* design, const CommandArgs& args) {
+    // Pack the selected nets into Tcl List
+    Tcl_Obj* tcl_list = Tcl_NewListObj(0, NULL);
+    for (auto module : design->selected_modules()) {
+	ExtractSelection(tcl_list, module, args);
     }
+    if (!args.is_quiet) {
+	log("\n");
+    }
+    Tcl_SetObjResult(yosys_get_tcl_interp(), tcl_list);
+}
 
+GetCmd::CommandArgs GetCmd::ParseCommand(const std::vector<std::string>& args) {
+    CommandArgs parsed_args{.current_args_idx = 0,
+                            .filters = Filters(),
+                            .is_quiet = false,
+                            .selection_objects = SelectionObjects()};
     size_t argidx;
-    Filters filters;
-    bool is_quiet = false;
-
-    // Parse command arguments
     for (argidx = 1; argidx < args.size(); argidx++) {
 	std::string arg = args[argidx];
 	if (arg == "-quiet") {
-	    is_quiet = true;
+	    parsed_args.is_quiet = true;
 	    continue;
 	}
 
@@ -90,10 +98,10 @@
 		    log_cmd_error("Incorrect filter expression: %s\n",
 		                  args[argidx].c_str());
 		}
-		filters.emplace_back(filter.substr(0, separator),
+		parsed_args.filters.emplace_back(filter.substr(0, separator),
 		                     filter.substr(separator + 2));
 	    }
-	    if (filters.size() > 1) {
+	    if (parsed_args.filters.size() > 1) {
 		log_warning(
 		    "Currently -filter switch supports only a single "
 		    "'equal(==)' condition expression, the rest will be "
@@ -108,17 +116,17 @@
 
 	break;
     }
+    std::copy(args.begin() + argidx, args.end(), std::back_inserter(parsed_args.selection_objects));
+    parsed_args.current_args_idx = argidx;
+    return parsed_args;
+}
 
-    ExecuteSelection(design, args, argidx, is_quiet);
+void GetCmd::execute(std::vector<std::string> args, RTLIL::Design* design) {
+    if (design->top_module() == nullptr) {
+	log_cmd_error("No top module detected\n");
+    }
 
-    // Pack the selected nets into Tcl List
-    Tcl_Interp* interp = yosys_get_tcl_interp();
-    Tcl_Obj* tcl_list = Tcl_NewListObj(0, NULL);
-    for (auto module : design->selected_modules()) {
-	ExtractSelection(tcl_list, module, filters, is_quiet);
-    }
-    if (!is_quiet) {
-	log("\n");
-    }
-    Tcl_SetObjResult(interp, tcl_list);
+    CommandArgs parsed_args(ParseCommand(args));
+    ExecuteSelection(design, args, parsed_args);
+    PackSelectionToTcl(design, parsed_args);
 }
diff --git a/design_introspection-plugin/get_cmd.h b/design_introspection-plugin/get_cmd.h
index 0cfdaee..70aaa5b 100644
--- a/design_introspection-plugin/get_cmd.h
+++ b/design_introspection-plugin/get_cmd.h
@@ -8,6 +8,13 @@
 struct GetCmd : public Pass {
     using Filter = std::pair<std::string, std::string>;
     using Filters = std::vector<Filter>;
+    using SelectionObjects = std::vector<std::string>;
+    struct CommandArgs {
+	size_t current_args_idx;
+	Filters filters;
+	bool is_quiet;
+	SelectionObjects selection_objects;
+    };
 
     GetCmd(const std::string& name, const std::string& description)
         : Pass(name, description) {}
@@ -15,13 +22,14 @@
     void help() override;
     void execute(std::vector<std::string> args, RTLIL::Design* design) override;
 
-   private:
+   protected:
     virtual std::string TypeName() = 0;
     virtual std::string SelectionType() = 0;
-    virtual void ExtractSelection(Tcl_Obj*, RTLIL::Module*, Filters&, bool) = 0;
+    CommandArgs ParseCommand(const std::vector<std::string>& args);
+    virtual void ExtractSelection(Tcl_Obj*, RTLIL::Module*, const CommandArgs& args) {}
     virtual void ExecuteSelection(RTLIL::Design* design,
-                                  std::vector<std::string>& args, size_t argidx,
-                                  bool is_quiet);
+                                  std::vector<std::string>& raw_args, const CommandArgs& args);
+    virtual void PackSelectionToTcl(RTLIL::Design* design, const CommandArgs& args);
 };
 
 #endif  // GET_CMD_H_
diff --git a/design_introspection-plugin/get_nets.cc b/design_introspection-plugin/get_nets.cc
index d44eb63..75adf91 100644
--- a/design_introspection-plugin/get_nets.cc
+++ b/design_introspection-plugin/get_nets.cc
@@ -7,17 +7,17 @@
 std::string GetNets::SelectionType() { return "w"; }
 
 void GetNets::ExtractSelection(Tcl_Obj* tcl_list, RTLIL::Module* module,
-                               Filters& filters, bool is_quiet) {
+                               const CommandArgs& args) {
     for (auto wire : module->selected_wires()) {
-	if (filters.size() > 0) {
-	    Filter filter = filters.at(0);
+	if (args.filters.size() > 0) {
+	    Filter filter = args.filters.at(0);
 	    std::string attr_value = wire->get_string_attribute(
 	        RTLIL::IdString(RTLIL::escape_id(filter.first)));
 	    if (attr_value.compare(filter.second)) {
 		continue;
 	    }
 	}
-	if (!is_quiet) {
+	if (!args.is_quiet) {
 	    log("%s ", id2cstr(wire->name));
 	}
 	Tcl_Obj* value_obj = Tcl_NewStringObj(id2cstr(wire->name), -1);
diff --git a/design_introspection-plugin/get_nets.h b/design_introspection-plugin/get_nets.h
index 8af0b9f..bd0f453 100644
--- a/design_introspection-plugin/get_nets.h
+++ b/design_introspection-plugin/get_nets.h
@@ -11,7 +11,7 @@
     std::string TypeName() override;
     std::string SelectionType() override;
     void ExtractSelection(Tcl_Obj* tcl_list, RTLIL::Module* module,
-                          Filters& filters, bool is_quiet) override;
+                          const CommandArgs& args) override;
 };
 
 #endif  // GET_NETS_H_
diff --git a/design_introspection-plugin/get_ports.cc b/design_introspection-plugin/get_ports.cc
index 1eaad8b..ccc422a 100644
--- a/design_introspection-plugin/get_ports.cc
+++ b/design_introspection-plugin/get_ports.cc
@@ -7,20 +7,20 @@
 std::string GetPorts::SelectionType() { return "x"; }
 
 void GetPorts::ExtractSelection(Tcl_Obj* tcl_list, RTLIL::Module* module,
-                                GetCmd::Filters& filters, bool is_quiet) {
+                                const CommandArgs& args) {
     for (auto wire : module->selected_wires()) {
 	if (!wire->port_input and !wire->port_output) {
 	    continue;
 	}
-	if (filters.size() > 0) {
-	    Filter filter = filters.at(0);
+	if (args.filters.size() > 0) {
+	    Filter filter = args.filters.at(0);
 	    std::string attr_value = wire->get_string_attribute(
 	        RTLIL::IdString(RTLIL::escape_id(filter.first)));
 	    if (attr_value.compare(filter.second)) {
 		continue;
 	    }
 	}
-	if (!is_quiet) {
+	if (!args.is_quiet) {
 	    log("%s ", id2cstr(wire->name));
 	}
 	Tcl_Obj* value_obj = Tcl_NewStringObj(id2cstr(wire->name), -1);
diff --git a/design_introspection-plugin/get_ports.h b/design_introspection-plugin/get_ports.h
index f00dd5f..70c4996 100644
--- a/design_introspection-plugin/get_ports.h
+++ b/design_introspection-plugin/get_ports.h
@@ -11,7 +11,7 @@
     std::string TypeName() override;
     std::string SelectionType() override;
     void ExtractSelection(Tcl_Obj* tcl_list, RTLIL::Module* module,
-                          Filters& filters, bool is_quiet) override;
+                          const CommandArgs& args) override;
     void execute(std::vector<std::string> args, RTLIL::Design* design) override;
 };