Skip to content

Instantly share code, notes, and snippets.

@nodamushi
Last active February 17, 2019 13:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nodamushi/7e59da9502bfbb01cfdd67fb091525be to your computer and use it in GitHub Desktop.
Save nodamushi/7e59da9502bfbb01cfdd67fb091525be to your computer and use it in GitHub Desktop.
Rustのマクロを試し中。C++ライクなクラス構文を導入してみる
macro_rules! defclass {
(class $name:ident;) =>{struct $name;};
(class $name:ident {$($contents:tt)*}) =>{defclass!{$name,,{},$($contents)*}};
(struct $name:ident;) =>{struct $name;};
(struct $name:ident {$($contents:tt)*}) =>{defclass!{$name,pub,{},$($contents)*}};
($name:ident,$($visible:ident)*,{$($field:tt)*},public:$($rest:tt)*) =>{
defclass!{$name,pub,{$($field)*},$($rest)*}
};
($name:ident,$($visible:ident)*,{$($field:tt)*},private:$($rest:tt)*) =>{
defclass!{$name,,{$($field)*},$($rest)*}
};
// Field
($name:ident,pub,{$($field:tt)*},$($fname:ident),* : $ftype:ty;$($rest:tt)*) =>{
defclass!{$name,pub,{$($field)*$(pub $fname:$ftype,)*},$($rest)*}
};
($name:ident,,{$($field:tt)*},$($fname:ident),* : $ftype:ty;$($rest:tt)*) =>{
defclass!{$name,,{$($field)*$($fname:$ftype,)*},$($rest)*}
};
// constructor
($name:ident,$($visible:ident)*,{$($field:tt)*},
new($($arg:tt)*){$($body:tt)*}
$($rest:tt)*) =>{
defclass!{$name,$($visible)*,{$($field)*},$($rest)*}
defmethod!{$($visible)*,$name,,new,($($arg)*),$name,$($body)*}
};
// function
($name:ident,$($visible:ident)*,{$($field:tt)*},
$fname:ident($($arg:tt)*){$($body:tt)*}
$($rest:tt)*) =>{
defclass!{$name,$($visible)*,{$($field)*},$($rest)*}
defmethod!{$($visible)*,$name,,$fname,($($arg)*),,$($body)*}
};
($name:ident,$($visible:ident)*,{$($field:tt)*},
$fname:ident($($arg:tt)*)->$ret:ty {$($body:tt)*}
$($rest:tt)*) =>{
defclass!{$name,$($visible)*,{$($field)*},$($rest)*}
defmethod!{$($visible)*,$name,,$fname,($($arg)*),$ret,$($body)*}
};
($name:ident,$($visible:ident)*,{$($field:tt)*},
<$($t:tt)*> $fname:ident($($arg:tt)*)->$ret:ty {$($body:tt)*}
$($rest:tt)*) =>{
defclass!{$name,$($visible)*,{$($field)*},$($rest)*}
defmethod!{$($visible)*,$name,($($t:tt)*),$fname,($($arg)*),$ret,$($body)*}
};
($name:ident,$($visible:ident)*,{$($field:tt)*},) =>{
struct $name{
$($field)*
}
};
}
macro_rules! defmethod {
($($visible:ident)*,$clname:ident,($($t:tt)*),$name:ident,($($arg:tt)*),$ret:ty,$($body:tt)*) => {
impl<$($t)*> $clname{
$($visible)* fn $name($($arg)*)->$ret{$($body)*}
}
};
($($visible:ident)*,$clname:ident,($($t:tt)*),$name:ident,($($arg:tt)*),,$($body:tt)*) => {
impl<$($t)*> $clname{
$($visible)* fn $name($($arg)*){$($body)*}
}
};
($($visible:ident)*,$clname:ident,,$name:ident,($($arg:tt)*),$ret:ty,$($body:tt)*) => {
impl $clname{
$($visible)* fn $name($($arg)*)->$ret{$($body)*}
}
};
($($visible:ident)*,$clname:ident,,$name:ident,($($arg:tt)*),,$($body:tt)*) => {
impl $clname{
$($visible)* fn $name($($arg)*){$($body)*}
}
};
}
//----------------------------------------------------------------------------
defclass!{
class Point {
private:
x,y,length:f64;
public:
new(x:f64,y:f64){
Point{x:x,y:y,length:x.hypot(y)}
}
x(&self) -> f64{self.x}
y(&self) -> f64{self.y}
length(&self)->f64{self.length}
}
}
fn main() {
let p = Point::new(1.0,20.0);
println!("{},{},{}",p.x(),p.y(),p.length());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment