meowscript

MeowScript reference

MeowScript is a small, dynamically typed scripting language. Its keywords are cat puns, its values are the usual ones under different names, and its interpreter is written in Rust. This page is the whole language.

If you just want to poke at it, the playground runs everything on this page. Every listing has a Try it button.

A first program

scratch cat = { name: "Whiskers", lives: 9 }; pawction describe(c) {    tail c's name + " has " + c's lives + " lives";} meow(describe(cat));

Statements end with a semicolon. You may leave it off before a closing } and at the very end of a file, and after anything that already ends in a } such as a purrhaps or a pawction declaration.

Comments are // to the end of the line or /* anywhere in between */.

Printing

meow prints its arguments separated by spaces, announced with Meow!. purr prints them without the announcement. log is the same as purr, for people who miss JavaScript.

meow("hello", 42, purrfect);   // Meow! hello 42 purrfectpurr("hello", 42, purrfect);   //       hello 42 purrfect

Values

TypeCalledLooks like
numbernumber42, 3.5, 1_000, 2e3
stringwhiskers"meow"
booleanbooleanpurrfect, clawful
nullmewmew
arrayfurrball[1, 2, 3]
objectobject{ name: "Tom", age: 3 }
functionpawctionpawction(a, b) { tail a + b; }

furreal tells you which one you have: furreal [] is "furrball".

Numbers

All numbers are 64-bit floats. Whole numbers print without a decimal point. Dividing by zero is an error rather than infinity.

Whiskers

Strings use double quotes and understand \n, \t, \", \\, and \u{1F431}. They may span lines.

+ joins whiskers with anything, converting the other side the way meow would print it. * repeats.

purr("cats: " + 3);        // cats: 3purr("=^.^= " * 3);        // =^.^= =^.^= =^.^=purr("meow"[0]);           // mpurr("meow"[-1]);          // w

Furrballs

Furrballs are arrays. Indexes start at 0 and negative indexes count from the end. Reading past either end is an error, not mew.

scratch toys = ["yarn", "box"];purr(toys[0], toys[-1]);     // yarn boxamew toys[1] = "sunbeam";purr(toys);                  // ["yarn", "sunbeam"]

Furrballs and objects are shared, not copied. Two variables pointing at the same furrball see the same changes, like in JavaScript or Python. == compares contents, though, so [1, 2] == [1, 2] is purrfect.

Objects

Objects are ordered maps from whiskers to values. Keys can be written bare or quoted; { name } is short for { name: name }; [expr] computes a key.

Read a key with obj's key or obj["key"]. A key that isn't there gives mew. Write one with amew.

scratch cat = { name: "Tom", "fur color": "grey" };purr(cat's name, cat["fur color"]);amew cat's age = 4;purr("age" ~ cat);          // purrfect

Variables

scratch declares a variable in the current scope. amew changes one that already exists, searching outward through enclosing scopes. Using amew on a name that was never scratched is an error, and so is reading one, with a did you mean hint when there's a close match.

scratch lives = 9;purrhaps purrfect {    amew lives = lives - 1;    // changes the outer `lives`    scratch lives = 100;       // a new, inner `lives`}purr(lives);                   // 8

Blocks, loops, and pawction calls each open a new scope.

Operators

From loosest to tightest binding. Operators on the same row are applied left to right.

OperatorsMeaning
||or (short-circuits, returns the deciding value)
&&and (short-circuits, returns the deciding value)
== !=equal, not equal (by contents)
< > <= >= ~compare; ~ is "is in"
|bitwise or
^bitwise xor
&bitwise and
<< >>shift
+ -add, subtract (and join whiskers or furrballs)
* / %multiply, divide, remainder (and repeat whiskers)
-x !x furreal xnegate, not, type of
f(x) a[i] a's bcall, index, property

This is the ordering Python and Rust use, so 6 & 3 == 2 means (6 & 3) == 2.

~ works on all three containers: 2 ~ [1, 2], "age" ~ cat, and "ow" ~ "meow".

Only mew and clawful are falsy. 0, "", and [] are all truthy, so purrhaps count { ... } doesn't skip zero.

Conditions

purrhaps is if, meowtually is else. Parentheses around the condition are optional. Chains work as you'd expect.

purrhaps hour < 6 {    meow("too early");} meowtually purrhaps hour < 12 {    meow("breakfast time");} meowtually {    meow("second breakfast time");}

purrhaps is an expression. A block's value is the value of its last statement, so you can use it on the right of a scratch or as the last line of a pawction.

scratch mood = purrhaps fed { "purring" } meowtually { "plotting" };

Loops

furrever loops forever, or while a condition holds if you give one. hiss breaks out; continue skips to the next round.

scratch n = 0;furrever {    amew n = n + 1;    purrhaps n % 2 == 0 { continue; }    purrhaps n > 7 { hiss; }    purr(n);} furrever n > 0 {    amew n = n - 3;}

fur walks over something: the items of a furrball, the characters of whiskers, the keys of an object, or the numbers from 0 up to (not including) a number.

fur toy ~ ["yarn", "box"] { purr(toy); }fur letter ~ "cat"        { purr(letter); }fur key ~ { a: 1, b: 2 }  { purr(key); }fur i ~ 3                 { purr(i); }       // 0 1 2

Pawctions

Declare a named pawction, or make an anonymous one and keep it in a variable. Either way they are values: pass them around, return them, put them in furrballs.

pawction add(a, b) {    tail a + b;} scratch double = pawction(x) { x * 2 }; purr(add(2, 3), double(4));

tail returns. If a pawction runs off the end, it returns the value of its last statement, which is why double above works without one. A pawction with no useful last statement returns mew.

Pawctions close over the scope they were made in:

pawction counter() {    scratch n = 0;    tail pawction() {        amew n = n + 1;        tail n;    };} scratch next = counter();next(); next();purr(next());    // 3

Calling with the wrong number of arguments is an error. So is nesting calls more than a thousand deep, which usually means a recursion with no way out.

Pawckages

pawckage pulls in a library. The built-in ones start with nya: and are listed under Standard library.

pawckage "nya:furrball";pawckage "nya:catculator"; purr(map(range(5), pawction(n) { round(sqrt(n)) }));

Any .meow file is also a pawckage. Everything scratched or declared at its top level becomes available to whoever imports it. Paths are relative to the importing file, and the .meow can be left off.

pawckage "./lib/kitty_math";purr(lives_left(2));

File pawckages need a filesystem, so they work from the command line but not in the browser playground.

Errors

Every error says what went wrong and points at where:

Furbidden! type error: `-` doesn't work between whiskers and a number  --> toys.meow:4:12   | 4 | scratch n = "nine" - 1;   |             ^^^^^^^^^^

The exclamation tells you the kind: Meowch! for syntax, Meow-sterious! for an unknown name, Furbidden! for a type mismatch, Paws off! for the wrong number of arguments, Lost kitten! for a pawckage that can't be found, Scratched! for file trouble, and Hiss! for everything else at run time.

The command line

Prebuilt binaries are on the download page. With a Rust toolchain you can also build it yourself:

cargo install --git https://github.com/AlenVelocity/MeowScript meowscript-cli meowscript                   # start the REPLmeowscript hello.meow        # run a filemeowscript eval "1 + 2"      # evaluate a snippetmeowscript packages          # list the nya: pawckages

The REPL keeps reading lines while a block is open, prints the value of each expression, and leaves when you type scram.

Standard library

These tables come from the interpreter itself (meowscript packages --json), so they can't drift from the code. Arities are checked before a function runs: the wrong number of arguments is a Paws off! error, not a silent mew.

Always available

PawctionTakesDoes
meowat least 0 argumentsPrint the arguments on one line, announced with "Meow!".
purrat least 0 argumentsPrint the arguments on one line, separated by spaces.
logat least 0 argumentsThe same as `purr`, for people who miss JavaScript.
lengthexactly 1 argumentHow many characters, items, or keys something has.

pawckage "nya:clawtility";

Input, timing, objects, and other everyday tools.

PawctionTakesDoes
lengthexactly 1 argumentHow many characters, items, or keys something has.
kibblebetween 0 and 1 argumentsRead a line of input. Shows the prompt first if you give one.
napexactly 1 argumentPause for that many milliseconds.
nowexactly 0 argumentsMilliseconds since the Unix epoch.
keysexactly 1 argumentA furrball of an object's keys, in insertion order.
valuesexactly 1 argumentA furrball of an object's values, in insertion order.
removeexactly 2 argumentsRemove a key from an object. Returns the removed value, or mew.
assertbetween 1 and 2 argumentsStop with an error unless the first argument is truthy.
applyexactly 2 argumentsCall a pawction with a furrball of arguments.

pawckage "nya:furrball";

Everything for furrballs (arrays).

PawctionTakesDoes
pushat least 2 argumentsAdd items to the end of a furrball. Changes it in place and returns it.
pounceexactly 1 argumentRemove and return the last item, or mew if the furrball is empty.
topexactly 1 argumentThe first item, or mew.
lastexactly 1 argumentThe last item, or mew.
bottomexactly 1 argumentA new furrball with everything but the first item.
includesexactly 2 argumentsWhether a furrball has an item, or whiskers contain a substring. Same as `~`.
index_ofexactly 2 argumentsWhere an item (or substring) first appears, or -1.
mapexactly 2 argumentsA new furrball made by calling the pawction on each item.
filterexactly 2 argumentsA new furrball of the items the pawction says purrfect to.
reducebetween 2 and 3 argumentsFold a furrball into one value with `pawction(total, item)`, starting from the optional initial value.
eachexactly 2 argumentsCall the pawction on every item. Returns mew.
findexactly 2 argumentsThe first item the pawction says purrfect to, or mew.
rangebetween 1 and 3 argumentsNumbers from `start` (default 0) up to but not including `end`, in `step`s (default 1).
reverseexactly 1 argumentA reversed copy of a furrball or whiskers.
sortbetween 1 and 2 argumentsA sorted copy. Give a `pawction(a, b)` returning a number to decide the order.
joinbetween 1 and 2 argumentsGlue the items into whiskers with a separator (default none).
slicebetween 2 and 3 argumentsA copy of part of a furrball or whiskers, from `start` up to (not including) `end`. Negative counts from the end.
concatat least 1 argumentA new furrball with the items of all the given furrballs.

pawckage "nya:whiskers";

Everything for whiskers (strings).

PawctionTakesDoes
in_whiskersexactly 1 argumentTurn anything into whiskers, the way `meow` would print it.
pawrseexactly 1 argumentRead a number out of whiskers, or mew if there isn't one.
replaceexactly 3 argumentsReplace every occurrence of `from` with `to`.
splitbetween 1 and 2 argumentsSplit into a furrball on a separator. With no separator, splits on whitespace.
upperexactly 1 argumentSHOUTING.
lowerexactly 1 argumentwhispering.
trimexactly 1 argumentStrip whitespace from both ends.
starts_withexactly 2 argumentsWhether the whiskers begin with the given prefix.
ends_withexactly 2 argumentsWhether the whiskers end with the given suffix.
includesexactly 2 argumentsWhether a furrball has an item, or whiskers contain a substring. Same as `~`.
index_ofexactly 2 argumentsWhere an item (or substring) first appears, or -1.
charsexactly 1 argumentA furrball of the individual characters.
repeatexactly 2 argumentsThe whiskers repeated that many times. Same as `*`.
pad_startbetween 2 and 3 argumentsPad on the left to a width, with spaces or the given filler.
pad_endbetween 2 and 3 argumentsPad on the right to a width, with spaces or the given filler.
reverseexactly 1 argumentA reversed copy of a furrball or whiskers.
slicebetween 2 and 3 argumentsA copy of part of a furrball or whiskers, from `start` up to (not including) `end`. Negative counts from the end.

pawckage "nya:catculator";

Maths. Angles are in radians.

PawctionTakesDoes
randombetween 0 and 2 argumentsA random number: in [0, 1) with no arguments, [0, n) with one, or [min, max) with two.
roundexactly 1 argumentRound to the nearest whole number.
ceilexactly 1 argumentRound up.
floorexactly 1 argumentRound down.
truncexactly 1 argumentDrop the fractional part.
absexactly 1 argumentDistance from zero.
sqrtexactly 1 argumentSquare root.
sinexactly 1 argumentSine (radians).
cosexactly 1 argumentCosine (radians).
tanexactly 1 argumentTangent (radians).
log2exactly 1 argumentLogarithm base 2.
log10exactly 1 argumentLogarithm base 10.
lnexactly 1 argumentNatural logarithm.
expexactly 1 argumente raised to the power.
powexactly 2 arguments`base` raised to `exponent`.
moduloexactly 2 argumentsRemainder that is never negative for a positive divisor, unlike `%`.
minat least 1 argumentThe smallest of the numbers, or of one furrball of numbers.
maxat least 1 argumentThe largest of the numbers, or of one furrball of numbers.
clampexactly 3 argumentsKeep a number between `low` and `high`.
ConstantValue
PI3.141592653589793
TAU6.283185307179586
E2.718281828459045
INFINITYInfinity

pawckage "nya:rundamn";

Random numbers, choices, and shuffles.

PawctionTakesDoes
seedexactly 1 argumentRestart the random sequence from a number, so runs repeat exactly.
randombetween 0 and 2 argumentsA random number: in [0, 1) with no arguments, [0, n) with one, or [min, max) with two.
uniformexactly 2 argumentsA random float in [a, b).
randintexactly 2 argumentsA random whole number from a to b, including both ends.
choiceexactly 1 argumentA random item from a furrball.
shuffleexactly 1 argumentShuffle a furrball in place and return it.

pawckage "nya:scratchpad";

Reading and writing files. Not available in the browser.

PawctionTakesDoes
read_fileexactly 1 argumentThe whole contents of a file as whiskers.
write_fileexactly 2 argumentsWrite whiskers to a file, replacing what was there.
append_fileexactly 2 argumentsAdd whiskers to the end of a file.
existsexactly 1 argumentWhether a file or directory is there.