3
About SMNP Language
Bartłomiej Przemysław Pluta edited this page 2020-04-01 21:05:03 +02:00

SMNP language is interpreted, high-level, formal language with syntax mostly inspired by Java language with - according to Chomsky's hierarchy - context-free grammar.

The language is designed to make writing music easy and straightforward and to reduce unnecessary boilerplate when typing notes by simply adapting general purpose languages' syntax and introducing new syntax constructs, including i.e. note literal or staff syntax.

Type system

SMNP is dynamic language, because there are no any static analyzer between parsing and evaluating stages. It means that any type-mismatching will be raised on runtime, when control flow reaches the point of error.

For example:

function foo(n: int) {
    println(n);
}

x = false;

if (x) {
    foo("hello");
}

As long as x == false, the code will be executed without any errors, even though foo function expects integer argument and is being called with string. However, if you switch x value to true, error will be thrown when control flow reaches foo function invocation with wrong argument's type. Even though there is no real definition of strongly-typed language, we can say SMNP is strongly-typed, because there are no any implicit type coercion. You always have to provide correct, expected type.

Comments

SMNP language allows you to make comments in the code. It can be done with # character, like:

# This is a comment

There is no syntax for multiline comment, but you can of course do something like this:

# This is
# a multiline
# comment

Note that because of hash-beginning comments you can put a shebang at the very first of your code making it more convenient to execute:

#!/usr/bin/smnp
println("Hello, world!");

# And now add executable flag (chmod +x) 
# to the file and execute it like any other 
# script/program from the shell 

Instruction terminator

SMNP language doesn't require you to delimit instructions, however it is still possible and highly recommended, because it helps you to get rid of code ambiguity.

Example:

size = [1, 2, 3].size
(size - 1) as i ^ print(i)

Execution of this code is interrupted with error, because SMNP parser tries to interpret size property as method [1, 2, 3].size(size - 1). As long as lists don't have size method (but they have size property), error will be raised and you will be able to fix problem. However, ambiguity could be a less obvious and you can stick with debugging code having no idea what is going wrong. To remove ambiguity you can end each instruction with semicolon ;:

size = [1, 2, 3].size;
(size - 1) as i ^ print(i);  # 01

All code snippets of present document follows the convention of ending each instruction with semicolon.