yarv-diff:139
From: ko1 atdot.net
Date: 28 Nov 2005 00:10:31 -0000
Subject: [yarv-diff:139] r298 - in trunk: . benchmark lib yarvtest
Author: ko1
Date: 2005-11-28 09:10:29 +0900 (Mon, 28 Nov 2005)
New Revision: 298
Added:
trunk/lib/tempfile.rb
trunk/lib/tmpdir.rb
Modified:
trunk/ChangeLog
trunk/benchmark/bmx_temp.rb
trunk/compile.c
trunk/eval_intern.h
trunk/eval_method.h
trunk/eval_thread.c
trunk/insns.def
trunk/string.c
trunk/test.rb
trunk/time.c
trunk/vm.c
trunk/vm_evalbody.h
trunk/vm_macro.def
trunk/yarvcore.c
trunk/yarvcore.h
trunk/yarvtest/test_class.rb
Log:
* compile.c, insns.def, vm_evalbody.h : support super
with splat argument and block (and zsuper with block)
* yarvtest/test_class.rb : add tests for above
* compile.c, yarvcore.h, yarvcore.c, insns.def, time.c, string.c :
add opt_succ insn
* eval_method.h : fix indent
* eval_thread.c : apply cast to vanish a warning
* lib/tempfile.rb, lib/tmpdir.rb : added
* vm.c : eval_method_missing added
* vm_macro.def : refactoring
Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog 2005-11-21 12:22:32 UTC (rev 297)
+++ trunk/ChangeLog 2005-11-28 00:10:29 UTC (rev 298)
@@ -4,7 +4,27 @@
# from Mon, 03 May 2004 01:24:19 +0900
#
+2005-11-28(Mon) 09:02:57 +0900 Koichi Sasada <ko1 atdot.net>
+ * compile.c, insns.def, vm_evalbody.h : support super
+ with splat argument and block (and zsuper with block)
+
+ * yarvtest/test_class.rb : add tests for above
+
+ * compile.c, yarvcore.h, yarvcore.c, insns.def, time.c, string.c :
+ add opt_succ insn
+
+ * eval_method.h : fix indent
+
+ * eval_thread.c : apply cast to vanish a warning
+
+ * lib/tempfile.rb, lib/tmpdir.rb : added
+
+ * vm.c : eval_method_missing added
+
+ * vm_macro.def : refactoring
+
+
2005-11-21(Mon) 21:21:33 +0900 Koichi Sasada <ko1 atdot.net>
* compile.c, compile.h, yarvcore.c : remove "iseqobj"
Modified: trunk/benchmark/bmx_temp.rb
===================================================================
--- trunk/benchmark/bmx_temp.rb 2005-11-21 12:22:32 UTC (rev 297)
+++ trunk/benchmark/bmx_temp.rb 2005-11-28 00:10:29 UTC (rev 298)
@@ -1 +1,17 @@
-0
+
+
+
+__END__
+class Integer
+ def times_
+ i=0
+ while i<self
+ yield(i)
+ i = i.succ
+ end
+ end
+end
+
+10000000.times{}
+
+
Modified: trunk/compile.c
===================================================================
--- trunk/compile.c 2005-11-21 12:22:32 UTC (rev 297)
+++ trunk/compile.c 2005-11-28 00:10:29 UTC (rev 298)
@@ -654,6 +654,9 @@
if(mid == idLength){
iobj = new_insn_body(iseq, line_no, BIN(opt_length), 0);
}
+ else if(mid == idSucc){
+ iobj = new_insn_body(iseq, line_no, BIN(opt_succ), 0);
+ }
}
else if(argc == I2F(2)){
if(mid == idASET){
@@ -789,7 +792,7 @@
static ID id_dollar_bang;
if(!id_dollar_bang){
- id_dollar_bang = rb_intern("$!");
+ id_dollar_bang = rb_intern("__$!");
}
iseq->local_tbl = (ID*)ALLOC_N(ID*, 1);
iseq->local_size = 1;
@@ -3125,20 +3128,20 @@
*/
DECL_ANCHOR(recv);
DECL_ANCHOR(args);
+ ID mid = node->nd_mid;
VALUE argc;
VALUE flag = 0;
VALUE block = 0;
VALUE parent_block = iseq->compile_data->current_block;
iseq->compile_data->current_block = Qfalse;
-
#if SUPPORT_JOKE
if(nd_type(node) == NODE_VCALL){
- if(node->nd_mid ==idBitblt){
+ if(mid ==idBitblt){
ADD_INSN(ret, nd_line(node), bitblt);
break;
}
- else if(node->nd_mid == idAnswer){
+ else if(mid == idAnswer){
ADD_INSN(ret, nd_line(node), answer);
break;
}
@@ -3156,7 +3159,7 @@
}
if(nd_type(node) == NODE_FCALL &&
- (node->nd_mid == goto_id || node->nd_mid == label_id)){
+ (mid == goto_id || mid == label_id)){
if(nd_type(node->nd_args->nd_head) == NODE_LIT &&
SYMBOL_P(node->nd_args->nd_head->nd_lit)){
@@ -3171,7 +3174,7 @@
}
- if(node->nd_mid == goto_id){
+ if(mid == goto_id){
ADD_INSNL(ret, nd_line(node), jump, label);
}
else{
@@ -3181,7 +3184,6 @@
}
}
#endif
-
/* reciever */
if(type == NODE_CALL){
COMPILE(recv, "recv", node->nd_recv);
@@ -3237,7 +3239,7 @@
}
debugp_param("call args argc", argc);
- debugp_param("call method", ID2SYM(node->nd_mid));
+ debugp_param("call method", ID2SYM(mid));
switch(nd_type(node)){
NODE_VCALL:
@@ -3247,7 +3249,7 @@
flag |= VM_CALL_FCALL_BIT;
}
- ADD_SEND_R(ret, nd_line(node), ID2SYM(node->nd_mid), argc,
+ ADD_SEND_R(ret, nd_line(node), ID2SYM(mid), argc,
block, I2F(flag));
if(poped){
@@ -3259,6 +3261,9 @@
DECL_ANCHOR(args);
VALUE argc;
VALUE flag = 0;
+ VALUE block = 0;
+ VALUE parent_block = iseq->compile_data->current_block;
+ iseq->compile_data->current_block = Qfalse;
/* args */
if(type != NODE_VCALL && node->nd_args){
@@ -3284,19 +3289,45 @@
else{
argc = I2F(0);
}
-
+
ADD_INSN(ret, nd_line(node), putnil); /* dummy reciever */
ADD_SEQ(ret, args);
- ADD_INSN2(ret, nd_line(node), super, argc, I2F(flag));
+ /* block */
+ if(parent_block){
+ if(parent_block & 1){
+ flag |= VM_CALL_ARGS_BLOCKARG_BIT;
+ //dump_disasm_list((LINK_ANCHOR *)(parent_block & (~1)));
+ ADD_SEQ(ret, (LINK_ANCHOR *)(parent_block & (~1)));
+ }
+ else{
+ block = parent_block;
+ }
+ }
+
+ ADD_INSN3(ret, nd_line(node), super, argc, block, I2F(flag));
+
if(poped){
ADD_INSN(ret, nd_line(node), pop);
}
break;
}
case NODE_ZSUPER:{
- ADD_INSN(ret, nd_line(node), zsuper);
+ VALUE block = 0;
+ VALUE parent_block = iseq->compile_data->current_block;
+
+ /* block */
+ if(parent_block){
+ if(parent_block & 1){
+ rb_bug("zsuper with blockval");
+ }
+ else{
+ block = parent_block;
+ }
+ }
+ ADD_INSN1(ret, nd_line(node), zsuper, block);
+
if(poped){
ADD_INSN(ret, nd_line(node), pop);
}
Modified: trunk/eval_intern.h
===================================================================
--- trunk/eval_intern.h 2005-11-21 12:22:32 UTC (rev 297)
+++ trunk/eval_intern.h 2005-11-28 00:10:29 UTC (rev 298)
@@ -248,8 +248,8 @@
#define SCOPE_PROTECTED 2
#define SCOPE_MODFUNC 5
#define SCOPE_MASK 7
-#define SCOPE_SET(f) (scope_vmode=(f))
-#define SCOPE_TEST(f) (scope_vmode&(f))
+#define SCOPE_SET(f) (f)
+#define SCOPE_TEST(f) (0&(f))
struct ruby_env {
struct ruby_env *prev;
Modified: trunk/eval_method.h
===================================================================
--- trunk/eval_method.h 2005-11-21 12:22:32 UTC (rev 297)
+++ trunk/eval_method.h 2005-11-28 00:10:29 UTC (rev 298)
@@ -21,244 +21,228 @@
void
rb_clear_cache()
{
- struct cache_entry *ent, *end;
+ struct cache_entry *ent, *end;
- if (!ruby_running) return;
- ent = cache; end = ent + CACHE_SIZE;
- while (ent < end) {
- ent->mid = 0;
- ent++;
- }
+ if (!ruby_running) return;
+ ent = cache; end = ent + CACHE_SIZE;
+ while (ent < end) {
+ ent->mid = 0;
+ ent++;
+ }
}
static void
-rb_clear_cache_for_undef(klass, id)
- VALUE klass;
- ID id;
+rb_clear_cache_for_undef(VALUE klass, ID id)
{
- struct cache_entry *ent, *end;
+ struct cache_entry *ent, *end;
- if (!ruby_running) return;
- ent = cache; end = ent + CACHE_SIZE;
- while (ent < end) {
- if (ent->origin == klass && ent->mid == id) {
- ent->mid = 0;
- }
- ent++;
+ if (!ruby_running) return;
+ ent = cache; end = ent + CACHE_SIZE;
+ while (ent < end) {
+ if (ent->origin == klass && ent->mid == id) {
+ ent->mid = 0;
}
+ ent++;
+ }
}
static void
-rb_clear_cache_by_id(id)
- ID id;
+rb_clear_cache_by_id(ID id)
{
- struct cache_entry *ent, *end;
+ struct cache_entry *ent, *end;
- if (!ruby_running) return;
- ent = cache; end = ent + CACHE_SIZE;
- while (ent < end) {
- if (ent->mid == id) {
- ent->mid = 0;
- }
- ent++;
+ if (!ruby_running) return;
+ ent = cache; end = ent + CACHE_SIZE;
+ while (ent < end) {
+ if (ent->mid == id) {
+ ent->mid = 0;
}
+ ent++;
+ }
}
void
-rb_clear_cache_by_class(klass)
- VALUE klass;
+rb_clear_cache_by_class(VALUE klass)
{
- struct cache_entry *ent, *end;
+ struct cache_entry *ent, *end;
- if (!ruby_running) return;
- ent = cache; end = ent + CACHE_SIZE;
- while (ent < end) {
- if (ent->klass == klass || ent->origin == klass) {
- ent->mid = 0;
- }
- ent++;
+ if (!ruby_running) return;
+ ent = cache; end = ent + CACHE_SIZE;
+ while (ent < end) {
+ if (ent->klass == klass || ent->origin == klass) {
+ ent->mid = 0;
}
+ ent++;
+ }
}
void
-rb_add_method(klass, mid, node, noex)
- VALUE klass;
- ID mid;
- NODE *node;
- int noex;
+rb_add_method(VALUE klass, ID mid, NODE* node, int noex)
{
- NODE *body;
+ NODE *body;
- if (NIL_P(klass)) klass = rb_cObject;
- if (ruby_safe_level >= 4 && (klass == rb_cObject || !OBJ_TAINTED(klass))) {
- rb_raise(rb_eSecurityError, "Insecure: can't define method");
+ if (NIL_P(klass)){
+ klass = rb_cObject;
+ }
+ if (ruby_safe_level >= 4 && (klass == rb_cObject || !OBJ_TAINTED(klass))) {
+ rb_raise(rb_eSecurityError, "Insecure: can't define method");
+ }
+ if (!FL_TEST(klass, FL_SINGLETON) &&
+ node && nd_type(node) != NODE_ZSUPER &&
+ (mid == rb_intern("initialize" )|| mid == rb_intern("initialize_copy"))) {
+ noex = NOEX_PRIVATE | noex;
+ }
+ else if (FL_TEST(klass, FL_SINGLETON) && node && nd_type(node) == NODE_CFUNC &&
+ mid == rb_intern("allocate")) {
+ rb_warn("defining %s.allocate is deprecated; use rb_define_alloc_func()",
+ rb_class2name(rb_iv_get(klass, "__attached__")));
+ mid = ID_ALLOCATOR;
+ }
+ if (OBJ_FROZEN(klass)){
+ rb_error_frozen("class/module");
+ }
+ rb_clear_cache_by_id(mid);
+ body = NEW_METHOD(node, noex);
+ st_insert(RCLASS(klass)->m_tbl, mid, (st_data_t)body);
+ if (node && mid != ID_ALLOCATOR && ruby_running) {
+ if (FL_TEST(klass, FL_SINGLETON)) {
+ rb_funcall(rb_iv_get(klass, "__attached__"), singleton_added, 1, ID2SYM(mid));
}
- if (!FL_TEST(klass, FL_SINGLETON) &&
- node && nd_type(node) != NODE_ZSUPER &&
- (mid == rb_intern("initialize" )|| mid == rb_intern("initialize_copy"))) {
- noex = NOEX_PRIVATE | noex;
+ else {
+ rb_funcall(klass, added, 1, ID2SYM(mid));
}
- else if (FL_TEST(klass, FL_SINGLETON) && node && nd_type(node) == NODE_CFUNC &&
- mid == rb_intern("allocate")) {
- rb_warn("defining %s.allocate is deprecated; use rb_define_alloc_func()",
- rb_class2name(rb_iv_get(klass, "__attached__")));
- mid = ID_ALLOCATOR;
- }
- if (OBJ_FROZEN(klass)) rb_error_frozen("class/module");
- rb_clear_cache_by_id(mid);
- body = NEW_METHOD(node, noex);
- st_insert(RCLASS(klass)->m_tbl, mid, (st_data_t)body);
- if (node && mid != ID_ALLOCATOR && ruby_running) {
- if (FL_TEST(klass, FL_SINGLETON)) {
- rb_funcall(rb_iv_get(klass, "__attached__"), singleton_added, 1, ID2SYM(mid));
- }
- else {
- rb_funcall(klass, added, 1, ID2SYM(mid));
- }
- }
+ }
}
void
-rb_define_alloc_func(klass, func)
- VALUE klass;
- VALUE (*func) _((VALUE));
+rb_define_alloc_func(VALUE klass, VALUE (*func) _((VALUE)))
{
- Check_Type(klass, T_CLASS);
- rb_add_method(CLASS_OF(klass), ID_ALLOCATOR, NEW_CFUNC(func, 0), NOEX_PRIVATE);
+ Check_Type(klass, T_CLASS);
+ rb_add_method(CLASS_OF(klass), ID_ALLOCATOR, NEW_CFUNC(func, 0), NOEX_PRIVATE);
}
void
-rb_undef_alloc_func(klass)
- VALUE klass;
+rb_undef_alloc_func(VALUE klass)
{
- Check_Type(klass, T_CLASS);
- rb_add_method(CLASS_OF(klass), ID_ALLOCATOR, 0, NOEX_UNDEF);
+ Check_Type(klass, T_CLASS);
+ rb_add_method(CLASS_OF(klass), ID_ALLOCATOR, 0, NOEX_UNDEF);
}
static NODE*
-search_method(klass, id, origin)
- VALUE klass, *origin;
- ID id;
+search_method(VALUE klass, ID id, VALUE *origin)
{
- NODE *body;
+ NODE *body;
+ if (!klass) return 0;
+ while (!st_lookup(RCLASS(klass)->m_tbl, id, (st_data_t *)&body)) {
+ klass = RCLASS(klass)->super;
if (!klass) return 0;
- while (!st_lookup(RCLASS(klass)->m_tbl, id, (st_data_t *)&body)) {
- klass = RCLASS(klass)->super;
- if (!klass) return 0;
- }
+ }
- if (origin) *origin = klass;
- return body;
+ if (origin) *origin = klass;
+ return body;
}
NODE*
-rb_get_method_body(klassp, idp, noexp)
- VALUE *klassp;
- ID *idp;
- int *noexp;
+rb_get_method_body(VALUE *klassp, ID *idp, int *noexp)
{
- ID id = *idp;
- VALUE klass = *klassp;
- VALUE origin;
- NODE * volatile body;
- struct cache_entry *ent;
+ ID id = *idp;
+ VALUE klass = *klassp;
+ VALUE origin;
+ NODE * volatile body;
+ struct cache_entry *ent;
- if ((body = search_method(klass, id, &origin)) == 0 || !body->nd_body) {
- /* store empty info in cache */
- ent = cache + EXPR1(klass, id);
- ent->klass = klass;
- ent->origin = klass;
- ent->mid = ent->mid0 = id;
- ent->noex = 0;
- ent->method = 0;
+ if ((body = search_method(klass, id, &origin)) == 0 || !body->nd_body) {
+ /* store empty info in cache */
+ ent = cache + EXPR1(klass, id);
+ ent->klass = klass;
+ ent->origin = klass;
+ ent->mid = ent->mid0 = id;
+ ent->noex = 0;
+ ent->method = 0;
- return 0;
- }
+ return 0;
+ }
- if (ruby_running) {
- /* store in cache */
- ent = cache + EXPR1(klass, id);
- ent->klass = klass;
- ent->noex = body->nd_noex;
- if (noexp) *noexp = body->nd_noex;
- body = body->nd_body;
- if (nd_type(body) == NODE_FBODY) {
- ent->mid = id;
- *klassp = body->nd_orig;
- ent->origin = body->nd_orig;
- *idp = ent->mid0 = body->nd_mid;
- body = ent->method = body->nd_head;
- }
- else {
- *klassp = origin;
- ent->origin = origin;
- ent->mid = ent->mid0 = id;
- ent->method = body;
- }
+ if (ruby_running) {
+ /* store in cache */
+ ent = cache + EXPR1(klass, id);
+ ent->klass = klass;
+ ent->noex = body->nd_noex;
+ if (noexp) *noexp = body->nd_noex;
+ body = body->nd_body;
+ if (nd_type(body) == NODE_FBODY) {
+ ent->mid = id;
+ *klassp = body->nd_orig;
+ ent->origin = body->nd_orig;
+ *idp = ent->mid0 = body->nd_mid;
+ body = ent->method = body->nd_head;
}
else {
- if (noexp) *noexp = body->nd_noex;
- body = body->nd_body;
- if (nd_type(body) == NODE_FBODY) {
- *klassp = body->nd_orig;
- *idp = body->nd_mid;
- body = body->nd_head;
- }
- else {
- *klassp = origin;
- }
+ *klassp = origin;
+ ent->origin = origin;
+ ent->mid = ent->mid0 = id;
+ ent->method = body;
}
+ }
+ else {
+ if (noexp) *noexp = body->nd_noex;
+ body = body->nd_body;
+ if (nd_type(body) == NODE_FBODY) {
+ *klassp = body->nd_orig;
+ *idp = body->nd_mid;
+ body = body->nd_head;
+ }
+ else {
+ *klassp = origin;
+ }
+ }
- return body;
+ return body;
}
NODE*
-rb_method_node(klass, id)
- VALUE klass;
- ID id;
+rb_method_node(VALUE klass, ID id)
{
- int noex;
- struct cache_entry *ent;
+ int noex;
+ struct cache_entry *ent;
- ent = cache + EXPR1(klass, id);
- if (ent->mid == id && ent->klass == klass && ent->method){
- return ent->method;
- }
+ ent = cache + EXPR1(klass, id);
+ if (ent->mid == id && ent->klass == klass && ent->method){
+ return ent->method;
+ }
- return rb_get_method_body(&klass, &id, &noex);
+ return rb_get_method_body(&klass, &id, &noex);
}
static void
-remove_method(klass, mid)
- VALUE klass;
- ID mid;
+remove_method(VALUE klass, ID mid)
{
- NODE *body;
+ NODE *body;
- if (klass == rb_cObject) {
- rb_secure(4);
- }
- if (ruby_safe_level >= 4 && !OBJ_TAINTED(klass)) {
- rb_raise(rb_eSecurityError, "Insecure: can't remove method");
- }
- if (OBJ_FROZEN(klass)) rb_error_frozen("class/module");
- if (mid == __id__ || mid == __send__ || mid == init) {
- rb_warn("removing `%s' may cause serious problem", rb_id2name(mid));
- }
- if (!st_delete(RCLASS(klass)->m_tbl, &mid, (st_data_t *)&body) ||
- !body->nd_body) {
- rb_name_error(mid, "method `%s' not defined in %s",
- rb_id2name(mid), rb_class2name(klass));
- }
- rb_clear_cache_for_undef(klass, mid);
- if (FL_TEST(klass, FL_SINGLETON)) {
- rb_funcall(rb_iv_get(klass, "__attached__"), singleton_removed, 1, ID2SYM(mid));
- }
- else {
- rb_funcall(klass, removed, 1, ID2SYM(mid));
- }
+ if (klass == rb_cObject) {
+ rb_secure(4);
+ }
+ if (ruby_safe_level >= 4 && !OBJ_TAINTED(klass)) {
+ rb_raise(rb_eSecurityError, "Insecure: can't remove method");
+ }
+ if (OBJ_FROZEN(klass)) rb_error_frozen("class/module");
+ if (mid == __id__ || mid == __send__ || mid == init) {
+ rb_warn("removing `%s' may cause serious problem", rb_id2name(mid));
+ }
+ if (!st_delete(RCLASS(klass)->m_tbl, &mid, (st_data_t *)&body) ||
+ !body->nd_body) {
+ rb_name_error(mid, "method `%s' not defined in %s",
+ rb_id2name(mid), rb_class2name(klass));
+ }
+ rb_clear_cache_for_undef(klass, mid);
+ if (FL_TEST(klass, FL_SINGLETON)) {
+ rb_funcall(rb_iv_get(klass, "__attached__"), singleton_removed, 1, ID2SYM(mid));
+ }
+ else {
+ rb_funcall(klass, removed, 1, ID2SYM(mid));
+ }
}
void
@@ -278,36 +262,29 @@
*/
static VALUE
-rb_mod_remove_method(argc, argv, mod)
- int argc;
- VALUE *argv;
- VALUE mod;
+rb_mod_remove_method(int argc, VALUE *argv, VALUE mod)
{
- int i;
+ int i;
- for (i=0; i<argc; i++) {
- remove_method(mod, rb_to_id(argv[i]));
- }
- return mod;
+ for (i=0; i<argc; i++) {
+ remove_method(mod, rb_to_id(argv[i]));
+ }
+ return mod;
}
#undef rb_disable_super
#undef rb_enable_super
void
-rb_disable_super(klass, name)
- VALUE klass;
- const char *name;
+rb_disable_super(VALUE klass, const char *name)
{
- /* obsolete - no use */
+ /* obsolete - no use */
}
void
-rb_enable_super(klass, name)
- VALUE klass;
- const char *name;
+rb_enable_super(VALUE klass, const char *name)
{
- rb_warning("rb_enable_super() is obsolete");
+ rb_warning("rb_enable_super() is obsolete");
}
static void
@@ -365,50 +342,49 @@
}
void
-rb_attr(klass, id, read, write, ex)
- VALUE klass;
- ID id;
- int read, write, ex;
+rb_attr(VALUE klass, ID id, int read, int write, int ex)
{
- const char *name;
- char *buf;
- ID attriv;
- int noex;
- size_t len;
+ const char *name;
+ char *buf;
+ ID attriv;
+ int noex;
+ size_t len;
- if (!ex) noex = NOEX_PUBLIC;
- else {
- if (SCOPE_TEST(SCOPE_PRIVATE)) {
- noex = NOEX_PRIVATE;
- rb_warning((scope_vmode == SCOPE_MODFUNC) ?
- "attribute accessor as module_function" :
- "private attribute?");
- }
- else if (SCOPE_TEST(SCOPE_PROTECTED)) {
- noex = NOEX_PROTECTED;
- }
- else {
- noex = NOEX_PUBLIC;
- }
+ if (!ex) {
+ noex = NOEX_PUBLIC;
+ }
+ else {
+ if (SCOPE_TEST(SCOPE_PRIVATE)) {
+ noex = NOEX_PRIVATE;
+ rb_warning((scope_vmode == SCOPE_MODFUNC) ?
+ "attribute accessor as module_function" :
+ "private attribute?");
}
-
- if (!rb_is_local_id(id) && !rb_is_const_id(id)) {
- rb_name_error(id, "invalid attribute name `%s'", rb_id2name(id));
+ else if (SCOPE_TEST(SCOPE_PROTECTED)) {
+ noex = NOEX_PROTECTED;
}
- name = rb_id2name(id);
- if (!name) {
- rb_raise(rb_eArgError, "argument needs to be symbol or string");
+ else {
+ noex = NOEX_PUBLIC;
}
- len = strlen(name)+2;
- buf = ALLOCA_N(char,len);
- snprintf(buf, len, "@%s", name);
- attriv = rb_intern(buf);
- if (read) {
- rb_add_method(klass, id, NEW_IVAR(attriv), noex);
- }
- if (write) {
- rb_add_method(klass, rb_id_attrset(id), NEW_ATTRSET(attriv), noex);
- }
+ }
+
+ if (!rb_is_local_id(id) && !rb_is_const_id(id)) {
+ rb_name_error(id, "invalid attribute name `%s'", rb_id2name(id));
+ }
+ name = rb_id2name(id);
+ if (!name) {
+ rb_raise(rb_eArgError, "argument needs to be symbol or string");
+ }
+ len = strlen(name)+2;
+ buf = ALLOCA_N(char,len);
+ snprintf(buf, len, "@%s", name);
+ attriv = rb_intern(buf);
+ if (read) {
+ rb_add_method(klass, id, NEW_IVAR(attriv), noex);
+ }
+ if (write) {
+ rb_add_method(klass, rb_id_attrset(id), NEW_ATTRSET(attriv), noex);
+ }
}
static VALUE
@@ -542,53 +518,51 @@
}
void
-rb_alias(klass, name, def)
- VALUE klass;
- ID name, def;
+rb_alias(VALUE klass, ID name, ID def)
{
- VALUE origin;
- NODE *orig, *body, *node;
- VALUE singleton = 0;
+ VALUE origin;
+ NODE *orig, *body, *node;
+ VALUE singleton = 0;
- rb_frozen_class_p(klass);
- if (name == def) return;
- if (klass == rb_cObject) {
- rb_secure(4);
+ rb_frozen_class_p(klass);
+ if (name == def) return;
+ if (klass == rb_cObject) {
+ rb_secure(4);
+ }
+ orig = search_method(klass, def, &origin);
+ if (!orig || !orig->nd_body) {
+ if (TYPE(klass) == T_MODULE) {
+ orig = search_method(rb_cObject, def, &origin);
}
- orig = search_method(klass, def, &origin);
- if (!orig || !orig->nd_body) {
- if (TYPE(klass) == T_MODULE) {
- orig = search_method(rb_cObject, def, &origin);
- }
- }
- if (!orig || !orig->nd_body) {
- print_undef(klass, def);
- }
- if (FL_TEST(klass, FL_SINGLETON)) {
- singleton = rb_iv_get(klass, "__attached__");
- }
- body = orig->nd_body;
- orig->nd_cnt++;
- if (nd_type(body) == NODE_FBODY) { /* was alias */
- def = body->nd_mid;
- origin = body->nd_orig;
- body = body->nd_head;
- }
+ }
+ if (!orig || !orig->nd_body) {
+ print_undef(klass, def);
+ }
+ if (FL_TEST(klass, FL_SINGLETON)) {
+ singleton = rb_iv_get(klass, "__attached__");
+ }
+ body = orig->nd_body;
+ orig->nd_cnt++;
+ if (nd_type(body) == NODE_FBODY) { /* was alias */
+ def = body->nd_mid;
+ origin = body->nd_orig;
+ body = body->nd_head;
+ }
- rb_clear_cache_by_id(name);
- if (RTEST(ruby_verbose) && st_lookup(RCLASS(klass)->m_tbl, name, (st_data_t *)&node)) {
- if (node->nd_cnt == 0 && node->nd_body) {
- rb_warning("discarding old %s", rb_id2name(name));
- }
+ rb_clear_cache_by_id(name);
+ if (RTEST(ruby_verbose) && st_lookup(RCLASS(klass)->m_tbl, name, (st_data_t *)&node)) {
+ if (node->nd_cnt == 0 && node->nd_body) {
+ rb_warning("discarding old %s", rb_id2name(name));
}
- st_insert(RCLASS(klass)->m_tbl, name,
- (st_data_t)NEW_METHOD(NEW_FBODY(body, def, origin), orig->nd_noex));
- if (singleton) {
- rb_funcall(singleton, singleton_added, 1, ID2SYM(name));
- }
- else {
- rb_funcall(klass, added, 1, ID2SYM(name));
- }
+ }
+ st_insert(RCLASS(klass)->m_tbl, name,
+ (st_data_t)NEW_METHOD(NEW_FBODY(body, def, origin), orig->nd_noex));
+ if (singleton) {
+ rb_funcall(singleton, singleton_added, 1, ID2SYM(name));
+ }
+ else {
+ rb_funcall(klass, added, 1, ID2SYM(name));
+ }
}
/*
Modified: trunk/eval_thread.c
===================================================================
--- trunk/eval_thread.c 2005-11-21 12:22:32 UTC (rev 297)
+++ trunk/eval_thread.c 2005-11-28 00:10:29 UTC (rev 298)
@@ -1850,7 +1850,7 @@
return;
}
}
- th_signm = sig;
+ th_signm = (char *)sig;
curr_thread = main_thread;
rb_thread_restore_context(curr_thread, RESTORE_SIGNAL);
}
Modified: trunk/insns.def
===================================================================
--- trunk/insns.def 2005-11-21 12:22:32 UTC (rev 297)
+++ trunk/insns.def 2005-11-28 00:10:29 UTC (rev 298)
@@ -1215,11 +1215,15 @@
VALUE klass;
yarv_block_t *blockptr = 0;
ulong num = op_argc;
- macro_eval_setup_send_arguments(num, recv, blockptr, flag, blockval);
+ int noex;
+ macro_eval_setup_send_arguments(num, blockptr, flag, blockval);
+ recv = TOPN(num);
+ klass = CLASS_OF(recv);
+
+
// dpi(id);
-
- mn = eval_method_search(id, klass, ic);
+ mn = eval_method_search(id, klass, ic, &noex);
#if CURRENT_INSN_send || CURRENT_INSN_send_SC_xx_ax
#if !YARV_AOT_COMPILED
@@ -1243,6 +1247,7 @@
klass = CLASS_OF(recv);
blockptr = 0;
mn = rb_method_node(klass, id);
+ noex = 0; // TODO
}
if(0){
LABEL_IS_SC(start_init_in_super):
@@ -1257,12 +1262,13 @@
}
id = rb_to_id(ip->name);
- num = (ulong)tmp_id;
+ num = tmp_num;
recv = GET_SELF();
klass = eval_search_super_klass(ip->klass, recv);
- blockptr = GET_BLOCK_PTR();
- mn = rb_method_node(klass, id);
+ blockptr = tmp_blockptr;
+ mn = rb_method_node(klass, id);
+ noex = 0;
}
}
if(0){
@@ -1280,11 +1286,11 @@
id = rb_to_id(ip->name);
num = ip->argc;
recv = GET_SELF();
-
klass = eval_search_super_klass(ip->klass, recv);
- blockptr = GET_BLOCK_PTR();
+ blockptr = tmp_blockptr;
mn = rb_method_node(klass, id);
+ noex = 0;
/* copy locals */
sp = GET_SP();
@@ -1298,7 +1304,7 @@
}
#endif
#endif
- macro_eval_invoke_method(recv, klass, id, num, mn, blockptr);
+ macro_eval_invoke_method(recv, klass, id, num, mn, noex, blockptr);
}
/**
@@ -1308,7 +1314,7 @@
*/
DEFINE_INSN
super
-(ulong num, ulong flag)
+(ulong op_argc, VALUE blockval, ulong flag)
(...)
(VALUE val)
{
@@ -1316,8 +1322,13 @@
#if YARV_AOT_COMPILED
rb_bug("...");
#else
- /* expand flag */
- tmp_id = (ID)num;
+ tmp_num = op_argc;
+ tmp_blockptr = 0;
+ macro_eval_setup_send_arguments(tmp_num, tmp_blockptr,
+ flag, blockval);
+ if(!tmp_blockptr){
+ tmp_blockptr = GET_BLOCK_PTR();
+ }
goto LABEL_IS_SC(start_init_in_super);
#endif
}
@@ -1329,13 +1340,23 @@
*/
DEFINE_INSN
zsuper
-()
+(VALUE blockval)
(...)
(VALUE val)
{
#if YARV_AOT_COMPILED
#else
- // TODO
+ tmp_blockptr = 0;
+ if(blockval){
+ yarv_iseq_t *blockiseq;
+ GetISeqVal(blockval, blockiseq);
+ tmp_blockptr = GET_BLOCK_PTR_IN_CFP(GET_CFP());
+ tmp_blockptr->iseq = blockiseq;
+ tmp_blockptr->proc = 0;
+ }
+ else{
+ tmp_blockptr = GET_BLOCK_PTR();
+ }
goto LABEL_IS_SC(start_init_in_zsuper);
#endif
}
@@ -2298,6 +2319,53 @@
/**
@c optimize
+ @e optimized succ
+ @j optimized succ
+ */
+DEFINE_INSN
+opt_succ
+()
+(VALUE recv)
+(VALUE val)
+{
+ if(SPECIAL_CONST_P(recv)){
+ if(FIXNUM_P(recv) && BASIC_OP_UNREDEFINED(FIXNUM_SUCC)){
+ const VALUE obj = INT2FIX(1);
+ /* fixnum + INT2FIX(1) */
+ val = (recv + (obj & (~1)));
+ if((~(recv^obj)&(recv^val))&0x80000000){
+ val = rb_big_plus(rb_int2big(INT2FIX(recv)),
+ rb_int2big(INT2FIX(obj)));
+ }
+ }
+ else{
+ goto INSN_LABEL(normal_dispatch);
+ }
+ }
+ else{
+ if(HEAP_CLASS_OF(recv) == rb_cString){
+ val = rb_str_succ(recv);
+ }
+ else if(HEAP_CLASS_OF(recv) == rb_cTime){
+ val = rb_time_succ(recv);
+ }
+ else{
+ goto INSN_LABEL(normal_dispatch);
+ }
+ }
+ if(0){
+ INSN_LABEL(normal_dispatch):
+ /* other */
+#ifdef YARV_AOT_COMPILED
+ val = rb_funcall(recv, idSucc, 0);
+#else
+ val = rb_funcall(recv, idSucc, 0);
+#endif
+ }
+}
+
+/**
+ @c optimize
@e optimized regexp match
@j KK\}b`
*/
Added: trunk/lib/tempfile.rb
===================================================================
--- trunk/lib/tempfile.rb 2005-11-21 12:22:32 UTC (rev 297)
+++ trunk/lib/tempfile.rb 2005-11-28 00:10:29 UTC (rev 298)
@@ -0,0 +1,195 @@
+#
+# tempfile - manipulates temporary files
+#
+# $Id: tempfile.rb,v 1.28 2005/05/11 01:46:00 ocean Exp $
+#
+
+require 'delegate'
+require 'tmpdir'
+
+# A class for managing temporary files. This library is written to be
+# thread safe.
+class Tempfile < DelegateClass(File)
+ MAX_TRY = 10
+ @@cleanlist = []
+
+ # Creates a temporary file of mode 0600 in the temporary directory
+ # whose name is basename.pid.n and opens with mode "w+". A Tempfile
+ # object works just like a File object.
+ #
+ # If tmpdir is omitted, the temporary directory is determined by
+ # Dir::tmpdir provided by 'tmpdir.rb'.
+ # When $SAFE > 0 and the given tmpdir is tainted, it uses
+ # /tmp. (Note that ENV values are tainted by default)
+ def initialize(basename, tmpdir=Dir::tmpdir)
+ if $SAFE > 0 and tmpdir.tainted?
+ tmpdir = '/tmp'
+ end
+
+ lock = nil
+ n = failure = 0
+
+ begin
+ Thread.critical = true
+
+ begin
+ tmpname = File.join(tmpdir, make_tmpname(basename, n))
+ lock = tmpname + '.lock'
+ n += 1
+ end while cleanlist.include?(tmpname) or
+ File.exist?(lock) or File.exist?(tmpname)
+
+ Dir.mkdir(lock)
+ rescue
+ failure += 1
+ retry if failure < MAX_TRY
+ raise "cannot generate tempfile `%s'" % tmpname
+ ensure
+ Thread.critical = false
+ end
+
+ @data = [tmpname]
+ @clean_proc = Tempfile.callback(@data)
+ ObjectSpace.define_finalizer(self, @clean_proc)
+
+ @tmpfile = File.open(tmpname, File::RDWR|File::CREAT|File::EXCL, 0600)
+ @tmpname = tmpname
+ @@cleanlist << @tmpname
+ @data[1] = @tmpfile
+ @data[2] = @@cleanlist
+
+ super(@tmpfile)
+
+ # Now we have all the File/IO methods defined, you must not
+ # carelessly put bare puts(), etc. after this.
+
+ Dir.rmdir(lock)
+ end
+
+ def make_tmpname(basename, n)
+ sprintf('%s%d.%d', basename, $$, n)
+ end
+ private :make_tmpname
+
+ # Opens or reopens the file with mode "r+".
+ def open
+ @tmpfile.close if @tmpfile
+ @tmpfile = File.open(@tmpname, 'r+')
+ @data[1] = @tmpfile
+ __setobj__(@tmpfile)
+ end
+
+ def _close # :nodoc:
+ @tmpfile.close if @tmpfile
+ @tmpfile = nil
+ @data[1] = nil if @data
+ end
+ protected :_close
+
+ #Closes the file. If the optional flag is true, unlinks the file
+ # after closing.
+ #
+ # If you don't explicitly unlink the temporary file, the removal
+ # will be delayed until the object is finalized.
+ def close(unlink_now=false)
+ if unlink_now
+ close!
+ else
+ _close
+ end
+ end
+
+ # Closes and unlinks the file.
+ def close!
+ _close
+ @clean_proc.call
+ ObjectSpace.undefine_finalizer(self)
+ @data = @tmpname = nil
+ end
+
+ # Unlinks the file. On UNIX-like systems, it is often a good idea
+ # to unlink a temporary file immediately after creating and opening
+ # it, because it leaves other programs zero chance to access the
+ # file.
+ def unlink
+ # keep this order for thread safeness
+ begin
+ File.unlink(@tmpname) if File.exist?(@tmpname)
+ cleanlist.delete( tmpname)
+ @data = @tmpname = nil
+ ObjectSpace.undefine_finalizer(self)
+ rescue Errno::EACCES
+ # may not be able to unlink on Windows; just ignore
+ end
+ end
+ alias delete unlink
+
+ # Returns the full path name of the temporary file.
+ def path
+ @tmpname
+ end
+
+ # Returns the size of the temporary file. As a side effect, the IO
+ # buffer is flushed before determining the size.
+ def size
+ if @tmpfile
+ @tmpfile.flush
+ @tmpfile.stat.size
+ else
+ 0
+ end
+ end
+ alias length size
+
+ class << self
+ def callback(data) # :nodoc:
+ pid = $$
+ Proc.new {
+ if pid == $$
+ path, tmpfile, cleanlist = *data
+
+ print "removing ", path, "..." if $DEBUG
+
+ tmpfile.close if tmpfile
+
+ # keep this order for thread safeness
+ File.unlink(path) if File.exist?(path)
+ cleanlist.delete(path) if cleanlist
+
+ print "done\n" if $DEBUG
+ end
+ }
+ end
+
+ # If no block is given, this is a synonym for new().
+ #
+ # If a block is given, it will be passed tempfile as an argument,
+ # and the tempfile will automatically be closed when the block
+ # terminates. In this case, open() returns nil.
+ def open(*args)
+ tempfile = new(*args)
+
+ if block_given?
+ begin
+ yield(tempfile)
+ ensure
+ tempfile.close
+ end
+
+ nil
+ else
+ tempfile
+ end
+ end
+ end
+end
+
+if __FILE__ == $0
+# $DEBUG = true
+ f = Tempfile.new("foo")
+ f.print("foo\n")
+ f.close
+ f.open
+ p f.gets # => "foo\n"
+ f.close!
+end
Added: trunk/lib/tmpdir.rb
===================================================================
--- trunk/lib/tmpdir.rb 2005-11-21 12:22:32 UTC (rev 297)
+++ trunk/lib/tmpdir.rb 2005-11-28 00:10:29 UTC (rev 298)
@@ -0,0 +1,42 @@
+#
+# tmpdir - retrieve temporary directory path
+#
+# $Id: tmpdir.rb,v 1.5 2003/07/26 15:38:58 eban Exp $
+#
+
+class Dir
+
+ @@systmpdir = '/tmp'
+
+ begin
+ require 'Win32API'
+ max_pathlen = 260
+ windir = ' '*(max_pathlen+1)
+ begin
+ getdir = Win32API.new('kernel32', 'GetSystemWindowsDirectory', 'PL', 'L')
+ rescue RuntimeError
+ getdir = Win32API.new('kernel32', 'GetWindowsDirectory', 'PL', 'L')
+ end
+ getdir.call(windir, windir.size)
+ windir = File.expand_path(windir.rstrip.untaint)
+ temp = File.join(windir, 'temp')
+ @@systmpdir = temp if File.directory?(temp) and File.writable?(temp)
+ rescue LoadError
+ end
+
+ def Dir::tmpdir
+ tmp = '.'
+ if $SAFE > 0
+ tmp = @@systmpdir
+ else
+ for dir in [ENV['TMPDIR'], ENV['TMP'], ENV['TEMP'],
+ ENV['USERPROFILE'], @@systmpdir, '/tmp']
+ if dir and File.directory?(dir) and File.writable?(dir)
+ tmp = dir
+ break
+ end
+ end
+ end
+ File.expand_path(tmp)
+ end
+end
Modified: trunk/string.c
===================================================================
--- trunk/string.c 2005-11-21 12:22:32 UTC (rev 297)
+++ trunk/string.c 2005-11-28 00:10:29 UTC (rev 298)
@@ -1283,7 +1283,7 @@
* "***".succ #=> "**+"
*/
-static VALUE
+VALUE
rb_str_succ(VALUE orig)
{
VALUE str;
Modified: trunk/test.rb
===================================================================
--- trunk/test.rb 2005-11-21 12:22:32 UTC (rev 297)
+++ trunk/test.rb 2005-11-28 00:10:29 UTC (rev 298)
@@ -1,6 +1,21 @@
+prs = []
+3.times{|i|
+ a = i+1
+ b = i*2
+ prs << lambda{p [a, b]}
+}
+prs.each{|pr|
+ pr.call
+}
-p [1, 2, 3].map{|e|
- p e
- e = e * 2
- e
+__END__
+prs = []
+1.times{|e|
+3.times{|e|
+ prs << lambda{p e}
}
+}
+prs.each{|pr|
+ pr.call
+}
+
Modified: trunk/time.c
===================================================================
--- trunk/time.c 2005-11-21 12:22:32 UTC (rev 297)
+++ trunk/time.c 2005-11-28 00:10:29 UTC (rev 298)
@@ -1325,6 +1325,12 @@
return rb_time_new(tobj->tv.tv_sec + 1, tobj->tv.tv_usec);
}
+VALUE
+rb_time_succ(VALUE time)
+{
+ return time_succ(time);
+}
+
/*
* call-seq:
* time.sec => fixnum
Modified: trunk/vm.c
===================================================================
--- trunk/vm.c 2005-11-21 12:22:32 UTC (rev 297)
+++ trunk/vm.c 2005-11-28 00:10:29 UTC (rev 298)
@@ -911,8 +911,19 @@
return klass;
}
+EVALBODY_HELPER_FUNCTION VALUE
+eval_method_missing(yarv_thread_t *th, ID id, VALUE recv, int num, int opt){
+ yarv_control_frame_t *reg_cfp = th->cfp;
+ VALUE *argv = STACK_ADDR_FROM_TOP(num+1);
+ VALUE val;
+ argv[0] = ID2SYM(id);
+ val = rb_funcall2(recv, idMethodMissing, num+1, argv);
+ POPN(num+1);
+ return val;
+}
+
EVALBODY_HELPER_FUNCTION NODE*
-eval_method_search(VALUE id, VALUE klass, IC ic)
+eval_method_search(VALUE id, VALUE klass, IC ic, int *noex)
{
NODE *mn;
Modified: trunk/vm_evalbody.h
===================================================================
--- trunk/vm_evalbody.h 2005-11-21 12:22:32 UTC (rev 297)
+++ trunk/vm_evalbody.h 2005-11-28 00:10:29 UTC (rev 298)
@@ -66,6 +66,8 @@
#endif
ID tmp_id;
+ yarv_block_t *tmp_blockptr;
+ ulong tmp_num;
#if OPT_TOKEN_THREADED_CODE || OPT_DIRECT_THREADED_CODE
#include "vmtc.inc"
Modified: trunk/vm_macro.def
===================================================================
--- trunk/vm_macro.def 2005-11-21 12:22:32 UTC (rev 297)
+++ trunk/vm_macro.def 2005-11-28 00:10:29 UTC (rev 298)
@@ -3,7 +3,7 @@
/* */
-MACRO macro_eval_setup_send_arguments(num, recv, blockptr, flag, blockval)
+MACRO macro_eval_setup_send_arguments(num, blockptr, flag, blockval)
{
if(flag & VM_CALL_ARGS_BLOCKARG_BIT){
yarv_proc_t *po;
@@ -34,9 +34,6 @@
blockptr->proc = 0;
}
- recv = TOPN(num);
- klass = CLASS_OF(recv);
-
/* expand top of stack? */
if(flag & VM_CALL_ARGS_SPLAT_BIT){
VALUE ary = TOPN(0);
@@ -213,7 +210,7 @@
}
}
-MACRO macro_eval_invoke_method(recv, klass, id, num, mn, blockptr)
+MACRO macro_eval_invoke_method(recv, klass, id, num, mn, noex, blockptr)
{
/* method missing */
if(mn == 0){
@@ -222,12 +219,19 @@
rb_bug("method missing");
}
else{
- VALUE *argv = STACK_ADDR_FROM_TOP(num+1);
- argv[0] = ID2SYM(id);
- val = rb_funcall2(recv, idMethodMissing, num+1, argv);
+ val = eval_method_missing(th, id, recv, num, 0);
}
- POPN(num+1);
}
+ else if(0 && noex & (NOEX_PRIVATE | NOEX_PROTECTED)){
+ /* TODO: resarch call statistics */
+ if((noex & NOEX_PRIVATE) && !(flag & VM_CALL_FCALL_BIT)){
+ printf("call noex: %d\n", mn->nd_noex);
+ val = eval_method_missing(th, id, recv, num, NOEX_PRIVATE);
+ }
+ if(0 /* TODO */ && (noex & NOEX_PUBLIC)){
+ rb_bug("unsupport protected");
+ }
+ }
else{
switch(nd_type(mn)){
case YARV_METHOD_NODE:{
Modified: trunk/yarvcore.c
===================================================================
--- trunk/yarvcore.c 2005-11-21 12:22:32 UTC (rev 297)
+++ trunk/yarvcore.c 2005-11-28 00:10:29 UTC (rev 298)
@@ -47,6 +47,7 @@
ID idEach;
ID idLength;
ID idGets;
+ID idSucc;
ID idBitblt;
ID idAnswer;
@@ -1002,6 +1003,8 @@
idLength = rb_intern("length");
idIntern = rb_intern("intern");
idGets = rb_intern("gets");
+ idSucc = rb_intern("succ");
+
idMethodMissing = rb_intern("method_missing");
idThrowState = rb_intern("#__ThrowState__");
Modified: trunk/yarvcore.h
===================================================================
--- trunk/yarvcore.h 2005-11-21 12:22:32 UTC (rev 297)
+++ trunk/yarvcore.h 2005-11-28 00:10:29 UTC (rev 298)
@@ -114,6 +114,7 @@
extern ID idEach;
extern ID idLength;
extern ID idGets;
+extern ID idSucc;
extern ID idBitblt;
extern ID idAnswer;
Modified: trunk/yarvtest/test_class.rb
===================================================================
--- trunk/yarvtest/test_class.rb 2005-11-21 12:22:32 UTC (rev 297)
+++ trunk/yarvtest/test_class.rb 2005-11-28 00:10:29 UTC (rev 298)
@@ -178,6 +178,44 @@
end
end
+ def test_super2
+ ae %q{
+ class C
+ def m(a, b)
+ a+b
+ end
+ end
+
+ class D < C
+ def m arg
+ super(*arg)
+ end
+ end
+
+ D.new.m([1, 2])
+ }
+
+ ae %q{
+ class C
+ def m
+ yield
+ end
+ end
+
+ class D < C
+ def m
+ super(){
+ :D
+ }
+ end
+ end
+
+ D.new.m{
+ :top
+ }
+ }
+ end
+
def test_zsuper
ae %q{
class C
@@ -243,6 +281,26 @@
remove_const(:C2)
remove_const(:C3)
end
+
+ ae %q{
+ class C
+ def m
+ yield
+ end
+ end
+
+ class D < C
+ def m
+ super{
+ :D
+ }
+ end
+ end
+
+ D.new.m{
+ :top
+ }
+ }
end
def test_const_in_other_scope
--
ML: yarv-diff quickml.atdot.net
Info: http://www.atdot.net/~ko1/quickml