summaryrefslogtreecommitdiffhomepage
path: root/src/variable.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/variable.c')
-rw-r--r--src/variable.c156
1 files changed, 100 insertions, 56 deletions
diff --git a/src/variable.c b/src/variable.c
index 74bb591cf..bda7b2a98 100644
--- a/src/variable.c
+++ b/src/variable.c
@@ -4,12 +4,11 @@
** See Copyright Notice in mruby.h
*/
-#include <ctype.h>
-#include "mruby.h"
-#include "mruby/array.h"
-#include "mruby/class.h"
-#include "mruby/proc.h"
-#include "mruby/string.h"
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/class.h>
+#include <mruby/proc.h>
+#include <mruby/string.h>
typedef int (iv_foreach_func)(mrb_state*,mrb_sym,mrb_value,void*);
@@ -283,7 +282,7 @@ iv_free(mrb_state *mrb, iv_tbl *t)
#else
-#include "mruby/khash.h"
+#include <mruby/khash.h>
#ifndef MRB_IVHASH_INIT_SIZE
#define MRB_IVHASH_INIT_SIZE 8
@@ -459,13 +458,14 @@ obj_iv_p(mrb_value obj)
case MRB_TT_SCLASS:
case MRB_TT_HASH:
case MRB_TT_DATA:
+ case MRB_TT_EXCEPTION:
return TRUE;
default:
return FALSE;
}
}
-mrb_value
+MRB_API mrb_value
mrb_obj_iv_get(mrb_state *mrb, struct RObject *obj, mrb_sym sym)
{
mrb_value v;
@@ -475,7 +475,7 @@ mrb_obj_iv_get(mrb_state *mrb, struct RObject *obj, mrb_sym sym)
return mrb_nil_value();
}
-mrb_value
+MRB_API mrb_value
mrb_iv_get(mrb_state *mrb, mrb_value obj, mrb_sym sym)
{
if (obj_iv_p(obj)) {
@@ -484,7 +484,7 @@ mrb_iv_get(mrb_state *mrb, mrb_value obj, mrb_sym sym)
return mrb_nil_value();
}
-void
+MRB_API void
mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v)
{
iv_tbl *t = obj->iv;
@@ -496,7 +496,7 @@ mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v)
iv_put(mrb, t, sym, v);
}
-void
+MRB_API void
mrb_obj_iv_ifnone(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v)
{
iv_tbl *t = obj->iv;
@@ -511,7 +511,7 @@ mrb_obj_iv_ifnone(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v)
iv_put(mrb, t, sym, v);
}
-void
+MRB_API void
mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v)
{
if (obj_iv_p(obj)) {
@@ -522,7 +522,7 @@ mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v)
}
}
-mrb_bool
+MRB_API mrb_bool
mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym)
{
iv_tbl *t;
@@ -534,14 +534,40 @@ mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym)
return FALSE;
}
-mrb_bool
+MRB_API mrb_bool
mrb_iv_defined(mrb_state *mrb, mrb_value obj, mrb_sym sym)
{
if (!obj_iv_p(obj)) return FALSE;
return mrb_obj_iv_defined(mrb, mrb_obj_ptr(obj), sym);
}
-void
+#define identchar(c) (ISALNUM(c) || (c) == '_' || !ISASCII(c))
+
+MRB_API mrb_bool
+mrb_iv_p(mrb_state *mrb, mrb_sym iv_name)
+{
+ const char *s;
+ mrb_int i, len;
+
+ s = mrb_sym2name_len(mrb, iv_name, &len);
+ if (len < 2) return FALSE;
+ if (s[0] != '@') return FALSE;
+ if (s[1] == '@') return FALSE;
+ for (i=1; i<len; i++) {
+ if (!identchar(s[i])) return FALSE;
+ }
+ return TRUE;
+}
+
+MRB_API void
+mrb_iv_check(mrb_state *mrb, mrb_sym iv_name)
+{
+ if (!mrb_iv_p(mrb, iv_name)) {
+ mrb_name_error(mrb, iv_name, "'%S' is not allowed as an instance variable name", mrb_sym2str(mrb, iv_name));
+ }
+}
+
+MRB_API void
mrb_iv_copy(mrb_state *mrb, mrb_value dest, mrb_value src)
{
struct RObject *d = mrb_obj_ptr(dest);
@@ -552,6 +578,7 @@ mrb_iv_copy(mrb_state *mrb, mrb_value dest, mrb_value src)
d->iv = 0;
}
if (s->iv) {
+ mrb_write_barrier(mrb, (struct RBasic*)d);
d->iv = iv_copy(mrb, s->iv);
}
}
@@ -582,7 +609,7 @@ inspect_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
else {
ins = mrb_inspect(mrb, v);
}
- mrb_str_append(mrb, str, ins);
+ mrb_str_cat_str(mrb, str, ins);
return 0;
}
@@ -608,7 +635,7 @@ mrb_obj_iv_inspect(mrb_state *mrb, struct RObject *obj)
return mrb_any_to_s(mrb, mrb_obj_value(obj));
}
-mrb_value
+MRB_API mrb_value
mrb_iv_remove(mrb_state *mrb, mrb_value obj, mrb_sym sym)
{
if (obj_iv_p(obj)) {
@@ -728,34 +755,46 @@ mrb_mod_class_variables(mrb_state *mrb, mrb_value mod)
return ary;
}
-mrb_value
+MRB_API mrb_value
mrb_mod_cv_get(mrb_state *mrb, struct RClass * c, mrb_sym sym)
{
struct RClass * cls = c;
+ mrb_value v;
while (c) {
- if (c->iv) {
- iv_tbl *t = c->iv;
- mrb_value v;
-
- if (iv_get(mrb, t, sym, &v))
- return v;
+ if (c->iv && iv_get(mrb, c->iv, sym, &v)) {
+ return v;
}
c = c->super;
}
+ if (cls && cls->tt == MRB_TT_SCLASS) {
+ mrb_value klass;
+
+ klass = mrb_obj_iv_get(mrb, (struct RObject *)cls,
+ mrb_intern_lit(mrb, "__attached__"));
+ c = mrb_class_ptr(klass);
+ if (c->tt == MRB_TT_CLASS) {
+ while (c) {
+ if (c->iv && iv_get(mrb, c->iv, sym, &v)) {
+ return v;
+ }
+ c = c->super;
+ }
+ }
+ }
mrb_name_error(mrb, sym, "uninitialized class variable %S in %S",
mrb_sym2str(mrb, sym), mrb_obj_value(cls));
/* not reached */
return mrb_nil_value();
}
-mrb_value
+MRB_API mrb_value
mrb_cv_get(mrb_state *mrb, mrb_value mod, mrb_sym sym)
{
return mrb_mod_cv_get(mrb, mrb_class_ptr(mod), sym);
}
-void
+MRB_API void
mrb_mod_cv_set(mrb_state *mrb, struct RClass *c, mrb_sym sym, mrb_value v)
{
struct RClass * cls = c;
@@ -781,13 +820,13 @@ mrb_mod_cv_set(mrb_state *mrb, struct RClass *c, mrb_sym sym, mrb_value v)
iv_put(mrb, cls->iv, sym, v);
}
-void
+MRB_API void
mrb_cv_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v)
{
mrb_mod_cv_set(mrb, mrb_class_ptr(mod), sym, v);
}
-mrb_bool
+MRB_API mrb_bool
mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym)
{
while (c) {
@@ -801,7 +840,7 @@ mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym)
return FALSE;
}
-mrb_bool
+MRB_API mrb_bool
mrb_cv_defined(mrb_state *mrb, mrb_value mod, mrb_sym sym)
{
return mrb_mod_cv_defined(mrb, mrb_class_ptr(mod), sym);
@@ -826,16 +865,6 @@ mrb_vm_cv_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
mrb_mod_cv_set(mrb, c, sym, v);
}
-mrb_bool
-mrb_const_defined(mrb_state *mrb, mrb_value mod, mrb_sym sym)
-{
- struct RClass *m = mrb_class_ptr(mod);
- iv_tbl *t = m->iv;
-
- if (!t) return FALSE;
- return iv_get(mrb, t, sym, NULL);
-}
-
static void
mod_const_check(mrb_state *mrb, mrb_value mod)
{
@@ -856,7 +885,7 @@ const_get(mrb_state *mrb, struct RClass *base, mrb_sym sym)
struct RClass *c = base;
mrb_value v;
iv_tbl *t;
- mrb_bool retry = 0;
+ mrb_bool retry = FALSE;
mrb_value name;
L_RETRY:
@@ -870,14 +899,14 @@ L_RETRY:
}
if (!retry && base && base->tt == MRB_TT_MODULE) {
c = mrb->object_class;
- retry = 1;
+ retry = TRUE;
goto L_RETRY;
}
name = mrb_symbol_value(sym);
return mrb_funcall_argv(mrb, mrb_obj_value(base), mrb_intern_lit(mrb, "const_missing"), 1, &name);
}
-mrb_value
+MRB_API mrb_value
mrb_const_get(mrb_state *mrb, mrb_value mod, mrb_sym sym)
{
mod_const_check(mrb, mod);
@@ -897,6 +926,14 @@ mrb_vm_const_get(mrb_state *mrb, mrb_sym sym)
if (c->iv && iv_get(mrb, c->iv, sym, &v)) {
return v;
}
+ if (c->tt == MRB_TT_SCLASS) {
+ mrb_value klass;
+ klass = mrb_obj_iv_get(mrb, (struct RObject *)c,
+ mrb_intern_lit(mrb, "__attached__"));
+ c2 = mrb_class_ptr(klass);
+ if (c2->tt == MRB_TT_CLASS)
+ c = c2;
+ }
c2 = c;
for (;;) {
c2 = mrb_class_outer_module(mrb, c2);
@@ -909,14 +946,14 @@ mrb_vm_const_get(mrb_state *mrb, mrb_sym sym)
return const_get(mrb, c, sym);
}
-void
+MRB_API void
mrb_const_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v)
{
mod_const_check(mrb, mod);
mrb_iv_set(mrb, mod, sym, v);
}
- void
+void
mrb_vm_const_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
{
struct RClass *c = mrb->c->ci->proc->target_class;
@@ -925,20 +962,20 @@ mrb_vm_const_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
mrb_obj_iv_set(mrb, (struct RObject*)c, sym, v);
}
-void
+MRB_API void
mrb_const_remove(mrb_state *mrb, mrb_value mod, mrb_sym sym)
{
mod_const_check(mrb, mod);
mrb_iv_remove(mrb, mod, sym);
}
-void
+MRB_API void
mrb_define_const(mrb_state *mrb, struct RClass *mod, const char *name, mrb_value v)
{
mrb_obj_iv_set(mrb, (struct RObject*)mod, mrb_intern_cstr(mrb, name), v);
}
-void
+MRB_API void
mrb_define_global_const(mrb_state *mrb, const char *name, mrb_value val)
{
mrb_define_const(mrb, mrb->object_class, name, val);
@@ -986,7 +1023,7 @@ mrb_mod_constants(mrb_state *mrb, mrb_value mod)
return ary;
}
-mrb_value
+MRB_API mrb_value
mrb_gv_get(mrb_state *mrb, mrb_sym sym)
{
mrb_value v;
@@ -999,7 +1036,7 @@ mrb_gv_get(mrb_state *mrb, mrb_sym sym)
return mrb_nil_value();
}
-void
+MRB_API void
mrb_gv_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
{
iv_tbl *t;
@@ -1013,7 +1050,7 @@ mrb_gv_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
iv_put(mrb, t, sym, v);
}
-void
+MRB_API void
mrb_gv_remove(mrb_state *mrb, mrb_sym sym)
{
if (!mrb->globals) {
@@ -1063,9 +1100,10 @@ mrb_f_global_variables(mrb_state *mrb, mrb_value self)
}
static mrb_bool
-mrb_const_defined_0(mrb_state *mrb, struct RClass *klass, mrb_sym id, mrb_bool exclude, mrb_bool recurse)
+mrb_const_defined_0(mrb_state *mrb, mrb_value mod, mrb_sym id, mrb_bool exclude, mrb_bool recurse)
{
- struct RClass * tmp;
+ struct RClass *klass = mrb_class_ptr(mod);
+ struct RClass *tmp;
mrb_bool mod_retry = 0;
tmp = klass;
@@ -1085,13 +1123,19 @@ retry:
return FALSE;
}
-int
-mrb_const_defined_at(mrb_state *mrb, struct RClass *klass, mrb_sym id)
+MRB_API mrb_bool
+mrb_const_defined(mrb_state *mrb, mrb_value mod, mrb_sym id)
{
- return mrb_const_defined_0(mrb, klass, id, TRUE, FALSE);
+ return mrb_const_defined_0(mrb, mod, id, TRUE, TRUE);
}
-mrb_value
+MRB_API mrb_bool
+mrb_const_defined_at(mrb_state *mrb, mrb_value mod, mrb_sym id)
+{
+ return mrb_const_defined_0(mrb, mod, id, TRUE, FALSE);
+}
+
+MRB_API mrb_value
mrb_attr_get(mrb_state *mrb, mrb_value obj, mrb_sym id)
{
return mrb_iv_get(mrb, obj, id);