summaryrefslogtreecommitdiff
path: root/cons.c
diff options
context:
space:
mode:
authorYukihiro Matsumoto <matz@ruby-lang.org>1995-01-10 00:58:20 +0900
committerTakashi Kokubun <takashikkbn@gmail.com>2019-08-17 22:09:31 +0900
commit5d828b25d4ae30a000c054a724ac248dadbb97b3 (patch)
tree080fc6e3b41b9c59cf5def77ae619a82e7e252db /cons.c
parentbd0c733b77b561f4d12daccebf06a7c71917000b (diff)
version 0.64v0_64
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変数として独立させた.
Diffstat (limited to 'cons.c')
-rw-r--r--cons.c270
1 files changed, 270 insertions, 0 deletions
diff --git a/cons.c b/cons.c
new file mode 100644
index 0000000..ac56281
--- /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);
+}