Last active
December 10, 2015 05:28
-
-
Save mattn/4388227 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
#ifndef mruby_hpp | |
#define mruby_hpp | |
#include "mruby.h" | |
#include "mruby/proc.h" | |
#include "mruby/array.h" | |
#include "mruby/string.h" | |
#include "mruby/compile.h" | |
#include "mruby/dump.h" | |
#include "mruby/variable.h" | |
#include <string> | |
#include <iostream> | |
#include <stdexcept> | |
namespace mruby { | |
class value { | |
protected: | |
mrb_state* mrb; | |
mrb_value v; | |
value() : mrb(nullptr), v(mrb_nil_value()) { } | |
public: | |
const mrb_value operator* () const { | |
return v; | |
} | |
value operator= (const value& v) { | |
this->v = v.v; | |
return *this; | |
} | |
value(const value& v) : mrb(v.mrb), v(v.v) { } | |
value(const mrb_state* mrb, const mrb_value& v) : mrb((mrb_state*) mrb), v(v) { } | |
const std::string inspect() { | |
mrb_value r = mrb_funcall(mrb, v, "inspect", 0); | |
return std::string(RSTRING_PTR(r), RSTRING_LEN(r)); | |
} | |
}; | |
class nil_value : public value { | |
public: | |
nil_value(const mrb_state* mrb, const mrb_value& v) : value(mrb, v) { } | |
}; | |
class true_value : public value { | |
public: | |
true_value(const mrb_state* mrb, const mrb_value& v) : value(mrb, v) { } | |
}; | |
class false_value : public value { | |
public: | |
false_value(const mrb_state* mrb, const mrb_value& v) : value(mrb, v) { } | |
}; | |
class string : public value { | |
public: | |
string(const mrb_state* mrb, const mrb_value& v) : value(mrb, v) { } | |
const string operator+= (const std::string str) const { | |
return string(mrb, mrb_str_cat(mrb, this->v, str.c_str(), str.size())); | |
} | |
}; | |
class array : public value { | |
public: | |
array(const mrb_state* mrb, const mrb_value& v) : value(mrb, v) { } | |
void push(const value& v) { | |
mrb_ary_push(mrb, this->v, *v); | |
} | |
void push(const mrb_value& v) { | |
mrb_ary_push(mrb, this->v, v); | |
} | |
const value pop() { | |
return value(mrb, mrb_ary_pop(mrb, this->v)); | |
} | |
const value entry(int n) const { | |
return value(mrb, mrb_ary_entry(this->v, n)); | |
} | |
const value delete_at(int n) const { | |
return value(mrb, mrb_funcall(mrb, this->v, "delete_at", 1, mrb_fixnum_value(n))); | |
} | |
}; | |
class hash : public value { | |
public: | |
hash(const mrb_state* mrb, const mrb_value& v) : value(mrb, v) { } | |
}; | |
class context { | |
mrb_state* mrb; | |
mrbc_context* ctx; | |
public: | |
context(mrb_state* mrb) : mrb(mrb) { | |
ctx = mrbc_context_new(mrb); | |
ctx->capture_errors = 1; | |
} | |
~context() { | |
mrbc_context_free(mrb, ctx); | |
} | |
const mrbc_context* operator* () const { | |
return ctx; | |
} | |
value load_string(const std::string& expr) { | |
return value(mrb, mrb_load_string_cxt(mrb, expr.c_str(), ctx)); | |
} | |
const char* filename(const char* fname) { | |
mrbc_filename(mrb, ctx, fname); | |
} | |
value run(const std::string& expr) { | |
struct mrb_parser_state *parser; | |
parser = mrb_parser_new(mrb); | |
parser->s = expr.c_str(); | |
parser->send = expr.c_str() + expr.size(); | |
parser->lineno = 1; | |
mrb_parser_parse(parser, ctx); | |
int n = mrb_generate_code(mrb, parser); | |
mrb_parser_free(parser); | |
mrb_value r = mrb_run( | |
mrb, | |
mrb_proc_new(mrb, | |
mrb->irep[n]), | |
mrb_top_self(mrb)); | |
if (mrb->exc) { | |
r = mrb_funcall(mrb, mrb_obj_value(mrb->exc), "inspect", 0); | |
mrb->exc = 0; | |
throw std::runtime_error(RSTRING_PTR(r)); | |
} | |
return value(mrb, r); | |
} | |
}; | |
class state { | |
mrb_state* mrb; | |
public: | |
state() { | |
mrb = mrb_open(); | |
} | |
~state() { | |
mrb_close(mrb); | |
} | |
const mrb_state* operator* () const { | |
return mrb; | |
} | |
void define_global_const(const char* name, const value& v) const { | |
mrb_define_global_const(mrb, name, *v); | |
} | |
const array new_array() const { | |
return array(mrb, mrb_ary_new(mrb)); | |
} | |
const hash new_hash() const { | |
return hash(mrb, mrb_ary_new(mrb)); | |
} | |
const nil_value new_nil() const { | |
return nil_value(mrb, mrb_nil_value()); | |
} | |
const string new_string() const { | |
return string(mrb, mrb_str_new2(mrb, "")); | |
} | |
const context new_context() const { | |
return context(mrb); | |
} | |
const value funcall(const value& v, const char* name, int argc, value* argv) { | |
mrb_value* av = new mrb_value[argc]; | |
for (int n = 0; n < argc; n++) { | |
av[n] = *argv[n]; | |
} | |
value r = value(mrb, mrb_funcall_argv(mrb, (mrb_value) *v, mrb_intern(mrb, name), argc, av)); | |
delete[] av; | |
return r; | |
} | |
}; | |
} | |
int | |
main() { | |
mruby::state s; | |
mruby::context c = s.new_context(); | |
mruby::array ary = s.new_array(); | |
s.define_global_const("A", ary); | |
c.run("A.push 1"); | |
c.run("A.push 2"); | |
c.run("A.push 3"); | |
ary.push(s.new_nil()); | |
mruby::string str = s.new_string(); | |
ary.push(str); | |
str += "foo"; | |
mruby::value v = c.run("A"); | |
std::cout << v.inspect() << std::endl; | |
return 0; | |
} | |
#endif /* mruby_hpp */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment