### ===========================================================================
### -package  : SimpleExtProc
# -version    : 0.2
# -purpose    : Procedures with extended argument syntax.
# -overview   :
#     This package provides a way to create procedures with extended argument
#  syntax.  This syntax includes argument types (with optional run-time type
#  checking) and argument flags with or without parameters which may be
#  interpreted or left to the user.
#
#     Procedures are provided to create, delete, rename, copy and get
#  information about procedures with extended argument syntax, as well as
#  others to handle arguments in the body of those procedures.
#
#     This package also allows to handle headers for code scripts.  Each
#  header is identified by a tag and, within a script, headers are ordered by
#  priority.  Procedures are provided to add, get and delete headers.
#
# -usage      :
#     Extended syntax procedures are created via the
#  K<::Simple::ExtProc::create> procedure.  The declaration specifies whether
#  to perform run-time checking of the arguments type as well as wether to
#  delegate the flag interpretation to the user.
#
#     Extended argument syntax procedures can be deleted via
#  K<::Simple::ExtProc::delete> or renamed via K<::Simple::ExtProc::rename>. 
#  The K<::Simple::ExtProc::information> procedure provides several
#  subcommands to query information about extended argument syntax procedures: 
#  K<is-subcommand>, K<subcommands>, K<runtimeparsing>, K<checktype>,
#  K<interpflags>, K<exists>, K<body>, K<args>, K<argsusage>, K<argslist>,
#  K<type>, K<default>, K<choices> and K<description>.  Refer to the
#  description of each procedure below for further information.
#
#     The syntax of the argument list, implemented by the P<SimpleExtVar>
#  package, is very similar to that of the P<opt> package distributed with Tcl
#  8.0, so that the upgrade should be easy; in fact this package was
#  implemented as an evolution of the P<opt> package for two reasons:  1)
#  P<opt> is B<slow> and 2) it was deprecated from Tcl 8.1.
#
#     This package encompasses the funcionality provided by the
#  P<SimpleSubcommand> package so it is recommended not to use the later if
#  using the former.  In fact, all procedures provided by this package work
#  for regular procedures also, so this is the only package needed to handle
#  regular or extended argument syntax procedures as well as regular or
#  subcommand procedures.
#
# -keywords   : procedure extended argument type flag
# -variables  :
#  { Arguments        -array         {Array containing for each argument list
#                                     its internal representation}}
#  { ArgumentNames    -array         {Array containing for each argument list
#                                     its argument names list}}
#  { FirstArg         -array         {Array containing for each extended
#                                     procedure the position of its first
#                                     argument to parse in run-time}}
#  { LastFlag         -array         {Array containing for each extended
#                                     procedure the position of the last flag
#                                     in its argument list}}
#  { InterpFlags      -array         {Array containing for each extended
#                                     procedure whether flag interpretation is
#                                     enabled or has been delegated to the
#                                     user}}
#  { CheckType        -boolean 0     {Stores the value of the I<-checktype>
#                                     package option}}
#  { AfterFlags       -int 2         {Stores the value of the I<-afterflags>
#                                     package option}}
#
# -options    :
#
#  * I<-checktype>:  this option controls whether argument run-time type
#    checking is performed for procedures created via the
#    P<::Simple::ExtProc::create> procedure in order to check whether the
#    actual arguments match their type.  This has a performance penalty which
#    should be considered.  Notice that only those procedures created via the
#    P<::Simple::ExtProc::create> procedure B<after> modifying this option are
#    affected by the change.
#
#  * I<-afterflags>:  if the number of arguments after the last flag in
#    procedures created via the P<::Simple::ExtProc::create> procedure
#    exceedes the value of this package option, those arguments are handled
#    via an auxiliary "after flags" procedure.  Notice that only those
#    procedures created via the P<::Simple::ExtProc::create> procedure
#    B<after> modifying this option are affected by the change.
#
# -commands   :
#
#  * K<next-arg>
#    Returns the next argument in the actual argument list.
#
#  * K<previous-arg>
#    Go back one argument in the actual argument list.
#
#  * K<::Simple::ExtProc::create> ?-interpflags extbool? ?-checktype extbool?
#    procedure arguments body
#    Creates a procedure with extended argument syntax.
#
#  * K<::Simple::ExtProc::delete> procedure
#    Deletes a procedure.
#
#  * K<::Simple::ExtProc::move> sourceProcedure targetProcedure
#    Renames a procedure.
#
#  * K<::Simple::ExtProc::copy> sourceProcedure targetProcedure
#    Copies a procedure.
#
#  * K<::Simple::ExtProc::information is-subcommand> procedure
#    Returns whether a procedure is a base subcommand procedure.
#
#  * K<::Simple::ExtProc::information subcommands> command
#    Returns a base subcommand procedure subcommand list.
#
#  * K<::Simple::ExtProc::information runtimeparsing> procedure
#    Returns whether a procedure run-time parses its arguments.
#
#  * K<::Simple::ExtProc::information checktype> procedure
#    Returns whether a procedure performs argument type checking.
#
#  * K<::Simple::ExtProc::information interpflags> procedure
#    Returns whether a procedure has flag interpretation enabled.
#
#  * K<::Simple::ExtProc::information exists> procedure
#    Returns whether an extended procedure exists.
#
#  * K<::Simple::ExtProc::information body> procedure
#    Returns a procedure body.
#
#  * K<::Simple::ExtProc::information args> procedure
#    Returns an extended procedure argument names list.
#
#  * K<::Simple::ExtProc::information argsusage> procedure
#    Returns a procedure argument usage string.
#
#  * K<::Simple::ExtProc::information argslist> procedure
#    Returns a procedure argument list.
#
#  * K<::Simple::ExtProc::information type> procedure argument
#    Returns an extended procedure argument type.
#
#  * K<::Simple::ExtProc::information default> procedure argument variableName
#    Returns whether a procedure argument has a default value.
#
#  * K<::Simple::ExtProc::information choices> procedure argument
#    Returns an extended procedure argument choices list.
#
#  * K<::Simple::ExtProc::information description> procedure argument
#    Returns an extended procedure argument desription.
#
#  * K<number-flags>
#    Returns the number of flags in an extended procedure call.
#
#  * K<flag-given> flag
#    Returns whether a flag was given in an extended procedure call.
#
#  * K<arg-is-default> argument
#    Returns whether the value of an argument is the default one.
#
#  * K<::Simple::ScriptHead::add> scriptName tag priority header
#    Prepends a header to a script.
#
#  * K<::Simple::ScriptHead::get> script ?pattern?
#    Gets headers from a script.
#
#  * K<::Simple::ScriptHead::delete> scriptName ?pattern?
#    Deletes headers from a script.
#
#  * K<::Simple::ExtProc::configure> ?-checktype extbool? ?-afterflags int?
#    Configures the package options.
#
#  * K<::Simple::ExtProc::cget> ?-checktype? ?-afterflags?
#    Gets the package options.
#
# -examples   :
#
#  # Install the package
#  package require SimplePackage
#  ::Simple::Package::require-and-install SimpleExtProc
#  
#  # Enable arguments run-time type checking
#  ::Simple::ExtProc::configure -checktype true
#  
#  # Create a procedure which takes an
#  # optional flag and a required integer
#  proc-ext {
#     zero
#  } {
#     {-zero             -boolflag      "Zero flag"}
#     { integer          -int           "Integer"}
#  } {
#     if {$zero} {
#        puts 0
#     } else {
#        puts $integer
#     }
#  }
#  
#  # Get some info about the procedure
#  # This displays the following:
#  #    0
#  #     ?-zero? integer
#  #    Zero flag
#  puts [::Simple::ExtProc::information is-subcommand zero]
#  puts [::Simple::ExtProc::information argsusage zero]
#  puts [::Simple::ExtProc::information description zero -zero]
#  
#  # Valid calls
#  # This displays the following:
#  #    23
#  #    0
#  #    0
#  zero 23      
#  zero 0       
#  zero -zero 23
#  
#  # Invalid call
#  # This displays the following:
#  #    invalid value "foo" for "integer" of type "-int"
#  catch {zero foo} result
#  puts $result
#  
#  # Create a couple of subcommand procedures
#  proc-ext {
#     command foo
#  } {
#     { integer          -int           "Integer"}
#     { choice           -choice {1 2}  "Choices"}
#  } {
#     if {$integer > $choice} {
#        puts {The integer is greater than the choice}
#     } else {
#        puts {The integer is lower or equal than the choice}
#     }
#  }
#  
#  proc-ext {
#     command bar
#  } {
#     {?integer?         -int 1         "Integer"}
#  } {
#     if {[arg-is-default integer]} {
#        puts {Default value}
#     } else {
#        puts {Non-default value}
#     }
#  }
#  
#  # This displays the following:
#  #    The integer is lower or equal than the choice
#  #    The integer is greater than the choice
#  #    Default value
#  #    Non-default value
#  command foo 1 2
#  command foo 8 1
#  command bar
#  command bar 8
#  
#  # Get some info about the subcommand
#  # This displays the following:
#  #    1
#  #    foo bar
#  puts [::Simple::ExtProc::information is-subcommand command]
#  puts [::Simple::ExtProc::information subcommands command]
#  
#  # Delete one of the subcommands
#  ::Simple::ExtProc::delete {command bar}
#  
#  # Get some info about the subcommand
#  # This displays the following:
#  #    foo
#  puts [::Simple::ExtProc::information subcommands command]
#
# -details    : 
#  * For the sake of performance, this package does not implement some of the
#    more esoteric features of the P<opt> package such as argument names
#    abbreviation, type guessing, completion of incomplete arguments or out of
#    order flags (this last feature might be added in a future revision of the
#    package). 
#
#     For procedures with flags and a small number of arguments and/or with
#    run-time type checking enabled, P<SimpleExtProc> is about ten times
#    faster than the P<opt> package.  Also, several tricks are applied to
#    improve performance (see the details section of the
#    P<::Simple::ExtProc::create> procedure) which result in typical
#    procedures (those which do not require argument run-time type checking
#    and have no flags in the argument list) B<behaving identically> to
#    regular Tcl procedures (no run-time parsing is required). 
#
#     For a ten non-flag arguments procedure, the P<opt> package requires
#    25000 microseconds per call (tcl 8.0, 233 MHz AMD K6, Linux Red Hat 5.1)
#    while P<SimpleExtProc> uses a mere 15 or 2500 microseconds when run-time
#    type checking is disabled or enabled, respectively; that means
#    performance improvement factors of B<1600> or B<10>, respectively.  For a
#    ten flag arguments procedure the times are 22900 and 1965 microseconds, a
#    factor of B<11.2>.  Even for procedures with flags, their interpretation
#    can be delegated to the user so, again, no overhead is introduced if
#    desired. 
#
#  * The extended procedure argument internal representation contained
#    in the V<Arguments> namespace array is a list with the following elements:
#     0: whether the argument is a flag
#     1: whether the argument has a default value
#     2: argument name
#     3: argument default value
#     4: argument type
#     5: argument choices (empty if type is not "-choice")
#     6: argument description
#
# -remarks    :
#  * This package is optimized for speed and not for maintenability.  In
#    particular the run-time parsing of the variable list is done by one of
#    two different private procedures
#    (P<::Simple::ExtProc::Priv::parse-arguments> and
#    P<::Simple::ExtProc::Priv::parse-arguments-checktype>) depending on
#    whether run-time type checking is enabled or not even though they share
#    most of the code.
#
# -todo       :
#  * Provide out of order flags.
#  * It might be useful to have a way to enable and disable I<-checktype> for
#    existing procedures.
#  * Provide a package option I<-storedetails> to choose whether to store or
#    not the extended arguments descriptions.
#
# -bugs       :
#  * When a namespace is deleted, the extended procedures therein are not
#    fully deleted.  This is because the state of the extended procedures is
#    stored in arrays in the ::Simple::ExtProc namespace instead in the
#    procedure namespace.
#
# -history    :
#  19-feb-1999   Unreleased first version 0.1
#  23-apr-2000   First public release, version 0.2
#
# -copyright  :
#  Copyright (C) 1999, 2000, Juan C. Gil (jgil@gmv.es)
#
### ===========================================================================
