specr-transpile converts specr lang code to Rust code.
Run it with cargo r <config-file>
.
The config file is a newline-separated list of statements.
Each statement is either
input <path>
: where to look for the input .md files.output <path>
: where to generate the output crate.attr <attribute>
: give additional rust crate attributes, like attr #![feature(never_type)]
If you have an enum with infinite size due to type recursion,
you might want to add an indirection as follows:
rust
enum List<T> {
Cons {
val: T,
#[specr::indirection]
next: List<T>,
},
Nil,
}
This will wrap next
behing a pointer.
Drawbacks:
1. You should not match against references of enums, if you want to use the field with #[specr::indirection]
.
When matching against &List<T>
(or &mut List<T>
) you will see that you still obtain next
of type List<T>
and not &List<T>
(or &mut List<T>
) as would be correct in Rust.
Hence code like this will not work:
rust
match &mut l {
List::Cons { val, next } => {
*next = Nil;
},
_ => {},
}
Similarly using ref
or ref mut
are not supported for fields behind an #[specr::indirection]
.
All types provided by specr like List
, Set
, Map
, BigInt
are Copy, as they only contain an index into a garbage-collected data structure.
Further, the enum indirection discussed before applies an indirection by using the same garbage collected index.
Hence user-defined types can implement Copy too, they should hence not using non-Copy types from the standard library.
This #[derive(Copy, Clone)]
is added by specr automatically.
Note that each mutation of a List
, Set
, or Map
currently requires a full clone of that datastructure.
So for example one should use collect()
over push()
whenever possible.
TODO: explain how to use the mark_and_sweep
function.
methods can match over an argument like so:
```rust
impl Foo {
#[specr::argmatch(x)]
fn foo(&self, x: Option
impl Foo {
fn foo(&self, Some(a): Option
Argmatch can also be applied to
self`.
Forward declarations in specr lang are method implementations missing their code block { ... }
.
Example:
rust
impl Foo {
fn func(&self);
}
specr will clear those forward declarations, and will generally provide an implementation for the method itself.
specr will also implement some methods that have not been forward-declarated, but those should be described in comments.
TODO: explain merge impls or remove it.
TODO: explain module structure.