Kid is a minimalist, sandboxed, dynamically typed scripting language. It has no support for explicit use of standard streams (stdin, stdout and stderr) nor command line arguments. It has limited support for interacting with files, only allowing interaction with program-local, program-created ones. Though, it does have networking support.
I was planning to add graphics support but I abandoned the language before that could happen.
Kid only has multiline comments, enclosed in ()
.
(Hey, kids (again)!)
As you can see, Kid allows nesting parentheses in comments.
All expressions in Kid are lazily evaluated: meaning they only get evaluated when they need to be.
Nulls are the no-values: they denote that there is no value.
...
They're written as an ellipsis because they can be used as empty expressions (like pass
in python) or placeholders.
Quantities in Kid are unsigned integers that are dynamically sized (with a 1-byte minimum).
123
Quantity literals can contain a single .
as a cosmetic decimal point.
100.00
This is equivalent to 10000
.
Strings are just lists of Unicode character quantities. You'll learn more about lists in the next section. Strings are enclosed in ""
.
":)"
Kid supports syntactic sugar for letter strings: ones containing ASCII letters.
ghoom
This is equivalent to "ghoom"
.
Letter strings are case-sensitive.
Escape sequences only apply inside quoted strings.
\\
—\
\'
—'
\"
—"
\(N)
— the unicode character with the code as the (decimal) integer numeralN
\0
— NUL\t
— TAB\n
— LF\r
— CR\e
— ESC
Spaces are associative arrays that can store mixed types of keys and items.
smiley=":)" score=123 percentage=45.00
Left operands of =
are keys, and right ones are items assigned to those keys. Keys can be of any type. As you can see, item separation is implicit and is not marked by anything.
Items in or outside a space can be accessed using the prefix operator $
:
smiley=":)" score=123 percentage=45.00 otherScore=$score
Here, $score
expands to 123
and is then assigned to the key otherScore
.
When accessing keys, the ones in the same space take priority over the ones outside.
We can also redefine keys:
smiley=":)" score=123 percentage=45.00 smiley=":^)"
Keys alongside =
can be omitted to automatically assign items to position-based quantity keys, called indices.
":)" score=123 45.00
Now, the item ":)"
is assigned to the index 0
, and 45.00
to 1
. It's equivalent to this:
0=":)" score=123 1=45.00
Accessing undefined keys returns null.
Spaces that only have indexed items are called lists. Ones that only have non-indexed (or keyed) items are called tables.
An assignment is enough to construct a space:
score=123
Notice how until now, we can't construct lists with less than two items. To fix this problem, nulls are ignored in space constructions.
":)"...
Now, Kid can detect that this is intended to be a list and construct it with only one item. Genius!
Following that logic, this is how to construct an empty list:
... ...
Let's consider two keyed spaces:
quantities =
43
21
65
otherQuantities =
198
777
You'll learn more about using tabs later.
We can access a space's number of items—its length—by prefixing its name by %
.
%quantities
This returns 3. If this operator is used on nulls, it returns 0. Otherwise, if it's used on other non-space values, it returns 1.
We can access keys of certain spaces using the binary operator #
:
otherQuantities =
198
777
quantities#1
To delete a key, we just set it to null, which will decrement the space's length.
otherQuantities =
198
777
21
1=...
This cancels out to:
otherQuantities =
198
21
Now, indices have been shifted and 21
is assigned to the index 1
instead of 2
.
If #
is used with non-space values, the key 0
refers to the value, and other keys refer to null.
The binary operator :
allows us to append an expression at the end of a space's constructor.
otherQuantities: 20
Now, otherQuantities
is 198 21 20
.
Using :
on a non-space value turns it into a list containing the value and the appended expression.
Omitting the left operand of :
evaluates the expression in the global space. The operator always returns the left operand.
Using :
with an undefined key automatically assigns an empty space to it.
If we omit keys from assignments, the space immediately returns the item instead of itself when evaluated.
otherQuantities =
198
=20
Here, otherQuantities
is assigned 20
.
To force-evaluate an expression, we use the suffix operator !
, essentially turning it into a function. This is called calling a key.
plusOne = ... args#0 + 1
args = 99
plusOne!
To return from a space while saving its constructor evaluation position, we use the prefix operator =>
. This introduces coroutines to the language.
Using !
on a key with a non-space item returns that item.
n = 100
n!
Here, n!
simply returns 100
.
Spaces are assigned and passed by reference.
All of the following operators have equal precedence.
$x + $y
$x - $y
$x * $y
$x / $y
(a space where the quotient is at0
and the remainder is atremainder
)~$x
(bitwise inversion)$x | $y
$x ^ $y
(bitwise XOR)$x & $y
$x << $y
(left logical shift)$x >> $y
(right logical shift)
In numeric operations, nulls are treated as 0, and spaces are treated as their first quantity item.
These operators return the right operand if it's greater, and null otherwise.
$x == $y
$x < $y
Nulls are treated as 0 in <
.
We can use the prefix operator `
to get the default value of a value's type.
`... (...)
`123 (0)
`":)" (... ...)
One benefit to this is checking a value's type by comparing against its default value.
You'll learn more about the other types later in this guide, don't worry. ;)
Kid features two types of inline conditionals. Both of them consider nulls to be the only falsy value.
The first is the if-then conditional:
$female -> ">:o"
If $female
is truthy (not null), this returns ">:o"
. Otherwise, it returns $female
.
The second type is the unless-then conditional:
$female |> ":|"
If $female
is null, this returns ":|"
. Otherwise, it returns $female
.
And so |>
can be used to specify a fallback in case a value is null.
->
and |>
can be combined to make an if-else combination:
$female -> ">:o" |> ":|"
If $female
is truthy, this returns ">:o"
. Otherwise, it returns ":|"
.
The left operands of these operators are optional, defaulting to null.
Blocks are syntactic sugar that uses newlines and tabs to hierarchically group spaces.
$female ->
face = ">:o"
interest = 100
Newlines into a deeper indentation introduce a space, and newlines into the same indentation separate items.
Blobs are keys stored in disk in a program-local folder. They're prefixed by @
.
@todos =
"do stuff"
"do more stuff"
"pet self"
"do even more stuff damn it!"
...
@todos: 3 = "ok i think i'm good for today"
The next time the program runs, todos
will be automatically in whatever state it was on before the program ended.
If todos
was part of a space, that space will get loaded alongside any other contained blobs. Non-blobs won't load.
Setting a blob or its containing space to null deletes it from disk.
Blobs have length limits because of filename limitations in common filesystems.
Kid only features While and Until loops at its core, using the respective binary operators -->
and ||>
.
nLooks = 0
$female --> :
nLooks = nLooks + 1
While $female
is truthy, this increments nLooks
by 1
.
The left operand is optional, defaulting to null.
**
is a millisecond-level Unix timestamp quantity referring to now. In addition to keeping the time with it, we can use it to wait a number of milliseconds.
(args: duration)
wait =
start = **
end = $start + $duration
** - $start < $duration --> ...
Expressions can be evaluated asynchronously if they're enclosed in {}
.
a = 1
{
duration = 1000
wait!
c = 3
}
b = 2
Here, a
and b
are defined before c
because c
was defined asynchronously after 1000
milliseconds. The whole asynchronous group returns null.
We can push the raw form of a value as a byte list onto the reception stack of an IP-identified network or computer using the binary operators <~
and <~~
.
2130706433 <~ "Hello!"
1 <~~ $n + 1 ...
The first operator uses IPv4, and the second one uses IPv6. The left operand is the raw address that corresponds to the IP version.
Nothing is sent when attempting to push null.
We can also pop data from the reception stack using the suffix operator ?
:
2130706433?
If the stack is empty, this returns null.
A special case of addresses is 0
which doesn't do anything with data.
All modules are global and are stored in one folder. The prefix operator .
is how we include modules by their names.
.discord
Module names are not the same as their filenames. Just like keys, module names can be of any type (discord
here is of course just a string). But just like blobs, they also have length limits.
Kid ensures that the same module is never included more than once in a program.