
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: cout, cerr: cerr, endl: endl}{
int max_prime = 1000;
mutable int counter = 0;
shared mutable int ok_count = 0;
mutable awaitable all_primes;
reentrant mutable merge utils.is_prime as is_prime(x int)::{ok_count: ok_count}{max_prime: 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: cout, cerr: cerr, endl: endl}{
int max_prime = 1000;
mutable int counter = 0;
shared mutable int ok_count = 0;
mutable awaitable 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: ok_count}{max_prime: 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: cout, cerr: cerr, endl: endl}{
int max_prime = 1000;
mutable int counter = 0;
shared mutable int ok_count = 0;
mutable awaitable 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: ok_count}{max_prime: 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: cout, cerr: cerr, endl: endl}{
int max_prime = 1000;
mutable int counter = 0;
shared mutable int ok_count = 0;
mutable awaitable 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: ok_count}{max_prime: 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.