Apacen an Open Source Declarative Type Dependent System Prover in Prolog (Strategy, Proof Tree, Holes etc.).
Immofix Simuréno an Expert System Dedicated to Real-Estate Matchmaking and Negotiation, Integrating Sustainability Criteria.
Kaptngo a Secure Distributed System for Decentralized Executions with Streamlined Communications.
"A computer programming technique in which programs have the ability to treat other programs as their data." (wikipedia)
"A language is homoiconic if a program written in it can be manipulated as data using
the language."
(wikipedia)
Language extension proposition: Comprehension.
P = { (x,y) | x ∈ [1,3], y ∈ [1,x], y ≠ 2 }
// P = { (1, 1), (2, 1), (3, 1), (3, 3) }
for
for a <- 1 to 3
for a <- 1 to 3
b <- 1 to a if b != 2
for a <- 1 to 3
b <- 1 to a if b != 2
yield (a,b)
expr ::=
...
| "for" comprehension
expr ::=
...
| "for" comprehension
comprehension ::=
ident "<-" expr "yield" expr
expr ::=
...
| "for" comprehension
comprehension ::=
ident "<-" expr "yield" expr
| ident "<-" expr "if" expr "yield" expr
expr ::=
...
| "for" comprehension
comprehension ::=
ident "<-" expr "yield" expr
| ident "<-" expr "if" expr "yield" expr
| ident "<-" expr "if" expr comprehension
expr ::=
...
| "for" comprehension
comprehension ::=
ident "<-" expr "yield" expr
| ident "<-" expr "if" expr "yield" expr
| ident "<-" expr "if" expr comprehension
| ident "<-" expr comprehension
for a <- 1 to 3
b <- 1 to a if b != 2
yield (a,b)
: List[(Int,Int)]
(1 to 3).???????(a =>
for b <- 1 to a if b != 2
yield (a,b))
???????: List[Int] -> (Int -> List[(Int,Int)]) -> List[(Int,Int)]
(1 to 3).flatMap(a =>
for b <- 1 to a if b != 2
yield (a,b))
flatMap: List[A] -> (A -> List[B]) -> List[B]
(1 to 3).flatMap(a =>
for b <- (1 to a).??????????(b => b != 2)
yield (a,b))
??????????: List[Int] -> (Int -> Bool) -> List[Int]
(1 to 3).flatMap(a =>
for b <- (1 to a).withFilter(b => b != 2)
yield (a,b))
withFilter: List[A] -> (A -> Bool) -> List[A]
(1 to 3).flatMap(a =>
(1 to a).withFilter(b => b != 2).???(b =>
(a,b)))
???: List[Int] -> (Int -> (Int,Int)) -> List[(Int,Int)]
(1 to 3).flatMap(a =>
(1 to a).withFilter(b => b != 2).map(b =>
(a,b)))
map: List[A] -> (A -> B) -> List[B]
comprehension ::=
comprehension ::=
i:ident "<-" e:expr "yield" r:expr =>
{ e.map(i => r) }
comprehension ::=
i:ident "<-" e:expr "yield" r:expr =>
{ e.map(i => r) }
| i:ident "<-" e:expr "if" c:expr "yield" r:expr =>
{ e.withFilter(i => c).map(i => r) }
comprehension ::=
i:ident "<-" e:expr "yield" r:expr =>
{ e.map(i => r) }
| i:ident "<-" e:expr "if" c:expr "yield" r:expr =>
{ e.withFilter(i => c).map(i => r) }
| i:ident "<-" e:expr "if" c:expr r:comprehension =>
{ e.withFilter(i => c).flatMap(i => r) }
comprehension ::=
i:ident "<-" e:expr "yield" r:expr =>
{ e.map(i => r) }
| i:ident "<-" e:expr "if" c:expr "yield" r:expr =>
{ e.withFilter(i => c).map(i => r) }
| i:ident "<-" e:expr "if" c:expr r:comprehension =>
{ e.withFilter(i => c).flatMap(i => r) }
| i:ident "<-" e:expr c:comprehension =>
{ e.flatMap(i => c) }
#[macro_export]
macro_rules! macro_name { // Cannot by a keyword
}
#[macro_export]
macro_rules! macro_name {
pattern_with_bindings_1 => {{ production_rule_1 }};
}
#[macro_export]
macro_rules! macro_name {
pattern_with_bindings_1 => {{ production_rule_1 }};
pattern_with_bindings_2 => {{ production_rule_2 }};
...
}
macro_rules! for {
}
macro_rules! foreach {
}
macro_rules! foreach {
// i:ident "<-" e:expr "yield" r:expr =>
// { e.map(i => r) }
}
macro_rules! foreach {
($i:ident <- ($e:expr) yield $r:expr) => {{
// { e.map(i => r) }
}}
}
macro_rules! foreach {
($i:ident <- ($e:expr) yield $r:expr) => {{
$e.map(move |$i| $r)
}}
}
macro_rules! foreach {
($i:ident <- ($e:expr) yield $r:expr) => {{
$e.map(move |$i| $r)
}};
// i:ident "<-" e:expr "if" c:expr "yield" r:expr =>
// { e.withFilter(i => c).map(i => r) }
}
macro_rules! foreach {
($i:ident <- ($e:expr) yield $r:expr) => {{
$e.map(move |$i| $r)
}};
($i:ident <- ($e:expr) if ($c:expr) yield $r:expr) => {{
// { e.withFilter(i => c).map(i => r) }
}};
}
macro_rules! foreach {
($i:ident <- ($e:expr) yield $r:expr) => {{
$e.map(move |$i| $r)
}};
($i:ident <- ($e:expr) if ($c:expr) yield $r:expr) => {{
$e.filter(move |&$i| $c).map(move |$i| $r)
}}
}
macro_rules! foreach {
($i:ident <- ($e:expr) yield $r:expr) => {{
$e.map(move |$i| $r)
}};
($i:ident <- ($e:expr) if ($c:expr) yield $r:expr) => {{
$e.filter(move |&$i| $c).map(move |$i| $r)
}};
// i:ident "<-" e:expr "if" c:expr r:comprehension =>
// { e.withFilter(i => c).flatMap(i => r) }
}
macro_rules! foreach {
($i:ident <- ($e:expr) yield $r:expr) => {{
$e.map(move |$i| $r)
}};
($i:ident <- ($e:expr) if ($c:expr) yield $r:expr) => {{
$e.filter(move |&$i| $c).map(move |$i| $r)
}};
($i:ident <- ($e:expr) if ($c:expr) $($r:tt)+) => {{
// { e.withFilter(i => c).flatMap(i => r) }
}}
}
macro_rules! foreach {
($i:ident <- ($e:expr) yield $r:expr) => {{
$e.map(move |$i| $r)
}};
($i:ident <- ($e:expr) if ($c:expr) yield $r:expr) => {{
$e.filter(move |&$i| $c).map(move |$i| $r)
}};
($i:ident <- ($e:expr) if ($c:expr) $($r:tt)+) => {{
$e.filter(move |&$i| $c)
.flap_map(move |$i| foreach!($($r)+))
}}
}
macro_rules! foreach {
($i:ident <- ($e:expr) yield $r:expr) => {{
$e.map(move |$i| $r)
}};
($i:ident <- ($e:expr) if ($c:expr) yield $r:expr) => {{
$e.filter(move |&$i| $c).map(move |$i| $r)
}};
($i:ident <- ($e:expr) if ($c:expr) $($r:tt)+) => {{
$e.filter(move |&$i| $c)
.flap_map(move |$i| foreach!($($r)+))
}};
// i:ident "<-" e:expr r:comprehension =>
// { flatMap(i => r) }
}
macro_rules! foreach {
($i:ident <- ($e:expr) yield $r:expr) => {{
$e.map(move |$i| $r)
}};
($i:ident <- ($e:expr) if ($c:expr) yield $r:expr) => {{
$e.filter(move |&$i| $c).map(move |$i| $r)
}};
($i:ident <- ($e:expr) if ($c:expr) $($r:tt)+) => {{
$e.filter(move |&$i| $c)
.flap_map(move |$i| foreach!($($r)+))
}};
($i:ident <- ($e:expr) $($r:tt)+) => {{
// { flatMap(i => r) }
}}
}
macro_rules! foreach {
($i:ident <- ($e:expr) yield $r:expr) => {{
$e.map(move |$i| $r)
}};
($i:ident <- ($e:expr) if ($c:expr) yield $r:expr) => {{
$e.filter(move |&$i| $c).map(move |$i| $r)
}};
($i:ident <- ($e:expr) if ($c:expr) $($r:tt)+) => {{
$e.filter(move |&$i| $c)
.flap_map(move |$i| foreach!($($r)+))
}};
($i:ident <- ($e:expr) $($r:tt)+) => {{
$e.flat_map(move |$i| foreach!($($r)+))
}};
}
let r : Vec<_> =
foreach! {
a <- (1..=3)
b <- (1..=a) if (b != 2)
yield (a,b)
}
.collect();
let r : Vec<_> =
(1..=3).flat_map(move |a|
foreach! { b <- (1..=a) if (b != 2)
yield (a,b) })
.collect();
let r : Vec<_> =
(1..=3).flat_map(move |a|
(1..=a).filter(move |&b| b != 2)
.map(move |b|(a,b)))
.collect();
let r : Option<i32> =
foreach! {
a <- (Some(1))
b <- (Some(2)) if (b != 2)
c <- (Some(3))
yield a + b + c
};
let r: Option<i32> = foreach! {
______________________________^
| a <- (Some(1))
| b <- (Some(2)) if (b != 2)
| c <- (Some(3))
| yield a + b + c
| };
|_________^ `Option<i32>` is not an iterator
macro_rules! foreach {
($i:ident <- ($e:expr) yield $r:expr) => {{
$e.map(move |$i| $r)
}};
($i:ident <- ($e:expr) if ($c:expr) yield $r:expr) => {{
$e.filter(move |&$i| $c).map(move |$i| $r)
}};
($i:ident <- ($e:expr) if ($c:expr) $($r:tt)+) => {{
$e.filter(move |&$i| $c)
.flap_map(move |$i| foreach!($($r)+))
}};
($i:ident <- ($e:expr) $($r:tt)+) => {{
$e.flat_map(move |$i| foreach!($($r)+))
}};
}
macro_rules! foreach {
($i:ident <- ($e:expr) yield $r:expr) => {{
$e.map(move |$i| $r)
}};
($i:ident <- ($e:expr) if ($c:expr) yield $r:expr) => {{
$e.filter(move |&$i| $c).map(move |$i| $r)
}};
($i:ident <- ($e:expr) if ($c:expr) $($r:tt)+) => {{
$e.filter(move |&$i| $c)
.map(move |$i| foreach!($($r)+)).flatten()
}};
($i:ident <- ($e:expr) $($r:tt)+) => {{
$e.map(move |$i| foreach!($($r)+)).flatten()
}};
}
let r : Result<i32, ()> =
foreach! {
a <- (Ok(1))
b <- (Ok(2))
c <- (Ok(3))
yield a + b + c
};
($a:ident <- ($e:expr) yield $result:expr) => {{ ...
($a:ident <- $e:expr yield $result:expr) => {{ ...
($a:ident <- $e:expr yield $result:expr) => {{ ...
^^^^^ not allowed after `expr` fragments
($a:ident <- $e:expr yield $result:expr) => {{ ...
^^^^^ not allowed after `expr` fragments
#[proc_macro]
pub fn foreach(input: TokenStream) -> TokenStream {
...
}
expr ::=
...
| "for" comprehension
comprehension ::=
ident "<-" expr "yield" expr
| ident "<-" expr "if" expr "yield" expr
| ident "<-" expr "if" expr comprehension
| ident "<-" expr comprehension
expr ::=
...
| "for" comprehension
comprehension ::=
ident "<-" expr ("if" expr)? "yield" expr
| ident "<-" expr ("if" expr)? comprehension
expr ::=
...
| "for" comprehension
comprehension ::=
ident "<-" expr ("if" expr)? ("yield" expr | comprehension)
pub enum Comprehension {
// ident <- value (if condition)? yield result
MappingAndYield {
ident: syn::Ident,
value: syn::Expr,
condition: Option<syn::Expr>,
result: syn::Expr,
},
// ident <- value (if condition)? comprehension
...
}
pub enum Comprehension {
// ident <- value (if condition)? yield result
...,
// ident <- value (if condition)? comprehension
ChainedMapping {
ident: syn::Ident,
value: syn::Expr,
condition: Option<syn::Expr>,
comprehension: Box<Comprehension>,
},
}
impl syn::parse::Parse for Comprehension {
//
fn parse(input: ParseStream) -> syn::Result<Self> {
...
}
}
impl syn::parse::Parse for Comprehension {
// ident ...
fn parse(input: ParseStream) -> syn::Result<Self> {
let ident = input.parse::<syn::Ident>()?;
...
}
}
impl syn::parse::Parse for Comprehension {
// ident "<-" ...
fn parse(input: ParseStream) -> syn::Result<Self> {
let ident = input.parse::<syn::Ident>()?;
let _ = input.parse::<syn::Token![<-]>()?;
...
}
}
impl syn::parse::Parse for Comprehension {
// ident "<-" expr ...
fn parse(input: ParseStream) -> syn::Result<Self> {
let ident = input.parse::<syn::Ident>()?;
let _ = input.parse::<syn::Token![<-]>()?;
let value = input.parse::<syn::Expr>()?;
...
}
}
impl syn::parse::Parse for Comprehension {
// ident "<-" expr ("if" ...)? ...
fn parse(input: ParseStream) -> syn::Result<Self> {
let ident = input.parse::<syn::Ident>()?;
let _ = input.parse::<syn::Token![<-]>()?;
let value = input.parse::<syn::Expr>()?;
let cond = if input.lookahead1().peek(syn::Token![if]) ...
...
}
}
impl quote::ToTokens for Comprehension {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.extend(self.to_token_stream())
}
fn to_token_stream(&self) -> TokenStream {
match self {
Comprehension::MappingAndYield {
ident, value, condition, result,
} => {
if condition.is_none() {
quote! { #value.map(move |#ident| #result) }
} else {
...
#[proc_macro]
pub fn foreach(input: TokenStream) -> TokenStream {
}
#[proc_macro]
pub fn foreach(input: TokenStream) -> TokenStream {
let c = parse_macro_input!(input as Comprehension);
}
#[proc_macro]
pub fn foreach(input: TokenStream) -> TokenStream {
let c = parse_macro_input!(input as Comprehension);
quote! { #c }.into()
}
let r : Result<i32, ()> =
foreach! {
a <- Ok(1)
b <- Ok(2) if a != 1
c <- Ok(3)
yield a + b + c
};
Library for generalised parser combinators with a dedicated meta-language in Rust
parsec_rules! {
let json = (string|null|boolean|array|object|number)
let number = NUMBER -> {}
let string = STRING -> {}
let null = "null" -> {}
let boolean = ("true"|"false") -> {}
let array = ('[' (_=json (',' _=json)*)? ']') -> {}
let object = ('{' (_=attr (',' _=attr)*)? '}') -> {}
let attr = (STRING ":" json) -> {}
};
parsec_rules! {
...
let rule:{ASTParsecRule<char>} =
...
};
parsec_rules! {
...
let rule:{ASTParsecRule<char>} =
"let" n=ident i=kind? o=(':' _=kind)? '=' b=parsec
-> { mk_rule(n, i, o, b) }
...
};
Capability to manipulate parser at compile time!
flap: A Deterministic Parser with Fused Lexing
Jeremy Yallop, Ningning Xie and Neel Krishnaswami