Skip to content

Instantly share code, notes, and snippets.

@fero23
Created March 14, 2016 17:18
Show Gist options
  • Save fero23/14e0bdacfd59e1545f7a to your computer and use it in GitHub Desktop.
Save fero23/14e0bdacfd59e1545f7a to your computer and use it in GitHub Desktop.
js_fn! macro initial design, declaration and usage (will not work standalone, these are just the key components)
#[derive(Debug)]
struct JsFunction<T: JsType, P> {
params_type: PhantomData<P>,
operations: Vec<Box<JsSentence>>,
return_value: Option<T>,
}
impl<S:Borrow<str>> From<S> for JsString {
fn from(value: S) -> JsString {
JsString::new(JsValue::StaticValue(value.borrow().to_string()))
}
}
impl<O> From<O> for Box<JsType>
where O: 'static + JsOp<ReturnType = JsString>
{
fn from(op: O) -> Box<JsType> {
Box::new(JsString::new(JsValue::ResultValue(Box::new(op))))
}
}
#[macro_export]
macro_rules! js_fn {
{var $var: ident = $op: expr; $($tail: tt)*} => {{
let mut buffer: Vec<Box<$crate::types::JsSentence>> = Vec::new();
let $var = $crate::types::JsAssignation::new(stringify!($var), $op.into());
buffer.push(Box::new($var));
js_fn! {buf buffer; $($tail)*}
}};
{$op: expr; $($tail: tt)*} => {{
let mut buffer: Vec<Box<$crate::types::JsSentence>> = Vec::new();
buffer.push(Box::new($crate::types::JsExpression::new($op.into())));
js_fn! {buf buffer; $($tail)*}
}};
{buf $buffer: ident; var $var: ident = $op: expr; $($tail: tt)*} => {{
let $var = $crate::types::JsAssignation::new(stringify!($var), $op.into());
$buffer.push(Box::new($var));
js_fn! {buf $buffer; $($tail)*}
}};
{buf $buffer: ident; $op: expr; $($tail: tt)*} => {{
$buffer.push(Box::new($crate::types::JsExpression::new($op.into())));
js_fn! {buf $buffer; $($tail)*}
}};
{buf $buffer: ident;} => {{
$crate::types::ops::function::JsFunction::<$crate::types::JsUndefined, ()>::new($buffer, None)
}};
{buf $buffer: ident; $ret: expr} => {{
$crate::types::ops::function::JsFunction::new($buffer, Some($ret))
}};
{} => {{
$crate::types::ops::function::JsFunction::new(Vec::new(), None)
}};
}
#[cfg(test)]
mod test {
use super::JsFunction;
use types::{JsOp};
use types::primitives::str::JsString;
#[test]
fn test_fn_string() {
let f = js_fn! {
var test = JsString::from("hello") + "world".into();
};
assert_eq!("function(){var test = (\"hello\" + \"world\");}",
f.get_repr());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment