=pod

=encoding utf8

=head1 YAMLSCRIPT

Programming in YAML

=head2 SYNOPSIS

A YAMLScript program C<greet.ys> to greet someone 6 times:

    #!/usr/bin/env yamlscript

    # Defined a function called 'main' (entry-point):
    main(name):       # main args come from ARGV
    - min =: 1        # Assign 1 to variable 'min'
    - max =:          # max = 6
        (-): [10, 4]  # 10 - 4 = 6
    - for:            # Loop over array, calling a function for each
      - (..): [$min, $max]     # Range operator (1-6)
      - greet: [ $_, $name ]   # Call the local 'greet' function

    # Define another function:
    greet(num,name):  # Takes 2 arguments
    - greeting =: Hello, $name!
    - say: $num) $greeting

Run:

    $ yamlscript greet.ys YAMLScript
    1) Hello, YAMLScript!
    2) Hello, YAMLScript!
    3) Hello, YAMLScript!
    4) Hello, YAMLScript!
    5) Hello, YAMLScript!
    6) Hello, YAMLScript!

Use the YAMLScript REPL:

    $ ys    # or 'ys --repl'
    ys> {range: [1, 3]}
    ---
    - 1
    - 2
    - 3
    ys> {say: Hello!}
    Hello!
    --- null
    ys> ---
    ..> say: Goodbye!
    ..> ...
    Goodbye!
    --- null
    ys> exit  # (ctrl-D)
    $

See "Using the REPL" below.

=head2 DESCRIPTION

YAMLScript is a programming language that uses YAML as a base syntax. It feels like a YAML encoded Lisp, but with fewer parentheses. It takes inspiration from Clojure, Haskell and Perl.

YAMLScript adds various scalar (valid YAML) syntax forms to make coding it clean and flexible.

For instance you could use any of the following syntax forms to define and initialize the C<x> variable to the number 42:

    - x =: 42           # Special DSL for the `def` function
    - def: [x, 42]      # Literal function call of `def`
    - (=): [x, 42]      # Use the operator alias of `def`
    - !def [x, 42]      # Use YAML tag instead of simgle pair mapping
    - != [x, 42]        # Operator alias tag
    - !expr [def,x,42]  # Tagged expr(ession)
    - (def x 42)        # Lisp/Clojure expression form (as YAML scalar)
    - (x = 42)          # Operator expr using Haskell style
    - ((=) x 42)        # Alternate Haskell style #1
    - (x `def` 42)      # Alternate Haskell style #2

Take your pick. They are all valid YAML, they all compile to the same AST, they all evaluate to the same result.

YAMLScript's runtime engine is whatever programming language you are using it from. If you are using the C<yamlscript> or C<ys> CLI binaries, it picks one for you. The current prototypes are written in Perl, Python and JavaScript.

YAMLScript functions can be defined in the runtime language or in YAMLScript proper. YAMLScript has module support and they also can be written in either.

This is a powerful concept because it lets you have clean, multilanguage front end code, that can do absolutely anything the runtime language is capable of.

A good usage is writing tests. All of the YAMLScript tests are written in YAMLScript. The exact same test files are run, regardless of the runtime language they are testing, or the specific test framework in that language.

=head2 INSTALLATION

YAMLScript can be installed in several ways. Once installed you will have access to the C<yamlscript> and C<ys> CLI commands. You will also have library support to invoke YAMLScript directly from Perl, Python or JavaScript.

=over

=item * From the source repository

    $ git clone https://github.com/ingydotnet/yamlscript ~/.yamlscript
    $ source ~/.yamlscript/.rc    # Add this line to your shell rc file
    yamlscript --version

=item * From CPAN

    cpanm YAMLScript

=item * From PyPI

    pip install yamlscript

=item * From NPM

    npm install @yaml/yamlscript

=back

=head2 YAMLSCRIPT LANGUAGE CAPABILITIES

=over

=item * Variable binding

    name =: world

Variable names use lowercase letters C<a-z>, digits C<0-9> and must start with a letter. Name parts may be separated by a dash C<->.

=item * Variable dereferencing

    the-value =: $name

The C<$> sigil prefix is used to dereference a variable.

=item * String interpolation

Variable derefs are expanded in 'plain' (unquoted) YAML strings:

    - greeting =: Hello, $name!
    # Quoted strings are not interpolated
    - string =: 'Hello, $name!'
    # Unless tagged with '!'
    - greeting =: ! 'Hello, $name!'
    # Multiline strings need the tag
    - hi-bye =: ! |
      Hello, $name.
      Goodbye, $name.

=item * Function calls

    say:
      join: [' ', Hello, world!]

=item * Define functions

    square-and-add(x,y):
    - !expr [[$x, ^, 2], +, y]

=item * Define multiple arity functions

    sum:
      (): 0
      (x): x
      (x, y): (x + y)
      (x, y, z*): (x + (y + (sum z*)))

=item * Conditionals

    if:
    - (>): [x, 50         # condition
    - say: $x wins :)    # then
    - say: $x loses :(   # else

or:

    if:
      (>): [x, 50         # condition
    then:
      say: $x wins :)    # then
    else:
      say: $x loses :(   # else

=item * Try / Catch

    - try:
        (/): [42, 0]
      catch(e):
        say: Caught error '$e'

=item * Iteration

    for(name):
    - [Alice, Bob, Curly]
    - say: Hello, $name!

=item * Import Modules

    use:
    # Import 'foo.bar' namespace only:
    - Foo-Bar
    # Import all exported functions from module:
    - Some-Module: [+]
    # Import functions `this` and `that`
    - Another-Module: [this, that]
    # Import all except:
    - That-Module: [-one, -two]
    # Import a namespace using an alternate name
    - Your-String: my.str

YAMLScript modules may be written in YAMLScript or in the runtime language.

=item * Define YAMLScript Modules

Modules are referred to (C<use>d) with the naming style C<Foo-Bar>. They typically define a namespace C<foo.bar>. Their file names depend on the language they are written in:

=over

=item * YAMLScript — C<foo/bar.ys>

=item * Perl — C<Foo/Bar.pm>

=item * Python — C<foo/bar.py> or C<foo/bar/__init__.py>

=item * JavaScript — C<foo/bar.js> or C<foo/bar/index.js>

=back

To write a C<Foo-Bar> module in YAMLScript:

    name: foo.bar
    # Define public functions
    f1(): ...     # Fully qualified as foo.bar/f1
    f2(x,y): ...
    f3(+):            # Multi-arity function
      (): ...         # 0 args
      (x): ...        # 1 arg
      (x,y): ...      # 2 args
      (x,y,z*): ...   # 3 or more args
    hide:             # Private/local functions. Not exportable.
      p1(): ...
      p2(): ...

=back

=head2 POSSIBLE USE CASES

We will write example YAMLScript programs for each of these use cases, in time.

=over

=item * Programatic, full featured, software configurations.

=item * Data driven unit testing with data and assertions in same file.

=item * Simple template rendering using interpolated YAML literal scalars.

=item * Write (acmeist) programs that can run in multiple programming languages.

=item * Write modules that can be used natively from multiple programming languages.

=item * Since programs are data, YAMLScript code bases can be refactored using data manipulation tools like C<jq>.

=back

=head2 FUTURE PLANS

=over

=item * Implement most of the core libraries with YAMLScript

=item * Programatically port many functions from clojure/core source code

=item * Write an implementation spec for YAMLScript

=item * Port YAMLScript to many languages

=item * Write a Test Suite for YAMLScript (in YAMLScript)

=item * Write a multi-language test framework in YAMLScript

=item * Generate native programming language code from the YAMLScript AST

=over

=item * In multiple target programming languages

=back

=item * Write the YAML Reference Parser in YAMLScript

=item * Write YAMLScript in YAMLScript

=item * Spec the YAMLSchema (YAML Processor Config) language as a dialect of YAMLScript

=back

=head2 STATUS

This is very ALPHA software.

Some of the features documented here are not yet implemented:

=over

=item * YAMLScript REPL

=item * Python Port (Very soon)

=item * JavaScript Port (after Python)

=item * Some functions abaove

=back

Everything in the test files definitely works. :)

=head2 AUTHORS

=over

=item * Ingy döt Net L<ingy@ingy.net|mailto:ingy@ingy.net>

=back

=head2 COPYRIGHT AND LICENSE

Copyright 2022 by Ingy döt Net

This is free software, licensed under:

The MIT (X11) License

=cut
