From 5d828b25d4ae30a000c054a724ac248dadbb97b3 Mon Sep 17 00:00:00 2001 From: Yukihiro Matsumoto Date: Tue, 10 Jan 1995 00:58:20 +0900 Subject: version 0.64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://cache.ruby-lang.org/pub/ruby/1.0/ruby-0.64.tar.gz Tue Jan 10 00:58:20 1995 Yukihiro Matsumoto (matz@dyna) * eval.c: レシーバと引数は常にiterではない. * cons.c(aref,aset): negative offset対応. Mon Jan 9 14:40:39 1995 Yukihiro Matsumoto (matz@ix-02) * parse.y: foo{..}の形式において,fooをローカル変数やクラス名では なく,引数なしの関数型メソッド呼び出しとみなすようにした. * list.c -> cons.c: 名称変更(クラス名も). * list.c: a::b::c::nilをリスト(a b c)とみなすlisp形式から,a::b::c をリスト(a b c)とみなすruby形式に変更.[], []=, eachもそれに会わ せた仕様とする. * list.c: consペアとしての機能を強調.仕様変更. Sat Jan 7 01:26:26 1995 Yukihiro Matsumoto (matz@dyna) * eval.c: 自己代入の不具合修正. * eval.c(masign): 多重代入が配列もリストもとれるようにした. * list.c: assocを2要素の配列からList(CONSペア)に変更した. Fri Jan 6 13:42:12 1995 Yukihiro Matsumoto (matz@ix-02) * parse.y: a[b]+=cやa.b+=cなどの自己代入形式で,aやbを2度評価しな くなった. * eval.c: iterator設定のバグフィックス. * list.c: Listクラスを新設. Thu Jan 5 13:55:00 1995 Yukihiro Matsumoto (matz@ix-02) * parse.y: SCOPEのメモリリークをなくした. * eval.c: built-inメソッドへの引数の引き渡し方を変更して,配列の生 成数を減らした. * re.c: match-dataを毎回生成することをやめた.`$~'をアクセスした時 にon-demandで生成する. * string.c etc: 不必要なmemmoveをmemcpyに置換. * parse.y: =~, !~は副作用があるのでコンパイル時に展開できない. Tue Jan 3 02:04:36 1995 Yukihiro Matsumoto (matz@dyna) * eval.c: rest引数のbug fix. * eval.c,gc.c: scopeをオブジェクトにした. * eval.c: envとscopeの扱いを変更した. Wed Dec 28 09:46:57 1994 Yukihiro Matsumoto (matz@ix-02) * parse.y: evalでローカル変数が追加された場合に対応した. * parse.y: 演算子を含むaliasのbug fix. Tue Dec 27 16:45:20 1994 Yukihiro Matsumoto (matz@ix-02) * parse.y: def A Bをalias A Bに変更. * eval.c: alias関係のbug修正.nodeをオブジェクト化した時にenbugし たようだ. * signal.c: システムコールの再定義を止めた. * io.c(select): write/exceptのフラグ設定にバグ. * Makefile.in: static link用オプションをMake変数として独立させた. --- cons.c | 270 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 270 insertions(+) create mode 100644 cons.c (limited to 'cons.c') diff --git a/cons.c b/cons.c new file mode 100644 index 0000000000..ac562814ca --- /dev/null +++ b/cons.c @@ -0,0 +1,270 @@ +/************************************************ + + cons.c - + + $Author: matz $ + $Date: 1995/01/10 10:22:24 $ + created at: Fri Jan 6 10:10:36 JST 1995 + + Copyright (C) 1994 Yukihiro Matsumoto + +************************************************/ + +#include "ruby.h" + +VALUE C_Cons; + +static ID eq; + +VALUE rb_to_a(); + +VALUE +assoc_new(car, cdr) + VALUE car, cdr; +{ + NEWOBJ(cons, struct RCons); + OBJSETUP(cons, C_Cons, T_CONS); + + cons->car = car; + cons->cdr = cdr; + + return (VALUE)cons; +} + +#define cons_new assoc_new + +static VALUE +Fcons_car(cons) + struct RCons *cons; +{ + return cons->car; +} + +static VALUE +Fcons_cdr(cons) + struct RCons *cons; +{ + return cons->cdr; +} + +static VALUE +Fcons_set_car(cons, val) + struct RCons *cons; + VALUE val; +{ + return cons->car = val; +} + +static VALUE +Fcons_set_cdr(cons, val) + struct RCons *cons; + VALUE val; +{ + return cons->cdr = val; +} + +static int +cons_length(list) + struct RCons *list; +{ + int len = 1; + + while (TYPE(list) == T_CONS) { + len++; + list = RCONS(list->cdr); + } + return len; +} + +static VALUE +Fcons_length(list) + struct RCons *list; +{ + int len = cons_length(list); + return INT2FIX(len); +} + +static VALUE +cons_aref(list, nth) + struct RCons *list; + int nth; +{ + if (nth == 0) return list->car; + list = RCONS(list->cdr); + if (TYPE(list) != T_CONS) { + if (nth == 1) return (VALUE)list; + return Qnil; + } + + return cons_aref(list, nth-1); +} + +static VALUE +Fcons_aref(list, nth) + struct RCons *list; + VALUE nth; +{ + int n = NUM2INT(nth); + + if (n < 0) { + n = cons_length(list)+n; + if (n < 0) return Qnil; + } + return cons_aref(list, n); +} + +static VALUE +cons_aset(list, nth, val) + struct RCons *list; + int nth; + VALUE val; +{ + if (nth == 0) return list->car = val; + if (TYPE(list->cdr) != T_CONS) { + if (nth > 2) { + Fail("list too short"); + } + if (nth == 1) + list->cdr = val; + else + list->cdr = cons_new(list->cdr, val); + return val; + } + return cons_aset(list->cdr, nth-1, val); +} + +static VALUE +Fcons_aset(list, nth, val) + struct RCons *list; + VALUE nth, val; +{ + int n = NUM2INT(nth); + + if (n < 0) { + n = cons_length(list)+n; + if (n < 0) { + Fail("negative offset too big"); + } + } + return cons_aset(list, n, val); +} + +static VALUE +Fcons_each(list) + struct RCons *list; +{ + rb_yield(list->car); + if (TYPE(list->cdr) != T_CONS) { + rb_yield(list->cdr); + return Qnil; + } + return Fcons_each(list->cdr); +} + +static VALUE +Fcons_equal(cons1, cons2) + struct RCons *cons1, *cons2; +{ + if (TYPE(cons2) != T_CONS) return FALSE; + if (!rb_equal(cons1->car, cons2->car)) return FALSE; + return rb_equal(cons1->cdr, cons2->cdr); +} + +static ID hash; + +static VALUE +Fcons_hash(cons) + struct RCons *cons; +{ + int key; + + key = rb_funcall(cons->car, hash, 0, 0); + key ^= rb_funcall(cons->cdr, hash, 0, 0); + return INT2FIX(key); +} + +static VALUE +Fcons_to_s(cons) + struct RCons *cons; +{ + VALUE str1, str2; + ID to_s = rb_intern("to_s"); + + str1 = rb_funcall(cons->car, to_s, 0); + cons = RCONS(cons->cdr); + while (cons) { + if (TYPE(cons) != T_CONS) { + str2 = rb_funcall(cons, to_s, 0); + str_cat(str1, RSTRING(str2)->ptr, RSTRING(str2)->len); + break; + } + str2 = rb_funcall(cons->car, to_s, 0); + str_cat(str1, RSTRING(str2)->ptr, RSTRING(str2)->len); + cons = RCONS(cons->cdr); + } + + return str1; +} + +static VALUE +Fcons_inspect(cons) + struct RCons *cons; +{ + VALUE str1, str2; + ID inspect = rb_intern("_inspect"); + + str1 = rb_funcall(cons->car, inspect, 0, 0); + str2 = rb_funcall(cons->cdr, inspect, 0, 0); + str_cat(str1, "::", 2); + str_cat(str1, RSTRING(str2)->ptr, RSTRING(str2)->len); + + return str1; +} + +static VALUE +Fcons_copy(list) + struct RCons *list; +{ + VALUE cdr = list->cdr; + + if (TYPE(cdr) == T_CONS) + return cons_new(list->car, Fcons_copy(list->cdr)); + else + return cons_new(list->car, cdr); +} + +extern VALUE C_Kernel; +extern VALUE M_Enumerable; + +Init_Cons() +{ + C_Cons = rb_define_class("Cons", C_Object); + + rb_undef_method(CLASS_OF(C_Cons), "new"); + rb_undef_method(C_Cons, "clone"); + + rb_include_module(C_Cons, M_Enumerable); + + rb_define_method(C_Cons, "car", Fcons_car, 0); + rb_define_method(C_Cons, "cdr", Fcons_cdr, 0); + + rb_define_method(C_Cons, "car=", Fcons_set_car, 1); + rb_define_method(C_Cons, "cdr=", Fcons_set_cdr, 1); + + rb_define_method(C_Cons, "==", Fcons_equal, 1); + rb_define_method(C_Cons, "hash", Fcons_hash, 0); + hash = rb_intern("hash"); + rb_define_method(C_Cons, "length", Fcons_length, 0); + + rb_define_method(C_Cons, "to_s", Fcons_to_s, 0); + rb_define_method(C_Cons, "_inspect", Fcons_inspect, 0); + + /* methods to access as list */ + rb_define_method(C_Cons, "[]", Fcons_aref, 1); + rb_define_method(C_Cons, "[]=", Fcons_aset, 2); + rb_define_method(C_Cons, "each", Fcons_each, 0); + + rb_define_method(C_Cons, "copy", Fcons_copy, 0); + + rb_define_method(C_Kernel, "::", assoc_new, 1); +} -- cgit v1.2.3