- 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 }) | |
| }; |