Sharpen Your Tools
Wanna make some fun toys with YS? You'll need some sharp tools. You think those elves make all those toys with dull tools?
The CLI tool ys
is the main tool you'll use to work with YS.
Today we'll learn about all the things you can do with it.
Welcome to Day 7 of the YS Advent Calendar🔗
On Tuesday you learned how to install YS. Reminder, here's the quick way to install the latest version:
$ curl https://yamlscript.org/install | PREFIX=~/.yamlscript bash
$ export PATH=$HOME/.yamlscript/bin:$PATH
$ ys --version
YS (YAMLScript) v0.1.91
The best first command to run is ys --help
:
$ ys --help
ys - The YS Command Line Tool - v0.1.91
Usage: ys [<option...>] [<file>]
Options:
-l, --load Output (compact) JSON of YS evaluation
-e, --eval YSEXPR Evaluate a YS expression
multiple -e values joined by newline
-c, --compile Compile YS to Clojure
-b, --binary Compile to a native binary executable
-p, --print Print the result of --run in code mode
-o, --output FILE Output file for --load, --compile or --binary
-T, --to FORMAT Output format for --load:
json, yaml, edn
-J, --json Output (pretty) JSON for --load
-Y, --yaml Output YAML for --load
-E, --edn Output EDN for --load
-U, --unordered Mappings don't preserve key order (faster)
-m, --mode MODE Add a mode tag: code, data, or bare (for -e)
-C, --clojure Treat input as Clojure code
-d Debug all compilation stages
-D, --debug-stage STAGE Debug a specific compilation stage:
parse, compose, resolve, build,
transform, construct, print
can be used multiple times
-S, --stack-trace Print full stack trace for errors
-x, --xtrace Print each expression before evaluation
--install Install the libyamlscript shared library
--upgrade Upgrade both ys and libyamlscript
--version Print version and exit
-h, --help Print this help and exit
Ready, set, actions!🔗
The first thing to notice is that ys
has 3 "actions":
- Run (default) - Compile and evaluate a YS file
--load
- Output the evaluated YS value as JSON (by default)--compile
- Compile YS code to Clojure code
For each action you'll need some YS source code. This can come from 3 different places:
- The
--eval
(-e
) option - specifies a line of YS code. You can use this option multiple times to specify multiple lines of code. - A file path - specify a path to a file containing YS code.
- Standard input - specify
-
as the file path to read YS code from standard input. If no file or-e
options are specified,ys
will check to see if there is data on stdin. That means you can leave off the-
and pipe data intoys
like this:echo $'!yamlscript/v0\nsay: "Hello"' | ys
. Of course, it doesn't hurt to specify the-
anyway.
Running Clojure with ys
🔗
Clojure code is often valid YS code:
$ ys --compile -e '(println (+ 1 2))'
(println (+ 1 2))
This YS compiles to the exact same Clojure code.
If you want the code you run to be considered to be Clojure code (thus not
compiled by the yamlscript compiler), you can use the --clj
(-C
) option.
This is useful when you want to test out the YS runtime envronment
directly with Clojure code.
Also you can pipe the output of ys --compile
to ys --clj
to run the
compiler's Clojure code ouput:
$ ys -c -e 'say: 123' | ys -C -
Modes and Formats🔗
We learned about modes and the --mode
option yesterday.
You can set the mode for --eval
(-e
) code with the --mode
(-m
) option.
The accepted values are code
(c
), data
(d
) and bare
(b
).
When you "load" YS using --load
you get the result printed to stdout
as JSON.
These are 3 formatting options to control how the output is displayed:
--json
(-J
) - Output JSON (default) Note that this JSON is a bit more nicely formatted than the default output.--yaml
(-Y
) - Output YAML--edn
(-E
) - Output EDN. EDN is Clojure's native data format. It is also valid Clojure code.
Note that when you specify a formatting option, it implies the --load
action.
Debugging🔗
When you "run" a YS program it doesn't print anything unless you use a printing command. This isn't surprising; all languages work this way.
Sometimes you want to know what the final value of the run was.
To get this you could print it with say.
You can also use the special --print
(-p
) option, which does exactly that
(with less typing)..
Finally there a 3 special debugging options:
--stack-trace
(-S
) - Print a full stack trace for errors (more info)--debug-stage
(-D
) - Display the result of a stage/stages-d
- Short for--debug-stage=all
- Display the result of all stages
The --debug-stage
option is super useful for understanding exactly how YS
code compiles to Clojure code.
For example, to see the internal AST when compiling some YS:
$ ys -c -e 'say: "Hello"' -Dconstruct
*** construct output ***
{:Lst [{:Sym say} {:Str "Hello"}]}
(say "Hello")
And to see all 7 compilation stages:
$ ys -c -e 'say: "Hello"' -d
*** parse *** 0.181519 ms
({:+ "+MAP", :! "yamlscript/v0/code"}
{:+ "=VAL", := "say"}
{:+ "=VAL", :$ "Hello"}
{:+ "-MAP"}
{:+ "-DOC"})
*** compose *** 0.005334 ms
{:! "yamlscript/v0/code", :% [{:= "say"} {:$ "Hello"}]}
*** resolve *** 0.055135 ms
{:pairs [{:exp "say"} {:vstr "Hello"}]}
*** build *** 0.102548 ms
{:pairs [{:Sym say} {:Str "Hello"}]}
*** transform *** 0.014468 ms
{:pairs [{:Sym say} {:Str "Hello"}]}
*** construct *** 0.048013 ms
{:Top [{:Lst [{:Sym say} {:Str "Hello"}]}]}
*** print *** 0.006561 ms
"(say \"Hello\")"
(say "Hello")
We'll go over all of these stages in detail in a future post.
In the meantime, try out your new ys
tool and see what you can do with it.
The more you use it, the sharper it will get.
I'll see you tomorrow for day 8 of YS Advent 2023!