=pod

=encoding utf8

=head1 NAME

Muldis::D::Dialect::HDMD_Perl5_Tiny -
How to format Perl 5 Hosted Data Muldis D

=head1 VERSION

This document is Muldis::D::Dialect::HDMD_Perl5_Tiny 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.

=head1 DESCRIPTION

This document outlines the grammar of the I<Hosted Data Muldis D> dialect
named C<HDMD_Perl5_Tiny>.  The fully-qualified name of this Muldis D
dialect, in combination with the base language spec it is bundled with, is
C<[ 'Muldis_D', 'http://muldis.com', 'N.N.N', 'HDMD_Perl5_Tiny' ]> (when
the bundled base language version is substituted for the C<N.N.N>).

The C<HDMD_Perl5_Tiny> dialect is defined to be hosted in Perl 5, and is
composed of just|mainly core Perl 5 types.  This dialect is optimized for
Perl 5 specifically, and doesn't try to match the version for Perl 6; you
*will* have to reformat any Perl Hosted Data Muldis D when migrating
between Perl 5 and Perl 6, same as with your ordinary Perl code.

This dialect is designed to exactly match the structure of a possible
concrete syntax tree, comprised of native Perl 5 scalar and collection
typed values, resulting from parsing code written in the Muldis D dialect
L<PTMD_Tiny|Muldis::D::Dialect::PTMD_Tiny> using Perl 5.  This dialect
exists as a convenience to Perl 5 programmers that want to generate or
introspect Muldis D code by saving them the difficulty and overhead of
escaping and stitching plain text code; it is expected that a Muldis D
implementation written in Perl 5 will natively accept input in both the
C<PTMD_Tiny> and C<HDMD_Perl5_Tiny> dialects.  Furthermore, the
C<HDMD_Perl5_Tiny> dialect provides additional Muldis D syntax options to
Perl 5 programmers besides what C<PTMD_Tiny> would canonically parse into,
such as the direct use of some Perl 5-only features.  Note that most of the
details that the 2 dialects have in common are described just in the
C<PTMD_Tiny> file, for both dialects; this current file will mainly focus
on the differences; you should read the L<Muldis::D::Dialect::PTMD_Tiny>
file before the current one, so to provide a context for better
understanding it.

Fundamentally, the various Muldis D scalar and collection types are
represented by their equivalent Perl native scalar and collection types.
But since Muldis D is more strongly typed, or at least differently typed,
than Perl, each Muldis D literal is represented by a Perl array ref, whose
elements include both the payload Perl literal plus explicit meta-data for
how to interpret that Perl literal for mapping to Muldis D.

=head1 REWRITE PROGRESS MARKER

B<What follows next in this file, between this point and the SEE ALSO,
still has to be rewritten according to certain TODO plans, after which this
whole file should reflect what the DESCRIPTION etc above says.>

=head1 GENERAL STRUCTURE

A C<HDMD_Perl5_Tiny> Muldis D code file is a Perl 5 code file that defines
a Perl value that is a tree of Perl array ref, such that each array ref is
a tree I<node>; or such a Perl value definition may be embedded or
constructed in one or more files of a larger Perl 5 program that does more
than this.  The elements of each node/array ref include typically a native
Perl payload value, which may be a node itself, plus meta-data for that
payload, that meta-data typically including the analogy of a class name,
were nodes instead represented by a tree of node-specific objects.

Note that Perl undefined values are not allowed anywhere in a node in the
general case; you must use only defined values instead.  This documentation
also assumes that only defined values are used, and that supplying a Perl
undef will result in an error.  The few exceptions to this rule are
explicitly stated.

...

A PHMD value is composed mainly of a tree of Perl array ref, such that each
array ref is a tree node.  The elements of each node/array ref include
typically a native Perl payload value, which may be a PHMD value itself,
plus meta-data for that payload, that meta-data typically including the
analogy of a class name, were PHMD nodes instead represented by a tree of
PHMD-specific objects.

Every PHMD node representing a Muldis D value literal has 1-3 elements:

=over

=item *

Node kind: a Perl character string of the format C<< <[ a..z A..Z 0..9 _
]>+ >>.  All of the PHMD node kinds for Muldis D value literals are these
30: C<Bool>, C<Int>, C<String>, C<Blob>, C<Text>, C<Name>, C<NameChain>,
C<DeclNameChain>, C<Comment>, C<Order>, C<(Q|)Scalar>, C<(Q|)Tuple>,
C<(Q|)Relation>, C<(Q|)Set>, C<Nothing>, C<(Q|)Single>, C<(Q|)Array>,
C<(Q|)Bag>, C<Rat>, C<RatRoundMeth>, C<(UTC|Float)Instant>, C<Duration>.
All of the non-value-literal PHMD node kinds currently defined are these 2:
C<Muldis_D>, C<boot_stmt>.

=item *

Only when the node has 3 elements; type name: as per the payload of a
C<NameChain> PHMD node.  PHMD nodes of all of the aforementioned 30
value-specific kinds can have the 2nd type name node element except for
these 4: C<Bool>, C<Nothing>, C<Order>, C<RatRoundMeth>; this isn't because
those types can't be subtyped, but because in practice doing so isn't
useful.  Furthermore, with just the C<(Q|)Scalar> kinds, having the second
type name element is mandatory.  Non-value-literal PHMD nodes never have
this type name element.

=item *

Only when the node kind is not C<Nothing>; the payload: its allowed formats
depend on the node kind, and are defined separately per each node kind,
further below.

=back

Generally speaking, no Perl undefined values are allowed anywhere in a PHMD
value; you must use only defined values instead.  This documentation also
assumes that only defined values are used, and that supplying a Perl undef
will result in an error.  Exceptions to this are explicitly noted.

=head1 LANGUAGE NAME

As per the VERSIONING pod section of L<Muldis::D>, code written in
Muldis D must start by declaring the fully-qualified Muldis D language name
it is written in.  The C<HDMD_Perl5_Tiny> dialect formats this name as a
PHMD node having the following 5 elements:

=over

=item *

Node kind / language base name: the Perl character string C<Muldis_D>.

=item *

Base authority: a Perl character string as per the payload of a C<Text>
node; typically the Perl character string C<http://muldis.com>.

=item *

Base version number: a Perl character string as per the payload of a
C<Text> node; typically a Perl character string like C<1.2.3>.

=item *

Dialect: the Perl character string C<HDMD_Perl5_Tiny>.

=item *

Extensions: a Perl hash ref as per the payload of a C<Tuple> node;
see the L<MULDIS D TINY DIALECT PRAGMAS> pod section for more details.

=back

Examples:

    [ 'Muldis_D', 'http://muldis.com', '1.2.3', 'HDMD_Perl5_Tiny', {} ]

    [ 'Muldis_D', 'http://muldis.com', '1.2.3', 'HDMD_Perl5_Tiny', {
        'auto_add_attrs'          => [ 'Bool', 'true' ],
        'auto_unabbrev_std_names' => [ 'Bool', 'true' ],
        'auto_chains_from_names'  => [ 'Bool', 'true' ],
    } ]

More specifically, a language name PHMD node like the above would generally
be the input for a Perl Hosted Muldis D implementating virtual machine's
configuration step, which provides a context for subsequent feeding of
other PHMD trees to said virtual machine.

=head1 SIMPLE CORE SCALAR VALUE LITERALS

=head2 sys.std.Core.Type.Bool

This node kind represents a logical boolean value.  It is interpreted as a
Muldis D C<sys.std.Core.Type.Bool> value as follows:

=over

=item *

The canonical payload is the specific result of a Perl logical expression,
such as C<(1 == 0)> for 'false' or C<(1 == 1)> for 'true'; said values are
probably the empty string and number 1, respectively.

=item *

A few alternative payload formats are supported:  The Perl value literals
[C<'false'>, C<'0'>, C<0>, C<''>] all map to 'false', and the Perl value
literals [C<'true'>, C<'1'>, C<1>] all map to 'true'.  The 4 character
strings [C<false>, C<0>, C<true>, C<1>] specifically are what the Plain
Text Muldis D grammar uses, and are the results of parsing it in Perl 5.

=back

Examples:

    [ 'Bool', 'true' ]

    [ 'Bool', (1 == 0) ]

=head2 sys.std.Core.Type.Int

This node kind represents an integer value.  This node is interpreted as a
Muldis D C<sys.std.Core.Type.Int> value as follows:

=over

=item *

If the payload is a Perl scalar, then it must be just a canonical integer
value according to Perl, and it is mapped directly; since native Perl
integers are limited precision, larger integers can be represented by a
Perl character string of the format C<0> or C<< \-?<[1..9]><[ 0..9 _ ]>* >>
that is interpreted as base 10.

=item *

An alternative payload format is a C<bigint> object, which is conceptually
the closest thing Perl 5 has in core to a "big integer".

=item *

If the payload is a Perl hash ref, then it must have 1 element, whose key
and value are designated, in order, I<max-col-val> and I<main payload>; the
max-col-val must be a Perl string composed of a single C<[ 1..9 A..Z ]>
character, and the main payload must be a Perl character string of the
format C<0> or C<< \-?<[ 1..9 A..Z ]><[ 0..9 A..Z _ ]>* >>.  This format
specifically is what the Plain Text Muldis D grammar uses as its general
form for integer literals, and is the result of parsing it.  The main
payload is interpreted as a base-I<N> integer where I<N> might be between 2
and 36, and the given max-col-val says which possible value of I<N> to use.
Assuming all column values are between zero and I<N>-minus-one, the
max-col-val contains that I<N>-minus-one.  So to specify, eg, bases
[2,8,10,16], use max-col-val of [1,7,9,F].

=back

Examples:

    [ 'Int', { 1 => '11001001' } ] # binary

    [ 'Int', { 7 => '0' } ] # octal

    [ 'Int', { 7 => '644' } ] # octal

    [ 'Int', -34 ] # decimal

    [ 'Int', 42 ] # decimal

    [ 'Int', { F => 'DEADBEEF' } ] # hexadecimal

    [ 'Int', { Z => '-HELLOWORLD' } ] # base-36

    [ 'Int', { 3 => '301' } ] # base-4

    [ 'Int', { B => 'A09B' } ] # base-12

=head2 sys.std.Core.Type.String

This node kind represents an integer string value.  This node is
interpreted as a Muldis D C<sys.std.Core.Type.String> value as follows:

=over

=item *

If the payload is a Perl array ref, then every one of its elements must
constitute a valid payload for an C<Int> PHMD node.

=item *

If the payload is a Perl hash ref, then it must have 1 element, whose key
and value are designated, in order, I<max-col-val> and I<main payload>; the
max-col-val must be a Perl string and the main payload must be a Perl array
ref; every pairwise combination of the max-col-val with the elements of the
main payload must, when appropriately wrapped in a Perl hash ref, must
constitute a valid hash ref payload for an C<Int> PHMD node.

=back

Examples:

    [ 'String', { F => ['50','65','72','6C'] } ] # Unicode codepts = 'Perl'

    [ 'String', [80,101,114,109] ] # same thing

=head2 sys.std.Core.Type.Blob

This node kind represents a bit string.  This node is interpreted as a
Muldis D C<sys.std.Core.Type.Blob> value as follows:

=over

=item *

If the payload is a Perl scalar, then it must be a canonical Perl bit
string, which is a scalar whose utf-8 flag is false, and it is mapped
directly.

=item *

If the payload is a Perl hash ref, then it must have 1 element, whose key
and value are designated, in order, I<max-col-val> and I<main payload>; the
max-col-val must be a Perl string composed of a single C<[137F]> character,
and the main payload must be a Perl character string of the format C<< <[
0..9 A..F ]>* >>.  This format specifically is what the Plain Text Muldis D
grammar uses, and is the result of parsing it in Perl 5.  Each column of
the main payload specifies a sequence of one of [1,2,3,4] bits, depending
on whether max-col-val is [1,3,7,F].

=back

Examples:

    [ 'Blob', { 1 => '00101110100010' } ] # binary

    [ 'Blob', { 3 => '' } ]

    [ 'Blob', { F => 'A705E' } ] # hexadecimal

    [ 'Blob', { 7 => '523504376' } ]

    [ 'Blob', (pack 'H2', 'P') ]

    [ 'Blob', (pack 'H2', 'Z') ]

=head2 sys.std.Core.Type.Text

This node kind represents a character string.  This node is interpreted as
a Muldis D C<sys.std.Core.Type.Text> value by directly mapping the payload.
Note that, while Plain Text Muldis D may contain a few escape sequences,
those would be replaced with what they represent prior to making a PHMD
node.  The payload must be just a canonical Perl character string, which is
any Perl scalar value (a Muldis D implementation in Perl can ignore the
utf-8 flag as Perl itself knows how to treat its strings consistently).

Examples:

    [ 'Text', 'Ceres' ]

    [ 'Text', 'サンプル' ] # note: needs "use utf8;" pragma to work

    [ 'Text', '' ]

    [ 'Text', 'Perl' ]

=head2 sys.std.Core.Type.Cat.Name

This node kind represents a canonical short name for any kind of DBMS
entity when declaring it; it is a character string type, that is disjoint
from C<Text>.  This node is interpreted as a Muldis D
C<sys.std.Core.Type.Cat.Name> value by directly mapping the payload.  Note
that, while Plain Text Muldis D may contain a few escape sequences, those
would be replaced with what they represent prior to making a PHMD node.
The payload must be as per the payload of a C<Text> PHMD node.

Examples:

    [ 'Name', 'login_pass' ]

    [ 'Name', 'First Name' ]

=head2 sys.std.Core.Type.Cat.NameChain

This node kind represents a canonical long name for invoking a DBMS entity
in some contexts; it is conceptually a sequence of entity short names.  Its
payload is a Perl array ref or character string.  This node is interpreted
as a Muldis D C<sys.std.Core.Type.Cat.NameChain> value as follows:

=over

=item *

If the payload is an array ref, then it must have at least 2 elements,
and every element must be a valid payload for a C<Name> PHMD node (that
is, any Perl character string).  Each element of the payload, in order,
defines an element of the C<array> possrep's attribute of a C<NameChain>.

=item *

If the payload is a char str, then it must be formatted as a catenation
(using period (C<.>) separators) of at least 2 parts, where each part can
not have any literal period (C<.>) characters (if you want literal periods
then you can only use the array ref payload format to express it).  The
char str format of payload is interpreted by splitting it on the separators
into the array ref format, then processed as per the latter.

=back

Examples:

    [ 'NameChain', ['fed','data','the_db','gene','sorted_person_name'] ]

    [ 'NameChain', 'fed.data.the_db.stats.samples by order' ]

=head2 sys.std.Core.Type.Cat.DeclNameChain

This node kind is exactly the same as the C<NameChain> node kind, in both
structure/constraints and interpretation, etc, except that it represents a
canonical long name for declaring a DBMS entity in N-depth contexts, and
that the chain may have as few as zero parts rather than as few as 2;
however, a zero part chain can only be expressed with the array ref payload
format; an empty string char str format will be interpreted as having
a single element that is the empty string.

Examples:

    [ 'DeclNameChain', ['gene','sorted_person_name'] ]

    [ 'DeclNameChain', 'stats.samples by order' ]

=head2 sys.std.Core.Type.Cat.Comment

This node kind represents the text of a Muldis D code comment; it is a
character string type, that is disjoint from both C<Text> and C<Name>.
This node is interpreted as a Muldis D C<sys.std.Core.Type.Cat.Comment>
value by directly mapping the payload.  Note that, while Plain Text Muldis
D may contain a few escape sequences, those would be replaced with what
they represent prior to making a PHMD node.  The payload must be as per the
payload of a C<Text> PHMD node.

Examples:

    [ 'Comment', 'This does something.' ]

=head2 sys.std.Core.Type.Cat.Order

This node kind represents an order-determination.  This node is interpreted
as a Muldis D C<sys.std.Core.Type.Cat.Order> value as follows:

=over

=item *

The canonical payload is the specific result of a Perl order-determining
expression, such as C<< (1 <=> 2) >> for 'increase' or C<< (1 <=> 1) >> for
'same' or C<< (2 <=> 1) >> for 'decrease'; said values are probably the
numbers [-1,0,1], respectively.

=item *

A few alternative payload formats are supported:  The Perl value literals
[C<'increase'>, C<'-1'>, C<-1>] all map to 'increase', the Perl value
literals [C<'same'>, C<'0'>, C<0>] all map to 'same, and the Perl value
literals [C<'decrease'>, C<'1'>, C<1>] all map to 'decrease'.  The 6
character strings [C<increase>, C<-1>, C<same>, C<0>, C<decrease>, C<1>]
specifically are what the Plain Text Muldis D grammar uses, and are the
results of parsing it in Perl 5.

=back

Examples:

    [ 'Order', 'same' ]

    [ 'Order', (2 <=> 1) ]

=head1 GENERIC Q/SCALAR AND Q/NONSCALAR VALUE LITERALS

=head2 sys.std.Core.Type.(Q|)Scalar

This node kind represents a scalar subtype value.  This node is interpreted
as a Muldis D C<sys.std.Core.Type.(Q|)Scalar> subtype value whose declared
type is specified by the PHMD node's (mandatory for C<(Q|)Scalar>) type
name element and whose attributes are defined by the payload.  The payload
must be just a Perl array ref having exactly 2 elements, that are
designated I<possrep name> and I<possrep attrs>.  The possrep name and
possrep attrs must be as per the payload of a C<Name> and C<Tuple> PHMD
node payload, respectively.  The C<Scalar> PHMD node kind can only be used
for scalar types that have at least 1 possrep, and the I<possrep attrs> is
interpreted specifically as attributes of the declared type's possrep which
is specified by the I<possrep name>.  Each key+value pair of the second
payload element defines a named possrep attribute of the new scalar; the
pair's key and value are, respectively, a Perl character string that
specifies the possrep attribute name, and a PHMD node that specifies the
possrep attribute value.  (Note that most scalar types have at least 1
possrep; the only ones that don't are either union types of types having
possreps, or they are core system-defined types, and those all have their
own dedicated syntax for literals.)

Examples:

    [ 'Scalar', 'sys.std.Rational.Type.Rat', [ 'float', {
        'mantissa' => [ 'Int', 45207196 ],
        'radix'    => [ 'Int', 10 ],
        'exponent' => [ 'Int', 37 ],
    } ] ]

    [ 'Scalar', 'sys.std.Temporal.Type.UTCDateTime', [ 'datetime', {
        'year'   => [ 'Int', 2003 ],
        'month'  => [ 'Int', 10 ],
        'day'    => [ 'Int', 26 ],
        'hour'   => [ 'Int', 1 ],
        'minute' => [ 'Int', 30 ],
        'second' => [ 'Rat', 0 ],
    } ] ]

    [ 'Scalar', 'fed.lib.the_db.WeekDay', [ 'name', {
        '' => [ 'Text', 'monday' ],
    } ] ]

    [ 'Scalar', 'fed.lib.the_db.WeekDay', [ 'number', {
        '' => [ 'Int', 5 ],
    } ] ]

=head2 sys.std.Core.Type.(Q|)Tuple

This node kind represents a tuple value.  This node is interpreted as a
Muldis D C<sys.std.Core.Type.(Q|)Tuple> value whose attributes are defined
by the payload.  The payload must be just a Perl hash ref.  Each key+value
pair of the payload defines a named attribute of the new tuple; the pair's
key and value are, respectively, a Perl character string that specifies the
attribute name, and a PHMD node that specifies the attribute value.

Examples:

    [ 'Tuple', {} ]

    [ 'Tuple', 'type.tuple_from.var.fed.data.the_db.account.users', {
        'login_name' => [ 'Text', 'hartmark' ],
        'login_pass' => [ 'Text', 'letmein' ],
        'is_special' => [ 'Bool', 'true' ],
    } ]

    [ 'Tuple', {
        'name' => [ 'Text', 'Michelle' ],
        'age'  => [ 'Int', 17 ],
    } ]

=head2 sys.std.Core.Type.(Q|)Relation

This node kind represents a relation value.  This node is interpreted as a
Muldis D C<sys.std.Core.Type.(Q|)Relation> value whose attributes and
tuples are defined by the payload.  The payload is interpreted as follows:

=over

=item *

Iff the payload is a Perl array ref with zero elements, then it defines the
only relation value having zero attributes and zero tuples.

=item *

Iff the payload is a Perl array ref with at least one element, and every
element is a Perl character string (as per a valid payload for a C<Name>
PHMD node), then it defines the attribute names of a relation having zero
tuples.

=item *

Iff the payload is a Perl array ref with at least one element, and every
element is a Perl hash ref (as per a valid payload for a C<Tuple> PHMD
node), then each element of the payload defines a tuple of the new
relation; every tuple-defining element of the payload must be of the same
degree and have the same attribute names as its sibling elements; these are
the degree and attribute names of the relation as a whole, which is its
heading for the current purposes.

=item *

Iff the payload is a Perl array ref with exactly 2 elements, each of which
is a Perl array ref, then:  The new relation value's attribute names are
defined by the payload's first element, which is a Perl array ref of
character string (each as per a C<Name> node payload), and the relation
body's tuples' attribute values are defined by the payload's second
element, which is a Perl array ref of Perl array ref of tuple attribute
value defining PHMD nodes.  This format is meant to be the most compact of
the generic relation payload formats, as the attribute names only appear
once for the relation rather than repeating for each tuple.  As a
trade-off, the attribute values per tuple from the payload second element
must appear in the same order as their corresponding attribute names appear
in the payload first element, as the names and values in the relation
literal are matched up by ordinal position here.

=back

Examples:

    [ 'Relation', [] ]  # zero attrs + zero tuples

    [ 'Relation', [ 'x', 'y', 'z' ] ]  # 3 attrs + zero tuples

    [ 'Relation', [ {} ] ]  # zero attrs + 1 tuple

    [ 'Relation', [
        {
            'login_name' => [ 'Text', 'hartmark' ],
            'login_pass' => [ 'Text', 'letmein' ],
            'is_special' => [ 'Bool', 'true' ],
        },
    ] ]  # 3 attrs + 1 tuple

    [ 'Relation', 'fed.lib.the_db.gene.Person', [ [ 'name', 'age' ], [
        [ [ 'Text', 'Michelle' ], [ 'Int', 17 ] ],
    ] ] ]  # 2 attrs + 1 tuple

=head2 sys.std.Core.Type.(Q|)Set

This node kind represents a set value.  This node is interpreted as a
Muldis D C<sys.std.Core.Type.(Q|)Set> value whose elements are defined by
the payload.  The payload must be just a Perl array ref.  Each element of
the payload defines a unary tuple of the new set; each element is a PHMD
node that defines the C<value> attribute of the tuple.

Examples:

    [ 'Set', 'fed.lib.the_db.account.Country_Names', [
        [ 'Text', 'Canada' ],
        [ 'Text', 'Spain' ],
        [ 'Text', 'Jordan' ],
        [ 'Text', 'Thailand' ],
    ] ]

    [ 'Set', [
        [ 'Int', 3 ],
        [ 'Int', 16 ],
        [ 'Int', 85 ],
    ] ]

=head2 sys.std.Core.Type.Nothing

This node kind represents a 'nothing' value; it is interpreted as a Muldis
D C<sys.std.Core.Type.Nothing>.  It has 1 element, which is the Perl
character string C<Nothing>.

Examples:

    [ 'Nothing' ]

=head2 sys.std.Core.Type.(Q|)Single

This node kind represents a 'single' value.  Its payload is a PHMD node
that defines a single scalar or nonscalar value.  This node is interpreted
as a Muldis D C<sys.std.Core.Type.(Q|)Single> value whose element is
defined by the payload.  The payload is a PHMD node that defines the
C<value> attribute of the single tuple of the new 'single'.

Examples:

    [ 'Single', [ 'Text', 'I know this one!' ] ]

=head2 sys.std.Core.Type.(Q|)Array

This node kind represents a sequence value.  This node is interpreted as a
Muldis D C<sys.std.Core.Type.(Q|)Array> value whose elements are defined by
the payload.  The payload must be just a Perl array ref.  Each element of
the payload defines a binary tuple of the new sequence; the element value
is a PHMD node that defines the C<value> attribute of the tuple, and the
element index is used as the C<index> attribute of the tuple.

Examples:

    [ 'Array', [
        [ 'Text', 'Alphonse' ],
        [ 'Text', 'Edward' ],
        [ 'Text', 'Winry' ],
    ] ]

    [ 'Array', 'fed.lib.the_db.stats.Samples_By_Order', [
        [ 'Int', 57 ],
        [ 'Int', 45 ],
        [ 'Int', 63 ],
        [ 'Int', 61 ],
    ] ]

=head2 sys.std.Core.Type.(Q|)Bag

This node kind represents a bag value.  This node is interpreted as a
Muldis D C<sys.std.Core.Type.(Q|)Bag> value whose elements are defined by
the payload.  The payload is interpreted as follows:

=over

=item *

Iff the payload is a Perl array ref with zero elements, then it defines the
only bag value having zero elements.  Iff the payload is an array ref with
at least one element, then every one of the payload elements must be itself
a Perl array ref.

=item *

Iff the payload is an array ref with at least one (array ref) element, and
the first element of that element I<is> itself an array ref, then the
payload is interpreted as being of the I<array counted values> bag format.
Each element of the payload defines a binary tuple of the new bag; the
element is a 2-element array ref, and those 2 elements, by index order, are
a PHMD node that defines the C<value> attribute of the tuple, and a valid
C<Int> PHMD node payload that defines the C<count> attribute of the tuple;
the count must be a positive integer.

=item *

Iff the payload is an array ref with at least one (array ref) element, and
the first element of that element I<is not> itself an array ref, then the
payload is interpreted as being of the I<array repeated values> bag format.
Each element of the payload contributes to a binary tuple of the new bag;
the element value is a PHMD node that defines the C<value> attribute of the
tuple.  The bag has 1 tuple for every distinct (after format normalization)
element value in the payload, and the C<count> attribute of that tuple says
how many instances of said element were in the payload.

=back

Examples:

    [ 'Bag', 'fed.lib.the_db.inventory.Fruit', [
        [ [ 'Text', 'Apple'  ], 500 ],
        [ [ 'Text', 'Orange' ], 300 ],
        [ [ 'Text', 'Banana' ], 400 ],
    ] ]

    [ 'Bag', [
        [ 'Text', 'Foo' ],
        [ 'Text', 'Quux' ],
        [ 'Text', 'Foo' ],
        [ 'Text', 'Bar' ],
        [ 'Text', 'Baz' ],
        [ 'Text', 'Baz' ],
    ] ]

=head1 RATIONAL EXTENSION SCALAR VALUE LITERALS

=head2 sys.std.Rational.Type.Rat

This node kind represents a rational value.  This node is interpreted as a
Muldis D C<sys.std.Rational.Type.Rat> value as follows:

=over

=item *

If the payload is a Perl scalar, then it must be just a canonical numeric
value according to Perl, and it is mapped directly; since native Perl
numerics are limited precision or are inexact (IEEE float), larger numerics
can be represented by a Perl character string of the format C<< 0\.?<[ 0..9
_ ]>* >> or C<< \-?<[1..9]><[ 0..9 _ ]>*\.?<[ 0..9 _ ]>* >> that is
interpreted as base 10.

=item *

An alternative payload format is a C<bigrat|bignum|bigint> object, which is
conceptually the closest thing Perl 5 has in core to a "big rational".

=item *

If the payload is a Perl array ref, then the payload must have exactly 2 or
3 elements, each of which constitutes a valid payload of an C<Int> PHMD
node.  If the payload has 2 elements, then the rational's value is
interpreted as the first element (a numerator) divided by the second (a
denominator).  If the payload has 3 elements, then the rational's value is
interpreted as the first element (a mantissa) multiplied by the result of
the second element (a radix) taken to the power of the third (an exponent).

=item *

If the payload is a Perl hash ref, then it must have 1 element, whose key
and value are designated, in order, I<max-col-val> and I<main payload>; the
max-col-val must be a Perl string composed of a single C<[ 1..9 A..Z ]>
character.  If the main payload is a Perl scalar, then the main payload
must be a Perl character string of the format C<< 0\.?<[ 0..9 A..Z _ ]>* >>
or C<< \-?<[ 1..9 A..Z ]><[ 0..9 A..Z _ ]>*\.?<[ 0..9 A..Z _ ]>* >>.  This
format specifically is what the Plain Text Muldis D grammar uses as one
general form for rational literals, and is the result of parsing it.  The
main payload is interpreted as a base-I<N> rational where I<N> might be
between 2 and 36, and the given max-col-val says which possible value of
I<N> to use.  Assuming all column values are between zero and
I<N>-minus-one, the max-col-val contains that I<N>-minus-one.  So to
specify, eg, bases [2,8,10,16], use max-col-val of [1,7,9,F].  If the main
payload is a Perl array ref, then the main payload must have exactly 2 or 3
elements, and every pairwise combination of the max-col-val with the
elements of the main payload must, when appropriately wrapped in a Perl
hash ref, must constitute a valid hash ref payload for an C<Int> PHMD node;
the meaning of the 2 or 3 main payload elements is the same as the 2 or 3
payload elements mentioned in the previous bullet point.

=back

Examples:

    [ 'Rat', { 1 => '-1.1' } ]

    [ 'Rat', -1.5 ] # same val as prev

    [ 'Rat', 3.14159 ]

    [ 'Rat', { A => '0.0' } ]

    [ 'Rat', { F => 'DEADBEEF.FACE' } ]

    [ 'Rat', { Z => '0.000AZE' } ]

    [ 'Rat', { 6 => [ '500001', '1000' ] } ]

    [ 'Rat', { B => [ 'A09B', 'A' ] } ]

    [ 'Rat', { 1 => [ '1011101101', '10', '-11011' ] } ]

    [ 'Rat', [ '45207196', '10', '37' ] ]

    [ 'Rat', [ 1, 43 ] ]

    [ 'Rat', [ 314159, 10, -5 ] ]

=head2 sys.std.Rational.Type.RatRoundMeth

This node kind represents a rounding method.  This node is interpreted as a
Muldis D C<sys.std.Rational.Type.RatRoundMeth> value by directly mapping
the payload.  The payload must be a Perl character string having one of the
7 values C<half_down>, C<half_up>, C<half_even>, C<to_floor>,
C<to_ceiling>, C<to_zero>, C<to_inf>.

Examples:

    [ 'RatRoundMeth', 'half_up' ]

=head1 TEMPORAL EXTENSION SCALAR VALUE LITERALS

=head2 sys.std.Temporal.Type.(UTC|Float)Instant

This node kind represents an "instant"/"datetime" value that is (affiliated
with the UTC time-zone | "floating" / not affiliated with any time-zone).
This node is interpreted as a Muldis D
C<sys.std.Temporal.Type.(UTC|Float)Instant> value whose C<instant> possrep
attribute values are defined by the payload.  The payload is interpreted as
follows:

=over

=item *

If the payload is a Perl array ref, then it must have 6 elements, where
each element may be either undefined or defined; or if fewer than 6
elements are provided, the array ref will be implicitly extended to 6,
filling with undefs.  The 6 payload elements correspond in order, from the
lowest to the highest indexed, to the 6 attributes: C<year>, C<month>
C<day>, C<hour>, C<minute>, C<second>.  For each payload element that Perl
considers undefined or defined, the corresponding attribute has a
C<Nothing> or a C<Single> value, respectively.  For each of the first 5
elements, when it is defined, it must qualify as a valid payload for an
C<Int> PHMD node; for the 6th element, when it is defined, it must qualify
as a valid payload for a C<Rat> PHMD node.

A defined C<year> may be any integer, each of [C<month>, C<day>] must be a
positive integer, each of [C<hour>, C<minute>] must be a non-negative
integer, and C<second> must be a non-negative rational number.  If all 6
attributes are defined, then the new C<(UTC|Float)Instant> value is also a
C<UTCDateTime>; if just the first 3 or last 3 are defined, then the value
is not a C<UTCDateTime> but rather a C<UTCDate> or C<UTCTime>,
respectively; if any other combination of attributes are defined, then the
value is just a C<(UTC|Float)Instant> and not of any of the other 3
subtypes.

=item *

If the payload is a Perl hash ref, then it must have 1 element, whose key
and value are designated, in order, I<max-col-val> and I<main payload>; the
max-col-val must be a Perl string and the main payload must be a Perl array
ref as per the payload of the previous bullet point but that none of the 6
elements is a Perl hash ref.  Each of the 6 main payload elements, when
defined, is further interpreted according to the max-col-val, in the same
manner as how an C<Int> or C<Rat> node's hash ref payload's element's value
is interpreted.  The interpretation of this payload is the same as for the
Perl array ref payload.

=back

Examples:

    [ 'UTCInstant', [1964,10,16,16,12,47.5] ] # a UTCDateTime

    [ 'UTCInstant', [2002,12,6] ] # a UTCDate

    [ 'UTCInstant', [undef,undef,undef,14,2,29] ] # a UTCTime

    [ 'FloatInstant', [2003,4,5,2] ] # min,sec unknown or N/A

    [ 'FloatInstant', [1407] ] # just know its sometime in 1407

=head2 sys.std.Temporal.Type.Duration

This node kind represents a duration value, an amount of time, which is not
fixed to any instant in time.  This node is interpreted as a Muldis D
C<sys.std.Temporal.Type.Duration> value whose C<duration> possrep attribute
values are defined by the payload.  The payload is interpreted as follows:

=over

=item *

If the payload is a Perl array ref, then it must have 6 elements, where
each element may be either undefined or defined; or if fewer than 6
elements are provided, the array ref will be implicitly extended to 6,
filling with undefs.  The 6 payload elements correspond in order, from the
lowest to the highest indexed, to the 6 attributes: C<years>, C<months>
C<days>, C<hours>, C<minutes>, C<seconds>.  For each payload element that
Perl considers undefined or defined, the corresponding attribute has a
C<Nothing> or a C<Single> value, respectively.  For each of the first 5
elements, when it is defined, it must qualify as a valid payload for an
C<Int> PHMD node; for the 6th element, when it is defined, it must qualify
as a valid payload for a C<Rat> PHMD node.

A defined [C<years>, C<months>, C<days>, C<hours>, C<minutes>] may be any
integer, and C<seconds> may be any rational number.  I<Currently,
C<Duration> has no system-defined subtypes, but that may change later.>

=item *

If the payload is a Perl hash ref, then it must have 1 element, whose key
and value are designated, in order, I<max-col-val> and I<main payload>; the
max-col-val must be a Perl string and the main payload must be a Perl array
ref as per the payload of the previous bullet point but that none of the 6
elements is a Perl hash ref.  Each of the 6 main payload elements, when
defined, is further interpreted according to the max-col-val, in the same
manner as how an C<Int> or C<Rat> node's hash ref payload's element's value
is interpreted.  The interpretation of this payload is the same as for the
Perl array ref payload.

=back

Examples:

    [ 'Duration', [3,5,1,6,15,45.000012] ]

=head1 BOOTLOADER

A full or partial Muldis D C<bootloader> routine consists of a language
name declaration plus a series of 0..N imperative routine calls.  A
C<bootloader> is formatted as a PHMD node having 1..N elements, where the
first element is a PHMD node defining a Muldis D "language name", and each
remaining element is a PHMD node defining a "bootloader imperative routine
call".

Examples:

    [
        [ 'Muldis_D', 'http://muldis.com', '1.2.3', 'HDMD_Perl5_Tiny',
            {} ],
        [ 'boot_stmt', 'sys.std.Core.Cat.create_depot_procedure',
            {}, { ... } ],
    ]

=head1 BOOTLOADER STATEMENT

This PHMD node specifies one statement of a Muldis D C<bootloader> routine
which invokes an imperative routine, such statements being what the entire
body of a C<bootloader> is composed of.  A bootloader imperative routine
call is formatted as a PHMD node having the following 4 elements:

=over

=item *

Node kind: the Perl character string C<boot_stmt>.

=item *

Imperative routine name: a Perl array ref or character string as per the
payload of a C<NameChain> PHMD node.

=item *

Imperative routine subject-to-update args: a Perl hash ref as per the
payload of a C<Tuple> PHMD node except that every hash ref is just a Perl
array ref or character string as per the payload of a C<NameChain> PHMD
node (each value is the name of a global variable).

=item *

Imperative routine read-only args: a Perl hash ref as per the
payload of a C<Tuple> PHMD node.

=back

Examples

    [ 'boot_stmt', 'sys.std.Core.Cat.create_depot_procedure', {}, { ... } ]

=head1 MULDIS D TINY DIALECT PRAGMAS

All of the following pragmas apply to both the C<PTMD_Tiny> and
C<HDMD_Perl(6|5)_Tiny> dialects, and have the same semantics with both.

=head2 auto_add_attrs

All Muldis D values, besides scalars lacking any possreps, are defined in
terms of a collection of attribute values, and there is no such thing as an
attribute being undefined; normally when one selects a value of a
particular attribute-based type, they must supply values for I<all> of its
attributes; this is true with values comprising the system catalog as with
any other values.  Code written in the Muldis D C<PTMD_Tiny> or
C<HDMD_Perl(6|5)_Tiny> dialect is comprised almost entirely of value
literals, and by default all of the attribute values of said values must be
explicitly given in the literals as sub-literals, even in the common case
where some attributes just have the default values for their type.

While this fact allows for parsers to be very simple and for sub-literals
to be compilable into values without knowing the context they're compiled
into, it means that programmers would have to write maybe about twice as
much code as they otherwise would if they could simply not write out the
default-valued attributes.

If the 5th I<Extensions> portion of the fully-qualified Muldis D language
name contains a name+value pair of C<auto_add_attrs> + C<Bool:true>, then
this activates the optional C<auto_add_attrs> pragma, which provides one
kind of automatic code completion.  When C<auto_add_attrs> is active,
programmers may omit any literal attributes that they want, and those
attributes will be automatically defined by the parser to have the default
values for their type.  Or more specifically, the wider literal whose
attributes are missing will be extended to become the default value of the
type of the wider literal but that those attributes of its that I<were>
explicitly given will override the default's values for those attributes.
The actual behaviour is essentially what the
C<sys.std.QTuple.substitution_in_default> function does.

But the C<auto_add_attrs> pragma is not simply an automatically invoked
pre-processing Muldis D function, because it also serves the common case
where one is defining relation literals that have different attributes
specified per tuple; such a thing by itself isn't even valid as a generic
relation, so it certainly can't be given to a Muldis D function; so the
pragma has at least that advantage unique to itself.

Note that the lexer is exactly the same regardless of whether the
C<auto_add_attrs> pragma is turned on or off, because the matters of
missing attributes were never tested or enforced at the lexical level in
the first place; rather the pragma only affects the parsing stage that
follows the lexing.  In other words, the actual syntax or grammar is
identical regardless of the setting of this pragma.

Now one consequence of using the C<auto_add_attrs> pragma is that in
general the parser must be more complicated, and read type definitions from
the DBMS information schema so that it knows what attributes each literal
is supposed to have, and their declared types, and also sub-literals can no
longer in general be fully converted to values in isolation; now the
parent-most literal must be evaluated first, because its declared type
generally determines the declared types of its attributes, and then their
attributes recursively.  For nonscalar types, the initial declared type
being looked at is the declared type of the bootloader-invoked routine's
parameter that the literal is being given to as an argument.

Now if the declared type of said parameter is just a generic type, such as
C<Relation> or C<Array>, then often no information can be gleaned from this
context for what attributes should exist, and so you will need to make the
arg literal include treat-as-type metadata that explicitly provides the
specific type information needed; otherwise, C<auto_add_attrs> won't help
you and you must then fully define relation values with the same attributes
per tuple.  But fortunately for brevity, a lot of the places where
C<auto_add_attrs> would help you the most is when the bootloader is
invoking system-defined data-defining procedures, and their parameters are
all of attribute-specifying types, and it is in such data definition that
you may be most likely to face a large number of default-valued attributes,
such as C<comment>.

Note that the reason the C<auto_add_attrs> behaviour is turned off by
default is twofold.  First, the parser can be a lot simpler / more tiny
with it off.  Second, requiring users to explicitly define even
default-valued attributes can make the code more self-documenting and can
help users avoid some kinds of bugs due to action from unseen values, or
due to some default values "silently" changing between language versions.
So then essentially, turning on C<auto_add_attrs> means the programmer is
telling the parser "I know what I'm doing" by I<explicitly> asking for
potentially less-safe behaviour.  Of course, even with C<auto_add_attrs>
turned on, you can still explicitly define attribute values that are their
type's default values, so it is possible to compromise such as you like.

Also note that it should be trivial for a Muldis D implementation to let
users input code written with C<auto_add_attrs> turned on, and then output
the version of that code for their perusal with it turned off, so they can
see what extra values were filled in without having to manually write said.

=head2 auto_unabbrev_std_names

Normally when one is specifying a C<NameChain> literal that is a
reference to a standard system-defined type or routine, they must write out
the name in full, starting with C<sys.std> and so on through the unique
part of the entity name.  While this allows for clearly self-documenting
code, as well as for relatively simple parsers, it can also be added tedium
to programmers that would prefer to write out the names in a less verbose
manner, especially since to a point, a slightly more complicated parser
could still unambiguously resolve a much shorter substring of the name.

If the 5th I<Extensions> portion of the fully-qualified Muldis D language
name contains a name+value pair of C<auto_unabbrev_std_names> +
C<Bool:true>, then this activates the optional C<auto_unabbrev_std_names>
pragma, which provides one kind of automatic code completion.  When
C<auto_unabbrev_std_names> is active, programmers may omit any number of
consecutive leading chain elements from such a C<NameChain> literal, so
long as the remaining unqualified chain is distinct among all standard
system-defined (C<sys.std>-prefix) DBMS entities (but that as an exception,
a non-distinct abbreviation is allowed iff exactly 1 of the candidate
entities is in the language core, C<sys.std.Core>-prefix, in which case
that 1 is unambiguously the entity that is resolved to).  This feature has
no effect on the namespace prefixes like C<tuple_from> or C<array_of>; one
still writes those as normal prepended to the otherwise shortened chains.

So for example, one can just write C<Int> rather than
C<sys.std.Core.Type.Int>, C<is_identical> rather than
C<sys.std.Core.Universal.is_identical>, C<QTuple.attr> rather than
C<sys.std.Core.QTuple.attr>, C<min> rather than C<sys.std.Ordered.min>,
C<array_of.Rat> rather than C<array_of.sys.std.Rational.Type.Rat>, and so
on.

The C<auto_unabbrev_std_names> pragma intentionally does not empower auto
un-abbreviations of any namespaces other than C<sys.std>, to keep things
simple for users to predict and for systems to implement; it does not
affect C<sys.(imp|cat)>, nor any other top-level namespace.  When one is
referencing either any system-defined implementation-specific
(non-standard) types or routines, or any user-defined types or routines, or
any dbvars or constraints or whatever, their names can not be written
abbreviated due to the C<auto_unabbrev_std_names> pragma.

Note that the lexer is exactly the same regardless of whether the
C<auto_unabbrev_std_names> pragma is turned on or off, as per the
C<auto_add_attrs> pragma.  Many other comments about the other pragma also
apply to this one.

=head2 auto_chains_from_names

Iff both the C<auto_add_attrs> and C<auto_unabbrev_std_names> pragmas are
active, then the optional C<auto_chains_from_names> dependent pragma may be
activated in the same manner (as an I<Extensions> name+value pair with
C<Bool:true>.  When C<auto_chains_from_names> is active, programmers may
write an otherwise abbreviated-to-one-chain-element C<NameChain>
literal as a plain C<Name> literal; this can chop the literal down to a
third or fourth of its otherwise-length such as in the case of a reference
to the C<Int> type.  When the parent literal of such a faux-C<Name>
literal is examined for missing attributes, or examined that existing
attributes are of the correct type, any attributes whose declared type says
they are supposed to be C<NameChain> but that have an explicitly
defined C<Name> child literal will have that literal mapped to and
replaced with a single element C<NameChain> literal, which can be
subsequently un-abbreviated into a standard system-defined type or routine
name.  The C<auto_chains_from_names> pragma will not work when the declared
type being applied to a faux-C<Name> is not a C<NameChain> subtype,
and such literals will then be taken as actual C<Name>; where such
declared type information is missing, you will need to write out the
abbreviated chain as an actual C<NameChain> literal.  Note that the
C<auto_chains_from_names> pragma has no effect on C<NameChain> literal
bodies that don't comprise the payload portion of their parent literal,
such as with the imperative routine name composed into a C<boot_stmt>
literal; literal bodies in those positions will always be interpreted
according to C<NameChain> literal body syntax.

=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
