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%>,
|
||