Scripting - sid-code/nmoo GitHub Wiki
The scripting language is designed to be simple. It uses S-expressions to represent lists (and code) and borrows many concepts from Lisps. I am not a Lisp programmer and this guide is written for non-Lisp programmers.
An atom is defined as the following:
123
,1e9
,1.456
etc. (numbers - note that these are bound by the rules ofparseInt
andparseFloat
)"some characters"
(" and \\ are the only currently valid escapes)'symbol-name
(apostrophe is optional!)#345
(the number is an object ID)E_ERRORNAME
nil
(actually a symbol, but is bound to the nil value)
A list is defined as the following:
(
atom atom ... atom)
Together, the kinds of atoms and list make up the eight fundamental data types: int, float, string, symbol, object, error, list, nil
Because lists are a data type and lists are also code, code is data.
Scripts can call builtins: (builtin-name arg1 arg2 ...)
There are two kinds of builtins. Runtime builtins are simple argument/return value + optional
side-effect operations and compiler specials are special forms that are transformed by the
compiler. These are usually control-flow constructs such as let
, try
, if
, among many others.
These are documented along with builtins as they are almost exactly the same. The only difference
is that a compiler special can NOT be called using the call
builtin because the compiler needs
to know what's being called at compile-time. You can generate documentation for builtins and compiler specials alike by running nake docs
in the project root directory.
The data types are pretty straightforward with some exceptions. Symbols are identifiers that may
or may not be bound to a value. Here, "bound" means "interchangable with". For example, if a symbol
a
was bound to the value 3.6
, whenever you refer to a
, the compiler will instead look up
the symbol and insert instructions to access whatever was at a
. Using unbound symbols will result
in an error (see page on errors) unless it's quoted. quote
is a compiler special that takes one
argument and returns just that argument but with the guarantee that nothing inside it will be
evaluated. If you bind a symbol dog
and try to access it from within a quote
, you'll still
get the symbol dog
, and not whatever it was bound to. There is a construct called quasiquote
which
behaves exactly like quote but within a quasiquote
you can insert unquote
s anywhere inside it
which will evaluate their arguments (and insert more quasiquote
s or do whatever you want). More
information on quote
and friends is found on the builtin page.
Binding symbols is achieved through the compiler special let
. Here is how:
(let ((bound-symbol 5))
(echo (+ bound-symbol 50)))
let
takes 2 arguments. The first is a list of (symbol value)
pairs which binds each symbol
to value
but only while executing the second argument.
There is one more data type, but it is a sneaky one. It's called a lambda
or anonymous function but
it masquerades a list. Information on lambda
can be found on the builtin page and information about
its internal representation can be found on the lambda
page.