- PREFACE
This is a distilled overview of the Lojban language.
Major concepts of the language are introduced by saying as much with as little as possible.
That is to say:
- For each concept the most crucial aspects are presented
macro_rules! as_item { ($i:item) => ($i) } // <-- empirically, this is needed to placate the compiler | |
macro_rules! test_cases { | |
( | |
$test_name:ident | |
$param_names:tt, // <-- just treat the param names as a tuple (type 'tt' to delay parsing) | |
[$($case_name:ident : $test_params:tt)+] // <-- same for the param values | |
$test_code:block | |
) => (as_item!( | |
#[cfg(test)] | |
pub mod $test_name { |
// switch to nightly and uncomment these for debugging | |
//#![feature(trace_macros)] | |
//trace_macros!(true); | |
/// Trick the macro parser into outputting an item without checking its syntax | |
macro_rules! as_item( ($i:item) => ($i) ); | |
macro_rules! foo( | |
// first rule: define the invocation syntax and call myself again with some | |
// easily parseable parameters (notice everything is bracketed) |
// cargo-deps: lazy_static | |
#[macro_use] extern crate lazy_static; | |
macro_rules! declare_array { | |
// INTERNAL | |
// last element (proceed to output) | |
(@parse $size:expr, ($val:expr) -> [$($accs:expr),*] $thru:tt) => { | |
declare_array!(@output $size + 1usize, [$($accs,)* $val] $thru); |
trait Star<Ret> { | |
type F: ?Sized; | |
fn star(self, f: &Self::F) -> Ret; | |
} | |
macro_rules! star_impl { | |
($($n:ident),*) => { | |
impl<Ret,$($n),*> Star<Ret> for ($($n,)*) { | |
type F = Fn($($n),*) -> Ret; |
use std::io::{Cursor, Read, self}; | |
trait ReadExt { | |
fn read_to_vec(&mut self, buf: &mut Vec<u8>) -> io::Result<usize>; | |
} | |
impl<T: Read> ReadExt for T { | |
fn read_to_vec(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { | |
self.take(buf.capacity() as u64).read_to_end(buf) | |
} |
This is a distilled overview of the Lojban language.
Major concepts of the language are introduced by saying as much with as little as possible.
That is to say:
- For each concept the most crucial aspects are presented
use std::sync::Arc; | |
macro_rules! clone_army { | |
($vars:tt | | $body:expr) => { | |
clone_army!(@emit $vars [] [] $body) | |
}; | |
($vars:tt move | | $body:expr) => { | |
clone_army!(@emit $vars [] [move] $body) | |
}; | |
($vars:tt || $body:expr) => { |
#[cfg(debug_assertions)] use std::ops::*; | |
#[cfg(debug_assertions)] use std::{f32, f64, fmt}; | |
#[cfg(debug_assertions)] | |
#[derive(Copy, Clone, Debug)] | |
struct Signaling<T>(T); | |
#[cfg(debug_assertions)] | |
impl<T: fmt::Display> fmt::Display for Signaling<T> { | |
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
/// Wrapper for a struct declaration using C++-like "pub:" and "priv:" labels instead of Rust's individual member annotations | |
/// | |
/// Syntax is similar to a normal pub struct declaration (see example below) | |
/// The struct is given an automatic pub fn new() method which simply takes all members in order -- without this, there would be no way to construct an instance due to the private members | |
macro_rules! sticky_visibility { | |
// START INTERNAL RULES | |
// defeat the parser | |
(@as_item $i:item) => ($i); |
#![allow(dead_code, unused_variables)] | |
//#![feature(trace_macros)] trace_macros!(true); | |
// strategy: scan the pattern for idents and pull them out, so we can create a let statement in the enclosing scope | |
macro_rules! guard { | |
(@as_stmt $s:stmt) => { $s }; | |
(@collect () -> ($($idents:ident)*), [($pattern:pat) ($rhs:expr) ($diverge:expr)]) => { | |
guard!(@as_stmt let ($($idents,)*) = if let $pattern = $rhs { ($($idents,)*) } else { $diverge }) | |
}; |