Inspiration

I was inspired by the CWEB literate-programming system written by Donald Knuth and Silvio Levy. This program would take a specially formatted text file, and produce typeset TeX documentation with one command (CWEAVE) and C code with another (CTANGLE). I've attempted to write something similar to CTANGLE, but working with Markdown and Rust, rather than TeX and C.

What it does

This program takes a Markdown file, extracts Rust code snippets, and stitches them together into Rust source files using a simple templating language. Take the following example:

// <<*>>=
fn main() {
    // <<print hello>>
}
// <<print hello>>=
println!("Hello, World!");

Given this Markdown document as input, the program would process the code snippets. The comments that look like <<this>> are macros that will be expanded into source code defined in the snippet beginning with <<this>>=. In the example above, the program begins with the root snippet defined by <<*>>=, and the <<print hello>> macro is expanded to the code in the snippet defined in the block beginning with <<print hello>>=. Once the program has completed, it will have written a Rust file that looks like the following:

fn main() {
    println!("Hello, World")!
}

Macros can be nested.

How we built it

This program was written in Rust. The Markdown files are found in the filesystem using glob and parsed using pulldown-cmark. The text searches and expansions are performed using regex, and the dependency graph is built using petgraph.

Challenges we ran into

If macros are included in a cyclical manner, the program would loop infinitely. To combat this, I created a dependency graph that kept track of macro inclusions and checked to see if any cycles formed. If a cycle is found, the program throws an error.

Accomplishments that we're proud of

I only started learning Rust at the beginning of the semester, so it's nice that I was able to complete a project like this.

What's next for cargo-tangle

I'd like check that the source code in each macro definition is valid before tangling it into a source code file. Some extra error handling would also be nice.

Built With

Share this project:

Updates