359 lines
11 KiB
Plaintext
359 lines
11 KiB
Plaintext
#!/usr/bin/env nomsu -V7.0.0
|
|
### How do I...
|
|
### Write a comment? Put a # and go till the end of the line
|
|
### How do I write a multi-line comment?
|
|
After a comment line, any indented text
|
|
is considered part of the comment
|
|
(including any deeper-level indented text)
|
|
The comment ends when the indentation ends
|
|
|
|
### How do I import a libarary?
|
|
use "consolecolor"
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
### How do I print stuff?
|
|
say "Hello world!"
|
|
|
|
### How do I set a variable?
|
|
### Variables have "$" prefix:
|
|
$foobar = 1
|
|
$text = "Hello world"
|
|
|
|
### Expressions that are more than just literal values require parentheses:
|
|
$foobar = (2 + 3)
|
|
$one_two = 12
|
|
say $one_two
|
|
|
|
### How do I modify a variable?
|
|
$foobar = ($foobar + 1)
|
|
|
|
### Or, as a shorthand, you can do this to increment a variable:
|
|
$foobar += 1
|
|
|
|
### How do I define a multi-line string?
|
|
### In Nomsu, the name "text" is used, rather than "string", and multi-line text looks like:
|
|
$multi_text = ("
|
|
Start with a quotation mark, then put indented lines below it. The indented
|
|
lines will not include the indentation, except when the lines are indented
|
|
more than 4 spaces relative to the original quote mark.
|
|
<- E.g. the 2 spaces here will be included as part of the text.
|
|
But this line will have no leading spaces.
|
|
|
|
The text will continue until a closing quotation at the end of the text's
|
|
indentation level.
|
|
")
|
|
|
|
### How do I put values inside text? (AKA string formatting, string interpolation)
|
|
say ("
|
|
Text can contain a backslash followed by a variable, list, dict, or parenthesized
|
|
expression. This escaped value will be converted to readable text, like so:
|
|
The value of $foobar is \$foobar, isn't that nice?
|
|
These are some numbers: \[1, 2, 3]
|
|
The sum of 2 and 4 is \(2 + 4).
|
|
|
|
A backslash not followed by any of these, and not at the end of a line
|
|
like this: \\ will just be treated as a backslash.
|
|
|
|
Or, two backlashes will be treated as a single backslash, no matter what follows,
|
|
like this: \\$foobar <- won't insert any values
|
|
|
|
If you need to split a long line without inserting a newline, you can end a line with backslash \
|
|
..and start the next line with two periods, like that.
|
|
|
|
Similarly, you can put a long interpolated indented value like: \(
|
|
1000 + 2000 + 3000 + 4000 + 5000 + 6000 + 7000 + 8000 + 9000
|
|
) between a backslash and two periods.
|
|
")
|
|
say "Single-line text can contain escape sequences like \", \\, \000, and \n"
|
|
|
|
### How do I define a list?
|
|
$my_list = ["first", "second", "third", 4]
|
|
|
|
### Really long lists can use [..] followed by a bunch of indented values delimited
|
|
by commas and/or newlines
|
|
$my_really_long_list = [
|
|
10000, 20000, 30000, 40000, 50000, 60000, 70000, 80000, 90000, 100000, 110000
|
|
120000, 130000, 140000, 150000, 160000, 170000
|
|
]
|
|
|
|
### How do I use a list?
|
|
### Lists are 1-indexed because they're implemented as Lua tables, so this prints "first"
|
|
say $my_list.1
|
|
|
|
### List entries can be modified like this:
|
|
$my_list.1 = "ONE!!!"
|
|
|
|
### Or appended to/removed from:
|
|
$my_list, add "extra item"
|
|
$my_list, pop
|
|
|
|
### How do I define a dictionary/hash map?
|
|
One-word text keys don't need quotes, otherwise the key is an expression.
|
|
If the expression is more complex than a literal, it needs parentheses:
|
|
$my_dict = {.x = 101, .y = 2, ."my value" = 99, .653 = 292, .(5 + 6) = 11}
|
|
|
|
### How do I use a dict?
|
|
### Dicts are also implemented as Lua tables, so they're accessed and modified the same way as lists
|
|
say $my_dict.x
|
|
say $my_dict."how many bottles"
|
|
say $my_dict.653
|
|
$my_dict.x = 9999
|
|
|
|
### How do I do conditional branching?
|
|
if (1 < 10):
|
|
say "1 is indeed < 10"
|
|
|
|
if (1 > 10):
|
|
say "this won't print"
|
|
..else:
|
|
say "this will print"
|
|
|
|
### There's no "elseif", so for longer conditionals, a "when" branch is the best option
|
|
when:
|
|
(3 > 3):
|
|
say "this won't print"
|
|
|
|
(3 > 6) (3 > 5) (3 > 4):
|
|
say "this won't print because none of the conditions on the line above are true"
|
|
|
|
(3 > 2):
|
|
say "this will print"
|
|
|
|
else:
|
|
say "this is the default case"
|
|
|
|
### How do I do a switch statement?
|
|
if (1 + 2) is:
|
|
0 1:
|
|
say "this won't print"
|
|
|
|
2 3:
|
|
say "this will print"
|
|
|
|
else:
|
|
say "this won't print"
|
|
|
|
### How do I loop over a list (a foreach loop)?
|
|
$list = [1, 2, 3]
|
|
for $x in $list:
|
|
say "For $x loop #\$x"
|
|
|
|
### How do I loop over a number range?
|
|
### This is inclusive, so it will loop over 1,2, and 3
|
|
for $i in (1 to 3):
|
|
say "For $i in 1 to 3 loop #\$i"
|
|
|
|
### This will print 0,2, and 4
|
|
for $even in (0 to 5 by 2):
|
|
say "Even #\$even"
|
|
|
|
for $backwards in (3 to 1 by -1):
|
|
say "Backwards #\$backwards"
|
|
|
|
### How do I do a 'while' loop?
|
|
$x = 1
|
|
repeat while ($x <= 3):
|
|
say "repeat while loop #\$x"
|
|
$x += 1
|
|
$x = 1
|
|
repeat until ($x > 3):
|
|
say "repeat until loop #\$x"
|
|
$x += 1
|
|
|
|
### How do I do an infinite loop?
|
|
$x = 1
|
|
repeat:
|
|
say "repeat loop #\$x"
|
|
$x += 1
|
|
if ($x > 3): stop
|
|
|
|
### How do I do a 'goto'?
|
|
do:
|
|
$x = 1
|
|
--- (my loop) ---
|
|
say "GOTO loop #\$x"
|
|
$x += 1
|
|
if ($x <= 3):
|
|
go to (my loop)
|
|
say "finished going to"
|
|
|
|
### How do I define a function/method/procedure?
|
|
### In nomsu, they're called "action"s, and they can be declared like this:
|
|
(say both $first and also $second) means:
|
|
say $first
|
|
say $second
|
|
|
|
### Actions can have parts of the action's name spread throughout.
|
|
Everything that's not a literal value is treated as part of the action's name
|
|
say both "Hello" and also "world!"
|
|
|
|
### Actions can use "return" to return a value early
|
|
(first fibonacci above $n) means:
|
|
$f1 = 0
|
|
$f2 = 1
|
|
repeat:
|
|
$tmp = ($f1 + $f2)
|
|
$f1 = $f2
|
|
$f2 = $tmp
|
|
if ($f2 > $n):
|
|
return $f2
|
|
|
|
say (first fibonacci above 10)
|
|
|
|
### Actions can have aliases, which may or may not have the arguments in different order
|
|
[
|
|
I hate $worse_things more than $better_things
|
|
I think $worse_things are worse than $better_things
|
|
I like $better_things more than $worse_things
|
|
] all mean:
|
|
say "\($better_things, capitalized) rule and \$worse_things drool!"
|
|
I like "dogs" more than "cats"
|
|
I think "chihuahuas" are worse than "corgis"
|
|
|
|
### Actions can even start with a parameter
|
|
($what_she_said is what she said) means:
|
|
say $what_she_said
|
|
say "-- she said"
|
|
"Howdy pardner" is what she said
|
|
|
|
### The language only reserves []{}().,:;$\ as special characters, so actions
|
|
and variables can use symbols freely:
|
|
(>> $(∐) @&' -->< $ @&_~-^ ⊗⊞√ $1 !) means:
|
|
say $(∐)
|
|
say $
|
|
say $1
|
|
|
|
>> "wow" @&' -->< "so flexible!" @&_~-^ ⊗⊞√
|
|
.."even numbers can be variables!" !
|
|
|
|
### You can also use unicode in variable and action names:
|
|
$こんにちは = "こんにちは"
|
|
($ と言う) means "\($)世界"
|
|
say ($こんにちは と言う)
|
|
|
|
### Math and logic operations are just treated the same as actions in the syntax
|
|
say (2 + 3)
|
|
|
|
### So you can define your own operators, although they will need to be parenthesized to
|
|
play nicely with other operators
|
|
($a ++ $b) means (2 * ($a + $b))
|
|
say (1 ++ (2 * 3))
|
|
|
|
### How do I do grouping?
|
|
### Expressions can be grouped by enclosing parentheses:
|
|
say (2 + 3)
|
|
|
|
### Or by (..) followed by an indented region
|
|
say (2 + 3)
|
|
|
|
### If you need to keep going after an indented region, you can start the next line with ".."
|
|
say both "Very very very very long first argument that needs its own line"
|
|
..and also "short second arg"
|
|
(my favorite number) means (21 + 2)
|
|
|
|
### This can be nested:
|
|
say both (my favorite number) and also "foo"
|
|
|
|
### Object-oriented programming:
|
|
### How do I define a class?
|
|
(a Vec) is (a thing) with [$x, $y]:
|
|
($self, +$other) means (Vec ($x + $other.x) ($y + $other.y))
|
|
($self, length) means (sqrt ($x * $x + $y * $y))
|
|
$(a Vec).is_a_vec = (yes)
|
|
(Vec $x $y) means (a Vec {.x = $x, .y = $y})
|
|
$v1 = (Vec 1 2)
|
|
assume ($v1 + $v1) == (Vec 2 4)
|
|
say $v1
|
|
|
|
### Macros:
|
|
### The "lua>" and "=lua" macros can be used to write raw lua code:
|
|
(say the time) means:
|
|
lua> "io.write(\"The OS time is: \", os.time(), \"\\n\");"
|
|
say the time
|
|
say "Math expression result is: \(=lua "(1 + 2*3 + 3*4)^2 % 5")"
|
|
|
|
### Variables can be accessed via \$var
|
|
(square root of $n) means (=lua "math.sqrt(\$n)")
|
|
say "The square root of 2 is \(square root of 2)"
|
|
|
|
### Macros can be defined to transform one bit of nomsu code into another using "parse $ as $":
|
|
(if $condition is untrue $body) parses as (if (not $condition) $body)
|
|
|
|
### Or to transform nomsu code into custom lua code using "compile $ to $"
|
|
(debug only $body) compiles to:
|
|
if $DEBUG_ENABLED:
|
|
return
|
|
Lua ("
|
|
-- Debug code:
|
|
\($body as lua)
|
|
")
|
|
..else:
|
|
return (Lua "-- (debug code removed for production)")
|
|
|
|
$DEBUG_ENABLED = (yes)
|
|
|
|
### Constants can be defined as macros
|
|
(TWENTY) parses as 20
|
|
|
|
### When they're invoked, they'll need parentheses just like a function call
|
|
(TWENTY ONE) parses as 21
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
### If you need to use compile-time actions in the same file that they're defined in, you
|
|
can add a line of tildes (3 or more), and the file will be split into chunks, and each
|
|
chunk will run before the next one compiles. (note that each chunk has its own scope)
|
|
if (1 > (TWENTY)) is untrue:
|
|
say "Nomsu parsing macros work!"
|
|
say "It looks like a keyword, but there's no magic here!"
|
|
|
|
debug only:
|
|
say "Lua compiling macros work!"
|
|
|
|
### How do I use an action as a value?
|
|
### Well... it's always *possible* to fall back to Lua behavior for something like this:
|
|
(best of $items according to $key_fn) means:
|
|
[$best, $best_key] = [nil, nil]
|
|
for $item in $items:
|
|
$key = ($key_fn $item)
|
|
if (($best == (nil)) or ($key > $best_key)):
|
|
[$best, $best_key] = [$item, $key]
|
|
|
|
return $best
|
|
|
|
### Function literals look like: $x -> ($x * $x)
|
|
say (best of [2, -3, 4, -8] according to ($x -> ($x * $x)))
|
|
|
|
### Or, you can surround an action with $(...) to refer to it:
|
|
($x squared) means ($x * $x)
|
|
say (best of [2, -3, 4, -8] according to $($ squared))
|
|
|
|
### However, nomsu was designed with flexible alternatives that are often better
|
|
than passing functions. For example, instead of calling a key function on
|
|
every item, you could instead define a macro that will inline an expression
|
|
to produce faster code:
|
|
(best of $items where $item has score $key_expr) parses as
|
|
result of:
|
|
[$best, $best_key] = [nil, nil]
|
|
for $item in $items:
|
|
$key = $key_expr
|
|
if (($best == (nil)) or ($key > $best_key)):
|
|
[$best, $best_key] = [$item, $key]
|
|
|
|
return $best
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
say (best of [2, -3, 4, -8] where $x has score ($x * $x))
|
|
|
|
### The line above expands to:
|
|
say
|
|
result of:
|
|
[$best, $best_key] = [nil, nil]
|
|
for $x in [2, -3, 4, -8]:
|
|
$key = ($x * $x)
|
|
if (($best == (nil)) or ($key > $best_key)):
|
|
[$best, $best_key] = [$x, $key]
|
|
|
|
return $best |