# How do I... # Write a comment? Put a # and go till the end of the line #.. How do I write a multi-line comment? Put a #.. on its own line and write whatever you want in an indented area. # How do I import a file? use "core/control_flow.nom" # How do I import all the files in a directory? use "core" # Set a variable? %x <- 1 %str <- "Hello world" # Expressions that are more than just literal values require parentheses: %x <- (2 + 3) # Modify a variable? %foobar <- 100 # As a shorthand, you can type: %foobar +<- 1 # which does the same thing as: %foobar <- (%foobar + 1) # Print stuff? say "Hello world!" # Define a mutli-line string? %mutli_str <- ".." Start with "..", then put lines below it that are indented one level. The string will continue until the indentation ends. # Format a string? %format_str <- ".." Strings can contain a backslash followed by a variable, list, dict, or parenthesized expression. This escaped value will be converted to a readable string, like so: The value of %x is \%x, isn't that nice? The sum of 2 and 4 is \(2 + 4). If you need to use a plain ol' backslash, you can do \\ <-- that %format_str2 <- "Single-line strings can contain escape sequences like \", \\, \n, \065, and \x0A" # Define a list? %my_list <- [1,2,"hello"] #.. Really long lists can use [..] followed by a bunch of indented values delimited by commas and/or newlines %my_really_long_list <- [..] 1,2,3,4 5,6 7 8,9,10 # Use a list? %my_list <- ["first item", "second item", "third item"] # Lists are 1-indexed because they're implemented as Lua tables, so this prints "first item" say %my_list.1 # List entries can be modified like this: %my_list.1 <- "ONE!!!" say (length of %my_list) # Define a dictionary/hash map? %my_dict <- {x: 99, y: 101} %my_dict <- {..} x: 101, y: 2 "99 bottles": 99 653: 292 # 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 %my_dict.x <- 9999 # 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 > 6) * (3 > 5) * (3 > 4) say "this won't print" * (3 > 3) say "this won't print" * (3 > 2) say "this will print" * else say "this is the default case" # Do a switch statement? when 3 = ? * 0 * 1 * 2 say "this won't print" * 3 say "this will print" * else say "this won't print" # Loop over a list (a foreach loop)? %list <- [1,2,3] for %x in %list say "For %x loop #\%x" # There's also a slightly more concise version that automatically populates a loop variable "%" for all %list say "For all loop #\%" # Loop over a number range? # This is inclusive, so it will loop over 1,2, and 3 for %i from 1 to 3 say "For %i from 1 to 3 loop #\%i" for all 1 to 3 say "For all 1 to 3 loop #\%" # This will print 0,2, and 4 for %even from 0 to 5 by 2 say "Even #\%even" for %backwards from 3 to 1 by -1 say "Backwards #\%backwards" # While loops: %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 # Infinite loop: %x <- 1 repeat say "repeat loop #\%x" %x +<- 1 if: %x > 3 stop repeating # GOTOs: do %x <- 1 === %again === say "GOTO loop #\%x" %x +<- 1 if: %x <= 3 go to %again say "finished going to" # Function definition: action [say both %first and also %second] say %first # Function arguments are accessed just like variables say %second # Functions can use "return" to return a value early action [first fibonacci above %n] %f1 <- 0 %f2 <- 1 repeat %tmp <- (%f1 + %f2) %f1 <- %f2 %f2 <- %tmp if: %f2 > %n return %f2 say (first fibonacci above 10) # Functions can have aliases, which may or may not have the arguments in different order action [..] 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 .. say "\(%better_things capitalized) rule and \%worse_things drool!" I like "dogs" more than "cats" I think "chihuahuas" are worse than "corgis" #.. Function calls can have parts of the function's name spread throughout. Everything that's not a literal value is treated as part of the function's name say both "Hello" and also "again!" # Functions can even have their name at the end: action [%what_she_said is what she said] say %what_she_said say "-- she said" "Howdy pardner" is what she said #.. The language only reserves []{}().,:;% as special characters, so functions can have really funky names! action [>> %foo_bar $$$^ --> % @& _~-^-~_~-^ %1 !] say %foo_bar say % say %1 >> "wow" $$$^ --> "so flexible!" @& _~-^-~_~-^ "even numbers can be variables!" ! # There's also full unicode support %こんにちは <- "こんにちは" action [% と言う] "\(%)世界" say (%こんにちは と言う) # Math and logic operations are just treated the same as function calls 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 action [%a ++ %b] 2 * (%a + %b) say (1 ++ (2 * 3)) # How do I do grouping? # Expressions can be grouped by enclosing parentheses: say (2 + 3) # Or by an indented region say 2 + 3 # Or by ":" until the end of the line say: 2 + 3 # If you need to keep going after an indented region, you can start the next line with ".." say both "Very long first argument that needs its own line" ..and also "short second arg" action [my favorite number]: 21 + 2 # This can be nested: say both my favorite ..number ..and also "foo" # Macros: # The "lua> %" and "=lua %" macros can be used to write raw lua code: action [say the time] 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")" # Variables can be accessed via \%varname action [square root of %n] =lua "math.sqrt(\%n)" say "The square root of 2 is \(square root of 2)" #.. The "immediately %" macro forces the indented code below it to run before the rest of the file finishes compiling, so it's often useful for writing your own macros. immediately # Macros can be defined to transform one bit of nomsu code into another using "parse % as %": parse [if %condition is untrue %body] as if (not %condition) %body # Or to transform nomsu code into custom lua code using "compile % to %" compile [if %condition on opposite day %body] to Lua ".." if not \(%condition as lua expr) then \(%body as lua statements) end # Constants can be defined as macros (but they need to be parenthesized when invoked) parse [TWENTY] as: 20 if (1 > (TWENTY)) is untrue say "Nomsu parsing macros work!" say "It looks like a keyword, but there's no magic here!" if (1 > (TWENTY)) on opposite day say "Lua compiling macros work!" say "It looks like a keyword, but there's no magic here!"