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:

if( $x==9 ) :
    say("
        This is some code
    ")

into this:

if ($x == 9):
    say "This is some code"

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]
    assume (frobnicate $nums) == 10

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

if ($x == 10):
    if ($y == 10):
        say "both 10"
    ..else:
        say "only x is 10"
..else:
    say "x isn't 10"

to be replaced with

unless (10 == $x):
    say "x isn't 10"
..else:
    unless (10 == $y):
        say "only x is 10"
    ..else:
        say "both 10"

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:

upgrade action (size of $) to "5.13" as #$

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:

upgrade action (zip file $f) to "myziplib2.0" as (zip the file $f)
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.