An ongoing series in my quest to untangle my own thoughts and goals for the Comp programming language.
A language focused on developer experience? So much of my focus has been on the syntax and grammar. The entire concept is built on a handful of core fundamental rules that everything expands from.
- No separators or terminators
- Whitespace independent
- No line-based statements
- No indentation
Along with these fundamentals there are a few other strongly motivated designs.
- Use
kabab-casefor identifiers - No keywords
- Avoid nesting braces
Along with that there is has been from-the-start requirement that the structure literal has two forms.
-
{1 2 3}for positional sequences (lists, arrays) -
{a=1 b=2}for named mappings (dicts, hashes)
This has been a long and ongoing puzzle, but the payoff has been spectacular. Let’s look at another small code example and call out a few highlights.
!func shopping-cart-demo (
{
{"Apple" price=1.00}
{"Banana" price=0.50 quantity=2}
{"Apple" 1.00 quantity=2} // replace previous apples
}
| reduce :(| upsert :($.name))
| cart-total
| output "Total: %()"
)
- Keywords use a
!prefix. This makes them a bit noisier than I’d like, but it’s not a bad design to make them pronounced. This also allows freely introducing new keywords in the future. - Whitespace independence means this entire definition could be placed on a single line, or each statement split or joined as the author decides is most readable.
There’s a history of experiments, compromises, and undesirable workarounds to assemble these pieces. Much of this time I wasn’t sure these constraints could even be appeased.
I’ve been using the Lark library to handle parsing. I’d never experimented with it before, but now have a good deal of experience stretching it’s LALR rules. This gives an ideal O(n) performance. I have been surprised at the cost of building the grammar at runtime. Fortunately the library is quite prepared for this and comes with some high level caching options.