Nomsu Tools
Tools available for the Nomsu programming language.A programming language does not exist in a vacuum, so it’s important that the language be easy to work with. This section details some compiler features and tools that make working with Nomsu easier.
Vim Plugin
My editor of choice is Vim (or NeoVim). So, I wrote a Vim syntax plugin for Nomsu to do proper syntax highlighting and indenting. I recommend using Vim Plug to manage plugins, and if you do, you can just add this to your vimrc file to install the Nomsu plugin:
Plug 'https://bitbucket.org/spilt/vim-nomsu', { 'for': 'nomsu' }
Tutorial
Nomsu comes with a tutorial (in the style of Ruby Koans) that teaches you
some basic concepts. You can run the tutorial with nomsu -t tutorial
.
By default, the tutorial uses your system’s $EDITOR
to edit the files
as you go, but if you’d rather edit them in another window, you can run nomsu -t tutorial -x
instead. You can also look at the overview to see some
common usage patterns.
Auto-Formatting
Nomsu comes with a code auto-formatter which tidies up code and converts it to a standardized format.
Usage: nomsu -t format [-iq] file1.nom file2.nom...
The -i
flag
performs the auto-formatting in-place, otherwise the formatted code it printed
to stdout. -q
will
output the unmodified file without any error messages if the file fails to parse
(for external tools). For example, autoformatting will turn this:
$x==9 ) :
if( ("
say This is some code
")
into this:
$x == 9):
if ("This is some code" say
Code should generally always be autoformatted, as the autoformatter does a good job of making aesthetically pleasing code. Any time the autoformatter outputs uglier code than it’s given should be considered a bug in the autoformatter.
Testing
In Nomsu, you can write test cases using the test
action:
test:$nums = [1, 2, 3]
$nums) == 10 assume (frobnicate
When the file runs normally, these tests will not execute, they’ll just be
loaded into memory. The tests can be run using the “test” tool, which can be
invoked with: nomsu -t test file1.nom file2.nom...
.
Additionally, if you want to see the test code that is being run, you can add
the “-v” flag after “test”.
Searching
Nomsu’s actions can be a little tricky to find with a regular expression
(since the action’s name can be spread out, sometimes across multiple lines), so
the compiler comes with a “find” tool that parses Nomsu files, and looks for
places in the syntax tree that match the specified pattern. *
is
used as a wildcard, and **
is a variable-length wildcard.
Usage: nomsu -t find [-l] pattern file1.nom file2.nom...
Example: nomsu -t find "if (* == *) *" my_file.nom
This can be used for any syntax tree, including nested trees. If the
-l
(lowercase L) flag is used, only the names of files containing
matches will be printed.
Replacing
Along with searching, Nomsu also has a tool for find-and-replace. It takes a Nomsu code pattern and replacement Nomsu code. Replacements will be made everywhere a match is found, including nested matches.
Usage: nomsu -t replace [-ifq] pattern replacement file1.nom file2.nom...
Example: nomsu -t replace "if (\$L == \$R) \$true_body else \$false_body" "unless (\$R == \$L) \$false_body else \$true_body"
The above example will cause code like
$x == 10):
if ($y == 10):
if ("both 10"
say ..else:
"only x is 10"
say ..else:
"x isn't 10" say
to be replaced with
10 == $x):
unless ("x isn't 10"
say ..else:
10 == $y):
unless ("only x is 10"
say ..else:
"both 10" say
By default, the replaced code will be printed. If “-i” is used, the file will
be modified in-place, with user prompts to confirm. If “-i” and “-f” are both
used, the file will be modified in-place without prompts. “-q” will output the
unmodified file without any error messages if the file fails to parse (for
external tools). Optionally, --literal="$var1 $var2..."
can be used to match a specific variable.
Parsing
Nomsu has a parsing tool that takes a file and outputs human- or
machine-readable parse trees. By default, nomsu -t parse file.nom
will print a human readable parse tree, and the -x
flag will print the
parse tree in XML form: nomsu -t parse -x file.nom
.
Third Party Libraries
Nomsu has a very simple, but very powerful system for third party libraries. To install:
Usage: nomsu -t install github.com/user/repo
or: nomsu -t install ./local_library
The install tool will make a smart decision about how to install the library
you provide (using git
, curl
, or cp
). Libraries are stored
in /opt/nomsu
by default (this can be customized during
installation), and are shared across all Nomsu versions. A library named
foo
is either a single file called foo.nom
, or a
directory named foo
that contains a file called
init.nom
. Libraries are encouraged to maintain backwards
compatibility by storing different versions of the library in versioned
subdirectories, ensuring that use "foo/1.0"
will always allow a user to run code that uses version 1.0 of the “foo” library
API, even when a newer version of the library is installed. Backwards
compatibility can be maintained either by including the full older versions of
the library, or including compatibility shims that make use of the new version
of the library. A directory can be use
’d
directly if has a file called init.nom
, which may want to export
other files from that directory.
To uninstall a library: nomsu -t uninstall libname
.
To list installed libraries: nomsu -t list
.
Upgrading and Compatibility
Many languages have severe problems with updating syntax, and typically limit
themselves to only extending syntax, and never deprecating anything.
Nomsu anticipates this problem and aims to be adaptable, while still having full
backwards compatibility. In order to achieve this, Nomsu files may specify the
Nomsu version they were written for. The version can be specified in a
[shebang](https://en.wikipedia.org/wiki/Shebang_(Unix)) at the top of a file
like: #!/usr/bin/env nomsu -V5.12.12
.
The first number in the version determines which syntax version to use (Nomsu
ships with all past syntax versions), and the remaining numbers can be used for
custom compatibility upgrades. With Nomsu’s compatibility
library,
code can define exactly how a syntax tree from a given version will be upgraded
to the currently running version of Nomsu. For example, prior to version 5.13,
you had to use size of $thing
to get a
thing’s length. In 5.13, the new syntax #$thing
was introduced
to replace it, and the following upgrade rule was defined:
$) to "5.13" as #$ upgrade action (size of
Consequently, any code written for a version prior to 5.13 can be run without fear of breaking (as long as the compatibility library is included), because the code will be automatically upgraded during the compilation process.
This sort of on-the-fly upgrading is nice for running old code, but if you’re a code author and want to publish up-to-date code, you should really upgrade the old code before distributing it. Fortunately, Nomsu comes with a tool to automatically upgrade your own code!
Usage: nomsu -t upgrade [-i] file1.nom file2.nom...
The -i
flag will upgrade the files in-place. In
some rare cases, you may need to use --upgrade-from=<source version>
to manually specify
what version a Nomsu file is (by default, Nomsu assumes files that don’t have a
shebang are from the latest version), or --upgrade-to=<target version>
to specify a target version to upgrade to (instead of the latest version).
Upgrade rules can also be defined for specific libraries, if the version number is preceded by a library name, for example:
$f) to "myziplib2.0" as (zip the file $f) upgrade action (zip file
nomsu -t upgrade --upgrade-from=myziplib1.0 --upgrade-to=myziplib2.0 **.nom
Conclusion
Hopefully, you find these tools useful and enjoy using Nomsu as well! If you want to get involved with Nomsu, the best first step is to use Nomsu to write a program that solves a real-world problem you are interested in, which is a great first step for learning any new programming language.
If you have any comments or feedback, you can send them to , or open an issue on the Bitbucket repository.