code / nomsu

Lines6.6K Lua5.1K PEG1.3K make117
2 others 83
Markdown60 Bourne Again Shell23
(354 lines)
1 #!/usr/bin/env nomsu -V7.0.0
2 ### How do I...
3 ### Write a comment? Put a # and go till the end of the line
4 ### How do I write a multi-line comment?
5 After a comment line, any indented text
6 is considered part of the comment
7 (including any deeper-level indented text)
8 The comment ends when the indentation ends
10 ### How do I import a libarary?
11 use "consolecolor"
13 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
15 ### How do I print stuff?
16 say "Hello world!"
18 ### How do I set a variable?
19 ### Variables have "$" prefix:
20 $foobar = 1
21 $text = "Hello world"
23 ### Expressions that are more than just literal values require parentheses:
24 $foobar = (2 + 3)
25 $one_two = 12
26 say $one_two
28 ### How do I modify a variable?
29 $foobar = ($foobar + 1)
31 ### Or, as a shorthand, you can do this to increment a variable:
32 $foobar += 1
34 ### How do I define a multi-line string?
35 ### In Nomsu, the name "text" is used, rather than "string", and multi-line text looks like:
36 $multi_text = ("
37 Start with a quotation mark, then put indented lines below it. The indented
38 lines will not include the indentation, except when the lines are indented
39 more than 4 spaces relative to the original quote mark.
40 <- E.g. the 2 spaces here will be included as part of the text.
41 But this line will have no leading spaces.
43 The text will continue until a closing quotation at the end of the text's
44 indentation level.
45 ")
47 ### How do I put values inside text? (AKA string formatting, string interpolation)
48 say ("
49 Text can contain a backslash followed by a variable, list, dict, or parenthesized
50 expression. This escaped value will be converted to readable text, like so:
51 The value of $foobar is \$foobar, isn't that nice?
52 These are some numbers: \[1, 2, 3]
53 The sum of 2 and 4 is \(2 + 4).
55 A backslash not followed by any of these, and not at the end of a line
56 like this: \\ will just be treated as a backslash.
58 Or, two backlashes will be treated as a single backslash, no matter what follows,
59 like this: \\$foobar <- won't insert any values
61 If you need to split a long line without inserting a newline, you can end a line with backslash \
62 ..and start the next line with two periods, like that.
64 Similarly, you can put a long interpolated indented value like: \(
65 1000 + 2000 + 3000 + 4000 + 5000 + 6000 + 7000 + 8000 + 9000
66 ) between a backslash and two periods.
67 ")
68 say "Single-line text can contain escape sequences like \", \\, \000, and \n"
70 ### How do I define a list?
71 $my_list = ["first", "second", "third", 4]
73 ### Really long lists can use [..] followed by a bunch of indented values delimited
74 by commas and/or newlines
75 $my_really_long_list = [
76 10000, 20000, 30000, 40000, 50000, 60000, 70000, 80000, 90000, 100000, 110000
77 120000, 130000, 140000, 150000, 160000, 170000
80 ### How do I use a list?
81 ### Lists are 1-indexed because they're implemented as Lua tables, so this prints "first"
82 say $my_list.1
84 ### List entries can be modified like this:
85 $my_list.1 = "ONE!!!"
87 ### Or appended to/removed from:
88 $my_list, add "extra item"
89 $my_list, pop
91 ### How do I define a dictionary/hash map?
92 One-word text keys don't need quotes, otherwise the key is an expression.
93 If the expression is more complex than a literal, it needs parentheses:
94 $my_dict = {.x = 101, .y = 2, ."my value" = 99, .653 = 292, .(5 + 6) = 11}
96 ### How do I use a dict?
97 ### Dicts are also implemented as Lua tables, so they're accessed and modified the same way as lists
98 say $my_dict.x
99 say $my_dict."how many bottles"
100 say $my_dict.653
101 $my_dict.x = 9999
103 ### How do I do conditional branching?
104 if (1 < 10):
105 say "1 is indeed < 10"
107 if (1 > 10):
108 say "this won't print"
109 ..else:
110 say "this will print"
112 ### There's no "elseif", so for longer conditionals, a "when" branch is the best option
113 when:
114 (3 > 3):
115 say "this won't print"
117 (3 > 6) (3 > 5) (3 > 4):
118 say "this won't print because none of the conditions on the line above are true"
120 (3 > 2):
121 say "this will print"
123 else:
124 say "this is the default case"
126 ### How do I do a switch statement?
127 if (1 + 2) is:
128 0 1:
129 say "this won't print"
131 2 3:
132 say "this will print"
134 else:
135 say "this won't print"
137 ### How do I loop over a list (a foreach loop)?
138 $list = [1, 2, 3]
139 for $x in $list:
140 say "For $x loop #\$x"
142 ### How do I loop over a number range?
143 ### This is inclusive, so it will loop over 1,2, and 3
144 for $i in (1 to 3):
145 say "For $i in 1 to 3 loop #\$i"
147 ### This will print 0,2, and 4
148 for $even in (0 to 5 by 2):
149 say "Even #\$even"
151 for $backwards in (3 to 1 by -1):
152 say "Backwards #\$backwards"
154 ### How do I do a 'while' loop?
155 $x = 1
156 repeat while ($x <= 3):
157 say "repeat while loop #\$x"
158 $x += 1
159 $x = 1
160 repeat until ($x > 3):
161 say "repeat until loop #\$x"
162 $x += 1
164 ### How do I do an infinite loop?
165 $x = 1
166 repeat:
167 say "repeat loop #\$x"
168 $x += 1
169 if ($x > 3): stop
171 ### How do I do a 'goto'?
172 do:
173 $x = 1
174 --- (my loop) ---
175 say "GOTO loop #\$x"
176 $x += 1
177 if ($x <= 3):
178 go to (my loop)
179 say "finished going to"
181 ### How do I define a function/method/procedure?
182 ### In nomsu, they're called "action"s, and they can be declared like this:
183 (say both $first and also $second) means:
184 say $first
185 say $second
187 ### Actions can have parts of the action's name spread throughout.
188 Everything that's not a literal value is treated as part of the action's name
189 say both "Hello" and also "world!"
191 ### Actions can use "return" to return a value early
192 (first fibonacci above $n) means:
193 $f1 = 0
194 $f2 = 1
195 repeat:
196 $tmp = ($f1 + $f2)
197 $f1 = $f2
198 $f2 = $tmp
199 if ($f2 > $n):
200 return $f2
202 say (first fibonacci above 10)
204 ### Actions can have aliases, which may or may not have the arguments in different order
206 I hate $worse_things more than $better_things
207 I think $worse_things are worse than $better_things
208 I like $better_things more than $worse_things
209 ] all mean:
210 say "\($better_things, capitalized) rule and \$worse_things drool!"
211 I like "dogs" more than "cats"
212 I think "chihuahuas" are worse than "corgis"
214 ### Actions can even start with a parameter
215 ($what_she_said is what she said) means:
216 say $what_she_said
217 say "-- she said"
218 "Howdy pardner" is what she said
220 ### The language only reserves []{}().,:;$\ as special characters, so actions
221 and variables can use symbols freely:
222 (>> $(∐) @&' -->< $ @&_~-^ βŠ—βŠžβˆš $1 !) means:
223 say $(∐)
224 say $
225 say $1
227 >> "wow" @&' -->< "so flexible!" @&_~-^ βŠ—βŠžβˆš
228 .."even numbers can be variables!" !
230 ### You can also use unicode in variable and action names:
231 $こんにけは = "こんにけは"
232 ($ と言う) means "\($)δΈ–η•Œ"
233 say ($こんにけは と言う)
235 ### Math and logic operations are just treated the same as actions in the syntax
236 say (2 + 3)
238 ### So you can define your own operators, although they will need to be parenthesized to
239 play nicely with other operators
240 ($a ++ $b) means (2 * ($a + $b))
241 say (1 ++ (2 * 3))
243 ### How do I do grouping?
244 ### Expressions can be grouped by enclosing parentheses:
245 say (2 + 3)
247 ### If you need to keep going after an indented region, you can start the next line with ".."
248 say both "Very very very very long first argument that needs its own line"
249 ..and also "short second arg"
250 (my favorite number) means (21 + 2)
252 ### This can be nested:
253 say both (my favorite number) and also "foo"
255 ### Object-oriented programming:
256 ### How do I define a class?
257 (a Vec) is (a thing) with [$x, $y]:
258 ($self, +$other) means (Vec ($x + $other.x) ($y + $other.y))
259 ($self, length) means (sqrt ($x * $x + $y * $y))
260 $(a Vec).is_a_vec = (yes)
261 (Vec $x $y) means (a Vec {.x = $x, .y = $y})
262 $v1 = (Vec 1 2)
263 assume ($v1 + $v1) == (Vec 2 4)
264 say $v1
266 ### Macros:
267 ### The "lua>" and "=lua" macros can be used to write raw lua code:
268 (say the time) means:
269 lua> "io.write(\"The OS time is: \", os.time(), \"\\n\");"
270 say the time
271 say "Math expression result is: \(=lua "(1 + 2*3 + 3*4)^2 % 5")"
273 ### Variables can be accessed via \$var
274 (square root of $n) means (=lua "math.sqrt(\$n)")
275 say "The square root of 2 is \(square root of 2)"
277 ### Macros can be defined to transform one bit of nomsu code into another using "parse $ as $":
278 (if $condition is untrue $body) parses as (if (not $condition) $body)
280 ### Or to transform nomsu code into custom lua code using "$ compiles to $"
281 (debug only $body) compiles to:
282 if $DEBUG_ENABLED:
283 return
284 Lua ("
285 -- Debug code:
286 \($body as lua)
288 ..else:
289 return (Lua "-- (debug code removed for production)")
291 $DEBUG_ENABLED = (yes)
293 ### Constants can be defined as macros
294 ### When they're invoked, they'll need parentheses just like a function call
295 (TWENTY) parses as 20
297 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
299 ### If you need to use compile-time actions in the same file that they're defined in, you
300 can add a line of tildes (3 or more), and the file will be split into chunks, and each
301 chunk will run before the next one compiles. (note that each chunk has its own scope)
302 if (1 > (TWENTY)) is untrue:
303 say "Nomsu parsing macros work!"
304 say "It looks like a keyword, but there's no magic here!"
306 debug only:
307 say "Lua compiling macros work!"
309 ### How do I use an action as a value?
310 ### Well... it's always *possible* to fall back to Lua behavior for something like this:
311 (best of $items according to $key_fn) means:
312 [$best, $best_key] = [nil, nil]
313 for $item in $items:
314 $key = ($key_fn $item)
315 if (($best == (nil)) or ($key > $best_key)):
316 [$best, $best_key] = [$item, $key]
318 return $best
320 ### Function literals look like: $x -> ($x * $x)
321 say (best of [2, -3, 4, -8] according to ($x -> ($x * $x)))
323 ### Or, you can surround an action with $(...) to refer to it:
324 ($x squared) means ($x * $x)
325 say (best of [2, -3, 4, -8] according to $($ squared))
327 ### However, nomsu was designed with flexible alternatives that are often better
328 than passing functions. For example, instead of calling a key function on
329 every item, you could instead define a macro that will inline an expression
330 to produce faster code:
331 (best of $items where $item has score $key_expr) parses as
332 result of:
333 [$best, $best_key] = [nil, nil]
334 for $item in $items:
335 $key = $key_expr
336 if (($best == (nil)) or ($key > $best_key)):
337 [$best, $best_key] = [$item, $key]
339 return $best
341 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
343 say (best of [2, -3, 4, -8] where $x has score ($x * $x))
345 ### The line above expands to:
346 say
347 result of:
348 [$best, $best_key] = [nil, nil]
349 for $x in [2, -3, 4, -8]:
350 $key = ($x * $x)
351 if (($best == (nil)) or ($key > $best_key)):
352 [$best, $best_key] = [$x, $key]
354 return $best