====== Language plugins : Implementation ======
===== parse, print module =====
==== Background ====
A module is container of instances.  To a compiler, a module can also contain code to be executed, but gnucap does not directly support that.
A Spice "subckt" is a module.
  * type -- A module defines a new type.
  * [[.:label]] -- The label is the name of the new type.
  * [[.:ports]] -- This is the list of connections.
  * [[.:args]] -- The arg list is optional.  If left out, the arg list is open.  It accepts whatever it is fed.
==== parse_module ====
A module is a collection.  Parsing it means to parse the header, then the body, then the trailer.  Parsing the body is a loop, getting text and calling ''new_''''_instance'' on each pass, until some indication that it is done.  It is important to have some kind of guarantee that the loop will exit.
/*--------------------------------------------------------------------------*/
MODEL_SUBCKT* LANG_SPECTRE::parse_module(CS& cmd, MODEL_SUBCKT* x)
{
  assert(x);
  // header
  cmd.reset(0).skipbl();
  cmd >> "subckt ";
  parse_label(cmd, x);
  parse_ports(cmd, x);
  // body
  for (;;) {
    cmd.get_line("spectre-subckt>");
    if (cmd >> "ends ") {
      break;
    }else{
      new__instance(cmd, x, x->subckt());
    }
  }
  return x;
}
/*--------------------------------------------------------------------------*/
==== print_module ====
/*--------------------------------------------------------------------------*/
void LANG_SPICE_BASE::print_module(OMSTREAM& o, const MODEL_SUBCKT* x)
{
  assert(x);
  assert(x->subckt());
  o << ".subckt " <<  x->short_label();
  print_ports(o, x);
  o << '\n';
  
  for (CARD_LIST::const_iterator 
	 ci = x->subckt()->begin(); ci != x->subckt()->end(); ++ci) {
    print_item(o, *ci);
  }
  
  o << ".ends " << x->short_label() << "\n";
}
/*--------------------------------------------------------------------------*/
==== A command to get it started ====
In addition to the above, it is necessary to make a command to recognize a keyword to get it started.
It needs to allocate a new ''MODEL_SUBCKT'', parse it, then store it.
/*--------------------------------------------------------------------------*/
class CMD_SUBCKT : public CMD {
  void do_it(CS& cmd, CARD_LIST* Scope)
  {
    MODEL_SUBCKT* new_module = new MODEL_SUBCKT;
    assert(new_module);
    assert(!new_module->owner());
    assert(new_module->subckt());
    assert(new_module->subckt()->is_empty());
    lang_spectre.parse_module(cmd, new_module);
    Scope->push_back(new_module);
  }
} p2;
DISPATCHER::INSTALL d2(&command_dispatcher, "subckt", &p2);
/*--------------------------------------------------------------------------*/