=pod

=encoding utf8

=head1 NAME

Muldis::D::Core::Routines -
Muldis D general purpose routines

=head1 VERSION

This document is Muldis::D::Core::Routines version 0.58.0.

=head1 PREFACE

This document is part of the Muldis D language specification, whose root
document is L<Muldis::D>; you should read that root document before
you read this one, which provides subservient details.  Moreover, you
should read the L<Muldis::D::Core> document before this current
document, as that forms its own tree beneath a root document branch.

=head1 DESCRIPTION

This document contains one or more sections that were moved here from
L<Muldis::D::Core> so that that other document would not be too
large.

=head1 SYSTEM-DEFINED GENERIC UNIVERSAL FUNCTIONS

These functions are applicable to values of any data type at all.

=over

=item C<function sys.std.Core.Universal.is_identical result Bool params {
topic(Universal), other(Universal) }>

This function results in C<Bool:true> iff its (mutually commutative) 2
arguments are exactly the same value, and C<Bool:false> otherwise.  This
function will warn if, in regards to the declared types of its arguments,
none the following are true: 1. they are both subtypes of a common q/scalar
root type; 2. they are both subtypes of a common complete q/tuple or
q/relation type, that is they essentially have the same headings; 3. at
least one type is a generic (eg-C<Universal>) or incomplete
(eg-C<Relation>) type, and it is a supertype of the other.

=item C<function sys.std.Core.Universal.is_not_identical result Bool params
{ topic(Universal), other(Universal) }>

This function is exactly the same as C<sys.std.Core.Universal.is_identical>
except that it results in the opposite boolean value when given the same
arguments.

=item C<function sys.std.Core.Universal.is_value_of_type result Bool params
{ topic(Universal), type(TypeRef) }>

This function results in C<Bool:true> iff the value of its C<topic>
argument is a member of the data type whose name is given in the C<type>
argument, and C<Bool:false> otherwise.  As trivial cases, this function
always results in C<Bool:true> if the named type is C<Universal>, and
C<Bool:false> if it is C<Empty>.  This function will fail if the named type
doesn't exist in the virtual machine.

=item C<function sys.std.Core.Universal.treated result Universal params {
topic(Universal), as(TypeRef) }>

This function results in the value of its C<topic> argument, but that the
declared type of the result is the not-C<Empty> data type whose name is
given in the C<as> argument.  This function will fail if the named type
doesn't exist in the virtual machine, or if C<topic> isn't a member of the
named type.  The purpose of C<treated> is to permit taking values from a
context having a more generic declared type, and using them in a context
having a more specific declared type; such an action would otherwise be
blocked at compile time due to a type-mismatch error; C<treated> causes the
type-mismatch validation, and possible failure, to happen at runtime
instead, on the actual value rather than declared value.  For example, if
you are storing an C<Int> value in a C<Scalar>-typed variable, using
C<treated> will cause the compiler to let you use that variable as an
argument to C<sys.std.Integer.difference>, which it otherwise wouldn't.

=item C<function sys.std.Core.Universal.default result Universal params {
of(TypeRef) }>

This function is the externalization of a not-C<Empty> data type's
C<type_default> function.  This function results in the default value of
the not-C<Empty> data type whose name is given in the C<of> argument, and
the declared type of the result is that same type.  This function will fail
if the named type doesn't exist in the virtual machine, either at compile
or runtime depending whether the type is in the system or user namespace.
This function is conceptually implicitly used to provide default values for
variables, so they always hold valid values of their declared type.

=item C<function sys.std.Core.Universal.assertion result Universal params {
is_true(Bool), result(Universal) }>

This function results in the value of its C<result> argument, when its
C<is_true> argument is C<Bool:true>.  This function will fail if its
C<is_true> argument is C<Bool:false>.  The purpose of C<assertion> is to
perform condition assertions in a pure functional context that may be
better done without the overhead of creating a new constrained data type,
especially when the assertion is on some fact that is only known after
performing calculations from multiple function arguments; this can
potentially be done at compile time as per type constraints.

=back

=head1 SYSTEM-DEFINED GENERIC QUASI-/SCALAR-CONCERNING FUNCTIONS

These functions are applicable to mainly q/scalar types, but are generic in
that they typically work with any q/scalar types.  Now some of these
functions (those with a parameter named C<possrep>) work only with q/scalar
values that have possreps, and not with values of the 2 system-defined
scalar types lacking any possreps: C<Int>, C<String>; other functions are
not limited in that way, but may be limited in other ways.  Note that the
terminology used to describe these functions is taking advantage of the
fact that a q/scalar possrep looks just like a q/tuple.  Each C<possrep>
and C<name> parameter is optional and each defaults to the empty string if
no explicit argument is given to it.

=over

=item C<function sys.std.Core.QScalar.attr result Universal params {
topic(QScalar), possrep(Name)?, name(Name)? }>

This function results in the q/scalar or q/nonscalar value of the possrep
attribute of C<topic> where the possrep name is given by C<possrep> and the
attribute name is given by C<name>.  This function will fail if C<possrep>
specifies a possrep name that C<topic> doesn't have or C<name> specifies an
attribute name that the named possrep of C<topic> doesn't have.

=item C<function sys.std.Core.QScalar.update_attr result QScalar params {
topic(QScalar), possrep(Name)?, name(Name)?, value(Universal) }>

This function results in its C<topic> argument but that its possrep
attribute whose possrep name is C<possrep> and whose attribute name is
C<name> has been updated with a new q/scalar or q/nonscalar value given by
C<value>.  This function will fail if C<possrep> specifies a possrep name
that C<topic> doesn't have or C<name> specifies an attribute name that the
named possrep of C<topic> doesn't have, or if C<value> isn't of the
declared type of the attribute; this function will otherwise warn if the
declared type of C<value> isn't a subtype of the declared type of the
attribute.

=item C<function sys.std.Core.QScalar.multi_update result QScalar params {
topic(QScalar), possrep(Name)?, attrs(QTuple) }>

This function is like C<sys.std.Core.QScalar.update_attr> except that it
handles N q/scalar possrep attributes at once rather than just 1.  The
heading of the C<attrs> argument must be a subset of the heading of the
C<topic> argument's possrep named by C<possrep>; this function's result is
C<topic> with all the possrep attribute values of C<attrs> substituted into
it.  This function could alternately be named
I<sys.std.Core.QScalar.static_substitution>.

=item C<function sys.std.Core.QScalar.projection result QTuple params {
topic(QScalar), possrep(Name)?, attrs(set_of.Name) }>

This function results in the C<QTuple> that is the projection of the
possrep (whose name is given in the C<possrep> argument) of its C<topic>
argument that has just the subset of attributes of C<topic> which are named
in its C<attrs> argument.  As a trivial case, this function's result is the
entire named possrep of C<topic> if C<attrs> lists all attributes of that
possrep; or, it is the nullary tuple if C<attrs> is empty.  This function
will fail if C<possrep> specifies a possrep name that C<topic> doesn't have
or C<attrs> specifies any attribute names that C<topic> doesn't have.

=item C<function sys.std.Core.QScalar.cmpl_projection result QTuple params
{ topic(QScalar), possrep(Name)?, attrs(set_of.Name) }>

This function is the same as C<projection> but that it results in the
complementary subset of possrep attributes of C<topic> when given the same
arguments.

=item C<function sys.std.Core.QScalar.QTuple_from_QScalar result QTuple
params { topic(QScalar), possrep(Name)? }>

This function results in the C<QTuple> that has all the same attributes of
the possrep of C<topic> whose name is given in C<possrep>; in other words,
the function results in the externalization of one of a q/scalar value's
possreps.  This function will fail if C<possrep> specifies a possrep name
that C<topic> doesn't have.

=item C<function sys.std.Core.QScalar.QScalar_from_QTuple result QScalar
params { topic(QTuple), type(TypeRef), possrep(Name)? }>

This function results in the C<QScalar> value whose q/scalar root
(|sub)type is named by C<type>, which has a possrep whose name matches
C<possrep>, and whose complete set of attributes of that named possrep
match the attributes of C<topic>.  This function can be used to select any
q/scalar value at all that has a possrep.

=item C<function sys.std.Core.QScalar.order result Order params {
topic(QScalar), other(QScalar), assuming(QTuple)? }>

This function is the externalization of a q/scalar root type's type-default
(total) C<order_determination> function.  This function results in
C<Order:same> iff its C<topic> and C<other> arguments are exactly the same
value, and otherwise it results in C<Order:increase> if the value of the
C<other> argument is considered to be an increase (as defined by the type)
over the value of the C<topic> argument, and otherwise it results in
C<Order:decrease> as the reverse of the last condition would be true.  This
function will fail if its C<topic> and C<other> arguments are not values of
a common q/scalar root type that declares a type-default
C<order_determination> function; this function will otherwise warn if the
declared types of those arguments are not both subtypes of such a common
q/scalar root type.  Note that C<order_determination> functions are
considered the only fundamental order-sensitive operators, and all others
are defined over them.  This function also has a C<QTuple>-typed third
parameter, named C<assuming>, which carries optional customization details
for the order-determination algorithm; this permits the function to
implement a choice between multiple (typically similar) ordering algorithms
rather than just one, which reduces the number of functions needed for
supporting that choice; if the algorithm is not customizable, then a
q/tuple argument would be of degree zero.  The C<assuming> parameter is
optional and defaults to the zero-attribute tuple if no explicit argument
is given to it.

=item C<function sys.std.Core.QScalar.has_possrep result Bool params {
topic(QScalar), possrep(Name)? }>

This function results in C<Bool:true> iff its C<topic> argument has a
possrep whose name is given by C<possrep>; otherwise it results in
C<Bool:false>.

=item C<function sys.std.Core.QScalar.possrep_names result set_of.Name
params { topic(QScalar) }>

This function results in the set of the names of the possreps of its
argument.

=item C<function sys.std.Core.QScalar.degree result NNInt params {
topic(QScalar), possrep(Name)? }>

This function results in the degree of its C<topic> argument's possrep
whose name is given by C<possrep> (that is, the count of attributes the
possrep has).

=item C<function sys.std.Core.QScalar.has_attrs result Bool params {
topic(QScalar), possrep(Name)?, attrs(set_of.Name) }>

This function results in C<Bool:true> iff, for every one of the attribute
names specified by its C<attrs> argument, its C<topic> argument's possrep
whose name is given by C<possrep> has an attribute with that name;
otherwise it results in C<Bool:false>.  As a trivial case, this function's
result is C<Bool:true> if C<attrs> is empty.

=item C<function sys.std.Core.QScalar.attr_names result set_of.Name params
{ topic(QScalar), possrep(Name)? }>

This function results in the set of the names of the attributes of its
C<topic> argument's possrep whose name is given by C<possrep>.

=back

=head1 SYSTEM-DEFINED BOOLEAN-CONCERNING FUNCTIONS

These functions implement commonly used boolean operations.

=over

=item C<function sys.std.Core.Bool.not result Bool params { topic(Bool) }>

This function results in the logical I<not> of its argument.

=item C<function sys.std.Core.Bool.and result Bool params {
topic(set_of.Bool) }>

This function is a reduction operator that recursively takes each pair of
its N input element values and does a logical I<and> (which is both
commutative and associative) on them until just one is left, which is the
function's result.  If C<topic> has zero values, then C<and> results in
C<Bool:true>, which is the identity value for logical I<and>.

=item C<function sys.std.Core.Bool.or result Bool params {
topic(set_of.Bool) }>

This function is a reduction operator that recursively takes each pair of
its N input element values and does a logical inclusive-or (which is both
commutative and associative) on them until just one is left, which is the
function's result.  If C<topic> has zero values, then C<or> results in
C<Bool:false>, which is the identity value for logical inclusive-or.

=item C<function sys.std.Core.Bool.xor result Bool params {
topic(bag_of.Bool) }>

This function is a reduction operator that recursively takes each pair of
its N input element values and does a logical exclusive-or (which is both
commutative and associative) on them until just one is left, which is the
function's result.  If C<topic> has zero values, then C<xor> results in
C<Bool:false>, which is the identity value for logical exclusive-or.

=back

=head1 SYSTEM-DEFINED GENERIC QUASI-/TUPLE-CONCERNING FUNCTIONS

These functions are applicable to mainly q/tuple types, but are generic in
that they typically work with any q/tuple types.

=over

=item C<function sys.std.Core.QTuple.attr result Universal params {
topic(QTuple), name(Name) }>

This function results in the q/scalar or q/nonscalar value of the attribute
of C<topic> whose name is given by C<name>.  This function will fail if
C<name> specifies an attribute name that C<topic> doesn't have.

=item C<function sys.std.Core.QTuple.update_attr result QTuple params {
topic(QTuple), name(Name), value(Universal) }>

This function results in its C<topic> argument but that its attribute whose
name is C<name> has been updated with a new q/scalar or q/nonscalar value
given by C<value>.  This function will fail if C<name> specifies an
attribute name that C<topic> doesn't have; this function will otherwise
warn if the declared type of C<value> isn't a subtype of the declared type
of the attribute.

=item C<function sys.std.Core.QTuple.multi_update result QTuple params {
topic(QTuple), attrs(QTuple) }>

This function is like C<sys.std.Core.QTuple.update_attr> except that it
handles N q/tuple attributes at once rather than just 1.  The heading of
the C<attrs> argument must be a subset of the heading of the C<topic>
argument; this function's result is C<topic> with all the attribute values
of C<attrs> substituted into it.  This function could alternately be named
I<sys.std.Core.QTuple.static_substitution>.

=item C<function sys.std.Core.QTuple.rename result QTuple params {
topic(QTuple), map(AttrRenameMap) }>

This function results in a C<QTuple> value that is the same as its C<topic>
argument but that some of its attributes have different names.  Each tuple
of the argument C<map> specifies how to rename one C<topic> attribute, with
the C<before> and C<after> attributes of a C<map> tuple representing the
old and new names of a C<topic> attribute, respectively.  As a trivial
case, this function's result is C<topic> if C<map> has no tuples.  This
function supports renaming attributes to each others' names.  This function
will fail if C<map> specifies any old names that C<topic> doesn't have, or
any new names that are the same as C<topic> attributes that aren't being
renamed.

=item C<function sys.std.Core.QTuple.projection result QTuple params {
topic(QTuple), attrs(set_of.Name) }>

This function results in the projection of its C<topic> argument that has
just the subset of attributes of C<topic> which are named in its C<attrs>
argument.  As a trivial case, this function's result is C<topic> if
C<attrs> lists all attributes of C<topic>; or, it is the nullary tuple if
C<attrs> is empty.  This function will fail if C<attrs> specifies any
attribute names that C<topic> doesn't have.

=item C<function sys.std.Core.QTuple.cmpl_projection result QTuple params {
topic(QTuple), attrs(set_of.Name) }>

This function is the same as C<projection> but that it results in the
complementary subset of attributes of C<topic> when given the same
arguments.

=item C<function sys.std.Core.QTuple.static_extension result QTuple params
{ topic(QTuple), attrs(QTuple) }>

This function results in the extension of its C<topic> argument by joining
that with its C<attrs> argument; the attribute names of the 2 arguments
must be disjoint.  See also C<sys.std.Core.QTuple.product> for an N-ary
version of this.

=item C<function sys.std.Core.QTuple.wrap result QTuple params {
topic(QTuple), inner(set_of.Name), outer(Name) }>

This function results in a C<QTuple> value that is the same as its C<topic>
argument but that some of its attributes have been wrapped up into a new
C<QTuple>-typed attribute, which exists in place of the original
attributes.  The C<inner> argument specifies which C<topic> attributes are
to be removed and wrapped up, and the C<outer> argument specifies the name
of their replacement attribute.  As a trivial case, if C<inner> is empty,
then the result has all the same attributes as before plus a new
tuple-typed attribute of degree zero; or, if C<inner> lists all attributes
of C<topic>, then the result has a single attribute whose value is the same
as C<topic>. This function supports the new attribute having the same name
as an old one being wrapped into it.  This function will fail if C<inner>
specifies any attribute names that C<topic> doesn't have, or if C<outer> is
the same as C<topic> attributes that aren't being wrapped.

=item C<function sys.std.Core.QTuple.cmpl_wrap result QTuple params {
topic(QTuple), cmpl_inner(set_of.Name), outer(Name) }>

This function is the same as C<wrap> but that it wraps the complementary
subset of attributes of C<topic> to those specified by C<cmpl_inner>.

=item C<function sys.std.Core.QTuple.unwrap result QTuple params {
topic(QTuple), outer(Name) }>

This function is the inverse of C<sys.std.Core.QTuple.wrap>, such that it
will unwrap a C<QTuple>-type attribute into its member attributes.  This
function will fail if C<outer> specifies any attribute name that C<topic>
doesn't have, or if an attribute of C<topic{outer}> is the same as another
C<topic> attribute.

=item C<function sys.std.Core.QTuple.product result QTuple params {
topic(quasi_set_of.QTuple) }>

This function is similar to C<sys.std.Core.QRelation.product> but that it
works with q/tuples rather than q/relations.  This function is mainly
intended for use in connecting q/tuples that have all disjoint headings,
such as for extending one q/tuple with additional attributes.

=back

=head1 SYSTEM-DEFINED GENERIC SINGLE INPUT QUASI-/RELATION FUNCTIONS

These functions are applicable to mainly q/relation types, but are generic
in that they typically work with any q/relation types.  Each C<\w*assuming>
parameter is optional and defaults to the zero-attribute tuple if no
explicit argument is given to it.

=over

=item C<function sys.std.Core.QRelation.cardinality result NNInt params {
topic(QRelation) }>

This function results in the cardinality of its argument (that is, the
count of q/tuples its body has).

=item C<function sys.std.Core.QRelation.is_member result Bool params {
r(QRelation), t(QTuple) }>

This function results in C<Bool:true> iff its C<t> argument matches a
q/tuple of its C<r> argument (that is, iff conceptually C<t> is a member of
C<r>), and C<Bool:false> otherwise.  This function is like
C<sys.std.Core.QRelation.is_subset> except that the q/tuple being looked
for doesn't have to be wrapped in a q/relation.  This function will warn if
its 2 arguments' common-named attributes have declared types that are
incompatible as per C<is_identical>.

=item C<function sys.std.Core.QRelation.is_not_member result Bool params {
r(QRelation), t(QTuple) }>

This function is exactly the same as C<sys.std.Core.QRelation.is_member>
except that it results in the opposite boolean value when given the same
arguments.

=item C<function sys.std.Core.QRelation.QTuple_from_QRelation result QTuple
params { topic(QRelation) }>

This function results in the C<QTuple> that is the sole member q/tuple of
its argument.  This function will fail if its argument does not have
exactly one q/tuple.

=item C<function sys.std.Core.QRelation.QRelation_from_QTuple result
QRelation params { topic(QTuple) }>

This function results in the C<QRelation> value those body has just the one
C<QTuple> that is its argument.

=item C<function sys.std.Core.QRelation.insertion result QRelation params {
r(QRelation), t(QTuple) }>

This function results in a C<QRelation> that is the relational union of
C<r> and a q/relation whose sole q/tuple is C<t>; that is, conceptually the
result is C<t> inserted into C<r>.  As a trivial case, if C<t> already
exists in C<r>, then the result is just C<r>.

=item C<function sys.std.Core.QRelation.disjoint_insertion result QRelation
params { r(QRelation), t(QTuple) }>

This function is exactly the same as C<sys.std.Core.QRelation.insertion>
except that it will fail if C<t> already exists in C<r>.

=item C<function sys.std.Core.QRelation.deletion result QRelation params {
r(QRelation), t(QTuple) }>

This function results in a C<QRelation> that is the relational difference
from C<r> of a q/relation whose sole q/tuple is C<t>; that is, conceptually
the result is C<t> deleted from C<r>.  As a trivial case, if C<t> already
doesn't exist in C<r>, then the result is just C<r>.

=item C<function sys.std.Core.QRelation.rename result QRelation params {
topic(QRelation), map(AttrRenameMap) }>

This function is the same as C<sys.std.Core.QTuple.rename> but that it
operates on and results in a C<QRelation> rather than a C<QTuple>.

=item C<function sys.std.Core.QRelation.projection result QRelation params
{ topic(QRelation), attrs(set_of.Name) }>

This function is the same as C<sys.std.Core.QTuple.projection> but that it
operates on and results in a C<QRelation> rather than a C<QTuple>.  But
note that the result q/relation will have fewer q/tuples than C<topic> if
any C<topic> q/tuples were non-distinct for just the projected attributes.

=item C<function sys.std.Core.QRelation.cmpl_projection result QRelation
params { topic(QRelation), attrs(set_of.Name) }>

This function is the same as C<sys.std.Core.QTuple.cmpl_projection> but
that it operates on and results in a C<QRelation> rather than a C<QTuple>.

=item C<function sys.std.Core.QRelation.wrap result QRelation params {
topic(QRelation), inner(set_of.Name), outer(Name) }>

This function is the same as C<sys.std.Core.QTuple.wrap> but that it
operates on and results in a C<QRelation> rather than a C<QTuple>, where
each of its member q/tuples was transformed as per
C<sys.std.Core.QTuple.wrap>.

=item C<function sys.std.Core.QRelation.cmpl_wrap result QRelation params {
topic(QRelation), cmpl_inner(set_of.Name), outer(Name) }>

This function is the same as C<sys.std.Core.QTuple.cmpl_wrap> but that it
operates on and results in a C<QRelation> rather than a C<QTuple>, where
each of its member q/tuples was transformed as per
C<sys.std.Core.QTuple.cmpl_wrap>.

=item C<function sys.std.Core.QRelation.unwrap result QRelation params {
topic(QRelation), outer(Name), inner(set_of.Name) }>

This function is the inverse of C<sys.std.Core.QRelation.wrap> as
C<sys.std.Core.QTuple.unwrap> is to C<sys.std.Core.QTuple.wrap>.  But
unlike the C<QTuple> variant of C<unwrap>, this current function requires
the extra C<inner> argument to prevent ambiguity in the general case where
C<topic> might have zero q/tuples, because in that situation the
most-specific-type of C<topic{outer}> would be C<Empty>, and the names of
the attributes to add to C<topic> in place of C<topic{outer}> are not
known.  This function will fail if C<topic> has at least 1 q/tuple and
C<inner> does not match the names of the attributes of C<topic{outer}>.
This function will fail with a non-C<Relation> valued C<topic> unless, for
every q/tuple of C<topic>, the attribute specified by C<outer> is valued
with a q/tuple of the same degree and heading (attribute names); this
failure is because there would be no consistent set of attribute names to
extend C<topic> with (a problem that would never happen by definition with
a non-quasi relation C<topic>).

=item C<function sys.std.Core.QRelation.group result QRelation params {
topic(QRelation), inner(set_of.Name), outer(Name) }>

This function is similar to C<sys.std.Core.QRelation.wrap> but that the
C<topic> attribute-wrapping transformations result in new
C<QRelation>-typed attributes rather than new C<QTuple>-typed attributes,
and moreover multiple C<topic> q/tuples may be combined into fewer q/tuples
whose new C<QRelation>-typed attributes have multiple q/tuples.  This
function takes a q/relation of N q/tuples and divides the q/tuples into M
groups where all the q/tuples in a group have the same values in the
attributes which aren't being grouped (and distinct values in the
attributes that are being grouped); it then results in a new q/relation of
M q/tuples where the new q/relation-valued attribute of the result has the
q/tuples of the M groups.  A grouped q/relation contains all of the
information in the original q/relation, but it has less redundancy due to
redundant non-grouped attributes now just being represented in one q/tuple
per the multiple q/tuples whose grouped attributes had them in common.  A
q/relation having q/relation-valued attributes like this is a common way to
group so-called child q/tuples under their parents.  As a trivial case, if
C<inner> is empty, then the result has all the same q/tuples and attributes
as before plus a new relation-typed attribute of degree zero whose value
per tuple is of cardinality one; or, if C<inner> lists all attributes of
C<topic>, then the result has a single q/tuple of a single attribute whose
value is the same as C<topic>.  This function supports the new attribute
having the same name as an old one being grouped into it.  This function
will fail if C<inner> specifies any attribute names that C<topic> doesn't
have, or if C<outer> is the same as C<topic> attributes that aren't being
grouped.

=item C<function sys.std.Core.QRelation.cmpl_group result QRelation params
{ topic(QRelation), group_per(set_of.Name), outer(Name) }>

This function is the same as C<group> but that it groups the complementary
subset of attributes of C<topic> to those specified by C<group_per>.

=item C<function sys.std.Core.QRelation.ungroup result QRelation params {
topic(QRelation), outer(Name), inner(set_of.Name) }>

This function is the inverse of C<sys.std.Core.QRelation.group> as
C<sys.std.Core.QRelation.unwrap> is to C<sys.std.Core.QRelation.wrap>; it
will ungroup a C<QRelation>-type attribute into its member attributes and
q/tuples.  A q/relation can be first grouped and then that result ungrouped
to produce the original q/relation, with no data loss.  However, the
ungroup of a q/relation on a q/relation-valued attribute will lose the
information in any outer q/relation q/tuples whose inner q/relation value
has zero q/tuples; a group on this result won't bring them back.  This
function will fail if C<outer> specifies any attribute name that C<topic>
doesn't have, or if an attribute of C<topic{outer}> is the same as another
C<topic> attribute.  This function will fail with a non-C<Relation> valued
C<topic> unless, for every q/tuple of C<topic>, the attribute specified by
C<outer> is valued with a q/relation of the same degree and heading
(attribute names); this failure is because there would be no consistent set
of attribute names to extend C<topic> with (a problem that would never
happen by definition with a non-quasi relation C<topic>).

=item C<function sys.std.Core.QRelation.restriction result QRelation params
{ topic(QRelation), func(FuncRef), assuming(QTuple)? }>

This function results in the relational restriction of its C<topic>
argument as determined by applying the C<Bool>-resulting function named in
its C<func> argument when the latter function is curried by its C<assuming>
argument.  The result q/relation has the same heading as C<topic>, and its
body contains the subset of C<topic> q/tuples where, for each q/tuple, the
function named by C<func> results in C<Bool:true> when passed the q/tuple
as its C<topic> argument and C<assuming> as its C<assuming> argument.  As a
trivial case, if C<func> is defined to unconditionally result in
C<Bool:true>, then this function results simply in C<topic>; or, for an
unconditional C<Bool:false>, this function results in the empty relation
with the same heading.  Note that this operation is also legitimately known
as I<where>.  See also the C<sys.std.Core.QRelation.semijoin> function,
which is a simpler-syntax alternative for
C<sys.std.Core.QRelation.restriction> in its typical usage where
restrictions are composed simply of anded or ored tests for attribute value
equality.

=item C<function sys.std.Core.QRelation.cmpl_restriction result QRelation
params { topic(QRelation), func(FuncRef), assuming(QTuple)? }>

This function is the same as C<restriction> but that it results in the
complementary subset of q/tuples of C<topic> when given the same arguments.
See also the C<sys.std.Core.QRelation.semidifference> function.

=item C<function sys.std.Core.QRelation.extension result QRelation params {
topic(QRelation), attrs(set_of.Name), func(FuncRef), assuming(QTuple)? }>

This function results in the relational extension of its C<topic> argument
as determined by applying the C<QTuple>-resulting function named in its
C<func> argument when the latter function is curried by its C<assuming>
argument.  The result q/relation has a heading that is a superset of that
of C<topic>, and its body contains the same number of q/tuples, with all
attribute values of C<topic> retained, and possibly extra present,
determined as follows; for each C<topic> q/tuple, the function named by
C<func> results in a second q/tuple when passed the first q/tuple as its
C<topic> argument and C<assuming> as its C<assuming> argument; the first
and second q/tuples must have no attribute names in common, and the result
q/tuple is derived by joining (cross-product) the q/tuples together.  As a
trivial case, if C<func> is defined to unconditionally result in the
degree-zero tuple, then this function results simply in C<topic>.  Now,
C<extension> requires the extra C<attrs> argument to prevent ambiguity in
the general case where C<topic> might have zero q/tuples, because in that
situation, C<func> would never be invoked, and the names of the attributes
to add to C<topic> are not known (we don't generally assume that
C<extension> can reverse-engineer C<func> to see what attributes it would
have resulted in).  This function will fail if C<topic> has at least 1
q/tuple and the result of C<func> does not have matching attribute names to
those named by C<attrs>.

=item C<function sys.std.Core.QRelation.static_extension result QRelation
params { topic(QRelation), attrs(QTuple) }>

This function is a simpler-syntax alternative to both
C<sys.std.Core.QRelation.extension> and C<sys.std.Core.QRelation.product>
in the typical scenario of extending a q/relation, given in the C<topic>
argument, such that every q/tuple has mutually identical values for each of
the new attributes; the new attribute names and common values are given in
the C<attrs> argument.

=item C<function sys.std.Core.QRelation.summary result QRelation params {
topic(QRelation), group_per(set_of.Name), result_attrs(set_of.Name),
summ_func(FuncRef), summ_assuming(QTuple)? }>

This function provides a convenient context for using aggregate functions
to derive a per-group summary q/relation, which is its result, from another
q/relation, which is its C<topic> argument.  This function first performs a
C<cmpl_group> on C<topic> using C<group_per> to specify which attributes
get grouped into a new q/relation-valued attribute and which don't; those
that don't instead get wrapped into a q/tuple-valued attribute.  Then, per
q/tuple in the main q/relation, this function applies the
C<QTuple>-resulting function named in its C<summ_func> argument when the
latter function is curried by its C<summ_assuming> argument (passed to it
as just C<assuming>); the curried function has, rather than the typical 1
C<topic> varying parameter, 2 varying parameters named C<summarize> and
C<per>, which are valued with the q/relation-valued attribute and
q/tuple-valued attribute, respectively.  As per a function that C<map>
applies, the function named by C<summ_func> effectively takes a whole
post-grouping input q/tuple and results in a whole q/tuple; the applied
function would directly invoke any N-ary / aggregate operators, and extract
their inputs from (or calculate) C<summarize> as it sees fit.  Note that
C<summary> is not intended to be used to summarize an entire C<topic>
q/relation at once (except by chance of it resolving to 1 group); you
should instead invoke your summarize-all C<func> directly, or inline it,
rather than by way of C<summary>, especially if you want a single-q/tuple
result on an empty C<topic> (which C<summary>) won't do.  Now, C<summary>
requires the extra C<result_attrs> argument to prevent ambiguity in the
general case where C<topic> might have zero q/tuples, because in that
situation, C<summ_func> would never be invoked, and the names of the
attributes of the result are not known (we don't generally assume that
C<summary> can reverse-engineer C<summ_func> to see what attributes it
would have resulted in).  This function will fail if C<topic> has at least
1 q/tuple and the result of C<summ_func> does not have matching attribute
names to those named by C<result_attrs>.

=back

=head1 SYSTEM-DEFINED GENERIC MULTIPLE INPUT QUASI-/RELATION FUNCTIONS

These functions are applicable to mainly q/relation types, but are generic
in that they typically work with any q/relation types.

=over

=item C<function sys.std.Core.QRelation.is_subset result Bool params {
look_in(QRelation), look_for(QRelation) }>

This function results in C<Bool:true> iff the set of q/tuples comprising
C<look_for> is a subset of the set of q/tuples comprising C<look_in>, and
C<Bool:false> otherwise.  This function will warn if the input q/relations
common-named attributes have declared types that are incompatible as per
C<is_identical>.

=item C<function sys.std.Core.QRelation.is_not_subset result Bool params {
look_in(QRelation), look_for(QRelation) }>

This function is exactly the same as C<sys.std.Core.QRelation.is_subset>
except that it results in the opposite boolean value when given the same
arguments.

=item C<function sys.std.Core.QRelation.union result QRelation params {
topic(quasi_set_of.QRelation) }>

This function results in the relational union/inclusive-or of the N element
values of its argument; it is a reduction operator that recursively takes
each pair of input values and relationally unions (which is both
commutative and associative) them together until just one is left, which is
the result.  The result q/relation has the same heading as all of its
inputs, and its body contains every q/tuple that is in any of the input
q/relations.  If C<topic> has zero values, then this function will fail.
Note that, conceptually C<union> I<does> have an identity value which could
be this function's result when C<topic> has zero values, which is the empty
relation with the same heading, which is the per-distinct-heading identity
value for relational union; however, since a C<topic> with zero values
wouldn't know the heading / attribute names for the result q/relation in
question, it seems the best alternative is to require invoking code to work
around the limitation somehow, which might mean it will supply the identity
value explicitly as an extra C<topic> element.

=item C<function sys.std.Core.QRelation.disjoint_union result QRelation
params { topic(quasi_set_of.QRelation) }>

This function is exactly the same as C<sys.std.Core.QRelation.union> except
that it will fail if any 2 input values have a q/tuple in common.

=item C<function sys.std.Core.QRelation.intersection result QRelation
params { topic(quasi_set_of.QRelation) }>

This function results in the relational intersection/and of the N element
values of its argument; it is a reduction operator that recursively takes
each pair of input values and relationally intersects (which is both
commutative and associative) them together until just one is left, which is
the result.  The result q/relation has the same heading as all of its
inputs, and its body contains only the q/tuples that are in every one of
the input q/relations.  If C<topic> has zero values, then this function
will fail.  Note that, conceptually C<intersection> I<does> have an
identity value which could be this function's result when C<topic> has zero
values, which is the universal q/relation with the same heading (that is,
the q/relation having all the q/tuples that could ever exist in a
q/relation with that heading), which is the per-distinct-heading identity
value for relational intersection; however, since a C<topic> with zero
values wouldn't know the heading / attribute names for the result
q/relation in question (and even if they were, more information on
attribute types would be needed to produce said universal q/relation, and
even then it might be infinite or impossibly large), it seems the best
alternative is to require invoking code to work around the limitation
somehow, which might mean it will supply the identity value explicitly as
an extra C<topic> element.  Note that this I<intersection> operator is
conceptually a special case of C<join>, applicable when the headings of the
inputs are the same, and the other will produce the same result as this
when given the same inputs, but with the exception that I<intersection> has
a different identity value when given zero inputs.

=item C<function sys.std.Core.QRelation.difference result QRelation params
{ source(QRelation), filter(QRelation) }>

This function results in the relational difference when its C<filter>
argument is subtracted from its C<source> argument.  The result q/relation
has the same heading as both of its arguments, and its body contains only
the q/tuples that are in C<source> and are not in C<filter>.  This function
will warn if the input q/relations common-named attributes have declared
types that are incompatible as per C<is_identical>.  Note that this
I<difference> operator is conceptually a special case of I<semidifference>,
applicable when the headings of the inputs are the same.

=item C<function sys.std.Core.QRelation.semidifference result QRelation
params { source(QRelation), filter(QRelation) }>

This function is the same as C<semijoin> but that it results in the
complementary subset of q/tuples of C<source> when given the same
arguments.  Note that this operation is also legitimately known as
I<antijoin> or I<anti-semijoin>.

=item C<function sys.std.Core.QRelation.semijoin result QRelation params {
source(QRelation), filter(QRelation) }>

This function results in the relational semijoin of its C<source> and
C<filter> arguments.  The result q/relation has the same heading as
C<source>, and its body contains the subset of C<source> q/tuples that
match those of C<filter> as per C<join>.  Note that relational semijoin is
conceptually a short-hand for first doing an ordinary relational join
between its 2 arguments, and then performing a relational projection on all
of the attributes that just C<source> has.  This function will fail|warn
any time that C<join> would fail|warn on the same 2 input q/relations.

=item C<function sys.std.Core.QRelation.join result QRelation params {
topic(quasi_set_of.QRelation) }>

This function results in the relational join of the N element values of its
argument; it is a reduction operator that recursively takes each pair of
input values and relationally joins (which is both commutative and
associative) them together until just one is left, which is the result.
The result q/relation has a heading that is a union of all of the headings
of its inputs, and its body is the result of first pairwise-matching every
q/tuple of each input q/relation with every q/tuple of each other input
q/relation, then where each member of a q/tuple pair has attribute names in
common, eliminating pairs where the values of those attributes differ and
unioning the remaining said q/tuple pairs, then eliminating any result
q/tuples that duplicate others.  If C<topic> has zero values, then C<join>
results in the nullary q/relation with one q/tuple, which is the identity
value for relational join.  As a trivial case, if any input q/relation has
zero q/tuples, then the function's result will too; or, if any input is the
nullary q/relation with one q/tuple, that input can be ignored (see
identity value); or, if any 2 inputs have no attribute names in common,
then the join of just those 2 is a cartesian product; or, if any 2 inputs
have all attribute names in common, then the join of just those 2 is an
intersection; or, if for 2 inputs, one's set of attribute names is a proper
subset of another's, then the join of just those two is a semijoin with the
former filtering the latter.  This function will warn if any input
q/relations have attributes with common names where their declared types
are incompatible as per C<is_identical>.  Note that this operation is also
legitimately known as I<natural inner join>.

=item C<function sys.std.Core.QRelation.product result QRelation params {
topic(quasi_set_of.QRelation) }>

This function results in the relational cartesian/cross product of the N
element values of its argument; it is conceptually a special case of
C<join> where all input q/relations have mutually distinct attribute names;
unlike C<join>, C<product> will fail if any inputs have attribute names in
common.  Note that this operation is also legitimately known as
I<cartesian/cross join>.

=item C<function sys.std.Core.QRelation.quotient result QRelation params {
dividend(QRelation), divisor(QRelation) }>

This function results in the quotient when its C<dividend> argument is
divided by its C<divisor> argument using relational division.  Speaking
informally, say the q/relations C<dividend> and C<divisor> are called C<A>
and C<B>, and their attribute q/sets are respectively named C<{X,Y}> and
C<{Y}>, then the result q/relation has a heading composed of attributes
C<{X}> (so the result and C<divisor> headings are both complementary
subsets of the C<dividend> heading); the result has all q/tuples C<{X}>
such that a q/tuple C<{X,Y}> appears in C<A> for all q/tuples C<{Y}>
appearing in C<B>; that is, C<A / B> is shorthand for C<A{X} - ((A{X} join
B) - A){X}>.

=back

=head1 SYSTEM-DEFINED GENERIC CONTROL FLOW FUNCTIONS

=over

=item C<function sys.std.Core.Control.func_invo result Universal params {
function(FuncRef), args(QTuple)? }>

This function results in the result of invoking the other function named in
its C<function> argument when the latter function is curried by its C<args>
argument; each attribute name of C<args> is mapped to a parameter name of
the invoked function, and the corresponding attribute value is the
corresponding argument for the function invocation.  This function will
fail if the invoked function has any non-optional parameters such that
there aren't any corresponding attributes in C<args>, or if there are any
attributes in C<args> that don't have corresponding parameters, or if any
attribute values aren't of the declared types of the corresponding
parameters.  The purpose of C<func_invo> is to support invocation of any
function whose name or parameters potentially aren't known until runtime;
it forms the foundation of all other system-defined functions that want to
invoke a function whose name they take as an argument.  The C<args>
parameter is optional and defaults to the zero-attribute quasi-tuple if no
explicit argument is given to it.

=back

=head1 SYSTEM-DEFINED GENERIC UNIVERSAL UPDATERS

These update operators are applicable to values of any data type at all.

=over

=item C<updater sys.std.Core.Universal.assign update { target(Universal) }
read { v(Universal) }>

This update operator will update the variable supplied as its C<target>
argument so that it holds the value supplied as its C<v> argument.  This
updater will fail if C<v> isn't of the declared type of the variable behind
C<target>; this function will otherwise warn if the declared type of C<v>
isn't a subtype of the declared type of the variable behind C<target>.

=back

=head1 SYSTEM-DEFINED GENERIC QUASI-/TUPLE VARIABLE UPDATERS

=head2 Updaters That Rename Attributes

=over

=item C<updater sys.std.Core.QTuple.assign_rename update { topic(QTuple) }
read { map(AttrRenameMap) }>

This update operator is a short-hand for first invoking the
C<sys.std.Core.QTuple.rename> function with the same arguments, and then
assigning the result of that function to C<topic>.  This procedure is
analagous to the data-manipulation phase of a SQL RENAME TABLE|VIEW or
ALTER TABLE|VIEW RENAME TO statement iff C<topic> is C<Database>-typed;
each tuple of C<map> corresponds to a renamed SQL table.

=back

=head2 Updaters That Add Attributes

=over

=item C<updater sys.std.Core.QTuple.assign_static_extension update {
topic(QTuple) } read { attrs(QTuple) }>

This update operator is a short-hand for first invoking the
C<sys.std.Core.QTuple.static_extension> function with the same arguments,
and then assigning the result of that function to C<topic>.  This procedure
is analagous to the data-manipulation phase of a SQL CREATE TABLE|VIEW
statement iff both arguments are C<Database>-typed; each q/relation-typed
attribute of C<attrs> corresponds to a created SQL table.

=back

=head2 Updaters That Remove Attributes

=over

=item C<updater sys.std.Core.QTuple.assign_projection update {
topic(QTuple) } read { attrs(set_of.Name) }>

This update operator is a short-hand for first invoking the
C<sys.std.Core.QTuple.projection> function with the same arguments, and
then assigning the result of that function to C<topic>.

=item C<updater sys.std.Core.QTuple.assign_cmpl_projection update {
topic(QTuple) } read { attrs(set_of.Name) }>

This update operator is a short-hand for first invoking the
C<sys.std.Core.QTuple.cmpl_projection> function with the same arguments,
and then assigning the result of that function to C<topic>.  This procedure
is analagous to the data-manipulation phase of a SQL DROP TABLE|VIEW
statement iff C<topic> is C<Database>-typed; each q/relation-typed
attribute named by C<attrs> corresponds to a dropped SQL table.

=back

=head1 SYSTEM-DEFINED GENERIC QUASI-/RELATION VARIABLE UPDATERS

=head2 Updaters That Add Q/Tuples

=over

=item C<updater sys.std.Core.QRelation.assign_insertion update {
r(QRelation) } read { t(QTuple) }>

This update operator is a short-hand for first invoking the
C<sys.std.Core.QRelation.insertion> function with the same arguments, and
then assigning the result of that function to C<r>.  This updater is
analagous to the general case of the single-row SQL "INSERT" statement.

=item C<updater sys.std.Core.QRelation.assign_disjoint_insertion update {
r(QRelation) } read { t(QTuple) }>

This update operator is a short-hand for first invoking the
C<sys.std.Core.QRelation.disjoint_insertion> function with the same
arguments, and then assigning the result of that function to C<r>.

=item C<updater sys.std.Core.QRelation.assign_union update {
topic(QRelation) } read { other(QRelation) }>

This update operator is a short-hand for first invoking the
C<sys.std.Core.QRelation.union> function such that it has 2 input
q/relations from C<assign_union>'s 2 arguments, and then assigning the
result of that function to C<topic>.  This updater is analagous to the
general case of the multiple-row SQL "INSERT" statement.

=item C<updater sys.std.Core.QRelation.assign_disjoint_union update {
topic(QRelation) } read { other(QRelation) }>

This update operator is to C<sys.std.Core.QRelation.disjoint_union> what
the function C<sys.std.Core.QRelation.assign_union> is to
C<sys.std.Core.QRelation.union>.

=back

=head2 Updaters That Remove Q/Tuples

=over

=item C<updater sys.std.Core.QRelation.assign_deletion update {
r(QRelation) } read { t(QTuple) }>

This update operator is a short-hand for first invoking the
C<sys.std.Core.QRelation.deletion> function with the same arguments, and
then assigning the result of that function to C<r>.

=item C<updater sys.std.Core.QRelation.assign_restriction update {
topic(QRelation) } read { func(FuncRef), assuming(QTuple)? }>

This update operator is a short-hand for first invoking the
C<sys.std.Core.QRelation.restriction> function with the same arguments, and
then assigning the result of that function to C<topic>.

=item C<updater sys.std.Core.QRelation.assign_cmpl_restriction update {
topic(QRelation) } read { func(FuncRef), assuming(QTuple)? }>

This update operator is a short-hand for first invoking the
C<sys.std.Core.QRelation.cmpl_restriction> function with the same
arguments, and then assigning the result of that function to C<topic>.
This updater is analagous to the general case of the SQL "DELETE"
statement.

=item C<updater sys.std.Core.QRelation.assign_intersection update {
topic(QRelation) } read { other(QRelation) }>

This update operator is to C<sys.std.Core.QRelation.intersection> what the
function C<sys.std.Core.QRelation.assign_union> is to
C<sys.std.Core.QRelation.union>.

=item C<updater sys.std.Core.QRelation.assign_difference update {
source(QRelation) } read { filter(QRelation) }>

This update operator is a short-hand for first invoking the
C<sys.std.Core.QRelation.difference> function with the same arguments, and
then assigning the result of that function to C<source>.

=item C<updater sys.std.Core.QRelation.assign_semidifference update {
source(QRelation) } read { filter(QRelation) }>

This update operator is a short-hand for first invoking the
C<sys.std.Core.QRelation.semidifference> function with the same arguments,
and then assigning the result of that function to C<source>.  This updater
is analagous to the common case of the SQL "DELETE" statement where the
criteria is simply a set of and-ed and or-ed value equality tests.

=item C<updater sys.std.Core.QRelation.assign_semijoin update {
source(QRelation) } read { filter(QRelation) }>

This update operator is a short-hand for first invoking the
C<sys.std.Core.QRelation.semijoin> function with the same arguments, and
then assigning the result of that function to C<source>.

=back

=head2 Updaters That Rename Attributes

=over

=item C<updater sys.std.Core.QRelation.assign_rename update {
topic(QRelation) } read { map(AttrRenameMap) }>

This update operator is a short-hand for first invoking the
C<sys.std.Core.QRelation.rename> function with the same arguments, and then
assigning the result of that function to C<topic>.  This procedure is
analagous to the data-manipulation phase of a SQL ALTER TABLE|VIEW RENAME
COLUMN statement; each tuple of C<map> corresponds to a renamed SQL table
column.

=back

=head2 Updaters That Add Attributes

=over

=item C<updater sys.std.Core.QRelation.assign_extension update {
topic(QRelation) } read { attrs(set_of.Name), func(FuncRef),
assuming(QTuple)? }>

This update operator is a short-hand for first invoking the
C<sys.std.Core.QRelation.extension> function with the same arguments, and
then assigning the result of that function to C<topic>.

=item C<updater sys.std.Core.QRelation.assign_static_extension update {
topic(QRelation) } read { attrs(QTuple) }>

This update operator is a short-hand for first invoking the
C<sys.std.Core.QRelation.static_extension> function with the same
arguments, and then assigning the result of that function to C<topic>.
This procedure is analagous to the data-manipulation phase of a SQL ALTER
TABLE|VIEW ADD COLUMN statement; each attribute of C<attrs> corresponds to
an added SQL table column.

=back

=head2 Updaters That Remove Attributes

=over

=item C<updater sys.std.Core.QRelation.assign_projection update {
topic(QRelation) } read { attrs(set_of.Name) }>

This update operator is a short-hand for first invoking the
C<sys.std.Core.QRelation.projection> function with the same arguments, and
then assigning the result of that function to C<topic>.

=item C<updater sys.std.Core.QRelation.assign_cmpl_projection update {
topic(QRelation) } read { attrs(set_of.Name) }>

This update operator is a short-hand for first invoking the
C<sys.std.Core.QRelation.cmpl_projection> function with the same arguments,
and then assigning the result of that function to C<topic>.  This procedure
is analagous to the data-manipulation phase of a SQL ALTER TABLE|VIEW DROP
COLUMN statement; each attribute named by C<attrs> corresponds to an
dropped SQL table column.

=back

=head1 SYSTEM-DEFINED GENERIC CONTROL FLOW UPDATERS

=over

=item C<updater sys.std.Core.Control.upd_invo update { upd_args(QTuple)
} read { updater(ProcRef), ro_args(QTuple)? }>

This update operator has the same purpose and features as
C<sys.std.Core.Control.func_invo> but that it invokes an updater rather
than a function; there is no result to deal with, and there are both
subject-to-update parameters and read-only parameters of the invoked
updater to bind to; they are bound with the attributes of this updater's
C<upd_args> and C<ro_args> arguments, respectively.  The C<ro_args>
parameter is optional and defaults as per the C<args> parameter of
C<func_invo>; the C<upd_args> parameter is non-optional because an updater
must always be invoked with at least one subject-to-update argument.

=back

=head1 SYSTEM-DEFINED GENERIC SYSTEM SERVICES FOR STANDARD I/O

These system services are provided so Muldis D can do basic user
input/output by itself, using standard input and standard output, like any
general purpose programming language, and help satisfy its need to be
computationally complete.  For now they just work with plain (Unicode) text
data, so one can implement a basic command-line program interface, or do
basic invoker-setup file piping, as well as display diagnostics to standard
error.  These routines are not exhaustive, and their details are subject to
future revision.

=over

=item C<system_service sys.std.Core.STDIO.read_Text update { target(Text) }
read { length_in_graphemes(NNInt) }>

This system service routine will attempt to read C<length_in_graphemes>
characters from standard input as a single C<Text> value, blocking the
current in-DBMS process until it finishes, and then update the variable
supplied as its C<target> argument so that it holds the read value.  The
routine will only fetch fewer than the requested number of characters if
the input stream is closed first.  This routine will throw an exception if
any system errors occur.

=item C<system_service sys.std.Core.STDIO.read_Text_line update {
target(Text) } read { ignore_empty_lines(Bool)? }>

This system service routine is the same as C<sys.std.Core.STDIO.read_Text>
except that it will read from standard input until an
implementation-defined end-of-line character is read, rather than reading a
fixed number of characters; this end-of-line character will not be included
in the read C<Text> value.  If the C<ignore_empty_lines> argument is
C<Bool:true>, then this routine will keep reading lines from standard input
until it reads a non-empty line, and then C<target> is only updated to hold
that last non-empty line; otherwise, this routine will end as soon as one
line is read, even if it is empty.

=item C<system_service sys.std.Core.STDIO.write_Text update {} read {
v(Text) }>

This system service routine will attempt to write the characters of its
C<v> argument to standard output, blocking the current in-DBMS process
until it finishes.  This routine will throw an exception if any system
errors occur.

=item C<system_service sys.std.Core.STDIO.write_Text_line update {} read {
v(Text) }>

This system service routine is the same as C<sys.std.Core.STDIO.write_Text>
except that it will additionally write an implementation-defined
end-of-line character after writing C<v>.

=item C<system_service sys.std.Core.STDIO.prompt_Text_line update {
target(Text) } read { prompt(Text), ignore_empty_lines(Bool)?  }>

This system service routine is a wrapper over first invoking
C<sys.std.Core.STDIO.write_Text> with its C<prompt> argument and then
invoking C<sys.std.Core.STDIO.read_Text_line> with its C<target> argument.
A true C<ignore_empty_lines> argument will result in I<both> of the wrapped
routines being invoked repeatedly, not just C<read_text_line>.

=item C<system_service sys.std.Core.STDIO.error_Text update {} read {
v(Text) }>

This system service routine is the same as C<sys.std.Core.STDIO.write_Text>
except that it will write to standard error rather than standard output.

=item C<system_service sys.std.Core.STDIO.error_Text_line update {} read {
v(Text) }>

This system service routine is the same as
C<sys.std.Core.STDIO.write_Text_line> except that it will write to standard
error rather than standard output.

=back

=head1 SYSTEM-DEFINED GENERIC CONTROL FLOW PROCEDURES

These procedures are applicable to use in all kinds of procedures.

=over

=item C<procedure sys.std.Core.Control.proc_invo update {
upd_args(QTuple)? } read { procedure(ProcRef), ro_args(QTuple)? }>

This procedure is the same as C<sys.std.Core.Control.upd_invo> but that it
invokes a procedure rather than an updater, and that C<upd_args> is
optional.

=item C<procedure sys.std.Core.Control.fail update {} read {
topic(Exception) }>

This procedure will throw the exception given as its argument; this results
in the call stack unwinding, and transaction rollbacks, until it is caught.

=item C<procedure sys.std.Core.Control.try_catch update {
try_updating(QTuple)?, catch_updating(QTuple)? } read {
try(ProcRef), catch(ProcRef), try_assuming(QTuple)?,
catch_assuming(QTuple)? }>

This procedure invokes the procedure named in its C<try> argument, giving
it the arguments C<try_updating> and C<try_assuming> as its C<updating> and
C<assuming> arguments, respectively.  If the C<try> procedure throws an
exception, then any state changes it made roll back (but changes made
before that don't), and the call stack unwinds to the C<try_catch> itself;
then the procedure named by C<catch> is invoked similarly to C<try> was,
with corresponding arguments, but with the extra read-only argument
C<topic> whose value is an C<Exception>; if the C<catch> procedure also
throws an exception (such as to say its not handling the thrown one), then
that one is not caught and the call stack unwinding plus applicable
transaction rollback carries on to the caller of the C<try_catch>.  If the
C<try> procedure succeeds (doesn't throw an exception), then the C<catch>
procedure is not called.  Each of the C<(try|catch)_(updating|assuming)>
parameters is optional and defaults to the zero-attribute tuple if no
explicit argument is given to it.

=back

=head1 SYSTEM-DEFINED GENERIC BOOTLOADER EXCLUSIVES

These system services may only be invoked directly by a C<bootloader>
routine.

=over

=item C<bootloader_exclusive sys.std.Core.Control.start_trans read {}>

This system service starts a new child-most transaction.

=item C<bootloader_exclusive sys.std.Core.Control.commit_trans read {}>

This system service commits the child-most transaction; it will fail if
there isn't one.

=item C<bootloader_exclusive sys.std.Core.Control.rollback_trans read {}>

This system service rolls back the child-most transaction; it will fail if
there isn't one.

=back

=head1 SEE ALSO

Go to L<Muldis::D> for the majority of distribution-internal
references, and L<Muldis::D::SeeAlso> for the majority of
distribution-external references.

=head1 AUTHOR

Darren Duncan (C<perl@DarrenDuncan.net>)

=head1 LICENSE AND COPYRIGHT

This file is part of the formal specification of the Muldis D language.

Muldis D is Copyright © 2002-2009, Darren Duncan.

See the LICENSE AND COPYRIGHT of L<Muldis::D> for details.

=head1 TRADEMARK POLICY

The TRADEMARK POLICY in L<Muldis::D> applies to this file too.

=head1 ACKNOWLEDGEMENTS

The ACKNOWLEDGEMENTS in L<Muldis::D> apply to this file too.

=cut
