Skip to content

Commit

Permalink
Adds basic LP utility (moonbitlang#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
notch1p committed Aug 1, 2024
1 parent abf0b34 commit 5075eff
Show file tree
Hide file tree
Showing 4 changed files with 278 additions and 138 deletions.
146 changes: 96 additions & 50 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,89 +2,135 @@

This is a Markdown linter for MoonBit. It gathers all MoonBit codes in Markdown, checks them using MoonBit's compiler, and reports any diagnostics.

# Prerequisites
## Prerequisites

To use the MoonBit Markdown Linter, you need to install the [MoonBit compiler](https://www.moonbitlang.com/download/).

# Install
## Install

```
npm install -g @moonbit/markdown-linter
```

# Usage
## Usage

## Check Syntax and Type Errors
### Examples

Create a markdown file `fib.md`, write some MoonBit code in code block:
`mdlint` checks for possible errors in your moonbit code inside markdown documents:

# Fibonacci
````markdown
// test.md

Calculate the nth Fibonacci number using recursion and pattern matching.

```moonbit
fn fib(n : Int) -> Int {
match n {
0 => 0
1 => true // type error here
_ => fib(n - 1) + fib(n - 2)
}
```moonbit // defaults to normal
fn id[T : Eq](x : T) -> T {
x
}
```

```moonbit expr
id(5)
```

```moonbit no-check
// this is not moonbit at all
unsafe def gcd_unsafe: ℕ -> ℕ -> ℕ
| a, 0 => a
| a, b + 1 => gcd_unsafe (b + 1) (a % (b + 1))
```

```moonbit enclosed
fn fib(n : Int) -> Int {
match n {
0 => 0
1 => true // type error here
_ => fib(n - 1) + fib(n - 2)
}
```
}
```
````

Check it by MoonBit markdown linter.
Use `mdlint test.md` to check (the actual output is colored):

```
$ mdlint fib.md
fib.md:6:4-6:7 Warning 001: Unused function 'fib'
fib.md:9:14-9:18 Expr Type Mismatch
./fib.md:19:4 // correctly mapped!
[E1001] Warning: Warning: Unused function 'fib'
./fib.md:22:14
[E4014] Error: Expr Type Mismatch
has type : Bool
wanted : Int
```

## Run Inline Test or Evaluate Expression
The line number is correctly mapped to that in the markdown document, this is especially useful for debugging. Note that for multiple markdown files, each of them results in a independent project.

In file identity.md:
### Environments

# Identity
As seen above, `mdlint` supports several code environments including

```moonbit
fn id[T : Eq](x : T) -> T {
x
}
```
- `normal`: codeblocks marked w/ `normal` are copied as-is to generate moonbit project. Default behavior. Linting is performed.
- `expr`: codeblocks marked w/ `expr` are wrapped inside a `println()`, this environment only supports [expressions](https://www.moonbitlang.com/docs/syntax#expressions-and-statements). Linting is performed.
- `no-check`: codeblocks marked w/ `no-check` are ignored, not included in the generated project at all. Linting is NOT performed, suitable for writing pcode.
- `enclose`: codeblocks marked w/ `enclose` are enclosed inside a `init()`. Mainly used to avoid naming conflicts. Linting is performed.

You can also write expression directly.
### Flags

```moonbit expr
id(5)
```
#### --suppress

Test function `id`.
It's common to write not-so-well-formed code (e.g. Unused variables) for demonstration purposes, not production. It would be annoying if the compiler keeps complaining about those trivial problems. `mdlint` acknowledges that and provides `--suppress,-s` to suppress specific compiler error/warning in the output. It can be parsed inline:

```moonbit
test "id" {
if id(5) != 5 { return Result::Err("test failed") }
````
```moonbit enclosed -e1001 -e1002
fn fib(n : Int) -> Int {
match n {
0 => 0
1 => true // type error here
_ => fib(n - 1) + fib(n - 2)
}
```
}
```
````

Run test and evaluate the expression by `mdlint`:
or provided through cli:

```bash
mdlint -s=e1001,e1002 test.md # use comma-separated list
```
$ mdlint identity.md
5
running 1 tests in package identity
test identity::id ... ok

test result: 1 passed; 0 failed
- the special `-s=all-warnings` suppresses all warnings from `moon`.
- the `--ignore,-i` specifically ignores all error codes from codeblocks, useful for temporarily enabling error/warnings suppressed before.

#### --dump

`--dump,-d` dumps the project generated from the corresponding markdown document in the same directory with the extension `.proj`. e.g. `test.md` results in `test.md.proj`.

#### -f

A project generated by `mdlint` typically has the structure

```
.
├── README.md
├── lib
│ ├── fib.mbt
│ └── moon.pkg.json
├── moon.mod.json
├── moon.pkg.json
└── top.mbt
```

the `-f` flag is used to specify which moonbit source file the code should be copied to. This flag can only be parsed inline:

## Disable check
````markdown
// fib() now goes into lib/fib.mbt

You can also disable checking for some code block by sepcifying `no-check`.
```moonbit -e1001 -f=fib.mbt
fn fib(n : Int) -> Int {
match n {
0 => 0
1 => true // type error here
_ => fib(n - 1) + fib(n - 2)
}
}
```
````

```moonbit no-check
// some pseudo code
fn id(x : T) -> T
fn succ(x : T) -> T
```
By default, codeblocks are copied to `top.mbt`. If `-f` is provided with a value other than `top.mbt` (such as `fib.mbt`), `mdlint` would place that codeblock inside `lib/*.mbt`. This hopefully provides very basic literate programming utility.
Loading

0 comments on commit 5075eff

Please sign in to comment.