All,

This message is a follow-up both to my April 28th post of subject "ANNOUNCE - Muldis D v0.27.0 released", wherein I promised this message would soon follow, and also follows up a few other posts over the past year where I gave some pseudo-code examples.

At the end of this email is an example program written in Muldis D, which you can peruse to get familiar with what the language is like than just descriptions would do.

The example program will create a temporary depot/database, install a stored procedure in it, and invoke that stored procedure. The stored procedure will prompt the user to enter details for 3 people, specifically their names and addresses, which it will store in a relvar/table. It will then prompt the user to enter a person's name to search for, look for a matching person's details in the relvar/table, and then inform the user of that person's address. Note that for brevity this example program is naive does not check that the search name actually matched 1 person, and simply tries to use the result, meaning it will die if that expectation isn't met; a real program would do more testing.

The program is written in the PTMD_Tiny dialect of Muldis D, which is designed to exactly match the system catalog in structure. The majority of it, the stored procedure definition, consists of a single tuple/record for a catalog relvar/table, and some attributes/fields of that tuple/record have collection-typed values, several levels deep. This Muldis D code should resemble the AST you get after parsing a typical language's code and so is fairly verbose. Though verbose, it should work well in a situation where such code is mainly being generated or parsed or modified by a program, though doing it by hand should be tolerable. The dialect is designed to be parseable with a tiny grammar, which is where its name comes from. Muldis D is homoiconic, meaning Muldis D code fundamentally is a low level Muldis D data type, and you do all coding in it by manipulating data.

I assume that other Muldis D dialects will come about later where coding in it is a lot less verbose, at the cost of the grammar being more complicated, and code will translate between dialects. Or alternately the Tiny dialect may just be used as an intermediate language for a programming environment that, say, takes some specialized DWIM language as input, and by way of the intermediate, generate SQL for any SQL DBMS to do the work.

So if there are any complaints about verbosity, I can probably do more to get that down in these dialects, but after a point it would probably be better to use some translation layer and write to that instead.

Now the PTMD_Tiny dialect happens to be well handled by syntax colorers for the Perl language, but it isn't Perl. If you are a Perl programmer, you would probably be more interested in the HDMD_Perl_Tiny dialect, which looks very much like PTMD_Tiny, but consists of actual Perl arrays of arrays. In fact, to translate from what you see below to the Perl version, basically just do this:

  - any "Foo:'bar':'baz'" gets changed to "[ 'Foo', 'bar', 'baz' ]"
- any "\q" gets changed to "\'", or use alternate string quoting characters for string literals - for payloads of Relation and Set, change the delimiters to "[]" from "{}" since Perl 5 doesn't have set syntax so use array syntax instead - the framing code, the 'boot_call' etc need to be replaced with API calls to some Muldis D implementing Perl module such as Muldis Rosetta - for a further guide, just compare the docs for the 2 dialects, ad all the code examples directly correspond

Of course you don't have to use Perl, you could use some other host language instead as is your preference, as the structures map to any decent language easily enough. Both functional and imperative languages should work with it.

Now the program example you see below is complete, with all framing code needed to compile the plain text dialect, probably.

In the near future, I'll follow with another example email that just shows snippits rather than a complete program, and the snippits can focus on particular tasks such as doing joins or unions or defining database schemas etc.

On another note, considering my OSCON talk is July 23, I've set myself up with a hard deadline of July 1, and a soft deadline of June 1, to have an actual working implementation of the language. The only main prerequisite to making that is defining how to declare data types and schemas in the language, but that should be done in a few days I expect.

-- Darren Duncan

--------------

Muldis_D:'http://muldis.com':'0.28.0':'PTMD_Tiny':{};

boot_call:'sys.std.Core.Cat.create_temp_empty_depot':{
  'mount_name' => 'app',
};

boot_call:'sys.std.Core.Cat.create_depot_procedure':{
  'depot' => 'app',
  'parent' => Cat.DeclNameChain:'.',
  'name' => 'main',
  'comment' => Cat.Comment:'This is the program\qs main procedure.',
  'head' => Tuple:{},
  'body' => Tuple:{
    'main_body' => Tuple:{
      'vars' => Relation:[ 'name', 'type', ]:{
        [ 'msg_gather_name', Cat.NameChain:'sys.std.Core.Type.Text', ],
        [ 'msg_gather_addr', Cat.NameChain:'sys.std.Core.Type.Text', ],
        [ 'msg_search_name', Cat.NameChain:'sys.std.Core.Type.Text', ],
        [ 'msg_result_addr', Cat.NameChain:'sys.std.Core.Type.Text', ],
        [ 'people', Cat.NameChain:'sys.std.Core.Type.Relation', ],
        [ 'person_name', Cat.NameChain:'sys.std.Core.Type.Text', ],
        [ 'person_addr', Cat.NameChain:'sys.std.Core.Type.Text', ],
      },
      'stmts' => Seq:[
        Tuple:{
          'procedure' => Cat.NameChain:'inn.init_vars',
          'upd_args' => Relation:[ 'name', 'expr', ]:{
            [ 'msg_gather_name', Cat.NameChain:'lex.msg_gather_name', ],
            [ 'msg_gather_addr', Cat.NameChain:'lex.msg_gather_addr', ],
            [ 'msg_search_name', Cat.NameChain:'lex.msg_search_name', ],
            [ 'msg_result_addr', Cat.NameChain:'lex.msg_result_addr', ],
            [ 'people', Cat.NameChain:'lex.people', ],
          },
        },
        Tuple:{
          'procedure' => Cat.NameChain:'inn.gather_person',
          'upd_args' => Relation:[ 'name', 'expr', ]:{
            [ 'people', Cat.NameChain:'lex.people', ],
          },
          'ro_args' => Relation:[ 'name', 'expr', ]:{
            [ 'msg_gather_name', Cat.NameChain:'lex.msg_gather_name', ],
            [ 'msg_gather_addr', Cat.NameChain:'lex.msg_gather_addr', ],
          },
        },
        Tuple:{
          'procedure' => Cat.NameChain:'inn.gather_person',
          'upd_args' => Relation:[ 'name', 'expr', ]:{
            [ 'people', Cat.NameChain:'lex.people', ],
          },
          'ro_args' => Relation:[ 'name', 'expr', ]:{
            [ 'msg_gather_name', Cat.NameChain:'lex.msg_gather_name', ],
            [ 'msg_gather_addr', Cat.NameChain:'lex.msg_gather_addr', ],
          },
        },
        Tuple:{
          'procedure' => Cat.NameChain:'inn.gather_person',
          'upd_args' => Relation:[ 'name', 'expr', ]:{
            [ 'people', Cat.NameChain:'lex.people', ],
          },
          'ro_args' => Relation:[ 'name', 'expr', ]:{
            [ 'msg_gather_name', Cat.NameChain:'lex.msg_gather_name', ],
            [ 'msg_gather_addr', Cat.NameChain:'lex.msg_gather_addr', ],
          },
        },
        Tuple:{
          'procedure' => Cat.NameChain:'sys.std.Core.STDIO.prompt_Text_line',
          'upd_args' => Relation:[ 'name', 'expr', ]:{
            [ 'target', Cat.NameChain:'lex.person_name', ],
          },
          'ro_args' => Relation:[ 'name', 'expr', ]:{
            [ 'prompt', Cat.NameChain:'lex.msg_search_name', ],
          },
        },
        Tuple:{
          'procedure' => Cat.NameChain:'inn.search_for_address',
          'upd_args' => Relation:[ 'name', 'expr', ]:{
            [ 'person_addr', Cat.NameChain:'lex.person_addr', ],
          },
          'ro_args' => Relation:[ 'name', 'expr', ]:{
            [ 'people', Cat.NameChain:'lex.people', ],
            [ 'person_name', Cat.NameChain:'lex.person_name', ],
          },
        },
        Tuple:{
          'procedure' => Cat.NameChain:'sys.std.Core.STDIO.write_Text',
          'ro_args' => Relation:[ 'name', 'expr', ]:{
            [ 'v', Cat.NameChain:'lex.msg_result_addr', ],
          },
        },
        Tuple:{
          'procedure' => Cat.NameChain:'sys.std.Core.STDIO.write_Text_line',
          'ro_args' => Relation:[ 'name', 'expr', ]:{
            [ 'v', Cat.NameChain:'lex.person_addr', ],
          },
        },
      ],
    },
    'inner_procs' => Relation:{

      {
        'name' => 'gather_person',
        'comment' => Cat.Comment:'Gathers person info from user.',
        'head' => Tuple:{
          'upd_params' => Relation:[ 'name', 'type', ]:{
            [ 'people', Cat.NameChain:'sys.std.Core.Type.Relation', ],
          },
          'ro_params' => Relation:[ 'name', 'type', ]:{
            [ 'msg_gather_name', Cat.NameChain:'sys.std.Core.Type.Text', ],
            [ 'msg_gather_addr', Cat.NameChain:'sys.std.Core.Type.Text', ],
          },
        },
        'body' => Tuple:{
          'vars' => Relation:[ 'name', 'type', ]:{
            [ 'person_name', Cat.NameChain:'sys.std.Core.Type.Text', ],
            [ 'person_addr', Cat.NameChain:'sys.std.Core.Type.Text', ],
          },
          'stmts' => Seq:[
            Tuple:{
'procedure' => Cat.NameChain:'sys.std.Core.STDIO.prompt_Text_line',
              'upd_args' => Relation:[ 'name', 'expr', ]:{
                [ 'target', Cat.NameChain:'lex.person_name', ],
              },
              'ro_args' => Relation:[ 'name', 'expr', ]:{
                [ 'prompt', Cat.NameChain:'lex.msg_gather_name', ],
              },
            },
            Tuple:{
'procedure' => Cat.NameChain:'sys.std.Core.STDIO.prompt_Text_line',
              'upd_args' => Relation:[ 'name', 'expr', ]:{
                [ 'target', Cat.NameChain:'lex.person_addr', ],
              },
              'ro_args' => Relation:[ 'name', 'expr', ]:{
                [ 'prompt', Cat.NameChain:'lex.msg_gather_addr', ],
              },
            },
            Tuple:{
              'procedure' => Cat.NameChain:'inn.add_person',
              'upd_args' => Relation:[ 'name', 'expr', ]:{
                [ 'people', Cat.NameChain:'lex.people', ],
              },
              'ro_args' => Relation:[ 'name', 'expr', ]:{
                [ 'person_name', Cat.NameChain:'lex.person_name', ],
                [ 'person_addr', Cat.NameChain:'lex.person_addr', ],
              },
            },
          ],
        },
      },

    },
    'inner_upds' => Relation:{

      {
        'name' => 'init_vars',
        'comment' => Cat.Comment:'Initializes main routine\qs variables.',
        'head' => Tuple:{
          'upd_params' => Relation:[ 'name', 'type', ]:{
            [ 'msg_gather_name', Cat.NameChain:'sys.std.Core.Type.Text', ],
            [ 'msg_gather_addr', Cat.NameChain:'sys.std.Core.Type.Text', ],
            [ 'msg_search_name', Cat.NameChain:'sys.std.Core.Type.Text', ],
            [ 'msg_result_addr', Cat.NameChain:'sys.std.Core.Type.Text', ],
            [ 'people', Cat.NameChain:'sys.std.Core.Type.Relation', ],
          },
        },
        'body' => Tuple:{
          'exprs' => Tuple:{
            'sca_lit_exprs' => Relation:[ 'name', 'value', ]:{
              [ 'emgn', Text:'Enter a person\qs name: ', ],
              [ 'emga', Text:'Enter that person\qs address: ', ],
              [ 'emsn', Text:'Enter a name to search for: ', ],
              [ 'emrn', Text:'Found address for that person is: ', ],
            },
            'rel_lit_exprs' => Relation:{
              {
                'name' => 'ep',
                'head' => Set:{ 'person_name', 'person_addr', },
                'body' => Set:{},
              },
            },
          },
          'stmt' => Relation:{
            {
              'updater' => Cat.NameChain:'sys.std.Core.Universal.assign',
              'upd_args' => Relation:[ 'name', 'expr', ]:{
                [ 'target', Cat.NameChain:'lex.msg_gather_name', ],
              },
              'ro_args' => Relation:[ 'name', 'expr', ]:{
                [ 'v', Cat.NameChain:'lex.emgn', ],
              },
            },
            {
              'updater' => Cat.NameChain:'sys.std.Core.Universal.assign',
              'upd_args' => Relation:[ 'name', 'expr', ]:{
                [ 'target', Cat.NameChain:'lex.msg_gather_addr', ],
              },
              'ro_args' => Relation:[ 'name', 'expr', ]:{
                [ 'v', Cat.NameChain:'lex.emga', ],
              },
            },
            {
              'updater' => Cat.NameChain:'sys.std.Core.Universal.assign',
              'upd_args' => Relation:[ 'name', 'expr', ]:{
                [ 'target', Cat.NameChain:'lex.msg_search_name', ],
              },
              'ro_args' => Relation:[ 'name', 'expr', ]:{
                [ 'v', Cat.NameChain:'lex.emsn', ],
              },
            },
            {
              'updater' => Cat.NameChain:'sys.std.Core.Universal.assign',
              'upd_args' => Relation:[ 'name', 'expr', ]:{
                [ 'target', Cat.NameChain:'lex.msg_result_addr', ],
              },
              'ro_args' => Relation:[ 'name', 'expr', ]:{
                [ 'v', Cat.NameChain:'lex.emra', ],
              },
            },
            {
              'updater' => Cat.NameChain:'sys.std.Core.Universal.assign',
              'upd_args' => Relation:[ 'name', 'expr', ]:{
                [ 'target', Cat.NameChain:'lex.people', ],
              },
              'ro_args' => Relation:[ 'name', 'expr', ]:{
                [ 'v', Cat.NameChain:'lex.ep', ],
              },
            },
          },
        },
      },

      {
        'name' => 'add_person',
        'comment' => Cat.Comment:'Adds a person to our db of people.',
        'head' => Tuple:{
          'upd_params' => Relation:[ 'name', 'type', ]:{
            [ 'people', Cat.NameChain:'sys.std.Core.Type.Relation', ],
          },
          'ro_params' => Relation:[ 'name', 'type', ]:{
            [ 'person_name', Cat.NameChain:'sys.std.Core.Type.Text', ],
            [ 'person_addr', Cat.NameChain:'sys.std.Core.Type.Text', ],
          },
        },
        'body' => Tuple:{
          'exprs' => Tuple:{
            'tup_lit_exprs' => Relation:{
              {
                'name' => 'person',
                'attrs' => Relation:[ 'name', 'expr', ]:{
                  [ 'person_name', Cat.NameChain:'lex.person_name', ],
                  [ 'person_addr', Cat.NameChain:'lex.person_addr', ],
                },
              },
            },
          },
          'stmt' => Relation:{
            {
'updater' => Cat.NameChain:'sys.std.Core.Relation.assign_insertion',
              'upd_args' => Relation:[ 'name', 'expr', ]:{
                [ 'r', Cat.NameChain:'lex.people', ],
              },
              'ro_args' => Relation:[ 'name', 'expr', ]:{
                [ 't', Cat.NameChain:'lex.person', ],
              },
            },
          },
        },
      },

      {
        'name' => 'search_for_address',
        'comment' => Cat.Comment:'Look up person name, get their address.',
        'head' => Tuple:{
          'upd_params' => Relation:[ 'name', 'type', ]:{
            [ 'person_addr', Cat.NameChain:'sys.std.Core.Type.Text', ],
          },
          'ro_params' => Relation:[ 'name', 'type', ]:{
            [ 'people', Cat.NameChain:'sys.std.Core.Type.Relation', ],
            [ 'person_name', Cat.NameChain:'sys.std.Core.Type.Text', ],
          },
        },
        'body' => Tuple:{
          'exprs' => Tuple:{
            'rel_lit_exprs' => Relation:{
              {
                'name' => 'person_name_r',
                'head' => Set:{ 'person_name', },
                'body' => Set:{
                  Relation:[ 'name', 'expr', ]:{
                    [ 'person_name', Cat.NameChain:'lex.person_name', ],
                  },
                },
              },
            },
            'func_invo_exprs' => Relation:{
              {
                'name' => 'matched_people',
                'function' => Cat.NameChain:'sys.std.Core.Relation.semijoin',
                'args' => Relation:[ 'name', 'expr', ]:{
                  [ 'source', Cat.NameChain:'lex.people', ],
                  [ 'filter', Cat.NameChain:'lex.person_name_r', ],
                },
              },
              {
                'name' => 'matched_person',
                'comment' => 'Note, we\qre assuming exactly one match.',
'function' => Cat.NameChain:'sys.std.Core.Relation.Tuple_from_Relation',
                'args' => Relation:[ 'name', 'expr', ]:{
                  [ 'topic', Cat.NameChain:'lex.matched_person', ],
                },
              },
            },
          },
          'stmt' => Relation:{
            {
              'updater' => Cat.NameChain:'sys.std.Core.Universal.assign',
              'upd_args' => Relation:[ 'name', 'expr', ]:{
                [ 'target', Cat.NameChain:'lex.person_addr', ],
              },
              'ro_args' => Relation:[ 'name', 'expr', ]:{
                [ 'v', Cat.NameChain:'lex.matched_person.person_addr', ],
              },
            },
          },
        },
      },
    },
  },

};

boot_call:'fed.lib.app.main':{};

_______________________________________________
List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
Searchable Archive: http://www.grokbase.com/group/[EMAIL PROTECTED]

Reply via email to