[#688] mkmf.rb - add files to clean and distclean targets — Michal Rokos <michal@...>

Hi,

25 messages 2003/01/15
[#722] Re: [RFC] mkmf.rb - add files to clean and distclean targets — Mathieu Bouchard <matju@...> 2003/01/20

On Thu, 16 Jan 2003, Michal Rokos wrote:

[#740] Re: [RFC] mkmf.rb - add files to clean and distclean targets — matz@... (Yukihiro Matsumoto) 2003/01/21

Hi,

[#724] Symbols: More Functionality Wanted — Ryan Pavlik <rpav@...>

I've been discussing this for a bit on #ruby-lang on OPN (or freenode or

23 messages 2003/01/20
[#728] Re: Symbols: More Functionality Wanted — matz@... (Yukihiro Matsumoto) 2003/01/20

Hi,

[#743] Re: Symbols: More Functionality Wanted — "Pit Capitain" <pit@...> 2003/01/21

On 20 Jan 2003 at 15:49, Yukihiro Matsumoto wrote:

[#767] Re: Symbols: More Functionality Wanted — Mathieu Bouchard <matju@...> 2003/01/22

[#768] Re: Symbols: More Functionality Wanted — dblack@... 2003/01/22

Hi --

[#779] Re: Symbols: More Functionality Wanted — Gavin Sinclair <gsinclair@...> 2003/01/23

On Thursday, January 23, 2003, 6:28:04 AM, dblack wrote:

Re: Symbols: More Functionality Wanted

From: nobu.nokada@...
Date: 2003-01-20 09:20:54 UTC
List: ruby-core #732
Hi,

At Mon, 20 Jan 2003 15:49:27 +0900,
Yukihiro Matsumoto wrote:
> Interesting idea, but I feel like they are responsibility of Binding,
> not Symbol.  For example,
> 
>   b = binding()
>   b.bind(:a, 2)
>   b.value(:a)

Tried.

--- Binding#bind(symbol, value)
    symbol is
    * local (block or function level) variable if already
      exists, attr_writer if defined, or new dynamic variable.
    * instance variable
    * class variable

--- Binding#value(symbol)
    symbol is
    * local variable if exists, or attr_reader.
    * instance variable
    * class variable

Constants and global variables are not implemented.  Required?


Index: eval.c
===================================================================
RCS file: /cvs/ruby/src/ruby/eval.c,v
retrieving revision 1.386
diff -u -2 -p -r1.386 eval.c
--- eval.c	16 Jan 2003 07:38:39 -0000	1.386
+++ eval.c	20 Jan 2003 09:15:53 -0000
@@ -1609,7 +1609,8 @@ ev_const_get(cref, id, self)
 
 static VALUE
-cvar_cbase()
+cvar_cbase_in(frame)
+    struct FRAME *frame;
 {
-    NODE *cref = RNODE(ruby_frame->cbase);
+    NODE *cref = RNODE(frame->cbase);
 
     while (cref && cref->nd_next && FL_TEST(cref->nd_clss, FL_SINGLETON)) {
@@ -1622,4 +1623,6 @@ cvar_cbase()
 }
 
+#define cvar_cbase() cvar_cbase_in(ruby_frame)
+
 static VALUE
 rb_mod_nesting()
@@ -6412,4 +6415,114 @@ bind_clone(self)
 }
 
+static VALUE *
+bind_lvar(data, id)
+    struct BLOCK *data;
+    ID id;
+{
+    struct RVarmap *vars = data->dyna_vars;
+    struct SCOPE *scope = data->scope;
+    ID *tbl = scope->local_tbl;
+
+    for (; vars; vars = vars->next) {
+	if (vars->id == id) {
+	    return &vars->val;
+	}
+    }
+    if (tbl && scope->local_vars) {
+	long i, n = *tbl++;
+	for (i = 0; i < n; ++i) {
+	    if (tbl[i] == id) {
+		return &scope->local_vars[i];
+	    }
+	}
+    }
+    return NULL;
+}
+
+static VALUE
+bind_value(self, sym)
+    VALUE self, sym;
+{
+    ID id = rb_to_id(sym);
+    struct BLOCK *data;
+
+    Data_Get_Struct(self, struct BLOCK, data);
+    if (rb_is_local_id(id)) {
+	volatile int iter;
+	int state;
+	VALUE val, *vp;
+
+	if ((vp = bind_lvar(data, id))) return *vp;
+	iter = ruby_frame->iter;
+	ruby_frame->iter = ITER_NOT;
+	PUSH_TAG(PROT_NONE);
+	if ((state = EXEC_TAG()) == 0) {
+	    val = rb_funcall2(data->self, id, 0, 0);
+	}
+	POP_TAG();
+	ruby_frame->iter = iter;
+	if (state) JUMP_TAG(state);
+	return val;
+    }
+    else if (rb_is_instance_id(id)) {
+	return rb_ivar_get(data->self, id);
+    }
+    else if (rb_is_class_id(id)) {
+	return rb_cvar_get(cvar_cbase_in(&data->frame), id);
+    }
+    else {
+	rb_raise(rb_eArgError, "invalid variable name: %s", rb_id2name(id));
+    }
+    return Qnil;		/* not reached */
+}
+
+static VALUE
+bind_assign(self, sym, val)
+    VALUE self, sym, val;
+{
+    ID id = rb_to_id(sym);
+    struct BLOCK *data;
+
+    Data_Get_Struct(self, struct BLOCK, data);
+    if (rb_is_local_id(id)) {
+	ID setter;
+	VALUE *vp = bind_lvar(data, id);
+
+	if (vp) {
+	    *vp = val;
+	    return self;
+	}
+	else if (rb_respond_to(data->self, setter = rb_id_attrset(id))) {
+	    volatile int iter = ruby_frame->iter;
+	    int state;
+	    ruby_frame->iter = ITER_NOT;
+	    PUSH_TAG(PROT_NONE);
+	    if ((state = EXEC_TAG()) == 0) {
+		rb_funcall2(data->self, id, 1, &val);
+	    }
+	    POP_TAG();
+	    ruby_frame->iter = iter;
+	    if (state) JUMP_TAG(state);
+	}
+	else if (!data->dyna_vars) {
+	    data->dyna_vars = new_dvar(id, val, 0);
+	    if (data->scope == ruby_scope) ruby_dyna_vars = data->dyna_vars;
+	}
+	else {
+	    data->dyna_vars->next = new_dvar(id, val, data->dyna_vars->next);
+	}
+    }
+    else if (rb_is_instance_id(id)) {
+	rb_ivar_set(data->self, id, val);
+    }
+    else if (rb_is_class_id(id)) {
+	rb_cvar_set(cvar_cbase_in(&data->frame), id, val, Qtrue);
+    }
+    else {
+	rb_raise(rb_eArgError, "invalid variable name: %s", rb_id2name(id));
+    }
+    return self;
+}
+
 static VALUE
 rb_f_binding(self)
@@ -7292,4 +7405,8 @@ Init_Proc()
     rb_undef_method(CLASS_OF(rb_cBinding), "new");
     rb_define_method(rb_cBinding, "clone", bind_clone, 0);
+    rb_define_method(rb_cBinding, "value", bind_value, 1);
+    rb_define_method(rb_cBinding, "bind", bind_assign, 2);
+    rb_define_method(rb_cBinding, "[]", bind_value, 1);
+    rb_define_method(rb_cBinding, "[]=", bind_assign, 2);
 
     rb_cMethod = rb_define_class("Method", rb_cObject);


-- 
Nobu Nakada

In This Thread