#[macro_export]
macro_rules! lisp {
(false) => (false);
(true) => (true);
(self $(. $e:tt)* ) => (self $(. $e)* );
( $(#[$m:meta])* defstruct $struct_name:ident < $($generic:ident),+ >
(pub $( ($name:ident $typ:ty) )* )
( $( ($name2:ident $typ2:ty) )* )
) => (
$(#[$m]);*
struct $struct_name < $($generic),+ > {
$( pub $name: $typ),*
,
$( $name2: $typ2),*
}
);
( $(#[$m:meta])* defstruct $struct_name:ident < $($generic:ident),+ >
(pub $( ($name:ident $typ:ty) )* )
) => (
$(#[$m]);*
struct $struct_name < $($generic),+ > {
$( pub $name: $typ),*
}
);
( $(#[$m:meta])* defstruct $struct_name:ident < $($generic:ident),+ >
( $( ($name:ident $typ:ty) )* )
) => (
$(#[$m]);*
struct $struct_name < $($generic),+ > {
$( $name: $typ ),*
}
);
( $(#[$m:meta])* defstruct $struct_name:ident
(pub $( ($name:ident $typ:ty) )* )
( $( ($name2:ident $typ2:ty) )* )
) => (
$(#[$m]);*
struct $struct_name {
$( pub $name: $typ),*
,
$( $name2: $typ2),*
}
);
( $(#[$m:meta])* defstruct $struct_name:ident
(pub $( ($name:ident $typ:ty) )* )
) => (
$(#[$m]);*
struct $struct_name {
$( pub $name: $typ),*
}
);
( $(#[$m:meta])* defstruct $struct_name:ident
( $( ($name:ident $typ:ty) )* )
) => (
$(#[$m]);*
struct $struct_name {
$( $name: $typ ),*
}
);
( $(#[$m:meta])* defstruct $struct_name:ident) => (
$(#[$m]);*
struct $struct_name;
);
// match
(match $e:tt $( ( $pattern:pat $(| $pat2:pat)* => ( $($e2:tt)* ) ) )* ) => (
match $crate::lisp_arg!($e) {
$($pattern $(| $pat2)* => $crate::lisp_match_arg!($($e2)*) ),*
}
);
(with-input-from-file ($var:ident $path:tt)
$( ( $($e2:tt)* ) )*
) => ({
use std;
use std::io::Read;
let $var = std::fs::File::open($crate::lisp_arg!($path)).unwrap();
$( $crate::lisp!( $($e2)* ) );*
});
(with-input-from-mut-file ($var:ident $path:tt)
$( ( $($e2:tt)* ) )*
) => ({
use std;
use std::io::Read;
let mut $var = std::fs::File::open($crate::lisp_arg!($path)).unwrap();
$( $crate::lisp!( $($e2)* ) );*
});
(with-output-to-new-file ($var:ident $path:tt)
$( ( $($e2:tt)* ) )*
) => ({
use std;
use std::io::Write;
let mut $var = std::fs::File::create($crate::lisp_arg!($path)).unwrap();
$( $crate::lisp!( $($e2)* ) );*
});
(read $file:tt $s:ident) => ($crate::lisp_arg!($file).read(&mut $crate::lisp_arg!($s)));
(read-to-string $file:tt $s:ident) => ($crate::lisp_arg!($file).read_to_string(&mut $crate::lisp_arg!($s)));
(read-to-end $file:tt $s:ident) => ($crate::lisp_arg!($file).read_to_end(&mut $crate::lisp_arg!($s)));
(read-exact $file:tt $s:ident) => ($crate::lisp_arg!($file).read_exact(&mut $crate::lisp_arg!($s)));
(bytes $readable:tt) => ($crate::lisp_arg!($readable).bytes());
(chars $readable:tt) => ($crate::lisp_arg!($readable).chars());
(chain $readable:tt $next:tt) => ($crate::lisp_arg!($readable).chain($next));
(take $readable:tt $limit:tt) => ($crate::lisp_arg!($readable).take($limit));
(write $buffer:tt $e:tt) => ($crate::lisp_arg!($buffer).write($crate::lisp_arg!($e)));
(write-all $buffer:tt $e:tt) => ($crate::lisp_arg!($buffer).write_all($crate::lisp_arg!($e)));
(write-format $buffer:tt $fmt:tt) => ($crate::lisp_arg!($buffer).write_fmt($crate::lisp_arg!($fmt)));
(flush $writable:tt) => ($crate::lisp_arg!($writable).flush());
(seek $buffer:tt $e:tt) => ($crate::lisp_arg!($buffer).seek($crate::lisp_arg!($e)));
(by-ref $object:tt) => ($crate::lisp_arg!($object).by_ref());
(let ( $( ($var:ident $e:tt) )* )
$( ( $($e2:tt)* ) )*
) => ({
$(let mut $var = $crate::lisp_arg!($e);)*
$( $crate::lisp!( $($e2)* ) );*
});
(progn $( ( $($e:tt)* ) )* ) => ({ $( $crate::lisp!( $($e)* ) );* });
(break) => (break;);
(continue) => (continue;);
(loop $( ( $($e:tt)* ) )* ) => ( loop { $( $crate::lisp!( $($e)* ) );* });
(while $cond:tt $( ( $($e:tt)* ) )* ) => ( while $crate::lisp_arg!($cond) { $( $crate::lisp!( $($e)* ) );* });
(while-let ( $pattern:pat = $($cond:tt)* ) $( ( $($e:tt)* ) )* ) => ( while let $pattern = $crate::lisp_arg!($($cond)*) { $( $crate::lisp!( $($e)* ) );* });
(dotimes ($var:ident $count:tt) $( ( $($e:tt)* ) )* ) => (
for $var in 0..$crate::lisp_arg!($count) {
$( $crate::lisp!( $($e)* ) );*
}
);
(do ( $( ($var:ident $init:tt $step:tt) )* )
($cond:tt $result:tt)
$( ( $($e:tt)* ) )*
) => ({
$(let mut $var = $crate::lisp_arg!($init);)*
while !($crate::lisp_arg!($cond)) {
$( $crate::lisp!( $($e)* ) );*
$($var = $crate::lisp_arg!($step);)*
}
$crate::lisp_arg!($result)
});
(doiter ($var:ident $( $iter:tt )* ) $( ( $($e:tt)* ) )* ) => (
for $var in $crate::lisp_arg!( $($iter)* ) {
$( $crate::lisp!( $($e)* ) );*
}
);
(if ( $($cond:tt)* ) $e1:tt $e2:tt) => (if $crate::lisp!($($cond)*) { $crate::lisp_arg!($e1) }else{ $crate::lisp_arg!($e2) });
(if ( $($cond:tt)* ) $e:tt) => (if $crate::lisp!($($cond)*) { $crate::lisp_arg!($e) });
(if $cond:tt $e1:tt $e2:tt) => (if $cond { $crate::lisp_arg!($e1) }else{ $crate::lisp_arg!($e2) });
(if $cond:tt $e:tt) => (if $cond { $crate::lisp_arg!($e) });
(if-let ( $pattern:pat = $($cond:tt)* ) $e1:tt $e2:tt) => (if let $pattern = $crate::lisp_arg!($($cond)*) { $crate::lisp_arg!($e1) }else{ $crate::lisp_arg!($e2) });
(if-let ( $pattern:pat = $($cond:tt)* ) $e:tt) => (if let $pattern = $crate::lisp_arg!($($cond)*) { $crate::lisp_arg!($e) });
(when ( $($cond:tt)* ) $e:tt) => (if $crate::lisp!($($cond)*) { $crate::lisp_arg!($e) });
(when $cond:tt $e:tt) => (if $cond { $crate::lisp_arg!($e) });
(unless ( $($cond:tt)* ) $e:tt) => (if ! ($crate::lisp!($($cond)*)) { $crate::lisp_arg!($e) });
(unless $cond:tt $e:tt) => (if !($cond) { $crate::lisp_arg!($e) });
( $(#[$m:meta])* extern-crate $sym:ident) => ($(#[$m]);* extern crate $sym;);
(use $sym:tt $(:: $sym2:tt)* ) => (use $sym $(:: $sym2)* ;);
( $(#[$m:meta])* module $sym:ident
$( ( $($e:tt)* ))*
) => (
$(#[$m]);*
mod $sym {
$( $crate::lisp!( $($e)* ); )*
}
);
( $(#[$m:meta])* pub module $sym:ident
$( ( $($e:tt)* ))*
) => (
$(#[$m]);*
pub mod $sym {
$( $crate::lisp!( $($e)* ); )*
}
);
( $(#[$m:meta])* defun $sym:ident ( $( ( $name:ident $typ:ty ) )* ) $return_type:tt
$( ( $($e:tt)* ))*
) => (
$(#[$m]);*
fn $sym ( $($name : $typ),* ) -> $return_type {
$( $crate::lisp!( $($e)* ) );*
}
);
( $(#[$m:meta])* defun $sym:ident ( $( ( $name:ident $typ:ty ) )* )
$( ( $($e:tt)* ))*
) => (
$(#[$m]);*
fn $sym( $($name : $typ),* ) {
$( $crate::lisp!( $($e)* ) );*
}
);
( $(#[$m:meta])* pub defun $sym:ident ( $( ( $name:ident $typ:ty ) )* ) $return_type:tt
$( ( $($e:tt)* ))*
) => (
$(#[$m]);*
pub fn $sym( $($name : $typ),* ) -> $return_type {
$( $crate::lisp!( $($e)* ) );*
}
);
( $(#[$m:meta])* pub defun $sym:ident ( $( ( $name:ident $typ:ty ) )* )
$( ( $($e:tt)* ))*
) => (
$(#[$m]);*
pub fn $sym( $($name : $typ),* ) {
$( $crate::lisp!( $($e)* ) );*
}
);
(defconstant ($var:ident $typ:ty) ( $($e:tt)+ ) ) => (let $var:$typ = $crate::lisp!( $($e)+););
(defconstant ($var:ident $typ:ty) $e:expr) => (let $var:$typ = $e;);
(defconstant $var:ident ( $($e:tt)+ ) ) => (let $var = $crate::lisp!( $($e)+ ););
(defconstant $var:ident $e:expr) => (let $var = $e;);
(defvar ($var:ident $typ:ty) ( $($e:tt)+ )) => (let mut $var:$typ = $crate::lisp!( $($e)+););
(defvar ($var:ident $typ:ty) $e:expr) => (let mut $var:$typ = $e;);
(defvar $var:ident ( $($e: tt)+ )) => (let mut $var = $crate::lisp!( $($e)+););
(defvar $var:ident $e:expr) => (let mut $var = $e;);
(setf $var:ident ( $($e: tt)+ ) ) => ($var = $crate::lisp!( $($e)+););
(setf $var:ident $e:expr) => ($var = $e);
(eq $x:tt $y:tt) => ($crate::lisp_arg!($x) == $crate::lisp_arg!($y));
(== $x:tt $y:tt) => ($crate::lisp_arg!($x) == $crate::lisp_arg!($y));
(!= $x:tt $y:tt) => ($crate::lisp_arg!($x) != $crate::lisp_arg!($y));
(< $x:tt $y:tt) => ($crate::lisp_arg!($x) < $crate::lisp_arg!($y));
(> $x:tt $y:tt) => ($crate::lisp_arg!($x) > $crate::lisp_arg!($y));
(<= $x:tt $y:tt) => ($crate::lisp_arg!($x) <= $crate::lisp_arg!($y));
(>= $x:tt $y:tt) => ($crate::lisp_arg!($x) >= $crate::lisp_arg!($y));
(print $( $e:tt )+) => ( print!( $($e),+ ) );
(println $( $e:tt )+) => ( println!( $($e),+ ) );
(format $( $e:tt )+) =>( format!( $($e),+ ) );
(format-args $( $e:tt )+) => ( format_args!( $($e),+ ) );
(assert $e1:tt $e2:tt) => ( assert!($e1, $e2); );
(assert-eq $e1:tt $e2:tt) => ( assert_eq!($e1, $e2); );
(debug-assert $e1:tt $e2:tt) => ( debug_assert!($e1, $e2); );
(debug-assert-eq $e1:tt $e2:tt) => ( debug_assert_eq!($e1, $e2); );
(panic $($arg:tt)+ ) => ( panic!( $($arg)+ ); );
(+ $x:tt $y:tt) => ($crate::lisp_arg!($x) + $crate::lisp_arg!($y));
(- $x:tt $y:tt) => ($crate::lisp_arg!($x) - $crate::lisp_arg!($y));
(* $x:tt $y:tt) => ($crate::lisp_arg!($x) * $crate::lisp_arg!($y));
(/ $x:tt $y:tt) => ($crate::lisp_arg!($x) / $crate::lisp_arg!($y));
(% $x:tt $y:tt) => ($crate::lisp_arg!($x) % $crate::lisp_arg!($y));
(incf $var:ident) => ($var = $var + 1);
(decf $var:ident) => ($var = $var - 1);
(1+ $e:tt) => ($crate::lisp_arg!($e) + 1);
(1- $e:tt) => ($crate::lisp_arg!($e) - 1);
(! $e:tt) => ( ! $crate::lisp_arg!($e));
(len $e:tt) => ($crate::lisp_arg!($e).len());
(tuple $($e:tt)* ) => ( ($($crate::lisp_arg!($e)),*) );
(vec $($e:tt)* ) => ( vec![$($crate::lisp_arg!($e)),*] );
(lambda move ( $( ( $name:ident $typ:ty ) )* )
$( ( $($e:tt)* ))*
) => (move | $($name : $typ),* |{ $( $crate::lisp!( $($e)* ) );* });
(lambda ( $( ( $name:ident $typ:ty ) )* )
$( ( $($e:tt)* ))*
) => (| $($name : $typ),* |{ $( $crate::lisp!( $($e)* ) );* });
((lambda ( ( $($name:ident $typ:ty)* ) ) $( ( $($e:tt)* ))* ) $($e2:tt)*) => (
(| $($name : $typ),* | { $( $crate::lisp!( $($e)* ) );* })( $($crate::lisp_arg!($e2)),* )
);
( $sym:ident $(:: $sym2:ident )+ $( $e:tt )* ) => ( $sym $(:: $sym2 )+ ( $($crate::lisp_arg!($e)),* ) );
( $sym:ident . $( $sym2:ident ).+ $( $e:tt )* ) => ( $sym.$( $sym2 ).+ ( $($crate::lisp_arg!($e)),* ) );
( $sym:ident $( $e:tt )* ) => ( $sym ( $($crate::lisp_arg!($e)),* ) );
(rust $( $st:stmt )* ) => ( $($st);* );
($e:expr) => ($e);
}
#[macro_export]
macro_rules! lisp_arg {
( ( $($e:tt)* ) ) => ( $crate::lisp!( $($e)* ) );
($e:expr) => ($e);
}
#[macro_export]
macro_rules! lisp_match_arg {
($e:expr) => ($e);
( $($e:tt)* ) => ($crate::lisp!( $($e)* ));
}