- Minimalist programming language simple to read, write, extend.
- Influenced by: Python, Bash, XL.
- Axol is named after the axolotl animal for its ability to regrow missing body parts and for being cute.
- Version: 0.3.2
- Docs: {:toc}
# Text from `#` to the end of line is a comment,
# unless `#` is inside of a string.
"Double-quoted multiline string # here
expands \"escape\tsequences\"
including \\ and no-newline: \
It also expands var {names} and {other.code()}
unless curly braces are escaped like \{these\}."
'Single-quoted multiline raw string
expands \no {special sequences
to avoid escaping of "double quotes" and {code}
and double escaping of \regex.'
- String having no
"\{}
chars should be double-quoted to avoid conflicts of personal preferences.
null
false
true
-3.14
"string"
- These are examples of simple values:
null
, bools, numbers, strings. - More values like boxes and actions are described below.
- Examples below use placeholders:
aaa
,bbb
,ccc
,ddd
, ...,yyy
,zzz
. - They are simpler to invent and recognize than few well-known metasyntactic variables
foo
,bar
,baz
,qux
, ...what's next? - They avoid confusion with:
- Words that should be used as is, like
file
. - Short words like
a
being an article. - Each other, unlike
name1
,name2
,name3
, ...,name25
,name26
.
- Words that should be used as is, like
- Box is a namespace - a space with names, not values.
- Each name points to a value outside the box, e.g:
________
| |
| 0 -----> null
| 1 -----> false
| 2 -----> true /--\
| 3 -----> -3.14 | |
| aaa ---> "bbb" _______v_ |
| ccc -------^ | | |
| ddd ---------->| self ---/
|______| |_______|
- Given axol app:
name="Alice"
action: name=@nick
action(nick="Mad")
- the next boxes are created:
/--\
| |
____________v_ |
| | |
| $local -----/
| $import ----> : ...
| name -------> "Alice"
| action -----> : name=@nick
|____________|
^
| /--\
/--/ | |
| ____________v_ |
| | | |
| | $local -----/
\--- $outer |
\--- $caller | _________
| $args --------------->| |
| @nick ------> "Mad" <--- nick |
| name ----------^ |_______|
|____________|
- Each time axol app is executed,
- or a lib is imported,
- or an action is called,
- a new local scope is auto-created.
- Local scope is a box with:
- Custom local names created by the app/lib/action.
- Auto-created local names.
- Name auto-created in any scope is:
$local
- points to this local scope box itself.
- Name auto-created in scopes of app and lib is:
- $import - action to import other libs.
- Names auto-created in action scope are:
$outer
- points to the scope box where this action was created.$caller
- points to the scope box where this action was called.$args
- points to a box with arguments passed by the caller to this action.@0
- shortcut for$args.0
- the first positional argument.@1
- shortcut for$args.1
, and so on.@aaa
- shortcut for$args.aaa
- named argumentaaa="bbb"
- See also: env, cli_args, pos_args, nam_args.
- All names starting with
$
or@
are reserved for axol to avoid collision with custom names created by user.
aaa="bbb"
- Create or update name
aaa
in local scope. - Make it point to value
"bbb"
. - See also: up finds and updates name in local or outer scopes.
aaa
- Find name
aaa
in local scope. - If found, then return a value it points to.
- Else try the same in
$outer
scope, else in its$outer
, and so on.- This step is not applied for auto-created names starting with
$
or@
- they are always local.
- This step is not applied for auto-created names starting with
- Else throw "Name
aaa
is not found."
: bbb
- Get a new action.
- When this action is called, it will execute the code
bbb
inside of this action. - This trivial code
bbb
will return value of namebbb
visible from inside of this action, even if the caller of this action does not see thisbbb
. - Action is known in other languages as closure, lambda, function, procedure, method, etc.
aaa: bbb
- Create or update name
aaa
in local scope. - Make it point to a new action.
- This is a name=value composed with action, but:
- Cute
aaa: bbb
syntax should always be used instead ofaaa=: bbb
composed fromaaa=
and: bbb
- Cute
:
# Multiple
# lines here.
bbb
- Get a new action that will execute multiple indented lines and return value of
bbb
. - One indentation level should contain exactly two spaces, no tabs.
aaa:
# Multiple
# lines here.
bbb
- Create or update name
aaa
in local scope. - Make it point to a new multiline-action.
- This is a name=value composed with multiline-action, but:
- Cute
aaa: multiline_bbb
syntax should always be used instead ofaaa=: multiline_bbb
composed fromaaa=
and: multiline_bbb
- Cute
Given aaa: @0
result=aaa("bbb")
means:
- Get the action
: @0
pointed by nameaaa
. - Create its local scope box with few names inside, including:
$args
pointing to a new box with the only name0
inside, pointing to the value"bbb"
passed as the only positional argument.@0
being a shortcut for$args.0
hence pointing to the same value"bbb"
.
- Run the code of this trivial action
: @0
- Get the value
"bbb"
of the name@0
- Return this value to the caller of this action.
- Get the value
- As in name=value, create or update name
result
in local scope of the caller, make this name point to returned value"bbb"
. - See also: inline-call, newline-call, multiline-call, pipeline-call, box $call.
aaa(bbb "ccc" ddd="eee" fff: ggg)
- Get result of action
aaa
called with arguments:- name -
aaa(bbb)
- Value of name
bbb
is passed as a positional argument.
- Value of name
- value -
aaa("ccc")
- Value
"ccc"
is passed as a positional argument.
- Value
- action -
aaa(: hhh)
- Action
: hhh
is passed as a positional argument. - Supported only when it is the only argument - as otherwise it would be easy to confuse
aaa(bbb : hhh)
withaaa(bbb: hhh)
- Action
- multiline-action
- Not supported, use multiline-call.
- name=value -
aaa(ddd="eee")
- Passed as a named argument
ddd
with value being"eee"
.
- Passed as a named argument
- name: action -
aaa(fff: ggg)
- Passed as a named argument
fff
with value being an action: ggg
- Passed as a named argument
- name: multiline-action
- Not supported, use multiline-call.
- Without arguments -
aaa()
- name -
- If an inline-call starts on its own line and has arguments, then it should be converted to a newline-call by deleting the parentheses
()
for readability.
aaa bbb "ccc" ddd="eee" fff: ggg
- The same as inline-call, but:
- It should be on its own line in app/lib/action, as otherwise
aaa
andbbb
become arguments as inprint aaa bbb "ccc"
- Passing action without name: action is not supported, as
aaa : hhh
can be easily confused withaaa: hhh
- "Without arguments" case is not supported, as it would be the same as just getting a value of name
aaa
. - It can return result only when it is the only or the last line of an action to avoid confusing
result=aaa bbb=ccc
:
- It should be on its own line in app/lib/action, as otherwise
get_result: aaa bbb "ccc" ddd="eee"
get_result:
# Multiple
# lines here.
aaa bbb "ccc" ddd="eee"
result=get_result()
aaa bbb "ccc" ddd="eee" fff: ggg
: hhh
:
iii
jjj
kkk:
lll
mmm
nnn ooo "ppp" qqq="rrr" sss: ttt
: uuu
- The same as newline-call, but:
- All "not supported" and "supported only when" restrictions of inline-call and newline-call (except "Without arguments") are removed in multiline-call for indented arguments, each on its own line(s).
- One indentation level should contain exactly two spaces, no tabs.
- A multiline-call with all arguments indented can return result via name=value e.g:
result=aaa
bbb
"ccc"
ddd="eee"
fff: ggg
: hhh
a0|aaa(a1 a2)
a0|aaa a1 a2
a0|aaa
a1
a2
- The inline-call, newline-call, and multiline-call above have their first positional argument
a0
passed through the pipe|
- They all are equal to
aaa(a0 a1 a2)
- It makes naturally infix actions like
minus
more readable innnn|minus(1)
compared tominus(nnn 1)
. - It avoids need in operator precedence that can be confused with different operator precedence from another programming language:
- What
aaa / bbb % ccc
means?(aaa / bbb) % ccc
?aaa / (bbb % ccc)
?- Are you sure?
- With axol you are sure:
aaa|div(bbb|mod(ccc))
meansaaa / (bbb % ccc)
aaa|div(bbb)|mod(ccc)
means(aaa / bbb) % ccc
- What
- It enables concise left-to-right pipelines like
items|map(to: "{@name}={@value}")|sorted|join("\n")
- Note that parentheses
()
are omitted in|sorted
because it is definitely a pipeline-call, which cannot be confused with just getting a value of namesorted
. - For the same reason a pipeline can be split to multiple lines with exactly two-space indentation before the pipe
|
like this:
items
|map(to: "{@name}={@value}")
|sorted
|join("\n")
- Given
aaa
being a box with"bbb" ccc="ddd"
inside:
eee("fff" ggg="hhh" aaa...)
# is the same as:
eee("fff" "bbb" ggg="hhh" ccc="ddd")
- While:
eee(aaa... "fff" ggg="hhh")
# is the same as:
eee("bbb" "fff" ccc="ddd" ggg="hhh")
- So the ellipsis
...
unboxes whatever is inside of the box, before or after other arguments. - Multiple boxes can be unboxed in the same call.
- This works with any call type, not just inline-call.
aaa=$import("bbb ccc=ddd" file="../eee.axol")
-
If
file
is not passed, thenfile
is.axol/main.axol
- main features of axol standard library. -
If
file
starts with.axol/
- Then find it in:
- The same directory as the importer.
- Else in importer's parent directory.
- Else in one more parent directory, and so on.
- Else in OS-specific user home directory like
~
- Else in OS-specific shared directory like
/usr/local/lib
- Else throw "File
.axol/eee.axol
is not found."
- Else
file
path should start with either./
or../
to clearly be relative to importer's directory.
- Then find it in:
-
If the absolute path to the
file
is not in the import cache box yet, then:- Add this path to this cache as a name, pointing to a new box.
- Run the
file
passing this box as its local scope.
-
For each positional argument like
"bbb ccc=ddd"
passed:- Create or update names
bbb
andccc
in local scope of the caller. - Make them point to the values which names
bbb
andddd
point to in the cached scope box of thefile
:
- Create or update names
# lib.axol
bbb="fff"
ddd="ggg"
# app.axol
$import "bbb ccc=ddd" file="./lib.axol"
print bbb ccc # fff ggg
-
Return the cached scope box of the
file
to the caller, e.g.axol=$import()
will create a nameaxol
pointing to a box with main features of axol standard library. -
$import
is one of very few auto-created names. All custom names should be either imported from axol standard library or other libs or created by an app/lib/action:
$import "each print"
py=$import
file=".axol/python.axol"
"all any min max"
"sorted sum zip"
os=py.__import__("os")
os.listdir()
|sorted
|each do: print @value
- Lib
.axol/python.axol
contains axol bindings to all names available in python language, e.g. its built-in functions. python.__import__
can import any installed python packages and packages from its standard library.- That's how small axol regrows missing body parts!
$import "box print"
aaa=box(bbb "ccc" ddd="eee" fff: ggg)
print aaa.1 # ccc
print aaa.ddd # eee
aaa.fff()
aaa.hhh="iii"
print aaa.hhh # iii
- Create a box with passed args.
- They can be get and set using either dot
.
or actions - see get, set, etc. - See box-concept and inline-call.
- Implementation:
box: $args
$import "print"
print()
# (newline)
print "hi" # hi
# (newline)
print "yes/no: " end="" # yes/no: (no newline)
print "aaa bbb" "ccc" # aaa bbb ccc
print "aaa bbb" "ccc" sep="" # aaa bbbccc
print null false true "true" -3.14 # null false true true -3.14
print box(null false true "true" -3.14 aaa="bbb" ccc: ddd)
# null
# false
# true
# "true"
# -3.14
# aaa="bbb"
# ccc: ddd
print "failed" to=2 # failed
# (to stderr)
result=print("aaa" "bbb" to=null)
print result # aaa bbb
print aaa bbb sep=" " end="\n" to=1
- Join positional args to the resulting string using
sep
separator, default is one space.- Printing a
box
prints its items, each on its own line(s).
- Printing a
- Append the
end
, default is a newline. - If
to
is notnull
: print the resulting string to file descriptorto
, default is 1 akastdout
. - Return the resulting string.
$import "input"
aaa=input(end="\n")
- Input a string from stdin.
- End the input on EOF or when the
end
is consumed, newline by default. - Return the result excluding the
end
.
- Given command line:
AAA=bbb ccc=ddd path/to/app.axol
env
points to a box with environment variables:
env=box
AAA="bbb"
ccc="ddd"
# More inherited env vars.
- Usage:
$import "env print"
print env.AAA # bbb
- Given command line:
path/to/app.axol aaa "bbb ccc" -ddd --eee=fff
cli_args
points to a box with command line arguments:
cli_args=box
"path/to/app.axol"
"aaa"
"bbb ccc"
"-ddd"
"--eee=fff"
eee="fff"
- Usage:
$import "cli_args print"
print cli_args.0 # path/to/app.axol
print cli_args.1 # aaa
print cli_args.eee # fff
$import "nam_args pos_args print"
aaa:
pos_args "bbb ccc" ddd="eee" fff="ggg"
nam_args "hhh iii" jjj="kkk" lll="mmm"
print bbb ccc ddd fff
print hhh iii jjj lll
aaa
"nnn" "ooo" "ppp"
hhh="qqq" iii="rrr" lll="sss"
# nnn ooo ppp ggg
# qqq rrr kkk sss
pos_args
:- Set local name
bbb
to point to positional arg@0
. ccc
- to@1
.ddd
- to@2
, etc.
- Set local name
nam_args
:- Set local name
hhh
to point to named arg@hhh
. iii
- to@iii
.jjj
- to@jjj
, etc.
- Set local name
- For both
pos_args
andnam_args
:- Names passed in the positional args are required, e.g.
bbb
andhhh
. - Names passed as named args are optional with given default values, e.g.
fff="ggg"
andjjj="kkk"
.
- Names passed in the positional args are required, e.g.
$import "bool box"
bool(null)
bool(false)
bool(0)
bool("")
bool(box())
-
All
bool
-s above returnfalse
. -
bool
of anything else istrue
. -
Each bool comparison below is
true
:
$import
"eq ne lt gt lte gte"
"not and or xor"
"aaa"|eq("aaa") # EQual
"aaa"|ne("bbb") # Not Equal
"aaa"|lt("bbb") # Less Than
"bbb"|gt("aaa") # Greater Than
false|lte(true) # Less Than or Equal
true|gte(false) # Greater Than or Equal
not(false)|eq(true)
true|and(false)|eq(false)
true|or(false)|eq(true)
true|xor(true)|eq(false)
- Each comparison below is
true
:
$import "action bool box number is string"
null|is(null)
false|is(false)
true|is(not(false))
false|is(a=bool)
true|is(a=bool)
-3.14|is(a=number)
"-3.14"|is(a=string)
aaa: "bbb"
aaa|is(a=action)
box(ccc="ddd")|is(a=box)
box(ccc="ddd")
|is(box(ccc="ddd"))
|is(false)
- If only positional args
@0
and@1
are passed, then:- If they point to the same address in memory, then return
true
, else returnfalse
.
- If they point to the same address in memory, then return
- Else if positional arg
@0
and named arg@a
are passed, then:- If
@0
is created by an action@a
, then returntrue
, else returnfalse
.
- If
- Else throw "Unexpected args".
- Each line below is
true
:
$import
"plus minus mul div"
"pow mod abs eq"
2|plus(3)|eq(5) # 2 + 3 == 5
5|minus(3)|eq(2) # 5 - 3 == 2
2|mul(3)|eq(6) # 2 * 3 == 6
6|div(3)|eq(2) # 6 / 3 == 2
"2"|plus("3")|eq("23")
"2"|mul(3)|eq("222")
box("aaa" bbb="ccc" ddd="eee")
|plus(box("fff" bbb="ggg" hhh="iii"))
# aaa
# fff
# bbb="ggg"
# ddd="eee"
# hhh="iii"
box("aaa" "bbb" ccc="ddd")|mul(2)
# aaa
# bbb
# aaa
# bbb
# ccc="ddd"
2|pow(8)|eq(256) # POWer, ^, **
-2|abs|eq(2) # ABSolute value, |x|
256|pow(1|div(8))|minus(2)|abs|lt(0.001)
# 256^(1/8) is a float close to 2
5|mod(2)|eq(1) # MODulo, %
$import "box print set"
aaa=box()
aaa|set "bbb" "ccc"
print aaa # bbb="ccc"
- The same as setting
aaa.bbb="ccc"
using dot, butname
is passed as a positional argument@1
to support dynamic naming, e.g. in a loop.
$import "box get print"
aaa=box(bbb="ccc")
print aaa|get("bbb") # ccc
print aaa|get("ddd" default=null) # null
-
The same as getting
aaa.bbb
using dot, but:name
"bbb" is passed as a positional argument@1
to support dynamic naming, e.g. in a loop.
-
If name "ddd" is not found, then:
-
If bool comparisons
lt gt lte gte
are used as named arguments instead of the positional argument@1
:- Then return a new box with positional values (from original box
@0
) having indices satisfying all comparisons:
- Then return a new box with positional values (from original box
$import "box get print"
aaa=box("bbb" "ccc" "ddd" "eee" fff="ggg")
print aaa|get(lt=2)
# "bbb"
# "ccc"
print aaa|get(gte=1 lte=2)
# "ccc"
# "ddd"
print aaa|get(gt=0)
# "ccc"
# "ddd"
# "eee"
- Both dot
.
and get can be used to get substrings too:
import "get print"
aaa="string"
print aaa.0 # s
print aaa.1 # t
print aaa|get(2) # r
print aaa|get(gte=2 lte=3) # ri
print aaa|get(gt=3) # ng
$import "print up"
aaa="bbb"
ccc:
aaa="ddd"
print aaa # ddd
ccc()
print aaa # bbb
ccc:
up aaa="ddd"
print name # ddd
ccc()
print aaa # ddd
up eee="fff"
# Error: Name `eee` is not found.
ggg=box(hhh="iii" jjj: kkk)
ggg|up hhh="lll" jjj: mmm
print ggg.hhh # lll
ggg|up aaa="nnn"
# Error: Name `aaa` is not found.
- While name=value, name: action, and name: multiline-action create or update names in local scope only,
up
updates names (never creates) in the next way:- If a positional argument
@0
is passed:- Then set internal name
where
to this box:@0
. - Else set it to the local scope of the caller:
$caller
- Then set internal name
- For each name=value argument passed:
- If a positional argument
$import "add box print"
aaa=box("ccc" yyy="zzz")
aaa|add "ddd" "eee"
aaa|add "aaa" "bbb" at=0
print aaa
# "aaa"
# "bbb"
# "ccc"
# "ddd"
# "eee"
# yyy="zzz"
aaa=box("ccc" yyy="zzz")
aaa|add flat=true
"ddd"
box("eee" "fff")
box(ggg="hhh")
print aaa
# "ccc"
# "ddd"
# "eee"
# "fff"
# ggg="hhh"
# yyy="zzz"
aaa|add bbb ccc at=-1 flat=false
- Add values passed as positional arguments to the box passed as
@0
:- If
at
index is passed:- Then insert values at given index.
- Else append values after existing positional values in the box.
- If
flat
is passed and istrue
:- Then unpack all boxes passed as positional args, adding their contents to the target box.
- Else add such boxes as is, without unpacking.
- If
$import "box del print"
aaa=box("bbb" ccc="ddd")
print aaa|del(0) # bbb
print aaa
# ccc="ddd"
print aaa|del("ccc") # ddd
print aaa
#
print aaa|del("ccc" default=null) # null
- The same as get, but also deletes the name passed as
@1
from the box passed as@0
. - If bool comparisons are used instead of
@1
, then get and delete matching indices:
$import "box del print"
aaa=box("bbb" "ccc" "ddd" "eee" fff="ggg")
print aaa|del(gte=2)
# "ddd"
# "eee"
print aaa
# "bbb"
# "ccc"
# fff="ggg"
$import "box names print"
aaa=box("bbb" "ccc" ddd="eee")
print aaa|names
# 0
# 1
# "ddd"
print $local|names
# "$import"
# "$local"
# "aaa"
# "box"
# "names"
# "print"
- Get a new box with values being names from the box passed as
@0
$import "box print values"
aaa=box("bbb" "ccc" ddd="eee")
print aaa|values
# "bbb"
# "ccc"
# "eee"
- Get a new box with values from the box passed as
@0
$import "box join print"
aaa=box("bbb" "ccc" ddd="eee")
print aaa|join(",") # bbb,ccc,eee
- Get a string created by joining values from the box passed as
@0
using separator passed as@1
.
$import "print split"
print "aaa,bbb,ccc"|split(",")
# "aaa"
# "bbb"
# "ccc"
- Get a new box with values split from the string passed as
@0
using separator passed as@1
.
$import "box length print"
print "string"|length # 6
aaa=box("bbb" "ccc" ddd="eee")
print aaa|length # 2, not 3.
- If
@0
is a string: return its length in characters. - Else if
@0
is a box: return the length of its positional side, ignoringname="value"
pairs. - Else throw "Value
{@0}
has no length."
$import "box find print"
print "aaabbbccc"|find("bbb") # 3
print "aaabbbccc"|find("ddd") # null
aaa=box("bbb" "ccc" ddd="eee")
print aaa|find("bbb") # 0
print aaa|find("ddd") # null
print aaa|find("eee") # ddd
- If each value passed is a string:
- If
@1
is found in@0
:- Then return the first matching index.
- Else return
null
.
- If
- Else if
@0
is a box:- If
@1
is found in the values of the box@0
:- Then return the first matching name.
- Else return
null
.
- If
- Else throw "Presence of
{@1}
in{@0}
cannot be checked."
$import "box in names print"
print "bbb"|in("aaabbbccc") # true
print "ddd"|in("aaabbbccc") # false
aaa=box("bbb" "ccc" ddd="eee")
print "bbb"|in(aaa) # true
print "ddd"|in(aaa) # false
print "ddd"|in(aaa|names) # true
print "eee"|in(aaa) # true
- The same as
@1|find(@0)|ne(null)
- See find.
$import "if"
if aaa then: bbb
else: ccc
if aaa
then:
bbb
ddd
else:
ccc
eee
result=if
aaa
then: bbb
else: ccc
- If
bool
of conditionaaa
istrue
andthen
action is passed, then call it. - If
bool
of conditionaaa
isfalse
andelse
action is passed, then call it. - Return result of the action called.
$import "print then"
print aaa|then(bbb else=ccc)
- If
bool
of conditionaaa
istrue
:- Then return
bbb
. - Else return
ccc
.
- Then return
- Unlike short-circuit evaluation of actions in if, here both branches are evaluated instantly as simple values.
$import "elif"
elif
aaa
: bbb
ccc
: ddd
eee
: fff
else: ggg
- The same as few nested if-s:
$import "if"
if aaa
then: bbb
else:
if ccc
then: ddd
else:
if eee
then: fff
else: ggg
$import "case"
case aaa
"bbb"
: ccc
"ddd"
: eee
"fff"
: ggg
else: hhh
- The same as this elif:
$import "elif"
elif
aaa|eq("bbb")
: ccc
aaa|eq("ddd")
: eee
aaa|eq("fff")
: ggg
else: hhh
$import "loop"
loop
while: aaa
do: bbb
until: ccc
loop while: aaa
do: bbb
- Set name
do_result
in the local scope of thisloop
call to point tonull
. - Repeat the next steps:
- If
while
action is passed, then:- Call it.
- If
bool
of its result isfalse
, then:- Break the loop.
up do_result=do()
- Call the
do
action. - Update
do_result
name to point to the result ofdo
action.
- Call the
- If
until
action is passed, then:- Call it.
- If
bool
of its result istrue
, then:- Break the loop.
- If
- Return the value of
do_result
.
$import "box each print"
aaa=box("bbb" "ccc" ddd="eee")
aaa|each do: print @name @value
# 0 bbb
# 1 ccc
# ddd eee
- For each
name=value
in the box passed as@0
:do_result=do(name=name value=value)
.
- Return the value of
do_result
. - A string is treated as a box with characters:
$import "each print"
"str"|each do: print @name @value
# 0 s
# 1 t
# 2 r
$import "box map print"
aaa=box("bbb" "ccc" ddd="eee")
print aaa|map(to: "{@name}={@value}")
# "0=bbb"
# "1=ccc"
# "ddd=eee"
print aaa|map(
to: $value
if: $name|ne(1)
)
# "bbb"
# "eee"
print aaa|map(flat=true to: $item)
# "bbb"
# "ccc"
# ddd="eee"
aaa|map
to: bbb
if: ccc
flat=false
- Create
map_result=box()
- For each
name=value
in the box passed as@0
:- Create
item=box()
item|set name value
- If
if
action is passed, then:- Call
if_result=if(name=name value=value item=item)
- If
bool
ofif_result
is false, then continue from the next iteration of the loop.
- Call
- Call
to_result=to(name=name value=value item=item)
map_result|add(to_result flat=flat)
- See add.
- Create
- Return
map_result
. - A string is treated as a box with characters:
$import "map print"
print "str"|map(flat=true to: $item)
# 0="s'
# 1="t"
# 2="r"
$import "box print"
aaa=box($call: "bbb")
print aaa
# $call: "bbb"
print aaa() # bbb
- Name
$call
is not auto-created, but it has a reserved meaning. - When a box is called, its
$call
action is called instead. - Else throw "Cannot call: neither an action, nor a box with
$call
action."
$import "catch throw"
aaa=null
bbb=catch
do:
up aaa="ccc"
throw "ddd" eee="fff"
up aaa="ggg"
finally:
print "always"
# always
print aaa # ccc
if bbb
then:
print bbb
# ddd
# eee="fff"
# $throw=box
# file="app.axol"
# line=7
# column=5
throw bbb
# Uncaught:
# ddd
# eee="fff"
# $throw=box
# file="app.axol"
# line=7
# column=5
- It
throw
is called:- If its only positional argument is an already thrown box (contains name
$throw
):- Then reuse this thrown box as is.
- Else create a new thrown box from all positional args, named args, and reserved name
$throw
pointing to a box with location of this throw (file, line, column).
- Find the nearest
catch
that called itsdo
action being a$caller
(of$caller
...) of thisthrow
. - If such
catch
is found:- Then:
- If this
catch
hasfinally
action, then call it. - Return the thrown box instantly from this
catch
.
- If this
- Else (no
catch
found), end the whole app instantly withUncaught: {thrown}
printed to stderr and exit code 1.
- Then:
- If its only positional argument is an already thrown box (contains name
- It no
throw
was called indo
action ofcatch
, then:- If
catch
hasfinally
action, then call it. - Return
null
fromcatch
.
- If
$import "break if input loop print"
loop
do:
line=input()
if line|eq("")
then: break()
print(line)
# Implementation:
break: throw break
- Throw itself.
- If loop or each catches a box where
.0
isbreak
:- Then it returns its
do_result
instantly.
- Then it returns its
- If map catches a
break
:- Then it returns its
map_result
instantly.
- Then it returns its
$import "continue if input loop print"
loop
do:
line=input()
if line|eq("")
then: continue()
print(line)
# Implementation:
continue: throw continue
- Throw itself.
- If loop, each, or map catches a box where
.0
iscontinue
:- Then it stops current iteration instantly and continues from the next iteration.
- Work on the drafts left.
- Add axol to the next highlighters to simplify the reviews:
- Rouge for our GitHub Pages website.
- github-linguist for GitHub main UI and for grammars used by popular code editors.
- Reviews and fixes of this draft specification.
- Implement it.
Thank you for reading.
Please post an issue or idea or contribute otherwise: