Skip to content
goFrendiAsgard edited this page May 23, 2018 · 15 revisions

CHIML is a superset of YAML. So, any valid YAML is also a valid CHIML. And as YAML itself is a superset of JSON, any valid JSON is also a valid CHIML

The only thing that make CHIML diferent from YAML is you are allowed to write any string after block delimiter (| and >). Under the hood, this |someString will be translated into "someString". If the string contains ", it is going to be automatically escaped, so you don't need to worry about it.

The CHIML-script should contain a single <program>.

Semantic (Backus Naur Form)

<program> ::= <completeVars>
              <completeVerbose>
              <command>
              <completeCatch>
              <completeThrow>

<command> ::= <completeCommand>
            | <shortCommand>

<completeCommand> ::= <completeIns>
                      <completeOut>
                      <completeIf>
                      "do: "<singleCommand><newLine>
                      <completeWhile>

                    | <completeIns>
                      <completeOut>
                      <completeIf>
                      "parallel: "<singleCommand><newLine>
                      <completeWhile>

                    | <completeIns>
                      <completeOut>
                      <completeIf>
                      "do: "<commandList>
                      <completeWhile>

                    | <completeIns>
                      <completeOut>
                      <completeIf>
                      "parallel: "<commandList>
                      <completeWhile>

                    | "map: "<variableName>
                      "into: "<variableName>
                      <completeCommand>

                    | "filter: "<variableName>
                      "into: "<variableName>
                      <completeCommand>

<shortCommand> ::= "|("<ins>") -> " <singleCommand> " -> " <out><newLine>
                 | "|("<ins>") -> " <singleCommand> "<newLine>
                 | "|"<singleCommand> " -> " <out><newLine>
                 | "|("<ins>") --> " <out><newLine>
                 | "|"<out> " <-- ("<ins>")"<newLine>

<commandList>  ::= "- "<command>
                 | <commandList><commandList>

<completeCatch> ::= "" 
                  | "catch: "<condition><newLine>

<completeThrow> ::= ""
                  | "throw: "<string><newLine>

<completeVars>  ::= ""
                  | "vars: "<variableList><newLine>

<completeVerbose> ::= ""
                    | "verbose: "<verbosity><newLine>

<completeIns>   ::= ""
                  | "ins: "<ins><newLine>

<completeOut>   ::= ""
                  | "out: "<out><newLine>

<completeIf>    ::= ""
                  | "if: "<condition><newLine>

<completeWhile> ::= ""
                  | "While: "<condition><newLine>

<ins> ::= <variableList>

<out> ::= <variableName>

<singleCommand> ::= <cliCommand>
                  | <jsArrowFunction>
                  | "{"<jsNormalFunction>"}"
                  | "["<jsFunctionWithCallback>"]"
                  | "<"<jsPromise>">"

<variableName> ::= <alpha>
                 | <alpha><alphaNumeric>

<variableList> ::= <variableName>
                 | <variableName>","<variableList>

<float> ::= <integer>
          | <integer>"."<integer>

<verbosity> ::= "1"
              | "2"
              | "3"
              | "4"

<condition> ::= "true"
              | "false"
              | Any JavaScript statement evaluated to either "true" or "false"

<string> ::= <string><string>
           | <alphanumeric>
           | <space>
           | <symbol>

<alphanumeric> ::= <alphanumeric><alphanumeric>
                 | <alpha>
                 | <integer>

<alpha> ::= <letter><alpha>

<letter> ::= "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m"
           | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z"
           | "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M"
           | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z"

<space> ::= " "

<newLine> ::= "\n"

<symbol> ::= "|" | " " | "!" | "#" | "$" | "%" | "&" | "(" | ")" | "*" | "+" | "," | "-"
           | "." | "/" | ":" | ";" | ">" | "=" | "<" | "?" | "@" | "[" | "\" | "]" | "^"
           | "_" | "`" | "{" | "}" | "~"

<integer> ::= <digit>
            | <digit><integer>

<digit> ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"

<cliCommand> ::= Any valid CLI command (e.g: ls, python, java, javac, node)

<jsArrowFunction> ::= Javascript arrow function (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)

<jsNormalFunction> ::= Javascript function returning a value (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions)

<jsFunctionWithCallback> ::= Javascript function that has "error-first-callback" (i.e: "function (error, value) {/*...*/}") as it's last parameter.

<jsPromise> ::= Javascript promise

Default Variables

There are some default variables in every CHIML script:

  • _chain_cwd: String, current working directory of CHIML script.
  • _process_cwd: String, current working directory of program that invoike CHIML script.
  • _error: Boolean, error status.
  • _error_message: String, error message.
  • _verbose: Integer, verbosity level, default to 0.
  • _ans: Default output variable.
  • _runChain (chain, ...ins, callback): function to run other chain.
  • _maps (list, chain, callback): function to map an array into a new array. Under the hood, this will process each element in parallel.
  • _filter (list, chain, callback): function to filter an array into a new array. Under the hood, this will process each element in parallel.

Control Flow

Every <command> has some keys including ins, out, if, do, and while. The control flow of a chain is as follow:

control

Examples

Run Single Command

# filename: cal.chiml
# execute: chimera cal.chiml
# expected output: calendar of current year
cal

Run Single Command with Input Parameters

# filename: cal.chiml
# execute: chimera cal.chiml 3 2018
# expected output: calendar of March, 2018
ins: month, year
do: cal

or

# filename: cal.chiml
# execute: chimera cal.chiml 3 2018
# expected output: calendar of March, 2018
do: |(month, year) -> cal

or

# filename: cal.chiml
# execute: chimera cal.chiml 3 2018
# expected output: calendar of March, 2018
|(month, year) -> cal

or

# filename: cal.chiml
# execute: chimera cal.chiml 3 2018
# expected output: calendar of March, 2018
|(month, year) -> cal -> output

Run Multiple Commands (Serial)

# filename: cowsay-cal.chiml
# execute: chimera cowsay-cal.chiml 3 2018
# expected output: calendar of March, 2018 inside cowsay
ins: month, year
out: output
do:
  - |(month, year) -> cal -> calendar
  - |(calendar) -> cowsay -> output

Run Multiple Commands (Parallel)

# filename: cal2.chiml
# execute: chimera cal2.chiml 3 4 2018
# expected output: calendar of March, 2018 and April, 2018
ins: month1, month2, year
out: output
do:
  - parallel:
    - |(month1, year) -> cal -> calendar1
    - |(month2, year) -> cal -> calendar2
  - |(calendar1, calendar2) -> {$.concat} -> output

Run Javascript Normal Function

# filename: add.chiml
# execute: chimera add.chiml 4 5
# expected output: 9
|(num1, num2) -> {(a, b) => {return a+b}}

Run Javascript Function with Callback

# filename: add.chiml
# execute: chimera add.chiml 4 5
# expected output: 9
|(num1, num2) -> [(a, b, callback) => {callback(null, a + b)}]

Run Javascript Promise

# filename: add.chiml
# execute: chimera add.chiml 4 5
# expected output: 9
ins: num1, num2
do: |<new Promise((resolve, reject) => {resolve(num1 + num2)})>

Use Map and Filter

# filename: functional.chiml
# execute: chimera functional.chiml
# expected output: {"map":[2,3,4,5,6,7,8,9,10,11],"filter":[2,4,6,8,10]}
vars:
  numbers: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  plus: 1
  divide: 2
out: result
parallel:

  - map: numbers
    into: result.map
    do: |(n) -> (x) => {return x+plus} -> y

  - filter: numbers
    into: result.filter
    ins: x
    out: y
    do:
      - if: x % divide === 0
        do: y <-- true
        else: y <-- false