Ait or Aisteach (ie) - Strange, unusual, curious, weird, funny
Programming language for visual and creative experiments on the web. Heavily influenced by the Forth-family of languages.
The language and runtime is still in a very experimental state.
Requirements: Node v6 or above
Install with npm npm install [-g] ait-lang
, use -g
if you want to add it as a global executable.
Clone repo and run npm i && npm run build
and an executable should appear in ait-lang/bin
.
After installing (or building from source) you can use ait-lang to interpret your .ait
-files like this:
> ait-lang source.ait
You can also run ait-lang
in your browser. It involves a bit more setting up (this is still a work in progress):
const fs = require('fs');
const Browser = require('ait-lang/runtimes/browser');
const src = fs.readFileSync('YOUR SOURCE HERE', 'utf8');
const runtime = Browser();
// Load some liberaries
Object.assign(runtime.lexicon, require('ait-canvas'));
Object.assign(runtime.lexicon, require('ait-dom'));
runtime.evaluate(src);
// Grab the canvas from the runtime
// It's a bit roundabout, working on a better solution
document.body.appendChild(runtime.scope['__aitCanvasContext'].body.canvas);
The Ait Playground has some examples you could follow. It also has some examples of usage in the browser.
TODO
These are the words currently shipping with the ait-lang
-runtime.
The normal operators found in JavaScript works as words in Ait:
+
, -
, *
, /
. %
exists as mod
and unary -
exists as neg
.
Most of the methods and constants normally found on Math
in JavaScript exist in Ait:
PI
, E
, random
, abs
, max
, min
, sqrt
, cbrt
, pow
, floor
, ceil
, round
, exp
, sign
, log
, log10
, cos
, acos
, cosh
, acosh
, sin
, asin
, sinh
, asinh
, tan
, atan
, atan2
, tanh
, atanh
.
In addition some helper words have been added:
lower upper random2
Generates a random float between lower
and upper
.
n succ
Generates the successor to n
. Equivalent to n 1 +
.
n pred
Generates the predecessor to n
. Equivalent to n 1 -
.
a b >
true
if a is greater than b, false
otherwise.
Desc
a b <
true
if a is smaller than b, false
otherwise.
Desc
a b =
true
if a is equal to b, false
otherwise. This uses ===
in JavaScript to determine equality.
Desc
a b !=
true
if a is not equal to b, false
otherwise. This uses !==
in JavaScript to determine equality.
Desc
a b >
true
if a is greater than or equal to b, false
otherwise.
Desc
a b >
true
if a is smaller than or equal to b, false
otherwise.
Desc
a b ||
true
if a or b is true
, false
otherwise.
Works the same way as JavaScripts ||
in that it will coerce operands to boolean values before comparing.
Desc
a b &&
true
if a and b is true
, false
otherwise.
Works the same way as JavaScripts &&
in that it will coerce operands to boolean values before comparing.
Desc
[aggr] small
or n small
true
if aggregate aggr
has 0 or 1 elements or if n
is a small number (-1
, 0
or 1
).
Desc
[aggr] zero
or n zero
true
if aggregate aggr
has 0 element or if n
is the number 0
.
Words for manipulating strings.
This module is unstable.
"string" "replacement" replace
Replaces the first %s
s in the string "string"
with replacement "replacement"
.
"%s extra" "nothing" replace
Resulting in "nothing extra"
being left on the stack.
"string" "replacement" replace2
Replaces the two first %s
s in the string "string"
with replacement "replacement"
.
"string" "replacement" replace3
Replaces the three first %s
s in the string "string"
with replacement "replacement"
.
a .
Pops the top element off the stack and prints it to stdout.
a dup
Duplicates the top element of the stack
a b dupd
dip
'ed version of dup
. Short-hand for a b [dup] dip
.
a pop
Pops the top element off the stack.
a b popd
dip
'ed version of pop
. Short-hand for a b [pop] dip
.
a b swap
Swaps the top two elements of the stack.
a b c swapd
dip
'ed version of swap
. Short-hand for a b c [swap] dip
.
a b c rollup
Rolls the 3rd element of the stack up to the top of the stack.
1 2 3 rollup
Results in the stack looking like this: 2 3 1
.
a b c d rollupd
dip
'ed version of rollup
. Short-hand for a b c d [rollup] dip
.
a b c rolldown
Rolls the 1st element of the stack up down 2 slots.
1 2 3 rolldown
Results in the stack looking like this: 3 1 2
.
a b c d rolldownd
dip
'ed version of rolldown
. Short-hand for a b c d [rolldown] dip
.
a b c rotate
Rotates the 1st and 3rd element of the stack.
1 2 3 rotate
Results in the stack looking like this: 3 2 1
.
a b c d rotated
dip
'ed version of rotate
. Short-hand for a b c d [rotate] dip
.
stack
Pushes a copy of the current stack onto the stack.
[aggr] unstack
Replaces the current stack with aggregate aggr
.
Words for working with quotations
[quot] exec
Executes quotation quot
.
[1 1 +] exec
Results in 2
being left on the stack.
[quot] nullary
Executes quotation quot
with arity 0. Reading as many elements of the stack as it needs, but does not consume any.
1 1 [+] nullary
Results in 1 1 2
being left on the stack.
[quot] unary
Executes quotation quot
with arity 1. Reading as many elements of the stack as it needs, but only consumes 1.
1 1 [+] unary
Results in 1 2
being left on the stack.
[quot] binary
Executes quotation quot
with arity 2. Reading as many elements of the stack as it needs, but only consumes 2.
1 1 [+] unary
Results in 2
being left on the stack.
[quot] ternary
Executes quotation quot
with arity 3. Reading as many elements of the stack as it needs, but only consumes 3.
1 2 3 4 [ + + + ] ternary
Resulting in 1 10
being left on the stack.
[quot] dip
Takes the top element of the stack, executes quotation quot
and puts top element back on the stack.
1 2 3 [+] dip
Results in 3 3
being left on the stack.
el [qout1] [qout2] cleave
Executes quotations quot1
and quot2
each with element el
as the top of the stack.
1 [1 +] [2 +]
Resulting in 2 3
being left on the stack.
Words for working with aggregates
el [aggr] cons
Conses el
onto aggregate aggr
.
1 0 [] cons cons
Constructs a two-element vector from 0
and 1
, resulting in [1 0]
being left on the stack.
[aggr] el swons
Short-hand for [aggr] el swap cons
.
el [aggr] append
Appends el
at the end of aggregate aggr
.
0 [1] append
Appends 0
at the end of [1]
resulting in [1 0]
being left on the stack.
[aggr] el swappend
Short-hand for [aggr] el swap append
.
[aggr] uncons
Unconses the first element of aggregate aggr
, leaving el
and aggr
on the stack.
[1 0] uncons
Unconses 1
from [1 0]
leaving the stack with 1 [0]
.
[aggr] unswons
Short-hand for [aggr] uncons swap
. Leaves result of uncons on the stack in the reverse order.
[1 0] unswons
Unconses 1
from [1 0]
leaving the stack with [0] 1
.
[aggr1] [aggr2] concat
Concats two aggregates. Follows the rules of Array.prototype.concat
in JavaScript.
[0] [1] concat
Concats aggregate [0]
and aggregate [1]
resulting in [0 1]
being left on the stack.
el [aggr1] [aggr2] enconcat
Concats aggregates aggr1
and aggr2
with el
in between.
1 [0] [2] enconcat
Concats aggregates [0]
and [2]
with 1
in between, resulting in [0 1 2]
being left on the stack.
[aggr] first
Gets the first element of aggregate aggr
.
[0 1 2] first
Leaves 0
on the stack.
[aggr] last
Gets the last element of aggregate aggr
.
[0 1 2] last
Leaves 2
on the stack.
[aggr] rest
Drops the first element and gives you the rest of aggreate aggr
.
[0 1 2] rest
Leaves [1 2]
on the stack.
i [aggr] of
Gets the element of aggregate aggr
at index i
. Equivalent to i [aggr] swap at
.
1 [0 1 2] of
Leaves 1
on the stack.
[aggr] i at
Gets the element at index i
of aggregate aggr
. Equivalent to [aggr] i swap of
.
[0 1 2] 1 at
Leaves 1
on the stack.
el [aggr] i ins
Inserts el
in aggregate aggr
at index i
. Follows the rules of assigning to index in JavaScript, meaning you can get sparse aggregates.
3 [0 1] 1 ins
Inserts 3
into [0 1]
at index 1
resulting in [0 3]
being left on the stack.
[aggr] size
Gets the size or length of aggregate aggr
.
[0 1 2] size
Leaves 3
on the stack.
[aggr] n drop
Drops the n
first elements of aggregate [aggr]
.
[0 1 2] 1 drop
Leaves [1 2]
on the stack.
[aggr] n take
Takes the n
first elements of aggregate [aggr]
.
[0 1 2] 2 take
Leaves [0 1]
on the stack.
[aggr] [s] step
Executes quotation s
with arity 1 once for every element of aggregate aggr
. Quotation s
has access to the variables _i
, which is the index of the current step, and _a
which is the aggregate.
[1 2 3] [ 1 + ] step
Results in 2 3 4
being left on the stack.
[aggr] [mapper] map
Executes quotation mapper
with arity 1 producing a new element for each element in aggregate aggr
.
Quotation mapper
has access to the variables _i
, which is the index of the current step, and _a
which is the aggregate.
[1 2 3] [ 1 + ] map
Results in [2 3 4]
being left on the stack.
[aggr1] [aggr2] [mapper] map2
Executes quotation mapper
with arity 2 producing a new element for each element in aggregate aggr1
and aggr2
. Aggregate aggr1
must have an equal or greater number of elements than aggregate aggr2
.
Quotation mapper
has access to the variables _i
, which is the index of the current step, _a1
, which is the first aggregate, and _a2
which is the second aggregate.
[2 4 6] [1 2 3] [ / ] map2
Results in [2 2 2]
being left on the stack.
[aggr] v0 [folder] fold
Executes quotation folder
with arity 2 producing a new value for each element in aggregate aggr
with v0
as the initial value.
Quotation folder
has access to the variables _i
, which is the index of the current step, and _a
which is the aggregate.
[1 2 3] 0 [ + ] fold
Results in 6
being left on the stack.
[aggr] sort
Sorts the aggregate aggr
in place using numerical comparison.
[3 1 2] sort
Results in [1 2 3]
being left on the stack.
[aggr] index sortBy
Sorts aggregate aggr
in place using numerical comparison on index
of each element.
[[1 3] [3 2] [2 1]] 1 sortBy
Results in [[2 1] [3 2] [1 3]]
being left on the stack.
[aggr] [test] filter
Filters the aggregate aggr
by executing test
with arity 1 for each element in aggregate.
Quotation test
has access to the variables _i
, which is the index of the current step, and _a
which is the aggregate.
[1 2 3 4 5 6] [2 mod 0 =] filter
Results in [2 4 6]
being left on the stack.
[aggr] [test] split
Splits aggregate aggr
into two aggregates according to the result of executing test
for each element.
Quotation test
has access to the variables _i
, which is the index of the current step, and _a
which is the aggregate.
[1 2 3 4 5 6] [3 <] split
Results in [1 2] [3 4 5 6]
being left on the stack.
[aggr] [test] some
Executes quotation test
with arity 1 for each element in aggregate aggr
and yields true
if atleast one element passes the test.
Quotation test
has access to the variables _i
, which is the index of the current step, and _a
which is the aggregate.
[1 2 3 4 5] [3 =] some
Results in true
being left on the stack.
[aggr] [test] all
Executes quotation test
with arity 1 for each element in aggregate aggr
and yields true
if all elements passes the test.
Quotation test
has access to the variables _i
, which is the index of the current step, and _a
which is the aggregate.
[1 2 3 4 5] [3 =] all
Results in false
being left on the stack.
Words for managing control flow.
test [quote]
Executes quote
if test
is true
.
0 10 random2 5 < ['less than five']
Tells if a random number between 0
and 10
is lower than 5
.
test [t] [f]
Executes t
if test
is true
or f
if test
is false
.
0 10 random2 5 < ['less than five'] ['bigger than or equal to five'] ifte
Tells if a random number between 0
and 10
is lower or higher than 5
.
[test] [t] [f] ifte
Executes test
with arity 0 to produce a boolean. Executes t
if boolean is true
or f
if boolean is false
.
Works like branch
except that test
can be a quotation.
0 10 random2 [5 <] ['less than five'] ['bigger than or equal to five'] ifte
Tells if a random number between 0
and 10
is lower or higher than 5
.
Words for doing iterations and other looping.
[ test ] [ step ] while
Executes test
with arity 0 to yield a boolean. Executes step
if boolean is true.
0
[ 10 < ]
[ 1 + ]
while
Will count up from 0 to 9 and stop, leaving 9 on the stack.
count [ step ] times
Executes step
count
times.
Inside step
you will have access to the _i
-variable, which has the value of the current step.
0 10 [ 1 + ] times
Will add 1
to the top of the stack 10
times, leaving 10
on top of the stack.
Words for doing anonymous recursion
[ test ] [ done ] [ generate ] [ collect ] linrec
linrec
takes 4 quotations off the stack and preforms linear recursion:
test
is executed with arity 0 to yield a boolean.done
is executed iftest
yieldstrue
.generate
is executed iftest
yieldsfalse
and will continue the recursion with whatevergenerate
leaves on the stack.collect
is executed after the recursion-step is done.
7 [ zero ] [ succ ] [ dup pred ] [ * ] linrec .
Will compute the factorial of 7
, which is 5040
.
[ test ] [ done ] [ step ] tailrec
tailrec
takes 3 quotations off the stack and preforms tail recursion:
test
is executed with arity 0 to yield a boolean.done
is executed iftest
yieldstrue
.step
is executed iftest
yieldsfalse
and will continue the recursion with whatevergenerate
leaves on the stack.
0 [1 2 3 4 5] [zero] [ pop ] [ uncons [+] dip ] tailrec .
Will do a tail recursive sum of the elements in an aggregate.
[ test ] [ done ] [ generate ] [ collect ] binrec
binrec
takes 4 quotations off the stack and preforms linear recursion:
test
is executed with arity 0 to yield a boolean.done
is executed iftest
yieldstrue
.generate
is executed iftest
yieldsfalse
and will produce 2 values. Binrec then recurses twice with each value on the top of the stack.collect
is executed after the recursion-step is done.
[2 4 6 8 1 3 5 7 9] [ small ] [] [ uncons [>] split ] [ enconcat ] binrec .
Will preform quicksort on the aggregate.