Skip to content

Instantly share code, notes, and snippets.

@mattn
Last active December 10, 2015 05:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mattn/4388227 to your computer and use it in GitHub Desktop.
Save mattn/4388227 to your computer and use it in GitHub Desktop.
#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