Feature #6242 » list3.diff
| common.mk | ||
|---|---|---|
| 		hash.$(OBJEXT) \ | ||
| 		inits.$(OBJEXT) \ | ||
| 		io.$(OBJEXT) \ | ||
| 		list.$(OBJEXT) \ | ||
| 		marshal.$(OBJEXT) \ | ||
| 		math.$(OBJEXT) \ | ||
| 		node.$(OBJEXT) \ | ||
| ... | ... | |
|   {$(VPATH)}internal.h | ||
| io.$(OBJEXT): {$(VPATH)}io.c $(RUBY_H_INCLUDES) {$(VPATH)}io.h \ | ||
|   {$(VPATH)}util.h $(ENCODING_H_INCLUDES) {$(VPATH)}dln.h {$(VPATH)}internal.h | ||
| list.$(OBJEXT): {$(VPATH)}list.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h \ | ||
|   $(ENCODING_H_INCLUDES) {$(VPATH)}internal.h {$(VPATH)}node.h | ||
| main.$(OBJEXT): {$(VPATH)}main.c $(RUBY_H_INCLUDES) {$(VPATH)}debug.h \ | ||
|   {$(VPATH)}node.h | ||
| marshal.$(OBJEXT): {$(VPATH)}marshal.c $(RUBY_H_INCLUDES) {$(VPATH)}io.h \ | ||
| gc.c | ||
|---|---|---|
| 	struct RMatch  match; | ||
| 	struct RRational rational; | ||
| 	struct RComplex complex; | ||
| 	struct RCons cons; | ||
|     } as; | ||
| #ifdef GC_DEBUG | ||
|     const char *file; | ||
| ... | ... | |
| 	gc_mark(objspace, obj->as.complex.imag, lev); | ||
| 	break; | ||
|       case T_CONS: | ||
| 	gc_mark(objspace, obj->as.cons.car, lev); | ||
| 	gc_mark(objspace, obj->as.cons.cdr, lev); | ||
| 	break; | ||
|       case T_STRUCT: | ||
| 	{ | ||
| 	    long len = RSTRUCT_LEN(obj); | ||
| include/ruby/ruby.h | ||
|---|---|---|
|     RUBY_T_MATCH  = 0x0d, | ||
|     RUBY_T_COMPLEX  = 0x0e, | ||
|     RUBY_T_RATIONAL = 0x0f, | ||
|     RUBY_T_CONS = 0x10, | ||
|     RUBY_T_NIL    = 0x11, | ||
|     RUBY_T_TRUE   = 0x12, | ||
| ... | ... | |
| #define T_SYMBOL RUBY_T_SYMBOL | ||
| #define T_RATIONAL RUBY_T_RATIONAL | ||
| #define T_COMPLEX RUBY_T_COMPLEX | ||
| #define T_CONS RUBY_T_CONS | ||
| #define T_UNDEF  RUBY_T_UNDEF | ||
| #define T_NODE   RUBY_T_NODE | ||
| #define T_ZOMBIE RUBY_T_ZOMBIE | ||
| ... | ... | |
|     VALUE imag; | ||
| }; | ||
| struct RCons { | ||
|     struct RBasic basic; | ||
|     VALUE car; | ||
|     VALUE cdr; | ||
| }; | ||
| struct RData { | ||
|     struct RBasic basic; | ||
|     void (*dmark)(void*); | ||
| ... | ... | |
| #define RFILE(obj)   (R_CAST(RFile)(obj)) | ||
| #define RRATIONAL(obj) (R_CAST(RRational)(obj)) | ||
| #define RCOMPLEX(obj) (R_CAST(RComplex)(obj)) | ||
| #define RCONS(obj)  (R_CAST(RCons)(obj)) | ||
| #define FL_SINGLETON FL_USER0 | ||
| #define FL_RESERVED1 (((VALUE)1)<<5) | ||
| ... | ... | |
| RUBY_EXTERN VALUE rb_cBignum; | ||
| RUBY_EXTERN VALUE rb_cBinding; | ||
| RUBY_EXTERN VALUE rb_cClass; | ||
| RUBY_EXTERN VALUE rb_cCons; | ||
| RUBY_EXTERN VALUE rb_cCont; | ||
| RUBY_EXTERN VALUE rb_cDir; | ||
| RUBY_EXTERN VALUE rb_cData; | ||
| ... | ... | |
| RUBY_EXTERN VALUE rb_cHash; | ||
| RUBY_EXTERN VALUE rb_cInteger; | ||
| RUBY_EXTERN VALUE rb_cIO; | ||
| RUBY_EXTERN VALUE rb_cList; | ||
| RUBY_EXTERN VALUE rb_cMatch; | ||
| RUBY_EXTERN VALUE rb_cMethod; | ||
| RUBY_EXTERN VALUE rb_cModule; | ||
| inits.c | ||
|---|---|---|
|     CALL(Cont); | ||
|     CALL(Rational); | ||
|     CALL(Complex); | ||
|     CALL(List); | ||
|     CALL(version); | ||
| } | ||
| #undef CALL | ||
| list.c | ||
|---|---|---|
| /********************************************************************** | ||
|   list.c - | ||
|   Copyright (C) 2012  Shugo Maeda | ||
| **********************************************************************/ | ||
| #include "ruby/ruby.h" | ||
| #include "ruby/util.h" | ||
| #include "ruby/encoding.h" | ||
| #include "internal.h" | ||
| #include "node.h" | ||
| VALUE rb_cCons; | ||
| static ID id_each; | ||
| static ID id_foldl; | ||
| static ID id_foldr; | ||
| static VALUE cons_new(VALUE car, VALUE cdr); | ||
| static VALUE | ||
| list_s_create(int argc, VALUE *argv, VALUE klass) | ||
| { | ||
|     if (argc == 0) { | ||
| 	return Qnil; | ||
|     } | ||
|     else { | ||
| 	int i; | ||
| 	VALUE cons = cons_new(argv[argc - 1], Qnil); | ||
| 	for (i = argc - 2; i >= 0; i--) { | ||
| 	    cons = cons_new(argv[i], cons); | ||
| 	} | ||
| 	return cons; | ||
|     } | ||
| } | ||
| static VALUE | ||
| list_cons(VALUE cdr, VALUE car) | ||
| { | ||
|     return cons_new(car, cdr); | ||
| } | ||
| static VALUE | ||
| cons_alloc(VALUE klass) | ||
| { | ||
|     NEWOBJ(ary, struct RCons); | ||
|     OBJSETUP(ary, klass, T_CONS); | ||
|     return (VALUE)ary; | ||
| } | ||
| static VALUE | ||
| cons_initialize(VALUE self, VALUE car, VALUE cdr) | ||
| { | ||
|     RCONS(self)->car = car; | ||
|     RCONS(self)->cdr = cdr; | ||
|     return Qnil; | ||
| } | ||
| static VALUE | ||
| cons_new(VALUE car, VALUE cdr) | ||
| { | ||
|     VALUE cons; | ||
|     cons = cons_alloc(rb_cCons); | ||
|     cons_initialize(cons, car, cdr); | ||
|     return cons; | ||
| } | ||
| static VALUE | ||
| cons_car(VALUE self) | ||
| { | ||
|     return RCONS(self)->car; | ||
| } | ||
| static VALUE | ||
| cons_cdr(VALUE self) | ||
| { | ||
|     return RCONS(self)->cdr; | ||
| } | ||
| static VALUE | ||
| cons_each(VALUE self) | ||
| { | ||
|     rb_yield(RCONS(self)->car); | ||
|     rb_funcall_passing_block(RCONS(self)->cdr, id_each, 0, 0); | ||
|     return Qnil; | ||
| } | ||
| static VALUE | ||
| nil_each(VALUE self) | ||
| { | ||
|     return Qnil; | ||
| } | ||
| static VALUE | ||
| cons_foldl(VALUE self, VALUE x) | ||
| { | ||
|     VALUE y = rb_yield_values(2, x, RCONS(self)->car); | ||
|     return rb_funcall_passing_block(RCONS(self)->cdr, id_foldl, 1, &y); | ||
| } | ||
| static VALUE | ||
| nil_foldl(VALUE self, VALUE x) | ||
| { | ||
|     return x; | ||
| } | ||
| static VALUE | ||
| cons_foldr(VALUE self, VALUE x) | ||
| { | ||
|     VALUE y = rb_funcall_passing_block(RCONS(self)->cdr, id_foldr, 1, &x); | ||
|     return rb_yield_values(2, RCONS(self)->car, y); | ||
| } | ||
| static VALUE | ||
| nil_foldr(VALUE self, VALUE x) | ||
| { | ||
|     return x; | ||
| } | ||
| static VALUE | ||
| list_plus_i(VALUE i, VALUE arg, int argc, VALUE *argv) | ||
| { | ||
|     if (argc != 2) { | ||
| 	rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", argc); | ||
|     } | ||
|     return cons_new(argv[0], argv[1]); | ||
| } | ||
| static VALUE | ||
| list_plus(VALUE self, VALUE other) | ||
| { | ||
|     return rb_block_call(self, id_foldr, 1, &other, list_plus_i, Qnil); | ||
| } | ||
| static VALUE | ||
| list_flatten_i(VALUE i, VALUE arg, int argc, VALUE *argv) | ||
| { | ||
|     if (argc != 2) { | ||
| 	rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", argc); | ||
|     } | ||
|     return rb_funcall(argv[0], '+', 1, argv[1]); | ||
| } | ||
| static VALUE | ||
| list_flatten(VALUE self) | ||
| { | ||
|     VALUE x = Qnil; | ||
|     return rb_block_call(self, id_foldr, 1, &x, list_flatten_i, Qnil); | ||
| } | ||
| static VALUE | ||
| list_map_i(VALUE i, VALUE arg, int argc, VALUE *argv) | ||
| { | ||
|     if (argc != 2) { | ||
| 	rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", argc); | ||
|     } | ||
|     return cons_new(rb_yield(argv[0]), argv[1]); | ||
| } | ||
| static VALUE | ||
| list_map(VALUE self) | ||
| { | ||
|     VALUE x = Qnil; | ||
|     return rb_block_call(self, id_foldr, 1, &x, list_map_i, Qnil); | ||
| } | ||
| static VALUE | ||
| list_flat_map_i(VALUE i, VALUE arg, int argc, VALUE *argv) | ||
| { | ||
|     if (argc != 2) { | ||
| 	rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", argc); | ||
|     } | ||
|     return rb_funcall(rb_yield(argv[0]), '+', 1, argv[1]); | ||
| } | ||
| static VALUE | ||
| list_flat_map(VALUE self) | ||
| { | ||
|     VALUE x = Qnil; | ||
|     return rb_block_call(self, id_foldr, 1, &x, list_flat_map_i, Qnil); | ||
| } | ||
| static VALUE | ||
| list_filter_i(VALUE i, VALUE arg, int argc, VALUE *argv) | ||
| { | ||
|     if (argc != 2) { | ||
| 	rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", argc); | ||
|     } | ||
|     if (RTEST(rb_yield(argv[0]))) { | ||
| 	return cons_new(argv[0], argv[1]); | ||
|     } | ||
|     else { | ||
| 	return argv[1]; | ||
|     } | ||
| } | ||
| static VALUE | ||
| list_filter(VALUE self) | ||
| { | ||
|     VALUE x = Qnil; | ||
|     return rb_block_call(self, id_foldr, 1, &x, list_filter_i, Qnil); | ||
| } | ||
| static VALUE | ||
| list_length_i(VALUE i, VALUE arg, int argc, VALUE *argv) | ||
| { | ||
|     if (argc != 2) { | ||
| 	rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", argc); | ||
|     } | ||
|     return LONG2NUM(NUM2LONG(argv[0]) + 1); | ||
| } | ||
| static VALUE | ||
| list_length(VALUE self) | ||
| { | ||
|     VALUE n = LONG2NUM(0); | ||
|     return rb_block_call(self, id_foldl, 1, &n, list_length_i, Qnil); | ||
| } | ||
| static VALUE | ||
| list_sum_i(VALUE i, VALUE arg, int argc, VALUE *argv) | ||
| { | ||
|     if (argc != 2) { | ||
| 	rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", argc); | ||
|     } | ||
|     return rb_funcall(argv[0], '+', 1, argv[1]); | ||
| } | ||
| static VALUE | ||
| list_sum(VALUE self) | ||
| { | ||
|     VALUE n = LONG2NUM(0); | ||
|     return rb_block_call(self, id_foldl, 1, &n, list_sum_i, Qnil); | ||
| } | ||
| static VALUE | ||
| list_reverse_i(VALUE i, VALUE arg, int argc, VALUE *argv) | ||
| { | ||
|     if (argc != 2) { | ||
| 	rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", argc); | ||
|     } | ||
|     return cons_new(argv[1], argv[0]); | ||
| } | ||
| static VALUE | ||
| list_reverse(VALUE self) | ||
| { | ||
|     VALUE x = Qnil; | ||
|     return rb_block_call(self, id_foldl, 1, &x, list_reverse_i, Qnil); | ||
| } | ||
| static VALUE | ||
| cons_inspect_i(VALUE i, VALUE arg, int argc, VALUE *argv) | ||
| { | ||
|     NODE *memo = RNODE(arg); | ||
|     VALUE str = memo->u1.value; | ||
|     long is_first = memo->u3.state; | ||
|     if (is_first) { | ||
| 	memo->u3.state = FALSE; | ||
|     } | ||
|     else { | ||
| 	rb_str_cat2(str, ", "); | ||
|     } | ||
|     rb_str_concat(str, rb_inspect(i)); | ||
|     return Qnil; | ||
| } | ||
| static VALUE | ||
| cons_inspect(VALUE self) | ||
| { | ||
|     VALUE str = rb_str_new2("S["); | ||
|     NODE *memo = NEW_MEMO(str, 0, TRUE); | ||
|     rb_block_call(self, id_each, 0, 0, cons_inspect_i, (VALUE) memo); | ||
|     rb_str_cat2(str, "]"); | ||
|     return str; | ||
| } | ||
| void | ||
| Init_List(void) | ||
| { | ||
|     rb_define_global_const("S", rb_cList); | ||
|     rb_include_module(rb_cList, rb_mEnumerable); | ||
|     rb_define_singleton_method(rb_cList, "[]", list_s_create, -1); | ||
|     rb_define_method(rb_cList, ":::", list_cons, 1); | ||
|     rb_cCons  = rb_define_class("Cons", rb_cList); | ||
|     rb_define_alloc_func(rb_cCons, cons_alloc); | ||
|     rb_define_method(rb_cCons, "initialize", cons_initialize, 2); | ||
|     rb_define_method(rb_cCons, "car", cons_car, 0); | ||
|     rb_define_method(rb_cCons, "head", cons_car, 0); | ||
|     rb_define_method(rb_cCons, "cdr", cons_cdr, 0); | ||
|     rb_define_method(rb_cCons, "tail", cons_cdr, 0); | ||
|     rb_define_method(rb_cCons, "each", cons_each, 0); | ||
|     rb_define_method(rb_cNilClass, "each", nil_each, 0); | ||
|     rb_define_method(rb_cCons, "foldl", cons_foldl, 1); | ||
|     rb_define_method(rb_cNilClass, "foldl", nil_foldl, 1); | ||
|     rb_define_method(rb_cCons, "foldr", cons_foldr, 1); | ||
|     rb_define_method(rb_cNilClass, "foldr", nil_foldr, 1); | ||
|     rb_define_method(rb_cList, "+", list_plus, 1); | ||
|     rb_define_method(rb_cList, "flatten", list_flatten, 0); | ||
|     rb_define_method(rb_cList, "concat", list_flatten, 0); | ||
|     rb_define_method(rb_cList, "map", list_map, 0); | ||
|     rb_define_method(rb_cList, "flat_map", list_flat_map, 0); | ||
|     rb_define_method(rb_cList, "concat_map", list_flat_map, 0); | ||
|     rb_define_method(rb_cList, "filter", list_filter, 0); | ||
|     rb_define_method(rb_cList, "length", list_length, 0); | ||
|     rb_define_method(rb_cList, "size", list_length, 0); | ||
|     rb_define_method(rb_cList, "sum", list_sum, 0); | ||
|     rb_define_method(rb_cList, "reverse", list_reverse, 0); | ||
|     rb_define_method(rb_cCons, "inspect", cons_inspect, 0); | ||
|     id_each = rb_intern("each"); | ||
|     id_foldl = rb_intern("foldl"); | ||
|     id_foldr = rb_intern("foldr"); | ||
| } | ||
| object.c | ||
|---|---|---|
| VALUE rb_cClass; | ||
| VALUE rb_cData; | ||
| VALUE rb_cList; | ||
| VALUE rb_cNilClass; | ||
| VALUE rb_cTrueClass; | ||
| VALUE rb_cFalseClass; | ||
| ... | ... | |
|     rb_define_global_function("Array", rb_f_array, 1); | ||
|     rb_define_global_function("Hash", rb_f_hash, 1); | ||
|     rb_cNilClass = rb_define_class("NilClass", rb_cObject); | ||
|     rb_cList  = rb_define_class("List", rb_cObject); | ||
|     rb_cNilClass = rb_define_class("NilClass", rb_cList); | ||
|     rb_define_method(rb_cNilClass, "to_i", nil_to_i, 0); | ||
|     rb_define_method(rb_cNilClass, "to_f", nil_to_f, 0); | ||
|     rb_define_method(rb_cNilClass, "to_s", nil_to_s, 0); | ||
| parse.y | ||
|---|---|---|
| %token tLSHFT tRSHFT	/* << and >> */ | ||
| %token tCOLON2		/* :: */ | ||
| %token tCOLON3		/* :: at EXPR_BEG */ | ||
| %token tCOLON4		/* ::: */ | ||
| %token <id> tOP_ASGN	/* +=, -=  etc. */ | ||
| %token tASSOC		/* => */ | ||
| %token tLPAREN		/* ( */ | ||
| ... | ... | |
| %right '=' tOP_ASGN | ||
| %left modifier_rescue | ||
| %right '?' ':' | ||
| %right tCOLON4 | ||
| %nonassoc tDOT2 tDOT3 | ||
| %left  tOROP | ||
| %left  tANDOP | ||
| ... | ... | |
| 		| tAREF		{ ifndef_ripper($$ = tAREF); } | ||
| 		| tASET		{ ifndef_ripper($$ = tASET); } | ||
| 		| '`'		{ ifndef_ripper($$ = '`'); } | ||
| 		| tCOLON4	{ ifndef_ripper($$ = tCOLON4); } | ||
| 		; | ||
| reswords	: keyword__LINE__ | keyword__FILE__ | keyword__ENCODING__ | ||
| ... | ... | |
| 			$$ = dispatch1(assign_error, $$); | ||
| 		    %*/ | ||
| 		    } | ||
| 		| arg tCOLON4 arg | ||
| 		    { | ||
| 		    /*%%%*/ | ||
| 			$$ = call_bin_op($3, tCOLON4, $1); | ||
| 		    /*% | ||
| 			$$ = dispatch3(binary, $1, ID2SYM(tCOLON4), $3); | ||
| 		    %*/ | ||
| 		    } | ||
| 		| arg tDOT2 arg | ||
| 		    { | ||
| 		    /*%%%*/ | ||
| ... | ... | |
|       case ':': | ||
| 	c = nextc(); | ||
| 	if (c == ':') { | ||
| 	    c = nextc(); | ||
| 	    if (c == ':') { | ||
| 		return tCOLON4; | ||
| 	    } | ||
| 	    pushback(c); | ||
| 	    if (IS_BEG() || lex_state == EXPR_CLASS || IS_SPCARG(-1)) { | ||
| 		lex_state = EXPR_BEG; | ||
| 		return tCOLON3; | ||
| ... | ... | |
|     {tLSHFT,	"<<"}, | ||
|     {tRSHFT,	">>"}, | ||
|     {tCOLON2,	"::"}, | ||
|     {tCOLON4,	":::"}, | ||
| }; | ||
| #define op_tbl_count numberof(op_tbl) | ||
| template/id.h.tmpl | ||
|---|---|---|
| vpath.find do |dir| | ||
|   begin | ||
|     if line = File.read(File.join(dir, input))[/^\s*enum\s+yytokentype\s*\{([^{}]*)\s*\};/m, 1] | ||
|       tokens = line.scan(/\b(t(?:LAST_TOKEN|U(?:PLUS|MINUS)|POW|CMP|EQQ?|[NGL]EQ|(?:AND|OR)OP|N?MATCH|DOT\d|AREF|ASET|[LR]SHFT|LAMBDA)|id\w+)\s*=\s*(\d+),?/m) | ||
|       tokens = line.scan(/\b(t(?:LAST_TOKEN|U(?:PLUS|MINUS)|POW|CMP|EQQ?|[NGL]EQ|(?:AND|OR)OP|N?MATCH|DOT\d|AREF|ASET|[LR]SHFT|COLON4|LAMBDA)|id\w+)\s*=\s*(\d+),?/m) | ||
|     end | ||
|   rescue Errno::ENOENT | ||
|     nil | ||
| ... | ... | |
|     idNeqTilde = tNMATCH, | ||
|     idAREF = tAREF, | ||
|     idASET = tASET, | ||
|     idColon4 = tCOLON4, | ||
|     idLAST_TOKEN = tLAST_TOKEN >> ID_SCOPE_SHIFT, | ||
| % method_ids.each do |token| | ||
|     t<%=token%>, | ||