This is part one in a series on the 0.3 version of the language spec for the Merg-E Domain Specific Language for the InnuenDo Web 3.0 stack. I'll add more parts to the below list as the spec progresses:
- part 1 : coding style, files, merging, scoping, name resolution and synchronisation
- part 2 : reverse markdown for documentation
- part 3 : Actors and pools.
- part 4 : Semantic locks, blockers, continuation points and hazardous blockers
- part 5 : Semantic lexing, DAGs, prune / ent and alias.
- part 6 : DAGs and DataFrames as only data structures.
- part 7 : Freezing
- part 8 : Attenuation, decomposition, and membranes
- part 9 : Sensitive data in immutables and future vault support.
- part 10 : Scalars and High Fidelity JSON
- part 11 : Operators, expressions and precedence.
- part 12 : Robust integers and integer bitwidth generic programming
- part 13 : The Merg-E ownership model, capture rules, and the --trustmebro compiler flag.
- part 14 : Actorcitos and structural iterators
- part 15: Explicit actorcitos, non-inline structural iterators, runtimes, and abstract schedular pipeline.
- part 16 : Async functions and resources and the full use of InnuenDo VaultFS
- part 17 : RAM-Points, RAM-points normalization bag, and the quota-membrane.
In this short blog post in this series I want to look at the least important language feature from a functionality point of view, but a very important language feature for maintainable code: code comments.
Let's start with a bit of undocumented Merg-E code
#!/usr/bin/env merg-e
app myApp lang ambient {
lang.assert lang.version.major == 0 && lang.version.minor == 0;
resolve_order lang.flow lang.type lang.share lang imported;
use ambient {
io.cout as cout;
io.cerr as cerr;
io.endl as endl;
};
mutable main ()::{
cout;
cerr;
endl;
}{
inert int max_prime = 1000;
mutable int counter = 0;
shared mutable int ok_count = 0;
mutable blocker all_primes;
reentrant mutable merge utils.is_prime as is_prime(x int)::{
ok_count;
}{
max_prime;
}@[range_error];
while counter < 100 {
counter += 1;
all_primes += is_prime(counter);
};
await_all all_primes;
cout "counted " ok_count " prime numbers" endl;
}!!{
switch scope.exceptions[-1] {
range_error : {
cerr "Something went wrong" endl;
};
};
};
};
};
Because Merg-E is supposed to be a Web 3.0 DSL and because markdown is an important format in Web 3.0 chains like HIVE, we are intoducing the concept of reversed-markdown for documentation.
reversed markdown
In markdown, if you want to include a bit of code, you need to start with three backtics ``` , optionaly a language name , then a newline, your code, another newline, and then three backticks again.
# My document
Some text here
```python
#!/usr/bin/env python
print("Helo world")
```
In code it is unlikely that you will want to quote other code, so how about we just reverse it. We use the three backticks to denote markdown documentation embedded in our code
#!/usr/bin/env merg-e
```userdoc
# myApp
This is a silly App to demonstrate some basic Merg-E syntax.
The App counts how many prime numbers there are between 1 and 100.
```
app myApp lang ambient {
lang.assert lang.version.major == 0 && lang.version.minor == 0;
resolve_order lang.flow lang.type lang.share lang imported;
};
doc levels
Note how we use userdoc as pseudo language name. We distinguish documentation at three levels.
- userdoc : High level documentation that uses language a non developer might grasp
- devdoc : Documentation for developers to get an idea of the what of tha code.
- impldoc : Implementation documentation on the how of the code.
It is recomended to keep impldoc to a bare minimum and only use it for non intuitive code or non-intuitive concurency constructs.
indentation
Documentation blocks dont need to strictly follow Ratliff style indentation, but the tripple backtics does. Next to that, up to the indentation of the tripple backtics, leading spaces are considered to need to be removed in order to try to make valid markdown.
#!/usr/bin/env merg-e
```userdoc
## myApp
This is a silly App to demonstrate some basic Merg-E syntax.
The App counts how many prime numbers there are between 1 and 100.
```
app myApp lang ambient {
lang.assert lang.version.major == 0 && lang.version.minor == 0;
resolve_order lang.flow lang.type lang.share lang imported;
```devdoc
### imports
Import the ambient authority needed for outputing text to the user.
```
use ambient {
io.cout as cout;
io.cerr as cerr;
io.endl as endl;
};
mutable main ()::{
cout;
cerr;
endl;
}{
inert int max_prime = 1000;
mutable int counter = 0;
shared mutable int ok_count = 0;
mutable blocker all_primes;
```impldoc
#### range errors on is_prime
Please note that is_prime will throw a range_error when given an integer smaller than 1 or larger than max_prime
```
reentrant mutable merge utils.is_prime as is_prime(x int)::{
ok_count;
}{
max_prime;
}@[range_error];
while counter < 100 {
counter += 1;
all_primes += is_prime(counter);
};
await_all all_primes;
cout "counted " ok_count " prime numbers" endl;
}!!{
switch scope.exceptions[-1] {
range_error : {
cerr "Something went wrong" endl;
};
};
};
};
};
markdown reverser
So what is so great about reverse markdown? Well, we can make a simple markdown reverser in just a few dozen lines of code. All it needs to do is de-indent inside of the comment blocks and move around som,e backtics. Let's see what a reversed markdown of the previous code looks like:
## myApp
This is a silly App to demonstrate some basic Merg-E syntax.
The App counts how many prime numbers there are between 1 and 100.
```merg-e
app myApp lang ambient {
lang.assert lang.version.major == 0 && lang.version.minor == 0;
resolve_order lang.flow lang.type lang.share lang imported;
```
### imports
Import the ambient authority needed for outputing text to the user.
```merg-e
use ambient {
io.cout as cout;
io.cerr as cerr;
io.endl as endl;
};
mutable main ()::{
cout;
cerr;
endl}{
inert int max_prime = 1000;
mutable int counter = 0;
shared mutable int ok_count = 0;
mutable blocker all_primes;
```
#### range errors on is_prime
Please note that is_prime will throw a range_error when given an integer smaller than 1 or larger than max_prime
```merg-e
reentrant mutable merge utils.is_prime as is_prime(x int)::{
ok_count;
}{
max_prime;
}@[range_error];
while counter < 100 {
counter += 1;
all_primes += is_prime(counter);
};
await_all all_primes;
cout "counted " ok_count " prime numbers" endl;
}!!{
switch scope.exceptions[-1] {
range_error : {
cerr "Something went wrong" endl;
};
};
};
};
};
```
Right now all three levels are there, but the idea is to allow the tool to be able to strip out impldoc or impldoc + devdoc if desired.
Pasting.
To better demonstrate, I'll paste the markdown below to show how a document markdown of this simple script would end up looking:
myApp
This is a silly App to demonstrate some basic Merg-E syntax.
The App counts how many prime numbers there are between 1 and 100.
app myApp lang ambient {
lang.assert lang.version.major == 0 && lang.version.minor == 0;
resolve_order lang.flow lang.type lang.share lang imported;
imports
Import the ambient authority needed for outputing text to the user.
use ambient {
io.cout as cout;
io.cerr as cerr;
io.endl as endl;
};
mutable main ()::{
cout;
cerr;
endl;
}{
inert int max_prime = 1000;
mutable int counter = 0;
shared mutable int ok_count = 0;
mutable blocker all_primes;
range errors on is_prime
Please note that is_prime will throw a range_error when given an integer smaller than 1 or larger than max_prime
reentrant mutable merge utils.is_prime as is_prime(x int)::{
ok_count;
}{
max_prime;
}@[range_error];
while counter < 100 {
counter += 1;
all_primes += is_prime(counter);
};
await_all all_primes;
cout "counted " ok_count " prime numbers" endl;
}!!{
switch scope.exceptions[-1] {
range_error : {
cerr "Something went wrong" endl;
};
};
};
};
};
Comming up
In this post I'v addressed the documentation strings in the Merg-E draft language design. I'll need a few more posts to talk about things like freezing, attenuation and decomposition, parallelism models, actors, capability patterns, and a few more. Things are still very fluid on a number of these, and the descriptions in this and the previous post are already different from my first post on the subject ten days ago. Stick around for upcoming posts in this series.