Last active
March 24, 2016 23:11
-
-
Save jFransham/6a66072516075ceb7a0c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extern crate ketos; | |
use ketos::{Interpreter, FromValue}; | |
macro_rules! ketos_mod { | |
( | |
mod $name:ident { | |
$( $inner:tt )* | |
} | |
) => { | |
mod $name { | |
use ketos::{ | |
self, | |
Arity, | |
Error, | |
BuiltinModuleLoader, Module, ModuleBuilder, ModuleLoader, | |
Name, | |
GlobalScope, Scope, | |
FromValueRef, Value | |
}; | |
#[derive(Debug)] | |
pub struct Loader; | |
ketos_mod!{ @fun $( $inner )* } | |
impl ModuleLoader for Loader { | |
fn load_module(&self, name: Name, scope: &Scope) -> Result<Module, Error> { | |
if scope.with_name( | |
name, |name| name == stringify!($name) | |
) { | |
let scope = GlobalScope::new_using(scope); | |
let module = ketos_mod!(@matchfns scope, $name { $( $inner )* }); | |
Ok(module) | |
} else { | |
BuiltinModuleLoader.load_module(name, scope) | |
} | |
} | |
} | |
} | |
}; | |
(@fun use $p:path; $( $rest:tt )*) => { | |
use $p; | |
ketos_mod!(@fun $( $rest )*); | |
}; | |
(@fun fn $fn_name:ident($( $arg:ident : $t:ty ),*) $body:block $( $rest:tt )*) => { | |
fn $fn_name( | |
_: &Scope, _args: &mut [Value] | |
) -> Result<Value, Error> { | |
let mut _i = 0; | |
$( | |
let $arg: $t = FromValueRef::from_value_ref(&_args[_i]) | |
.unwrap(); | |
_i = _i + 1; | |
)* | |
let cls = |$($arg: $t ),*| $body; | |
Ok(cls($( $arg ),*).into()) | |
} | |
ketos_mod!(@fun $( $rest )*); | |
}; | |
(@fun #[raw] fn $fn_name:ident($arg:ident : $t0:ty, $v:ident: $t1:ty) $body:block $( $rest:tt )*) => { | |
fn $fn_name($arg: &Scope, $v: &mut [Value]) -> Result<ketos::value::Value, ketos::error::Error> $body | |
ketos_mod!(@fun $( $rest )*); | |
}; | |
(@fun) => {}; | |
(@matchfns | |
$scope:expr, $name:ident { | |
$( | |
$(#[$raw:tt])* fn $fn_name:ident($( $arg:tt )*) $body:block | |
)* | |
} | |
) => { | |
{ | |
let mut m = ModuleBuilder::new(stringify!($name), $scope); | |
$( | |
m = ketos_mod!(@matchfn $scope, $name { | |
$(#[$raw])* fn $fn_name($($arg)*) $body | |
})(m); | |
)* | |
m.finish() | |
} | |
}; | |
(@matchfn | |
$scope:expr, $name:ident { | |
fn $fn_name:ident($( $arg:ident : $t:ty ),*) $b:block | |
} | |
) => { | |
|m: ModuleBuilder| m.add_function( | |
stringify!($fn_name), | |
$fn_name, | |
Arity::Exact( | |
{ | |
let arg_names: &[&str] = &[ | |
$( stringify!($arg) ),* | |
]; | |
arg_names.len() | |
} as u32 | |
) | |
) | |
}; | |
(@matchfn | |
$scope:expr, $name:ident { | |
#[raw] fn $fn_name:ident($arg:ident : $t:ty, $v:ident: &mut [Value]) $b:block | |
} | |
) => { | |
ketos_mod! { | |
@matchfn $scope, $name { | |
#[raw] fn $fn_name($arg : $t, $v: &mut [Value; 0..]) $b | |
} | |
} | |
}; | |
(@matchfn | |
$scope:expr, $name:ident { | |
#[raw] fn $fn_name:ident($arg:ident : $t:ty, $v:ident: &mut [Value; $a:tt]) $b:block | |
} | |
) => { | |
|m: ModuleBuilder| m.add_function( | |
stringify!($fn_name), | |
$fn_name, | |
ketos_mod!(@range_to_arity $a) | |
) | |
}; | |
(@matchfn | |
$scope:expr, $name:ident { | |
#[raw] fn $fn_name:ident($arg:ident : $t:ty, $v:ident: &mut [Value; $a:tt..$b:tt]) $body:block | |
} | |
) => { | |
|m: ModuleBuilder| m.add_function( | |
stringify!($fn_name), | |
$fn_name, | |
ketos_mod!(@range_to_arity $a..$b) | |
) | |
}; | |
(@matchfn | |
$scope:expr, $name:ident { | |
#[raw] fn $fn_name:ident($arg:ident : $t:ty, $v:ident: &mut [Value; $a:tt..]) $b:block | |
} | |
) => { | |
|m: ModuleBuilder| m.add_function( | |
stringify!($fn_name), | |
$fn_name, | |
ketos_mod!(@range_to_arity $a..) | |
) | |
}; | |
(@range_to_arity $i:tt..) => { | |
ketos::function::Arity::Min(ketos_mod!(@capture $i)) | |
}; | |
(@range_to_arity $a:tt..$b:tt) => { | |
ketos::function::Arity::Range( | |
ketos_mod!(@capture $a), | |
ketos_mod!(@capture $b) | |
) | |
}; | |
(@range_to_arity $i:tt) => { | |
ketos::function::Arity::Min(ketos_mod!(@capture $i)) | |
}; | |
(@capture $i:expr) => { $i } | |
} | |
ketos_mod! { | |
mod hello { | |
fn do_something(first: &str, second: &str) { | |
first.len() + second.len() | |
} | |
fn meaning_of_life() { | |
return "Fourty-two"; | |
} | |
fn interpret(inp: &str) { | |
use ketos::Interpreter; | |
let interp = Interpreter::new(); | |
interp.run_code(inp, None).unwrap() | |
} | |
#[raw] | |
fn set(s: &Scope, args: &mut [Value; 2..10]) { | |
Ok(().into()) | |
} | |
} | |
} | |
fn main() { | |
let interp = Interpreter::with_loader(Box::new(hello::Loader)); | |
// Import our custom module and run the imported function | |
let v = interp.run_code(r#" | |
(use hello (interpret)) | |
(interpret "(+ 1 2)") | |
"#, None).unwrap(); | |
println!("{:?}", v); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment