LoginSignup
14
15

More than 5 years have passed since last update.

rustとmrubyでdslを作成してみよう

Posted at

itamae-goの実装が面白そうだったので、ソースコードを調べていたんですが、
rustでもmrubyを組み込むcrateあったなーと思い、勉強ついでにマネをさせてもらいました。

用意するもの

  1. rust (1.10.0)

ソースコード

/tmp/madoka/homuraというディレクトリつくって、
そこに3つファイルを作るというあまり意味のないレシピ。

Cargo.toml

[dependencies]
mrusty = "*"

main.rs
#[macro_use]
extern crate mrusty;

use mrusty::*;


// ruby
static RUBY_RECIPE: &'static str = r#"
directory '/tmp/madoka/homura'

3.times do |i|
  file "/tmp/madoka/homura/#{i}"
end
"#;

#[allow(unused_must_use)]
#[allow(unused_variables)]
fn main() {
   let mruby = Mruby::new();
   let itamae = mruby.def_module("Itamae");
   let recipe = mruby.def_class_under("Recipe", &itamae);
   let context = mruby.def_class_under("Context", &recipe);

   mruby.def_method(context.clone(), "directory", mrfn!(|mruby, slf: Value, v: (&str)| {
     std::fs::create_dir_all(v)
       .map(|_| mruby.bool(true))
       .unwrap_or(mruby.bool(false))
   }));

   mruby.def_method(context, "file", mrfn!(|mruby, slf: Value, v: (&str)| {
     std::fs::File::create(v)
       .map(|_| mruby.bool(true))
       .unwrap_or(mruby.bool(false))
   }));

   // itamae-goのように実装してみたら、mrustyだとうまくできなかったので、
   // method_missingを利用。
   mruby.run(r#"
      class Wrapper
        def initialize
          @inst = Itamae::Recipe::Context.new
        end

        def method_missing(method, *args)
          @inst.send(method, *args)
        end
      end
      ITAMAE_CONTEXT = Wrapper.new
   "#);

   mruby.run(format!("ITAMAE_CONTEXT.instance_exec {{{}}}", RUBY_RECIPE).as_str());
}

まとめ

rustとmrubyでrubyのdslができたような気がします。
mrustyはrustのマクロ機能をいい感じにつかっていたので、とても勉強になりました。

14
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
15