summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYukihiro Matsumoto <matz@ruby-lang.org>1994-10-13 21:19:03 (GMT)
committerTakashi Kokubun <takashikkbn@gmail.com>2019-08-17 13:09:30 (GMT)
commit29f237a8b1df650089b54447f070726c75706b6f (patch)
treee6ee836a39a5f2f1d433d6532de32471b655fb6d
parent173976c97c9426aa8d96e53aef6c0e570c5fdfda (diff)
version 0.54v0_54
https://cache.ruby-lang.org/pub/ruby/1.0/ruby-0.54.tar.gz
-rw-r--r--CVS/Entries51
-rw-r--r--CVS/Repository1
-rw-r--r--Makefile6
-rw-r--r--Makefile.in4
-rw-r--r--README22
-rw-r--r--array.c12
-rw-r--r--bignum.c2
-rw-r--r--bring57
-rw-r--r--class.c84
-rwxr-xr-xconfig.status72
-rw-r--r--dict.c32
-rw-r--r--env.h33
-rw-r--r--error.c2
-rw-r--r--etc.c16
-rw-r--r--eval.c859
-rw-r--r--file.c4
-rw-r--r--gc.c13
-rw-r--r--gnuglob.c6
-rw-r--r--inits.c1
-rw-r--r--io.c55
-rw-r--r--math.c19
-rwxr-xr-x[-rw-r--r--]newver.rb4
-rw-r--r--node.h22
-rw-r--r--numeric.c144
-rw-r--r--object.c100
-rw-r--r--parse.y81
-rw-r--r--process.c50
-rw-r--r--random.c6
-rw-r--r--re.c131
-rw-r--r--ruby.c19
-rw-r--r--sample/caller.rb15
-rw-r--r--sample/dbm.rb2
-rw-r--r--sample/export.rb13
-rw-r--r--sample/fib.rb2
-rw-r--r--sample/fib.scm6
-rw-r--r--sample/list3.rb20
-rw-r--r--sample/ruby-mode.el5
-rwxr-xr-xsample/time.rb8
-rwxr-xr-xsample/uumerge.rb27
-rw-r--r--socket.c47
-rw-r--r--spec217
-rw-r--r--string.c96
-rw-r--r--time.c12
-rw-r--r--variable.c27
-rw-r--r--version.h4
45 files changed, 1501 insertions, 908 deletions
diff --git a/CVS/Entries b/CVS/Entries
new file mode 100644
index 0000000..067e16d
--- /dev/null
+++ b/CVS/Entries
@@ -0,0 +1,51 @@
+/autoexec.c/0.15/Wed Jun 1 23:40:54 1994 Thu Mar 17 18:49:43 1994//
+/class.c/0.22/Wed Jun 1 23:40:54 1994 Fri Mar 25 13:12:36 1994//
+/compar.c/0.15/Wed Jun 1 23:40:54 1994 Thu Mar 17 18:49:43 1994//
+/dln.h/0.14/Wed Jun 1 23:40:57 1994 Thu Mar 17 15:55:00 1994//
+/error.c/0.15/Wed Jun 1 23:40:57 1994 Thu Mar 17 18:49:43 1994//
+/etc.c/0.22/Wed Jun 1 23:40:58 1994 Fri Mar 25 13:12:36 1994//
+/ident.h/0.17/Wed Jun 1 23:41:00 1994 Wed May 25 00:56:16 1994//
+/inits.c/0.27/Wed Jun 1 23:41:00 1994 Mon Apr 25 23:30:29 1994//
+/io.h/0.14/Wed Jun 1 23:41:01 1994 Thu Mar 17 15:55:00 1994//
+/methods.c/0.20/Wed Jun 1 23:41:01 1994 Tue Mar 22 16:58:31 1994//
+/missing.c/0.29/Wed Jun 1 23:41:01 1994 Wed Jun 1 23:36:26 1994//
+/parse.y/0.35/Wed Jun 1 23:41:08 1994 Wed Jun 1 23:36:30 1994//
+/random.c/0.15/Wed Jun 1 23:41:09 1994 Thu Mar 17 18:49:43 1994//
+/range.c/0.15/Wed Jun 1 23:41:09 1994 Thu Mar 17 18:49:43 1994//
+/re.h/0.15/Wed Jun 1 23:41:10 1994 Thu May 26 00:41:30 1994//
+/regex.c/0.15/Wed Jun 1 23:41:12 1994 Wed Jun 1 23:36:35 1994//
+/regex.h/0.14/Wed Jun 1 23:41:12 1994 Thu Mar 17 15:55:00 1994//
+/st.h/0.14/Wed Jun 1 23:41:14 1994 Thu Mar 17 15:55:00 1994//
+/variable.c/0.29/Wed Jun 1 23:41:16 1994 Wed May 25 00:56:35 1994//
+/version.c/0.27/Wed Jun 1 23:41:16 1994 Mon Apr 25 23:30:35 1994//
+/Makefile/0.32/Fri Jun 3 00:15:00 1994 Fri Jun 3 00:15:00 1994//
+/Makefile.in/1.3/Fri Jun 3 00:15:01 1994 Fri Jun 3 00:15:01 1994//
+/array.c/0.29/Fri Jun 3 00:15:02 1994 Fri Jun 3 00:15:02 1994//
+/configure/1.3/Fri Jun 3 00:15:04 1994 Fri Jun 3 00:15:03 1994//
+/configure.in/1.3/Fri Jun 3 00:15:04 1994 Fri Jun 3 00:15:04 1994//
+/dbm.c/0.28/Fri Jun 3 00:15:05 1994 Fri Jun 3 00:15:05 1994//
+/defines.h/1.4/Fri Jun 3 00:15:06 1994 Fri Jun 3 00:15:06 1994//
+/dict.c/0.28/Fri Jun 3 00:15:06 1994 Fri Jun 3 00:15:06 1994//
+/dir.c/0.18/Fri Jun 3 00:15:07 1994 Fri Jun 3 00:15:07 1994//
+/dln.c/0.29/Fri Jun 3 00:15:08 1994 Fri Jun 3 00:15:08 1994//
+/enum.c/0.16/Fri Jun 3 00:15:09 1994 Fri Jun 3 00:15:08 1994//
+/eval.c/0.35/Fri Jun 3 00:15:10 1994 Fri Jun 3 00:15:09 1994//
+/file.c/0.29/Fri Jun 3 00:15:11 1994 Fri Jun 3 00:15:11 1994//
+/gc.c/0.30/Fri Jun 3 00:15:12 1994 Fri Jun 3 00:15:12 1994//
+/io.c/0.29/Fri Jun 3 00:15:13 1994 Fri Jun 3 00:15:13 1994//
+/math.c/0.28/Fri Jun 3 00:15:14 1994 Fri Jun 3 00:15:14 1994//
+/node.h/0.32/Fri Jun 3 00:15:15 1994 Fri Jun 3 00:15:14 1994//
+/numeric.c/0.19/Fri Jun 3 00:15:15 1994 Fri Jun 3 00:15:15 1994//
+/object.c/0.32/Fri Jun 3 00:15:16 1994 Fri Jun 3 00:15:16 1994//
+/pack.c/0.18/Fri Jun 3 00:15:17 1994 Fri Jun 3 00:15:17 1994//
+/process.c/0.30/Fri Jun 3 00:15:18 1994 Fri Jun 3 00:15:17 1994//
+/re.c/0.32/Fri Jun 3 00:15:19 1994 Fri Jun 3 00:15:18 1994//
+/ruby.c/0.34/Fri Jun 3 00:15:19 1994 Fri Jun 3 00:15:19 1994//
+/ruby.h/0.30/Fri Jun 3 00:15:20 1994 Fri Jun 3 00:15:20 1994//
+/socket.c/0.27/Fri Jun 3 00:15:21 1994 Fri Jun 3 00:15:21 1994//
+/sprintf.c/0.23/Fri Jun 3 00:15:22 1994 Fri Jun 3 00:15:21 1994//
+/st.c/0.15/Fri Jun 3 00:15:22 1994 Fri Jun 3 00:15:22 1994//
+/string.c/0.29/Fri Jun 3 00:15:23 1994 Fri Jun 3 00:15:23 1994//
+/struct.c/0.26/Fri Jun 3 00:15:25 1994 Fri Jun 3 00:15:24 1994//
+/time.c/0.29/Fri Jun 3 00:15:26 1994 Fri Jun 3 00:15:26 1994//
+/version.h/1.7/Fri Jun 3 00:15:27 1994 Fri Jun 3 00:15:27 1994//
diff --git a/CVS/Repository b/CVS/Repository
new file mode 100644
index 0000000..b98482f
--- /dev/null
+++ b/CVS/Repository
@@ -0,0 +1 @@
+/work/cvsroot/ruby
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..0908d49
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile -
+#
+# created at: Wed Aug 10 15:21:29 JST 1994
+
+all:; @echo "You must run configure first."
diff --git a/Makefile.in b/Makefile.in
index 4c8b457..6296a5e 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -154,7 +154,7 @@ parse.o : parse.y ruby.h defines.h env.h node.h st.h ident.h regex.h
###
array.o : array.c ruby.h defines.h
bignum.o : bignum.c ruby.h defines.h
-class.o : class.c ruby.h defines.h env.h node.h st.h methods.h
+class.o : class.c ruby.h defines.h env.h node.h st.h
compar.o : compar.c ruby.h defines.h
dbm.o : dbm.c ruby.h defines.h
dict.o : dict.c ruby.h defines.h st.h
@@ -163,7 +163,7 @@ dln.o : dln.c defines.h dln.h
enum.o : enum.c ruby.h defines.h
error.o : error.c ruby.h defines.h env.h
etc.o : etc.c ruby.h defines.h
-eval.o : eval.c ruby.h defines.h ident.h env.h node.h methods.h st.h
+eval.o : eval.c ruby.h defines.h ident.h env.h node.h st.h
file.o : file.c ruby.h defines.h io.h
fnmatch.o : fnmatch.c fnmatch.h
gc.o : gc.c ruby.h defines.h env.h st.h
diff --git a/README b/README
index 3ca523b..9dc79e8 100644
--- a/README
+++ b/README
@@ -49,3 +49,25 @@
sparc以外のレジスタウィンドウを持つCPUでは, レジスタウィン
ドウをフラッシュするコードを追加する必要があるかも知れない.
+
+配布条件
+
+ Rubyは最終的にはGNU Public Licenseにしたがった条件で配布さ
+ れる予定だが, 現時点では以下の条件で配布する.
+
+ * 更新
+
+ いかなる目的であれ自由である. ただし, バグ修正は作者への
+ フィードバックを期待する(強制ではない)
+
+ * 他のプログラムへの引用
+
+ いかなる目的であれ自由である. ただし, 配布したコードに含
+ まれる他の作者によるコードは, それぞれの作者の意向による
+ 制限が加えられる.
+
+ * 再配布
+
+ 禁止する. 入手したい人は作者に直接連絡をとること. これは
+ Rubyの言語仕様が不安定な状態のまま広く流布するのを制限す
+ るためであり, 言語仕様が安定した時点で再配布自由とする.
diff --git a/array.c b/array.c
index 581e028..a68f97a 100644
--- a/array.c
+++ b/array.c
@@ -456,6 +456,17 @@ Fary_each(ary)
}
static VALUE
+Fary_each_index(ary)
+ struct RArray *ary;
+{
+ int i;
+
+ for (i=0; i<ary->len; i++) {
+ rb_yield(INT2FIX(i));
+ }
+}
+
+static VALUE
Fary_length(ary)
struct RArray *ary;
{
@@ -870,6 +881,7 @@ Init_Array()
rb_define_method(C_Array, "shift", Fary_shift, 0);
rb_define_method(C_Array, "unshift", Fary_unshift, 1);
rb_define_method(C_Array, "each", Fary_each, 0);
+ rb_define_method(C_Array, "each_index", Fary_each_index, 0);
rb_define_method(C_Array, "length", Fary_length, 0);
rb_define_alias(C_Array, "size", "length");
rb_define_method(C_Array, "index", Fary_index, 1);
diff --git a/bignum.c b/bignum.c
index f83c5ec..1235e03 100644
--- a/bignum.c
+++ b/bignum.c
@@ -1075,7 +1075,7 @@ Init_Bignum()
{
C_Bignum = rb_define_class("Bignum", C_Integer);
rb_define_single_method(C_Bignum, "new", Fbig_new, 1);
- rb_define_method(C_Bignum, "clone", Fbig_clone, 0);
+
rb_define_method(C_Bignum, "to_s", Fbig_to_s, 0);
rb_define_method(C_Bignum, "coerce", Fbig_coerce, 1);
rb_define_method(C_Bignum, "-@", Fbig_uminus, 0);
diff --git a/bring b/bring
new file mode 100644
index 0000000..771cd04
--- /dev/null
+++ b/bring
@@ -0,0 +1,57 @@
+#! /usr/bin/bash
+
+function fdeject() {
+ if type eject > /dev/null 2>&1; then
+ eject
+ fi
+}
+
+function copyfiles() {
+ for d in . missing sample; do
+ if [ ! -d $1/$d ];then mkdir $1/$d; fi
+ for i in $d/*;do
+ case $i in
+ */ruby|*.o|*~|*.sav|*.bak|*.orig|*/core|"#"*);;
+ */Change*|*/config.status|*/Makefile);;
+ *)
+ if [ -f $i ]; then
+ if [ $i -nt $1/$i -o ! -f $1/$i ];then
+ echo copying $i
+ cp -p $i $1/$i
+ fi
+ fi;;
+ esac
+ done
+ done
+}
+
+if [ ! -d exchange ]; then mkdir exchange; fi
+
+if [ "$1" = "in" ]; then
+
+ cd exchange
+
+ mread ruby.tgz ruby.tgz
+ fdeject
+ tar zxf ruby.tgz
+ rm -f ruby.tgz
+ cd ruby
+
+ cp ChangeLog ../../Changes
+ copyfiles ../..
+
+else
+# bring out
+ if [ ! -d exchange/ruby ]; then mkdir exchange/ruby; fi
+
+ cp -p ChangeLog exchange/ruby
+ copyfiles exchange/ruby
+
+ cd exchange
+ (cd ruby; make realclean)
+
+ tar zcf ruby.tgz ruby
+ mwrite ruby.tgz ruby.tgz
+ fdeject
+ rm -f ruby.tgz
+fi
diff --git a/class.c b/class.c
index 075c847..26af086 100644
--- a/class.c
+++ b/class.c
@@ -14,7 +14,6 @@
#include "env.h"
#include "node.h"
#include "st.h"
-#include "methods.h"
struct st_table *new_idhash();
@@ -46,6 +45,16 @@ single_class_new(super)
return (VALUE)cls;
}
+static int
+clone_method(mid, body, tbl)
+ ID mid;
+ NODE *body;
+ st_table *tbl;
+{
+ st_insert(tbl, mid, NEW_METHOD(body->nd_body, body->nd_noex));
+ return ST_CONTINUE;
+}
+
VALUE
single_class_clone(class)
struct RClass *class;
@@ -54,14 +63,15 @@ single_class_clone(class)
return (VALUE)class;
else {
/* copy single(unnamed) class */
- NEWOBJ(cls, struct RClass);
- CLONESETUP(cls, class);
-
- cls->super = class->super;
- cls->m_tbl = st_copy(class->m_tbl);
- cls->c_tbl = Qnil;
- FL_SET(cls, FL_SINGLE);
- return (VALUE)cls;
+ NEWOBJ(clone, struct RClass);
+ CLONESETUP(clone, class);
+
+ clone->super = class->super;
+ clone->m_tbl = new_idhash();
+ st_foreach(class->m_tbl, clone_method, clone->m_tbl);
+ clone->c_tbl = Qnil;
+ FL_SET(clone, FL_SINGLE);
+ return (VALUE)clone;
}
}
@@ -169,13 +179,13 @@ rb_include_module(class, module)
}
void
-rb_add_method(class, mid, node, undef)
+rb_add_method(class, mid, node, noex)
struct RClass *class;
ID mid;
NODE *node;
- int undef;
+ int noex;
{
- struct SMethod *body;
+ NODE *body;
if (class == Qnil) class = (struct RClass*)C_Object;
if (st_lookup(class->m_tbl, mid, &body)) {
@@ -183,17 +193,12 @@ rb_add_method(class, mid, node, undef)
Warning("redefine %s", rb_id2name(mid));
}
rb_clear_cache(body);
- method_free(body);
+ freenode(body);
+ }
+ if (node && node->type != NODE_FBODY) {
+ node = NEW_FBODY(node, mid);
}
- body = ALLOC(struct SMethod);
- body->node = node;
- if (BUILTIN_TYPE(class) == T_MODULE)
- body->origin = Qnil;
- else
- body->origin = class;
- body->id = mid;
- body->undef = undef;
- body->count = 1;
+ body = NEW_METHOD(node, noex);
st_insert(class->m_tbl, mid, body);
}
@@ -204,9 +209,7 @@ rb_define_method(class, name, func, argc)
VALUE (*func)();
int argc;
{
- NODE *temp = NEW_CFUNC(func, argc);
-
- rb_add_method(class, rb_intern(name), temp, FALSE);
+ rb_add_method(class, rb_intern(name), NEW_CFUNC(func, argc), 0);
}
void
@@ -214,7 +217,17 @@ rb_undef_method(class, name)
struct RClass *class;
char *name;
{
- rb_add_method(class, rb_intern(name), Qnil, TRUE);
+ rb_add_method(class, rb_intern(name), Qnil, 0);
+}
+
+void
+rb_define_private_method(class, name, func, argc)
+ struct RClass *class;
+ char *name;
+ VALUE (*func)();
+ int argc;
+{
+ rb_add_method(class, rb_intern(name), NEW_CFUNC(func, argc), 1);
}
VALUE
@@ -228,7 +241,7 @@ rb_single_class(obj)
case T_STRUCT:
break;
default:
- Fail("can't define single method for built-in classes");
+ Fail("can't define single method for built-in class");
break;
}
@@ -245,7 +258,18 @@ rb_define_single_method(obj, name, func, argc)
VALUE (*func)();
int argc;
{
- rb_define_method(rb_single_class(obj), name, func, argc, FALSE);
+ rb_define_method(rb_single_class(obj), name, func, argc);
+}
+
+void
+rb_define_module_function(module, name, func, argc)
+ VALUE module;
+ char *name;
+ VALUE (*func)();
+ int argc;
+{
+ rb_define_private_method(module, name, func, argc);
+ rb_define_single_method(module, name, func, argc);
}
void
@@ -272,10 +296,10 @@ rb_define_attr(class, name, pub)
sprintf(buf, "@%s", name);
attriv = rb_intern(buf);
if (rb_method_boundp(class, attr) == Qnil) {
- rb_add_method(class, attr, NEW_IVAR(attriv), FALSE);
+ rb_add_method(class, attr, NEW_IVAR(attriv), 0);
}
if (pub && rb_method_boundp(class, attreq) == Qnil) {
- rb_add_method(class, attreq, NEW_ATTRSET(attriv), FALSE);
+ rb_add_method(class, attreq, NEW_ATTRSET(attriv), 0);
}
}
diff --git a/config.status b/config.status
new file mode 100755
index 0000000..7bdc7b2
--- /dev/null
+++ b/config.status
@@ -0,0 +1,72 @@
+#!/bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host dyna:
+#
+# ./configure
+
+for arg
+do
+ case "$arg" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo running ${CONFIG_SHELL-/bin/sh} ./configure
+ exec ${CONFIG_SHELL-/bin/sh} ./configure ;;
+ *) echo "Usage: config.status --recheck" 2>&1; exit 1 ;;
+ esac
+done
+
+trap 'rm -f Makefile; exit 1' 1 3 15
+PROGS='ruby'
+CC='gcc'
+CPP='gcc -E'
+DBM='-fpcc-struct-return'
+STATIC=''
+YACC='bison -y'
+INSTALL='/usr/bin/install -c'
+INSTALL_PROGRAM='$(INSTALL)'
+INSTALL_DATA='$(INSTALL) -m 644'
+ALLOCA=''
+LIBS=' -lm -ldbm'
+srcdir='.'
+DEFS=' -DHAVE_UNISTD_H=1 -DHAVE_SYSCALL_H=1 -DHAVE_A_OUT_H=1 -DDIRENT=1 -DGETGROUPS_T=gid_t -DRETSIGTYPE=void -DHAVE_GETOPT_LONG=1 -DHAVE_MEMMOVE=1 -DHAVE_STRERROR=1 -DHAVE_STRTOL=1 -DHAVE_STRTOUL=1 -DHAVE_STRDUP=1 -DHAVE_SETENV=1 -DHAVE_KILLPG=1 -DHAVE_MKDIR=1 -DHAVE_STRFTIME=1 -DHAVE_ALLOCA_H=1'
+prefix=''
+exec_prefix=''
+prsub=''
+extrasub=''
+
+top_srcdir=$srcdir
+
+CONFIG_FILES=${CONFIG_FILES-"Makefile"}
+for file in .. ${CONFIG_FILES}; do if test "x$file" != x..; then
+ srcdir=$top_srcdir
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ dir=`echo $file|sed 's%/[^/][^/]*$%%'`
+ if test "$dir" != "$file"; then
+ test "$top_srcdir" != . && srcdir=$top_srcdir/$dir
+ test ! -d $dir && mkdir $dir
+ fi
+ echo creating $file
+ rm -f $file
+ echo "# Generated automatically from `echo $file|sed 's|.*/||'`.in by configure." > $file
+ sed -e "
+$prsub
+$extrasub
+s%@PROGS@%$PROGS%g
+s%@CC@%$CC%g
+s%@CPP@%$CPP%g
+s%@DBM@%$DBM%g
+s%@STATIC@%$STATIC%g
+s%@YACC@%$YACC%g
+s%@INSTALL@%$INSTALL%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@ALLOCA@%$ALLOCA%g
+s%@LIBS@%$LIBS%g
+s%@srcdir@%$srcdir%g
+s%@DEFS@%$DEFS%
+" $top_srcdir/${file}.in >> $file
+fi; done
+
+
+exit 0
diff --git a/dict.c b/dict.c
index 419918f..e679c33 100644
--- a/dict.c
+++ b/dict.c
@@ -13,7 +13,9 @@
#include "ruby.h"
#include "st.h"
-VALUE C_Dict, C_EnvDict;
+VALUE C_Dict;
+
+static VALUE envtbl;
static ID hash, eq;
VALUE Fgetenv(), Fsetenv();
@@ -521,11 +523,16 @@ Fsetenv(obj, name, value)
return FALSE; /* not reached */
}
+static VALUE
+Fenv_to_s()
+{
+ return str_new2("$ENV");
+}
+
Init_Dict()
{
- extern VALUE C_Builtin;
+ extern VALUE C_Kernel;
extern VALUE M_Enumerable;
- static VALUE envtbl;
hash = rb_intern("hash");
eq = rb_intern("==");
@@ -567,17 +574,16 @@ Init_Dict()
rb_define_method(C_Dict,"has_value", Fdic_has_value, 1);
- C_EnvDict = rb_define_class("EnvDict", C_Object);
-
- rb_include_module(C_EnvDict, M_Enumerable);
+ envtbl = obj_alloc(C_Object);
+ rb_define_single_method(envtbl,"[]", Fgetenv, 1);
+ rb_define_single_method(envtbl,"[]=", Fsetenv, 2);
+ rb_define_single_method(envtbl,"each", Fenv_each, 0);
+ rb_define_single_method(envtbl,"delete", Fenv_delete, 1);
+ rb_define_single_method(envtbl,"to_s", Fenv_to_s, 0);
+ rb_include_module(CLASS_OF(envtbl), M_Enumerable);
- rb_define_method(C_EnvDict,"[]", Fgetenv, 1);
- rb_define_method(C_EnvDict,"[]=", Fsetenv, 2);
- rb_define_method(C_EnvDict,"each", Fenv_each, 0);
- rb_define_method(C_EnvDict,"delete", Fenv_delete, 1);
- envtbl = obj_alloc(C_EnvDict);
rb_define_variable("$ENV", &envtbl, Qnil, rb_readonly_hook);
- rb_define_method(C_Builtin, "getenv", Fgetenv, 1);
- rb_define_method(C_Builtin, "setenv", Fsetenv, 2);
+ rb_define_private_method(C_Kernel, "getenv", Fgetenv, 1);
+ rb_define_private_method(C_Kernel, "setenv", Fsetenv, 2);
}
diff --git a/env.h b/env.h
index fbb7ebd..34c411d 100644
--- a/env.h
+++ b/env.h
@@ -15,31 +15,24 @@ extern struct ENVIRON {
VALUE self;
int argc;
VALUE *argv;
- struct RClass *current_module;
- struct RClass *last_class;
-#ifdef USE_CALLER
- char *file;
- int line;
-#endif
ID last_func;
- ID *local_tbl;
- VALUE *local_vars;
- int in_eval;
- struct BLOCK *block;
- int iterator;
- int flags;
+ struct RClass *last_class;
struct ENVIRON *prev;
} *the_env;
-#define ITERATOR_P() (the_env->iterator == 1 || the_env->iterator == 2)
-
-#undef Qself
+#undef Qself
#define Qself the_env->self
-#define the_class the_env->current_module
-#define DURING_ITERATE 1
-#define DURING_RESQUE 2
-#define DURING_CALL 4
-#define VARS_MALLOCED 8
+extern struct SCOPE {
+ ID *local_tbl;
+ VALUE *local_vars;
+ VALUE block;
+ int flags;
+ struct SCOPE *prev;
+} *the_scope;
+
+#define VARS_MALLOCED (1<<2)
+
+extern int rb_in_eval;
#endif /* ENV_H */
diff --git a/error.c b/error.c
index 33309af..b67d79a 100644
--- a/error.c
+++ b/error.c
@@ -40,7 +40,7 @@ err_print(fmt, args)
char buf[BUFSIZ];
err_sprintf(buf, fmt, args);
- if (the_env->in_eval) {
+ if (rb_in_eval) {
if (errstr == Qnil) {
errstr = str_new2(buf);
}
diff --git a/etc.c b/etc.c
index 854d000..731ef9e 100644
--- a/etc.c
+++ b/etc.c
@@ -178,15 +178,13 @@ Init_Etc()
{
M_Etc = rb_define_module("Etc");
- rb_define_method(M_Etc, "getlogin", Fetc_getlogin, 0);
+ rb_define_module_function(M_Etc, "getlogin", Fetc_getlogin, 0);
- rb_define_method(M_Etc, "getpwuid", Fetc_getpwuid, -2);
- rb_define_method(M_Etc, "getpwnam", Fetc_getpwnam, 1);
- rb_define_method(M_Etc, "passwd", Fetc_passwd, 0);
+ rb_define_module_function(M_Etc, "getpwuid", Fetc_getpwuid, -2);
+ rb_define_module_function(M_Etc, "getpwnam", Fetc_getpwnam, 1);
+ rb_define_module_function(M_Etc, "passwd", Fetc_passwd, 0);
- rb_define_method(M_Etc, "getgrgid", Fetc_getgrgid, 1);
- rb_define_method(M_Etc, "getgrnam", Fetc_getgrnam, 1);
- rb_define_method(M_Etc, "group", Fetc_group, 0);
-
- rb_include_module(CLASS_OF(M_Etc), M_Etc);
+ rb_define_module_function(M_Etc, "getgrgid", Fetc_getgrgid, 1);
+ rb_define_module_function(M_Etc, "getgrnam", Fetc_getgrnam, 1);
+ rb_define_module_function(M_Etc, "group", Fetc_group, 0);
}
diff --git a/eval.c b/eval.c
index 21f7ecd..88ceaea 100644
--- a/eval.c
+++ b/eval.c
@@ -14,13 +14,11 @@
#include "ident.h"
#include "env.h"
#include "node.h"
-#include "methods.h"
#include <stdio.h>
#include <setjmp.h>
#include "st.h"
-void method_free();
void rb_clear_cache();
/* #define TEST /* prints cache miss */
@@ -43,42 +41,38 @@ struct cache_entry { /* method hash table. */
ID mid; /* method's id */
struct RClass *class; /* receiver's class */
struct RClass *origin; /* where method defined */
- struct SMethod *method;
- int undef;
+ NODE *method;
+ int noex;
};
static struct cache_entry cache[CACHE_SIZE];
-static struct SMethod*
+static NODE*
search_method(class, id, origin)
struct RClass *class, **origin;
ID id;
{
- struct SMethod *body;
- NODE *list;
+ NODE *body;
while (!st_lookup(class->m_tbl, id, &body)) {
class = class->super;
if (class == Qnil) return Qnil;
}
- if (body->origin)
- *origin = body->origin;
- else
- *origin = class;
+ *origin = class;
return body;
}
static NODE*
-rb_get_method_body(classp, idp)
+rb_get_method_body(classp, idp, noexp)
struct RClass **classp;
ID *idp;
+ int *noexp;
{
int pos, i;
ID id = *idp;
struct RClass *class = *classp;
- struct SMethod *method;
- struct SMethod *body;
+ NODE *body;
struct RClass *origin;
struct cache_entry *ent;
@@ -96,23 +90,14 @@ rb_get_method_body(classp, idp)
ent->mid = id;
ent->class = class;
ent->origin = origin;
- ent->method = body;
- ent->undef = body->undef;
-
- if (ent->undef) return Qnil;
- *idp = ent->method->id;
- *classp = ent->origin;
- return ent->method->node;
-}
-
-VALUE
-rb_method_boundp(class, id)
- struct RClass *class;
- ID id;
-{
- if (rb_get_method_body(&class, &id))
- return TRUE;
- return FALSE;
+ ent->method = body->nd_body;
+ ent->noex = body->nd_noex;
+
+ if (ent->method == Qnil) return Qnil;
+ *idp = ent->method->nd_mid;
+ *classp = origin;
+ if (noexp) *noexp = ent->noex;
+ return ent->method->nd_head;
}
void
@@ -120,23 +105,65 @@ rb_alias(class, name, def)
struct RClass *class;
ID name, def;
{
- struct SMethod *body;
+ struct RClass *origin;
+ NODE *body, *old;
+
+ if (name == def) return;
+ body = search_method(class, def, &origin);
+ if (body == Qnil) {
+ Fail("undefined method `%s' for class `%s'",
+ rb_id2name(def), rb_class2name(class));
+ }
+ body->nd_body->nd_cnt++;
- if (st_lookup(class->m_tbl, name, &body)) {
+ if (st_lookup(class->m_tbl, name, &old)) {
if (verbose) {
Warning("redefine %s", rb_id2name(name));
}
- rb_clear_cache(body);
- method_free(body);
+ rb_clear_cache(old->nd_body);
+ freenode(old);
}
- body = search_method(class, def, &body);
- body->count++;
- st_insert(class->m_tbl, name, body);
+
+ st_insert(class->m_tbl, name, NEW_METHOD(body->nd_body, body->nd_noex));
+}
+
+void
+rb_export_method(class, name, noex)
+ struct RClass *class;
+ ID name;
+ int noex;
+{
+ NODE *body;
+ struct RClass *origin;
+
+ body = search_method(class, name, &origin);
+ if (body == Qnil) {
+ Fail("undefined method `%s' for class `%s'",
+ rb_id2name(name), rb_class2name(class));
+ }
+ if (body->nd_noex != noex) {
+ if (class == origin) {
+ body->nd_noex = noex;
+ }
+ else {
+ rb_add_method(class, name, NEW_ZSUPER(), noex);
+ }
+ }
+}
+
+VALUE
+rb_method_boundp(class, id)
+ struct RClass *class;
+ ID id;
+{
+ if (rb_get_method_body(&class, &id, 0))
+ return TRUE;
+ return FALSE;
}
void
rb_clear_cache(body)
- struct SMethod *body;
+ NODE *body;
{
struct cache_entry *ent, *end;
@@ -166,17 +193,6 @@ rb_clear_cache2(class)
}
}
-void
-method_free(body)
- struct SMethod *body;
-{
- body->count--;
- if (body->count == 0) {
- freenode(body->node);
- free(body);
- }
-}
-
static ID match, each;
VALUE errstr, errat;
extern NODE *eval_tree;
@@ -184,12 +200,17 @@ extern int nerrs;
extern VALUE TopSelf;
struct ENVIRON *the_env, *top_env;
+struct SCOPE *the_scope, *top_scope;
#define PUSH_ENV() {\
struct ENVIRON _this;\
+ _this.prev = the_env;\
+ the_env = &_this;\
+
+#define DUP_ENV() {\
+ struct ENVIRON _this;\
_this = *the_env;\
_this.prev = the_env;\
- _this.flags = 0;\
the_env = &_this;\
#define POP_ENV() the_env = the_env->prev; }
@@ -198,12 +219,22 @@ struct BLOCK {
NODE *var;
NODE *body;
struct ENVIRON env;
+ struct SCOPE scope;
int level;
-};
+ struct BLOCK *prev;
+} *the_block;
+
+#define PUSH_BLOCK(v,b) { \
+ struct BLOCK _this; \
+ _this.level = tag_level; \
+ _this.var=v; \
+ _this.body = b; \
+ _this.env = *the_env; \
+ _this.scope = *the_scope; \
+ _this.prev = the_block; \
+ the_block = &_this; \
-#define SET_BLOCK(b,node) (b.level=tag_level,b.var=node->nd_var,\
- b.body=node->nd_body,b.env=*the_env,\
- the_env->block= &b)
+#define POP_BLOCK() the_block = the_block->prev; }
static int tag_level, target_level;
static struct tag {
@@ -211,30 +242,24 @@ static struct tag {
jmp_buf buf;
struct gc_list *gclist;
struct ENVIRON *env;
- VALUE self;
- int ilevel;
+ struct tag *prev;
} *prot_tag;
#define PUSH_TAG() {\
struct tag _this;\
- struct tag *_oldtag = prot_tag;\
- &_oldtag;\
_this.level= ++tag_level;\
- _this.env= the_env;\
- _this.self= Qself;\
- _this.ilevel= the_env->iterator;\
+ _this.env = the_env;\
+ _this.prev = prot_tag;\
prot_tag = &_this;\
#define POP_TAG() \
tag_level--;\
- prot_tag = _oldtag;\
+ prot_tag = prot_tag->prev;\
}
#define EXEC_TAG() (setjmp(prot_tag->buf))
#define JUMP_TAG(val) {\
the_env = prot_tag->env;\
- the_env->iterator = prot_tag->ilevel;\
- Qself = prot_tag->self;\
longjmp(prot_tag->buf,(val));\
}
@@ -248,8 +273,34 @@ static struct tag {
#define IN_BLOCK 0x08
+static struct RClass *the_class;
+struct class_link {
+ struct RClass *class;
+ struct class_link *prev;
+} *class_link;
+
+#define PUSH_CLASS() { \
+ struct class_link _link; \
+ _link.class = the_class; \
+ _link.prev = class_link; \
+ class_link = &_link \
+
+#define POP_CLASS() \
+ the_class = class_link->class; \
+ class_link = class_link->prev; }
+
+#define PUSH_SCOPE() { \
+ struct SCOPE _scope; \
+ _scope = *the_scope; \
+ _scope.prev = the_scope; \
+ _scope.block = Qnil; \
+ _scope.flags = 0; \
+ the_scope = &_scope; \
+
+#define POP_SCOPE() the_scope = the_scope->prev; }
+
static VALUE rb_eval();
-VALUE Feval();
+static VALUE Feval();
static VALUE rb_call();
VALUE rb_apply();
@@ -266,6 +317,8 @@ extern VALUE rb_stderr;
extern int sourceline;
extern char *sourcefile;
+static int iter_level = 0;
+
VALUE
rb_self()
{
@@ -302,9 +355,11 @@ ruby_init(argc, argv, envp)
char **argv, **envp;
{
int state;
- static struct ENVIRON top_env;
- the_env = &top_env;
-
+ static struct ENVIRON env;
+ static struct SCOPE scope;
+ the_env = top_env = &env;
+ the_scope = top_scope = &scope;
+
PUSH_TAG();
if ((state = EXEC_TAG()) == 0) {
ruby_init0(argc, argv, envp);
@@ -332,6 +387,8 @@ Eval(toplevel)
tree = eval_tree;
eval_tree = Qnil;
+ sourcefile = tree->src;
+
PUSH_TAG();
if ((state = EXEC_TAG()) == 0) {
result = rb_eval(tree);
@@ -359,12 +416,8 @@ ruby_run()
rb_define_variable("$!", &errstr, Qnil, Qnil);
errat = Qnil; /* clear for execution */
- PUSH_ENV();
- top_env = the_env;
PUSH_TAG();
if ((state = EXEC_TAG()) == 0) {
- int i;
-
the_class = (struct RClass*)C_Object;
Eval(1);
}
@@ -401,7 +454,6 @@ ruby_run()
Bug("Unknown longjmp status %d", state);
break;
}
- POP_ENV();
exit(0);
}
@@ -409,15 +461,30 @@ void
rb_trap_eval(cmd)
VALUE cmd;
{
- PUSH_ENV();
- the_env->self = TopSelf;
- the_env->current_module = top_env->current_module;
- the_env->local_vars = top_env->local_vars;
- the_env->local_tbl = top_env->local_tbl;
- the_class = (struct RClass*)C_Object;
+ int state, go_out;
+
+ DUP_ENV();
+ PUSH_CLASS();
+ PUSH_TAG();
+ PUSH_SCOPE();
+ if ((state = EXEC_TAG()) == 0) {
+ the_env->self = TopSelf;
+ the_class = (struct RClass*)C_Object;
+ the_scope->local_vars = top_scope->local_vars;
+ the_scope->local_tbl = top_scope->local_tbl;
- Feval(Qself, cmd);
+ Feval(Qself, cmd);
+ go_out = 0;
+ }
+ else {
+ go_out = 1;
+ }
+ POP_SCOPE();
+ POP_TAG();
+ POP_CLASS();
POP_ENV();
+
+ if (go_out) JUMP_TAG(state);
}
#define SETUP_ARGS {\
@@ -451,16 +518,15 @@ rb_eval(node)
register NODE *node;
{
int state;
- int go_out = 0;
+ int go_out;
VALUE result;
- &go_out;
again:
if (node == Qnil) return Qnil;
sourceline = node->line;
- sourcefile = node->src;
+#undef SAFE_SIGHANDLE
#ifdef SAFE_SIGHANDLE
{
extern int trap_pending;
@@ -529,14 +595,16 @@ rb_eval(node)
switch (state = EXEC_TAG()) {
case 0:
res = rb_eval(node->nd_cond);
+ go_out = 0;
break;
case TAG_FAIL:
res = Qnil;
+ go_out = 0;
break;
default:
- go_out++;
+ go_out = 1;
}
POP_TAG();
if (go_out) JUMP_TAG(state);
@@ -553,14 +621,17 @@ rb_eval(node)
while_redo:
rb_eval(node->nd_body);
}
+ go_out = 0;
break;
case TAG_REDO:
goto while_redo;
case TAG_CONTINUE:
goto while_cont;
default:
- go_out++;
+ go_out = 1;
+ break;
case TAG_BREAK:
+ go_out = 0;
break;
}
while_out:
@@ -577,13 +648,14 @@ rb_eval(node)
while2_redo:
rb_eval(node->nd_body);
} while (rb_eval(node->nd_cond));
+ go_out = 0;
break;
case TAG_REDO:
goto while2_redo;
case TAG_CONTINUE:
goto while2_cont;
default:
- go_out++;
+ go_out = 1;
case TAG_BREAK:
break;
}
@@ -592,31 +664,34 @@ rb_eval(node)
if (go_out) JUMP_TAG(state);
return Qnil;
- case NODE_DO:
+ case NODE_ITER:
case NODE_FOR:
{
- struct BLOCK block;
+ int iter_saved = iter_level;
- PUSH_ENV();
- SET_BLOCK(block, node);
+ DUP_ENV();
+ PUSH_BLOCK(node->nd_var, node->nd_body);
PUSH_TAG();
state = EXEC_TAG();
if (state == 0) {
- if (node->type == NODE_DO) {
- the_env->iterator = 1;
+ if (node->type == NODE_ITER) {
+ iter_level = 1;
result = rb_eval(node->nd_iter);
}
else {
VALUE recv;
+ iter_level = 0;
recv = rb_eval(node->nd_iter);
- the_env->iterator = 1;
+ iter_level = 1;
result = rb_call(CLASS_OF(recv), recv, each, 0, Qnil);
}
}
POP_TAG();
+ POP_BLOCK();
POP_ENV();
+ iter_level = iter_saved;
switch (state) {
case 0:
break;
@@ -626,9 +701,10 @@ rb_eval(node)
}
result = Qnil;
break;
+ case IN_BLOCK|TAG_RETRY:
case IN_BLOCK|TAG_RETURN:
if (target_level == tag_level) {
- state = TAG_RETURN;
+ state &= ~IN_BLOCK;
}
/* fall through */
default:
@@ -744,29 +820,78 @@ rb_eval(node)
case NODE_CALL2:
{
VALUE recv, *argv;
- int argc, last_iter;
+ int argc, iter_saved = iter_level;
VALUE args = Qnil; /* used in SETUP_ARGS */
+ VALUE buf[3];
- last_iter = the_env->iterator;
- the_env->iterator = 0; /* recv & args are not iter. */
+ iter_level = 0; /* recv & args are not iter. */
recv = node->nd_recv?rb_eval(node->nd_recv):Qself;
+#if 0
SETUP_ARGS;
- the_env->iterator = last_iter; /* restore iter. level */
+#else
+ {
+ NODE *n = node->nd_args;
+ if (n == Qnil) {
+ argc = 0;
+ argv = Qnil;
+ }
+ else if (n->type == NODE_ARRAY) {
+ if (n->nd_next == Qnil) {
+ /* 1 arg */
+ argc = 1;
+ buf[0] = rb_eval(n->nd_head);
+ argv = buf;
+ }
+ else if (n->nd_next->nd_next == Qnil) {
+ /* 2 args */
+ argc = 2;
+ buf[0] = rb_eval(n->nd_head);
+ buf[1] = rb_eval(n->nd_next->nd_head);
+ argv = buf;
+ }
+ else if (n->nd_next->nd_next->nd_next == Qnil) {
+ /* 3 args */
+ argc = 3;
+ buf[0] = rb_eval(n->nd_head);
+ buf[1] = rb_eval(n->nd_next->nd_head);
+ buf[2] = rb_eval(n->nd_next->nd_next->nd_head);
+ argv = buf;
+ }
+ else {
+ int i;
+ for (argc=0; n; n=n->nd_next) argc++;
+ n = node->nd_args;
+ argv = (VALUE*)alloca(sizeof(VALUE)*argc);
+ for (i=0;n;n=n->nd_next) {
+ argv[i++] = rb_eval(n->nd_head);
+ }
+ }
+ }
+ else {
+ args = rb_eval(n);
+ if (TYPE(args) != T_ARRAY)
+ args = rb_to_a(args);
+ argc = RARRAY(args)->len;
+ argv = RARRAY(args)->ptr;
+ }
+ }
+#endif
+ iter_level = iter_saved; /* restore iter. level */
- return rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv);
+ return rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,
+ node->nd_recv?0:1);
}
break;
case NODE_SUPER:
case NODE_ZSUPER:
{
- int last_iter;
+ int iter_saved = iter_level;
int i, argc;
VALUE *argv;
VALUE args = Qnil; /* used in SETUP_ARGS */
- last_iter = the_env->iterator; /* recv & args are not iter. */
- the_env->iterator = 0;
+ iter_level = 0; /* recv & args are not iter. */
if (node->type == NODE_ZSUPER) {
argc = the_env->argc;
@@ -776,19 +901,11 @@ rb_eval(node)
SETUP_ARGS;
}
- /* restore iter. level */
- switch (last_iter) {
- case 1: /* SUPER called as iter. */
- case 2: /* iter. called SUPER */
- the_env->iterator = 1;
- break;
- default: /* otherwise SUPER is not iter. */
- break;
- }
-
+ if (iter_saved == 0) iter_level = 1;
result = rb_call(the_env->last_class->super, Qself,
- the_env->last_func, argc, argv, Qnil);
- the_env->iterator = last_iter;
+ the_env->last_func, argc, argv, 1);
+ /* restore iter. level */
+ iter_level = iter_saved;
}
return result;
@@ -796,23 +913,25 @@ rb_eval(node)
{
VALUE result;
+ PUSH_SCOPE();
PUSH_TAG();
if (node->nd_cnt > 0) {
- the_env->local_vars = alloca(sizeof(VALUE)*node->nd_cnt);
- memset(the_env->local_vars, 0, sizeof(VALUE)*node->nd_cnt);
- the_env->local_tbl = node->nd_tbl;
+ the_scope->local_vars = (VALUE*)
+ alloca(sizeof(VALUE)*node->nd_cnt);
+ memset(the_scope->local_vars, 0, sizeof(VALUE)*node->nd_cnt);
+ the_scope->local_tbl = node->nd_tbl;
}
else {
- the_env->local_vars = Qnil;
- the_env->local_tbl = Qnil;
+ the_scope->local_vars = Qnil;
+ the_scope->local_tbl = Qnil;
}
if ((state = EXEC_TAG()) == 0) {
result = rb_eval(node->nd_body);
}
POP_TAG();
- if (the_env->local_vars && (the_env->flags&VARS_MALLOCED))
- free(the_env->local_vars);
- the_env->local_vars = Qnil;
+ if (the_scope->local_vars && (the_scope->flags&VARS_MALLOCED))
+ free(the_scope->local_vars);
+ POP_SCOPE();
if (state != 0) JUMP_TAG(state);
return result;
@@ -825,9 +944,9 @@ rb_eval(node)
}
case NODE_LASGN:
- if (the_env->local_vars == Qnil)
+ if (the_scope->local_vars == Qnil)
Bug("unexpected local variable asignment");
- return the_env->local_vars[node->nd_cnt] = rb_eval(node->nd_value);
+ return the_scope->local_vars[node->nd_cnt] = rb_eval(node->nd_value);
case NODE_GASGN:
{
@@ -850,15 +969,15 @@ rb_eval(node)
VALUE val;
val = rb_eval(node->nd_value);
- rb_const_set(node->nd_vid, val);
+ rb_const_set(the_class, node->nd_vid, val);
return val;
}
break;
case NODE_LVAR:
- if (the_env->local_vars == Qnil)
+ if (the_scope->local_vars == Qnil)
Bug("unexpected local variable");
- return the_env->local_vars[node->nd_cnt];
+ return the_scope->local_vars[node->nd_cnt];
case NODE_GVAR:
return rb_gvar_get(node->nd_entry);
@@ -980,19 +1099,19 @@ rb_eval(node)
Fail("Wrong # of arguments(%d for %d)", len, i);
local = node->nd_frml;
- if (the_env->local_vars == Qnil)
+ if (the_scope->local_vars == Qnil)
Bug("unexpected local variable asignment");
- for (i=1;local;i++) {
- the_env->local_vars[(int)local->nd_head] = the_env->argv[i-1];
+ for (i=0;local;i++) {
+ the_scope->local_vars[(int)local->nd_head] = the_env->argv[i];
local = local->nd_next;
}
if (node->nd_rest >= 0) {
if (the_env->argc == 0)
- the_env->local_vars[node->nd_rest] = ary_new();
+ the_scope->local_vars[node->nd_rest] = ary_new();
else
- the_env->local_vars[node->nd_rest] =
- ary_new4(the_env->argc-i+1, the_env->argv+i-1);
+ the_scope->local_vars[node->nd_rest] =
+ ary_new4(the_env->argc-i, the_env->argv+i);
}
}
return Qnil;
@@ -1000,8 +1119,9 @@ rb_eval(node)
case NODE_DEFN:
{
if (node->nd_defn) {
- rb_add_method(the_class,node->nd_mid,node->nd_defn,0);
- node->nd_defn = Qnil;
+ node->nd_defn->nd_cnt++;
+ rb_add_method(the_class,node->nd_mid,node->nd_defn,
+ node->nd_noex);
}
}
return Qnil;
@@ -1015,16 +1135,16 @@ rb_eval(node)
Fail("Can't define method \"%s\" for nil",
rb_id2name(node->nd_mid));
}
+ node->nd_defn->nd_cnt++;
rb_add_method(rb_single_class(recv),
node->nd_mid, node->nd_defn, 0);
- node->nd_defn = Qnil;
}
}
return Qnil;
case NODE_UNDEF:
{
- rb_add_method(the_class, node->nd_mid, Qnil, 1);
+ rb_add_method(the_class, node->nd_mid, Qnil, 0);
}
return Qnil;
@@ -1055,16 +1175,17 @@ rb_eval(node)
unliteralize(class);
}
- PUSH_ENV();
+ DUP_ENV();
+ PUSH_CLASS();
the_class = (struct RClass*)
rb_define_class_id(node->nd_cname, super);
Qself = (VALUE)the_class;
-
PUSH_TAG();
if ((state = EXEC_TAG()) == 0) {
rb_eval(node->nd_body);
}
POP_TAG();
+ POP_CLASS();
POP_ENV();
if (state) JUMP_TAG(state);
}
@@ -1081,15 +1202,16 @@ rb_eval(node)
unliteralize(module);
}
- PUSH_ENV();
+ DUP_ENV();
+ PUSH_CLASS();
the_class = (struct RClass*)rb_define_module_id(node->nd_cname);
Qself = (VALUE)the_class;
-
PUSH_TAG();
if ((state = EXEC_TAG()) == 0) {
rb_eval(node->nd_body);
}
POP_TAG();
+ POP_CLASS();
POP_ENV();
if (state) JUMP_TAG(state);
}
@@ -1144,7 +1266,7 @@ rb_exit(status)
exit(FIX2UINT(last_val));
}
-VALUE
+static VALUE
Fexit(obj, args)
VALUE obj, args;
{
@@ -1165,34 +1287,19 @@ Fexit(obj, args)
void
rb_break()
{
- if (the_env->flags & DURING_ITERATE) {
- JUMP_TAG(TAG_BREAK);
- }
- else {
- Fatal("unexpected break");
- }
+ JUMP_TAG(TAG_BREAK);
}
void
rb_redo()
{
- if (the_env->flags & DURING_ITERATE) {
- JUMP_TAG(TAG_REDO);
- }
- else {
- Fatal("unexpected redo");
- }
+ JUMP_TAG(TAG_REDO);
}
void
rb_retry()
{
- if (the_env->flags & DURING_RESQUE) {
- JUMP_TAG(TAG_RETRY);
- }
- else {
- Fatal("unexpected retry");
- }
+ JUMP_TAG(TAG_RETRY);
}
void
@@ -1226,7 +1333,15 @@ rb_fail(mesg)
VALUE
iterator_p()
{
- return ITERATOR_P();
+ if (iter_level == 0) return TRUE;
+ return FALSE;
+}
+
+static VALUE
+Fiterator_p()
+{
+ if (iter_level == -1) return TRUE;
+ return FALSE;
}
VALUE
@@ -1234,21 +1349,20 @@ rb_yield(val)
VALUE val;
{
struct BLOCK *block;
- int state;
- int go_out;
+ NODE *node;
+ int state, go_out;
VALUE result;
- int cnt;
- &go_out;
- block = the_env->block;
- if (!ITERATOR_P()) {
+ if (!iter_level == 0) {
Fail("yield called out of iterator");
}
- PUSH_ENV();
- block->env.prev = the_env->prev;
+ block = the_block;
+ block->env.prev = the_env;
the_env = &(block->env);
- the_env->flags = the_env->prev->flags;
+ block->scope.prev = the_scope;
+ the_scope = &(block->scope);
+ the_block = block->prev;
if (block->var) {
if (block->var->type == NODE_MASGN)
masign(block->var, val);
@@ -1256,33 +1370,37 @@ rb_yield(val)
asign(block->var, val);
}
- go_out = 0;
PUSH_TAG();
+ node = block->body;
switch (state = EXEC_TAG()) {
- retry:
+ redo:
case 0:
- if (block->body->type == NODE_CFUNC) {
- the_env->flags |= DURING_ITERATE;
- result = (*block->body->nd_cfnc)(val, block->body->nd_argc);
+ if (node->type == NODE_CFUNC) {
+ result = (*node->nd_cfnc)(val,node->nd_argc);
}
else {
- result = rb_eval(block->body);
+ result = rb_eval(node);
}
+ go_out = 0;
break;
- case TAG_RETRY:
- goto retry;
+ case TAG_REDO:
+ goto redo;
case TAG_CONTINUE:
+ go_out = 0;
break;
+ case TAG_RETRY:
case TAG_BREAK:
case TAG_RETURN:
target_level = block->level;
state = IN_BLOCK|state;
default:
- go_out++;
+ go_out = 1;
break;
}
POP_TAG();
- POP_ENV();
+ the_block = block;
+ the_env = the_env->prev;
+ the_scope = the_scope->prev;
if (go_out) JUMP_TAG(state);
return result;
@@ -1341,13 +1459,13 @@ asign(lhs, val)
break;
case NODE_LASGN:
- if (the_env->local_vars == Qnil)
+ if (the_scope->local_vars == Qnil)
Bug("unexpected iterator variable asignment");
- the_env->local_vars[lhs->nd_cnt] = val;
+ the_scope->local_vars[lhs->nd_cnt] = val;
break;
case NODE_CASGN:
- rb_const_set(lhs->nd_vid, val);
+ rb_const_set(the_class, lhs->nd_vid, val);
break;
case NODE_CALL:
@@ -1380,25 +1498,25 @@ rb_iterate(it_proc, data1, bl_proc, data2)
VALUE (*it_proc)(), (*bl_proc)();
char *data1, *data2;
{
- int state;
+ int state, iter_saved;
VALUE retval;
NODE *node = NEW_CFUNC(bl_proc, data2);
struct BLOCK block;
- PUSH_ENV();
- block.level = tag_level;
- block.var = Qnil;
- block.body = node;
- block.env = *the_env;
- the_env->block = &block;
+ DUP_ENV();
+ PUSH_BLOCK(Qnil, node);
PUSH_TAG();
+ iter_saved = iter_level;
+ iter_level = 1;
state = EXEC_TAG();
if (state == 0) {
- the_env->iterator = 1;
retval = (*it_proc)(data1);
}
+ iter_level = iter_saved;
+
POP_TAG();
+ POP_BLOCK();
POP_ENV();
freenode(node);
@@ -1412,9 +1530,10 @@ rb_iterate(it_proc, data1, bl_proc, data2)
}
retval = Qnil;
break;
+ case IN_BLOCK|TAG_RETRY:
case IN_BLOCK|TAG_RETURN:
if (target_level == tag_level) {
- state = TAG_RETURN;
+ state &= ~IN_BLOCK;
}
/* fall through */
default:
@@ -1433,13 +1552,12 @@ rb_resque(b_proc, data1, r_proc, data2)
int go_out;
VALUE result;
- &go_out;
- go_out = 0;
PUSH_TAG();
switch (state = EXEC_TAG()) {
case 0:
retry_entry:
result = (*b_proc)(data1);
+ go_out = 0;
break;
case TAG_FAIL:
@@ -1447,7 +1565,6 @@ rb_resque(b_proc, data1, r_proc, data2)
PUSH_TAG();
state = EXEC_TAG();
if (state == 0) {
- the_env->flags |= DURING_RESQUE;
result = (*r_proc)(data2);
}
POP_TAG();
@@ -1455,9 +1572,10 @@ rb_resque(b_proc, data1, r_proc, data2)
case TAG_RETRY:
goto retry_entry;
case 0:
+ go_out = 0;
break;
default:
- go_out++;
+ go_out = 1;
break;
}
}
@@ -1467,6 +1585,7 @@ rb_resque(b_proc, data1, r_proc, data2)
break;
default:
+ go_out = 1;
break;
}
POP_TAG();
@@ -1515,37 +1634,46 @@ rb_undefined(obj, id)
}
static VALUE
-rb_call(class, recv, mid, argc, argv)
+rb_call(class, recv, mid, argc, argv, func)
struct RClass *class;
VALUE recv, *argv;
int argc;
ID mid;
+ int func;
{
NODE *body;
+ int noex;
VALUE result;
- VALUE saved_self = Qself;
- int saved_ilevel = the_env->iterator;
struct cache_entry *ent;
- ID id;
+ PUSH_ENV();
Qself = recv;
- if (the_env->iterator != 0) the_env->iterator++;
+ the_env->last_func = mid;
+ the_env->argc = argc;
+ the_env->argv = argv;
+ iter_level--;
/* is it in the method cache? */
ent = cache + EXPR1(class, mid);
if (ent->class == class && ent->mid == mid) {
- if (ent->undef) rb_undefined(recv, mid);
+ if (ent->method == Qnil) rb_undefined(recv, mid);
class = ent->origin;
- id = ent->method->id;
- body = ent->method->node;
+ mid = ent->mid;
+ body = ent->method->nd_head;
+ noex = ent->noex;
}
else {
- id = mid;
- if ((body = rb_get_method_body(&class, &id)) == Qnil) {
+ ID id = mid;
+
+ if ((body = rb_get_method_body(&class, &id, &noex)) == Qnil) {
rb_undefined(recv, mid);
}
+ mid = id;
}
+ if (!func && noex) rb_undefined(recv, mid);
+ the_env->last_class = class;
+
if (body->type == NODE_CFUNC) {
int len = body->nd_argc;
@@ -1553,125 +1681,112 @@ rb_call(class, recv, mid, argc, argv)
Fail("Wrong # of arguments for(%d for %d)", argc, body->nd_argc);
}
- if (len == -2) {
+ switch (len) {
+ case -2:
result = (*body->nd_cfnc)(recv, ary_new4(argc, argv));
- }
- else if (len == -1) {
+ break;
+ case -1:
result = (*body->nd_cfnc)(argc, argv);
- }
- else if (len >= 0) {
- switch (argc) {
- case 0:
- result = (*body->nd_cfnc)(recv);
- break;
- case 1:
- result = (*body->nd_cfnc)(recv, argv[0]);
- break;
- case 2:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1]);
- break;
- case 3:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2]);
- break;
- case 4:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3]);
- break;
- case 5:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4]);
- break;
- case 6:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5]);
- break;
- case 7:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5],
- argv[6]);
- break;
- case 8:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5],
- argv[6], argv[7]);
- break;
- case 9:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5],
- argv[6], argv[7], argv[8]);
- break;
- case 10:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5],
- argv[6], argv[7], argv[8],
- argv[6], argv[7], argv[8],
- argv[9]);
- break;
- case 11:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5],
- argv[6], argv[7], argv[8],
- argv[6], argv[7], argv[8],
- argv[9], argv[10]);
- break;
- case 12:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5],
- argv[6], argv[7], argv[8],
- argv[6], argv[7], argv[8],
- argv[9], argv[10], argv[11]);
- break;
- case 13:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5],
- argv[6], argv[7], argv[8],
- argv[6], argv[7], argv[8],
- argv[9], argv[10], argv[11],
- argv[12]);
- break;
- case 14:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5],
- argv[6], argv[7], argv[8],
- argv[6], argv[7], argv[8],
- argv[9], argv[10], argv[11],
- argv[12], argv[13]);
- break;
- case 15:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5],
- argv[6], argv[7], argv[8],
- argv[6], argv[7], argv[8],
- argv[9], argv[10], argv[11],
- argv[12], argv[13], argv[14]);
- break;
- default:
+ break;
+ case 0:
+ result = (*body->nd_cfnc)(recv);
+ break;
+ case 1:
+ result = (*body->nd_cfnc)(recv, argv[0]);
+ break;
+ case 2:
+ result = (*body->nd_cfnc)(recv, argv[0], argv[1]);
+ break;
+ case 3:
+ result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2]);
+ break;
+ case 4:
+ result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
+ argv[3]);
+ break;
+ case 5:
+ result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
+ argv[3], argv[4]);
+ break;
+ case 6:
+ result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
+ argv[3], argv[4], argv[5]);
+ break;
+ case 7:
+ result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
+ argv[3], argv[4], argv[5],
+ argv[6]);
+ break;
+ case 8:
+ result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
+ argv[3], argv[4], argv[5],
+ argv[6], argv[7]);
+ break;
+ case 9:
+ result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
+ argv[3], argv[4], argv[5],
+ argv[6], argv[7], argv[8]);
+ break;
+ case 10:
+ result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
+ argv[3], argv[4], argv[5],
+ argv[6], argv[7], argv[8],
+ argv[6], argv[7], argv[8],
+ argv[9]);
+ break;
+ case 11:
+ result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
+ argv[3], argv[4], argv[5],
+ argv[6], argv[7], argv[8],
+ argv[6], argv[7], argv[8],
+ argv[9], argv[10]);
+ break;
+ case 12:
+ result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
+ argv[3], argv[4], argv[5],
+ argv[6], argv[7], argv[8],
+ argv[6], argv[7], argv[8],
+ argv[9], argv[10], argv[11]);
+ break;
+ case 13:
+ result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
+ argv[3], argv[4], argv[5],
+ argv[6], argv[7], argv[8],
+ argv[6], argv[7], argv[8],
+ argv[9], argv[10], argv[11],
+ argv[12]);
+ break;
+ case 14:
+ result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
+ argv[3], argv[4], argv[5],
+ argv[6], argv[7], argv[8],
+ argv[6], argv[7], argv[8],
+ argv[9], argv[10], argv[11],
+ argv[12], argv[13]);
+ break;
+ case 15:
+ result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
+ argv[3], argv[4], argv[5],
+ argv[6], argv[7], argv[8],
+ argv[6], argv[7], argv[8],
+ argv[9], argv[10], argv[11],
+ argv[12], argv[13], argv[14]);
+ break;
+ default:
+ if (len < 0) {
+ Bug("bad argc(%d) specified for `%s(%s)'",
+ len, rb_class2name(class), rb_id2name(mid));
+ }
+ else {
Fail("too many arguments(%d)", len);
- break;
}
- }
- else {
- Bug("bad argc(%d) specified for `%s(%s)'",
- len, rb_class2name(class), rb_id2name(mid));
+ break;
}
}
else {
int state;
- PUSH_ENV();
-
- the_env->local_vars = Qnil;
- the_env->local_tbl = Qnil;
- the_env->flags |= DURING_CALL;
- the_env->argc = argc;
- the_env->argv = argv;
- the_env->last_class = class;
- the_env->last_func = id;
-#ifdef USE_CALLER
- the_env->file = sourcefile;
- the_env->line = sourceline;
-#endif
-
+ sourcefile = body->src;
PUSH_TAG();
state = EXEC_TAG();
if (state == 0) {
@@ -1699,32 +1814,34 @@ rb_call(class, recv, mid, argc, argv)
default:
JUMP_TAG(state);
}
- POP_ENV();
}
- Qself = saved_self;
- the_env->iterator = saved_ilevel;
+ iter_level++;
+ POP_ENV();
return result;
}
VALUE
rb_apply(recv, mid, args)
- VALUE recv, args;
+ VALUE recv;
+ struct RArray *args;
ID mid;
{
VALUE *argv;
int argc, i;
- argc = RARRAY(args)->len + 1;
- argv = (VALUE*)alloca(sizeof(VALUE)*argc);
- for (i=1;i<argc;i++) {
- argv[i] = RARRAY(args)->ptr[i-1];
+ if (args) {
+ argc = args->len;
+ argv = args->ptr;
}
- argv[0] = Qnil;
- return rb_call(CLASS_OF(recv), recv, mid, argc, argv);
+ else {
+ argc = 0;
+ argv = Qnil;
+ }
+ return rb_call(CLASS_OF(recv), recv, mid, argc, argv, recv==Qself);
}
-VALUE
+static VALUE
Fapply(recv, args)
VALUE recv, args;
{
@@ -1768,49 +1885,12 @@ rb_funcall(recv, mid, n, va_alist)
argv = Qnil;
}
- return rb_call(CLASS_OF(recv), recv, mid, n, argv);
+ return rb_call(CLASS_OF(recv), recv, mid, n, argv, recv==Qself);
}
-#ifdef USE_CALLER
-VALUE
-Fcaller(obj, args)
- VALUE obj, args;
-{
- VALUE level, file, res, ary;
- int lev;
- struct ENVIRON *e;
-
- rb_scan_args(args, "01", &level);
- if (level == Qnil) {
- lev = 1;
- }
- else {
- lev = FIX2UINT(level);
- }
- if (lev < 0) Fail("negative level: %d", lev);
-
- e = the_env;
-
- while (lev > 0) {
- e = e->prev;
- if (e == Qnil) Fail("no caller");
- if (!(e->flags & DURING_CALL)) continue;
- lev--;
- }
- if (e->file == Qnil) Fail("initial frame");
-
- file = str_new2(e->file);
- ary = e->argv?ary_new4(e->argc, e->argv):ary_new2(0);
- res = ary_new3(5, file, INT2FIX(e->line),
- str_new2(rb_id2name(e->last_func)), Qself, ary);
-
- return res;
-}
-#endif
+int rb_in_eval = 0;
-int in_eval = 0;
-
-VALUE
+static VALUE
Feval(obj, src)
VALUE obj;
struct RString *src;
@@ -1822,15 +1902,13 @@ Feval(obj, src)
Check_Type(src, T_STRING);
PUSH_TAG();
- PUSH_ENV();
- the_env->in_eval = 1;
+ DUP_ENV();
+ rb_in_eval = 1;
node = eval_tree;
- if (the_env->prev) {
- the_class = the_env->prev->current_module;
- }
- else {
- the_class = (struct RClass*)C_Object;
+ PUSH_CLASS();
+ if (TYPE(the_class) == T_ICLASS) {
+ the_class = (struct RClass*)RBASIC(the_class)->class;
}
if ((state = EXEC_TAG()) == 0) {
@@ -1843,9 +1921,9 @@ Feval(obj, src)
}
}
eval_tree = node;
+ POP_CLASS();
POP_ENV();
POP_TAG();
- if (state) printf("exception in eval()\n");
if (state) JUMP_TAG(state);
if (nerrs > 0) {
@@ -1900,7 +1978,7 @@ Fload(obj, fname)
VALUE obj;
struct RString *fname;
{
- int state;
+ int state, in_eval = rb_in_eval;
NODE *node;
char *file;
@@ -1927,13 +2005,13 @@ Fload(obj, fname)
#endif
PUSH_TAG();
- PUSH_ENV();
+ DUP_ENV();
+ PUSH_CLASS();
the_class = (struct RClass*)C_Object;
Qself = TopSelf;
- the_env->current_module = top_env->current_module;
- the_env->local_vars = top_env->local_vars;
- the_env->local_tbl = top_env->local_tbl;
- the_env->in_eval = 1;
+ the_scope->local_vars = top_scope->local_vars;
+ the_scope->local_tbl = top_scope->local_tbl;
+ rb_in_eval = 1;
state = EXEC_TAG();
if (state == 0) {
rb_load_file(file);
@@ -1941,8 +2019,10 @@ Fload(obj, fname)
Eval(0);
}
}
+ POP_CLASS();
POP_ENV();
POP_TAG();
+ rb_in_eval = in_eval;
if (nerrs > 0) {
rb_fail(errstr);
}
@@ -2006,9 +2086,10 @@ addpath(path)
}
}
+extern VALUE C_Kernel;
+
Init_load()
{
- extern VALUE C_Builtin;
extern VALUE rb_check_str();
char *path;
@@ -2019,6 +2100,14 @@ Init_load()
addpath(getenv("RUBYLIB"));
addpath(RUBY_LIB);
- rb_define_method(C_Builtin, "load", Fload, 1);
- rb_define_method(C_Builtin, "require", Frequire, 1);
+ rb_define_private_method(C_Kernel, "load", Fload, 1);
+ rb_define_private_method(C_Kernel, "require", Frequire, 1);
+}
+
+Init_eval()
+{
+ rb_define_private_method(C_Kernel, "exit", Fexit, -2);
+ rb_define_private_method(C_Kernel, "eval", Feval, 1);
+ rb_define_private_method(C_Kernel, "iterator_p", Fiterator_p, 0);
+ rb_define_method(C_Kernel, "apply", Fapply, -2);
}
diff --git a/file.c b/file.c
index ebb9251..77245e0 100644
--- a/file.c
+++ b/file.c
@@ -1064,8 +1064,6 @@ Init_File()
C_File = rb_define_class("File", C_IO);
- rb_include_module(CLASS_OF(C_File), M_FileTest);
-
rb_define_single_method(C_File, "stat", Ffile_stat, 1);
rb_define_single_method(C_File, "lstat", Ffile_lstat, 1);
rb_define_single_method(C_File, "type", Ffile_type, 1);
@@ -1088,6 +1086,8 @@ Init_File()
rb_define_single_method(C_File, "umask", Ffile_umask, -1);
rb_define_single_method(C_File, "truncate", Ffile_truncate, 2);
+ rb_include_module(CLASS_OF(C_File), M_FileTest);
+
rb_define_method(C_File, "stat", Ffile_stat2, 0);
rb_define_method(C_File, "lstat", Ffile_lstat2, 0);
diff --git a/gc.c b/gc.c
index ea9ceeb..9961b44 100644
--- a/gc.c
+++ b/gc.c
@@ -164,7 +164,7 @@ rb_global_variable(var)
struct RVALUE {
union {
struct {
- int flag; /* alway 0 for freed obj */
+ UINT flag; /* alway 0 for freed obj */
struct RVALUE *next;
} free;
struct RObject object;
@@ -505,7 +505,7 @@ freemethod(key, body)
ID key;
void *body;
{
- method_free(body);
+ freenode(body);
return ST_CONTINUE;
}
@@ -570,6 +570,7 @@ gc()
struct literal_list *lit;
struct gc_list *list;
struct ENVIRON *env;
+ struct SCOPE *scope;
int i, max;
jmp_buf save_regs_gc_mark;
VALUE stack_end;
@@ -582,8 +583,12 @@ gc()
gc_mark(env->self);
if (env->argv)
mark_locations_array(env->argv, env->argc);
- if (env->local_vars)
- mark_locations_array(env->local_vars, env->local_tbl[0]);
+ }
+
+ /* mark scope stack */
+ for (scope = the_scope; scope; scope = scope->prev) {
+ if (scope->local_vars)
+ mark_locations_array(scope->local_vars, scope->local_tbl[0]);
}
FLUSH_REGISTER_WINDOWS;
diff --git a/gnuglob.c b/gnuglob.c
index e5eecc1..da758bc 100644
--- a/gnuglob.c
+++ b/gnuglob.c
@@ -86,6 +86,12 @@ extern void bcopy ();
# endif /* !RISC6000 */
#endif /* USG */
+#if defined(sparc) && !defined(__GNUC__)
+#include <alloca.h>
+#else
+char *alloca ();
+#endif
+
#include "fnmatch.h"
/* If the opendir () on your system lets you open non-directory files,
diff --git a/inits.c b/inits.c
index 3df1d27..609e125 100644
--- a/inits.c
+++ b/inits.c
@@ -18,6 +18,7 @@ rb_call_inits()
Init_var_tables();
Init_Object();
Init_GC();
+ Init_eval();
Init_Comparable();
Init_Enumerable();
Init_Numeric();
diff --git a/io.c b/io.c
index 8e0c6d8..dd01345 100644
--- a/io.c
+++ b/io.c
@@ -21,7 +21,7 @@
VALUE rb_ad_string();
-VALUE C_IO, C_ARGFILE;
+VALUE C_IO;
extern VALUE C_File;
VALUE rb_stdin, rb_stdout, rb_stderr, rb_defout;
@@ -29,6 +29,8 @@ VALUE rb_stdin, rb_stdout, rb_stderr, rb_defout;
VALUE FS, OFS;
VALUE RS, ORS;
+static VALUE argf;
+
ID id_write, id_fd, id_print_on;
extern char *inplace;
@@ -178,7 +180,7 @@ read_all(port)
for (;;) {
n = fread(buf, 1, BUFSIZ, fptr->f);
if (n == 0) {
- if (feof(fptr->f)) return Qnil;
+ if (feof(fptr->f)) break;
rb_sys_fail(Qnil);
}
str_cat(str, buf, n);
@@ -1261,26 +1263,26 @@ VALUE rb_readonly_hook();
Init_IO()
{
- extern VALUE C_Builtin;
+ extern VALUE C_Kernel;
id_write = rb_intern("write");
id_fd = rb_intern("fd");
id_print_on = rb_intern("print_on");
- rb_define_method(C_Builtin, "syscall", Fsyscall, -1);
+ rb_define_private_method(C_Kernel, "syscall", Fsyscall, -1);
- rb_define_method(C_Builtin, "open", Fopen, -2);
- rb_define_method(C_Builtin, "printf", Fprintf, -1);
- rb_define_method(C_Builtin, "print", Fprint, -1);
- rb_define_method(C_Builtin, "gets", Fgets, 0);
- rb_define_alias(C_Builtin,"readline", "gets");
- rb_define_method(C_Builtin, "eof", Feof, 0);
- rb_define_method(C_Builtin, "getc", Fgetc, 0);
- rb_define_method(C_Builtin, "select", Fselect, -2);
+ rb_define_private_method(C_Kernel, "open", Fopen, -2);
+ rb_define_private_method(C_Kernel, "printf", Fprintf, -1);
+ rb_define_private_method(C_Kernel, "gets", Fgets, 0);
+ rb_define_alias(C_Kernel,"readline", "gets");
+ rb_define_private_method(C_Kernel, "eof", Feof, 0);
+ rb_define_private_method(C_Kernel, "getc", Fgetc, 0);
+ rb_define_private_method(C_Kernel, "select", Fselect, -2);
- rb_define_method(C_Builtin, "readlines", Freadlines, 0);
+ rb_define_private_method(C_Kernel, "readlines", Freadlines, 0);
- rb_define_method(C_Builtin, "print_on", Fprint_on, 1);
+ rb_define_method(C_Kernel, "print_on", Fprint_on, 1);
+ rb_define_method(C_Kernel, "print", Fprint, -1);
C_IO = rb_define_class("IO", C_Object);
rb_include_module(C_IO, M_Enumerable);
@@ -1340,22 +1342,21 @@ Init_IO()
rb_define_single_method(C_IO, "default", Fio_defget, 0);
rb_define_single_method(C_IO, "default=", Fio_defset, 1);
- C_ARGFILE = rb_define_class("ARGFILE", C_Object);
- rb_include_module(C_ARGFILE, M_Enumerable);
-
- rb_define_variable("$ARGF", &C_ARGFILE, Qnil, rb_readonly_hook);
+ argf = obj_alloc(C_Object);
+ rb_define_variable("$ARGF", &argf, Qnil, rb_readonly_hook);
- rb_define_single_method(C_ARGFILE, "each", Farg_each, 0);
- rb_define_single_method(C_ARGFILE, "each_byte", Farg_each_byte, 0);
+ rb_define_single_method(argf, "each", Farg_each, 0);
+ rb_define_single_method(argf, "each_byte", Farg_each_byte, 0);
- rb_define_single_method(C_ARGFILE, "read", Farg_read, 0);
- rb_define_single_method(C_ARGFILE, "readlines", Freadlines, 0);
- rb_define_single_method(C_ARGFILE, "gets", Fgets, 0);
- rb_define_single_method(C_ARGFILE, "realine", Fgets, 0);
- rb_define_single_method(C_ARGFILE, "getc", Farg_getc, 0);
- rb_define_single_method(C_ARGFILE, "eof", Feof, 0);
+ rb_define_single_method(argf, "read", Farg_read, 0);
+ rb_define_single_method(argf, "readlines", Freadlines, 0);
+ rb_define_single_method(argf, "gets", Fgets, 0);
+ rb_define_single_method(argf, "realine", Fgets, 0);
+ rb_define_single_method(argf, "getc", Farg_getc, 0);
+ rb_define_single_method(argf, "eof", Feof, 0);
- rb_define_single_method(C_ARGFILE, "to_s", Farg_to_s, 0);
+ rb_define_single_method(argf, "to_s", Farg_to_s, 0);
+ rb_include_module(CLASS_OF(argf), M_Enumerable);
Init_File();
}
diff --git a/math.c b/math.c
index 5096ba6..09c9c8c 100644
--- a/math.c
+++ b/math.c
@@ -100,7 +100,6 @@ Fmath_sqrt(obj, x)
struct RFloat *x;
{
Need_Float(x);
- return float_new(log10(x->value));
if (x->value < 0.0) Fail("square root for negative number");
return float_new(sqrt(x->value));
@@ -110,15 +109,13 @@ Init_Math()
{
M_Math = rb_define_module("Math");
- rb_define_method(M_Math, "atan2", Fmath_atan2, 2);
- rb_define_method(M_Math, "cos", Fmath_cos, 1);
- rb_define_method(M_Math, "sin", Fmath_sin, 1);
- rb_define_method(M_Math, "tan", Fmath_tan, 1);
-
- rb_define_method(M_Math, "exp", Fmath_exp, 1);
- rb_define_method(M_Math, "log", Fmath_log, 1);
- rb_define_method(M_Math, "log10", Fmath_log10, 1);
- rb_define_method(M_Math, "sqrt", Fmath_sqrt, 1);
+ rb_define_module_function(M_Math, "atan2", Fmath_atan2, 2);
+ rb_define_module_function(M_Math, "cos", Fmath_cos, 1);
+ rb_define_module_function(M_Math, "sin", Fmath_sin, 1);
+ rb_define_module_function(M_Math, "tan", Fmath_tan, 1);
- rb_include_module(CLASS_OF(M_Math), M_Math);
+ rb_define_module_function(M_Math, "exp", Fmath_exp, 1);
+ rb_define_module_function(M_Math, "log", Fmath_log, 1);
+ rb_define_module_function(M_Math, "log10", Fmath_log10, 1);
+ rb_define_module_function(M_Math, "sqrt", Fmath_sqrt, 1);
}
diff --git a/newver.rb b/newver.rb
index a8cad4d..884e873 100644..100755
--- a/newver.rb
+++ b/newver.rb
@@ -9,8 +9,8 @@ if $_ =~ /"(\d+)\.(\d+)"/;
if $ARGV[0] == "-f"
i += 1
end
- date = Time.now.strftime("%d %b %y")
- printf("ruby version %d.%0d (%s)\n", $1, i, date)
+ date = Time.now.strftime("%y/%m/%d")
+ printf("ruby - version %d.%0d (%s)\n", $1, i, date)
printf(f, "#define RUBY_VERSION \"%d.%0d\"\n", $1, i)
printf(f, "#define VERSION_DATE \"%s\"\n", date)
f.close
diff --git a/node.h b/node.h
index 702f1e9..59aa240 100644
--- a/node.h
+++ b/node.h
@@ -14,6 +14,8 @@
#define NODE_H
enum node_type {
+ NODE_METHOD,
+ NODE_FBODY,
NODE_CFUNC,
NODE_SCOPE,
NODE_BLOCK,
@@ -23,7 +25,7 @@ enum node_type {
NODE_WHILE,
NODE_WHILE2,
NODE_EXNOT,
- NODE_DO,
+ NODE_ITER,
NODE_FOR,
NODE_PROT,
NODE_AND,
@@ -141,10 +143,11 @@ typedef struct node {
#define nd_mid u2.id
#define nd_args u3.node
+#define nd_noex u1.id
#define nd_defn u3.node
-#define nd_new u1.id
-#define nd_old u2.id
+#define nd_new u2.id
+#define nd_old u3.id
#define nd_cfnc u1.cfunc
#define nd_argc u2.argc
@@ -157,14 +160,15 @@ typedef struct node {
#define nd_beg u1.node
#define nd_end u2.node
#define nd_state u3.state
-
#define nd_rval u3.node
-#define NEW_DEFN(i,d) newnode(NODE_DEFN,Qnil,i,d)
-#define NEW_DEFS(r,i,d) newnode(NODE_DEFS,r,i,d)
+#define NEW_METHOD(n,x) newnode(NODE_METHOD,x,n,Qnil)
+#define NEW_FBODY(n,i) newnode(NODE_FBODY,n,i,1)
+#define NEW_DEFN(i,d,p) newnode(NODE_DEFN,p,i,NEW_FBODY(d,i))
+#define NEW_DEFS(r,i,d) newnode(NODE_DEFS,r,i,NEW_FBODY(d,i))
#define NEW_CFUNC(f,c) newnode(NODE_CFUNC,f,c,Qnil)
#define NEW_RFUNC(b1,b2) NEW_SCOPE(block_append(b1,b2))
-#define NEW_SCOPE(b) newnode(NODE_SCOPE, local_tbl(),(b),local_cnt(0))
+#define NEW_SCOPE(b) newnode(NODE_SCOPE,local_tbl(),(b),local_cnt(0))
#define NEW_BLOCK(a) newnode(NODE_BLOCK,a,Qnil,Qnil)
#define NEW_IF(c,t,e) newnode(NODE_IF,c,t,e)
#define NEW_EXNOT(c) newnode(NODE_EXNOT,c,Qnil,Qnil)
@@ -176,7 +180,7 @@ typedef struct node {
#define NEW_WHILE2(c,b) newnode(NODE_WHILE2,c,b,Qnil)
#define NEW_UNTIL2(c,b) newnode(NODE_WHILE2,NEW_EXNOT(c),b,Qnil)
#define NEW_FOR(v,i,b) newnode(NODE_FOR,v,b,i)
-#define NEW_DO(v,i,b) newnode(NODE_DO,v,b,i)
+#define NEW_ITER(v,i,b) newnode(NODE_ITER,v,b,i)
#define NEW_PROT(b,ex,en) newnode(NODE_PROT,b,ex,en)
#define NEW_REDO() newnode(NODE_REDO,Qnil,Qnil,Qnil)
#define NEW_BREAK() newnode(NODE_BREAK,Qnil,Qnil,Qnil)
@@ -212,7 +216,7 @@ typedef struct node {
#define NEW_SUPER(a) newnode(NODE_SUPER,Qnil,Qnil,a)
#define NEW_ZSUPER() newnode(NODE_ZSUPER,Qnil,Qnil,Qnil)
#define NEW_ARGS(f,r) newnode(NODE_ARGS,f,r,Qnil)
-#define NEW_ALIAS(n,o) newnode(NODE_ALIAS,n,o,Qnil)
+#define NEW_ALIAS(n,o) newnode(NODE_ALIAS,Qnil,n,o)
#define NEW_UNDEF(i) newnode(NODE_UNDEF,Qnil,i,Qnil)
#define NEW_CLASS(n,b,s) newnode(NODE_CLASS,n,NEW_SCOPE(b),s)
#define NEW_MODULE(n,b) newnode(NODE_MODULE,n,NEW_SCOPE(b),Qnil)
diff --git a/numeric.c b/numeric.c
index 9d13126..4310902 100644
--- a/numeric.c
+++ b/numeric.c
@@ -11,6 +11,7 @@
************************************************/
#include "ruby.h"
+#include "env.h"
#include <math.h>
static ID coerce;
@@ -36,11 +37,11 @@ float_new(d)
}
static
-num_coerce_bin(x, mid, y)
+num_coerce_bin(x, y)
VALUE x, y;
- ID mid;
{
- return rb_funcall(rb_funcall(y, coerce, 1, x), mid, 1, y);
+ return rb_funcall(rb_funcall(y, coerce, 1, x),
+ the_env->last_func, 1, y);
}
static VALUE
@@ -54,7 +55,7 @@ static VALUE
Fnum_uminus(num)
VALUE num;
{
- return rb_funcall(rb_funcall(num, coerce, 1, INT2FIX(0)), '-', 1, num);
+ return rb_funcall(rb_funcall(num, coerce, 1, INT2FIX(0)), 1, num);
}
static VALUE
@@ -166,20 +167,6 @@ Fnum_is_int(num)
}
static VALUE
-Fflo_new(flt)
- struct RFloat *flt;
-{
- Check_Type(flt, T_FLOAT);
- {
- NEWOBJ(flt2, struct RFloat);
- CLONESETUP(flt2, flt);
-
- flt2->value = flt->value;
- return (VALUE)flt2;
- }
-}
-
-static VALUE
Fflo_to_s(flt)
struct RFloat *flt;
{
@@ -229,7 +216,7 @@ Fflo_plus(x, y)
case T_STRING:
return Fstr_plus(obj_as_string(x), y);
default:
- return num_coerce_bin(x, '+', y);
+ return num_coerce_bin(x, y);
}
}
@@ -245,7 +232,7 @@ Fflo_minus(x, y)
case T_FLOAT:
return float_new(x->value - y->value);
default:
- return num_coerce_bin(x, '-', y);
+ return num_coerce_bin(x, y);
}
}
@@ -263,7 +250,7 @@ Fflo_mul(x, y)
case T_STRING:
return Fstr_times(y, INT2FIX((int)x->value));
default:
- return num_coerce_bin(x, '*', y);
+ return num_coerce_bin(x, y);
}
}
@@ -287,7 +274,7 @@ Fflo_div(x, y)
if (y->value == 0.0) Fail("devided by 0");
return float_new(x->value / y->value);
default:
- return num_coerce_bin(x, '/', y);
+ return num_coerce_bin(x, y);
}
}
@@ -308,7 +295,7 @@ Fflo_mod(x, y)
value = y->value;
break;
default:
- return num_coerce_bin(x, '%', y);
+ return num_coerce_bin(x, y);
}
#ifdef HAVE_FMOD
{
@@ -338,7 +325,7 @@ Fflo_pow(x, y)
case T_FLOAT:
return float_new(pow(x->value, y->value));
default:
- return num_coerce_bin(x, rb_intern("**"), y);
+ return num_coerce_bin(x, y);
}
}
@@ -357,7 +344,7 @@ Fflo_eq(x, y)
case T_FLOAT:
return (x->value == y->value)?TRUE:FALSE;
default:
- return num_coerce_bin(x, rb_intern("=="), y);
+ return num_coerce_bin(x, y);
}
}
@@ -399,7 +386,7 @@ Fflo_cmp(x, y)
break;
default:
- return num_coerce_bin(x, rb_intern("<=>"), y);
+ return num_coerce_bin(x, y);
}
if (a == b) return INT2FIX(0);
if (a > b) return INT2FIX(1);
@@ -428,15 +415,6 @@ Fflo_to_f(num)
}
static VALUE
-Fflo_clone(flt)
- struct RFloat *flt;
-{
- VALUE flt2 = float_new(flt->value);
- CLONESETUP(flt2, flt);
- return flt2;
-}
-
-static VALUE
Fflo_abs(flt)
struct RFloat *flt;
{
@@ -529,13 +507,6 @@ Fint_chr(num)
return str_new(&c, 1);
}
-VALUE
-Ffix_clone(num)
- VALUE num;
-{
- return num;
-}
-
static VALUE
Ffix_uminus(num)
VALUE num;
@@ -591,7 +562,7 @@ Ffix_plus(x, y)
case T_FLOAT:
return float_new((double)FIX2INT(x) + y->value);
default:
- return num_coerce_bin(x, '+', y);
+ return num_coerce_bin(x, y);
}
}
@@ -619,7 +590,7 @@ Ffix_minus(x, y)
case T_FLOAT:
return float_new((double)FIX2INT(x) - y->value);
default:
- return num_coerce_bin(x, '-', y);
+ return num_coerce_bin(x, y);
}
}
@@ -643,7 +614,7 @@ Ffix_mul(x, y)
case T_FLOAT:
return float_new((double)FIX2INT(x) * y->value);
default:
- return num_coerce_bin(x, '*', y);
+ return num_coerce_bin(x, y);
}
}
@@ -660,7 +631,7 @@ Ffix_div(x, y)
i = FIX2INT(x)/i;
return INT2FIX(i);
}
- return num_coerce_bin(x, '/', y);
+ return num_coerce_bin(x, y);
}
static VALUE
@@ -675,7 +646,7 @@ Ffix_mod(x, y)
i = FIX2INT(x)%i;
return INT2FIX(i);
}
- return num_coerce_bin(x, '%', y);
+ return num_coerce_bin(x, y);
}
static VALUE
@@ -698,7 +669,7 @@ Ffix_pow(x, y)
else if (NIL_P(y)) {
return INT2FIX(1);
}
- return num_coerce_bin(x, rb_intern("**"), y);
+ return num_coerce_bin(x, y);
}
static VALUE
@@ -712,7 +683,7 @@ Ffix_equal(x, y)
return Qnil;
}
else {
- return num_coerce_bin(x, rb_intern("=="), y);
+ return num_coerce_bin(x, y);
}
}
@@ -728,7 +699,67 @@ Ffix_cmp(x, y)
return INT2FIX(-1);
}
else {
- return num_coerce_bin(x, rb_intern("<=>"), y);
+ return num_coerce_bin(x, y);
+ }
+}
+
+static VALUE
+Ffix_gt(x, y)
+ VALUE x, y;
+{
+ if (FIXNUM_P(y)) {
+ int a = FIX2INT(x), b = FIX2INT(y);
+
+ if (a > b) return TRUE;
+ return FALSE;
+ }
+ else {
+ return num_coerce_bin(x, y);
+ }
+}
+
+static VALUE
+Ffix_ge(x, y)
+ VALUE x, y;
+{
+ if (FIXNUM_P(y)) {
+ int a = FIX2INT(x), b = FIX2INT(y);
+
+ if (a >= b) return TRUE;
+ return FALSE;
+ }
+ else {
+ return num_coerce_bin(x, y);
+ }
+}
+
+static VALUE
+Ffix_lt(x, y)
+ VALUE x, y;
+{
+ if (FIXNUM_P(y)) {
+ int a = FIX2INT(x), b = FIX2INT(y);
+
+ if (a < b) return TRUE;
+ return FALSE;
+ }
+ else {
+ return num_coerce_bin(x, y);
+ }
+}
+
+static VALUE
+Ffix_le(x, y)
+ VALUE x, y;
+{
+ if (FIXNUM_P(y)) {
+ int a = FIX2INT(x), b = FIX2INT(y);
+
+ if (a <= b) return TRUE;
+ return FALSE;
+ }
+ else {
+ return num_coerce_bin(x, y);
}
}
@@ -891,6 +922,10 @@ Init_Numeric()
to_i = rb_intern("to_i");
C_Numeric = rb_define_class("Numeric", C_Object);
+
+ rb_undef_method(CLASS_OF(C_Numeric), "new");
+ rb_undef_method(CLASS_OF(C_Numeric), "clone");
+
rb_include_module(C_Numeric, M_Comparable);
rb_define_method(C_Numeric, "+@", Fnum_uplus, 0);
rb_define_method(C_Numeric, "-@", Fnum_uminus, 0);
@@ -910,9 +945,9 @@ Init_Numeric()
rb_define_method(C_Integer, "chr", Fint_chr, 0);
C_Fixnum = rb_define_class("Fixnum", C_Integer);
+
rb_define_method(C_Fixnum, "to_s", Ffix_to_s, 0);
rb_define_method(C_Fixnum, "class", Ffix_class, 0);
- rb_define_method(C_Fixnum, "clone", Ffix_clone, 0);
rb_define_method(C_Fixnum, "id2name", Ffix_id2name, 0);
@@ -928,6 +963,10 @@ Init_Numeric()
rb_define_method(C_Fixnum, "==", Ffix_equal, 1);
rb_define_method(C_Fixnum, "<=>", Ffix_cmp, 1);
+ rb_define_method(C_Fixnum, ">", Ffix_gt, 1);
+ rb_define_method(C_Fixnum, ">=", Ffix_ge, 1);
+ rb_define_method(C_Fixnum, "<", Ffix_lt, 1);
+ rb_define_method(C_Fixnum, "<=", Ffix_le, 1);
rb_define_method(C_Fixnum, "..", Ffix_dot2, 1);
rb_define_method(C_Fixnum, "~", Ffix_rev, 0);
@@ -945,8 +984,7 @@ Init_Numeric()
rb_define_method(C_Fixnum, "next", Ffix_next, 0);
C_Float = rb_define_class("Float", C_Numeric);
- rb_define_single_method(C_Float, "new", Fflo_new, 1);
- rb_define_method(C_Float, "clone", Fflo_clone, 0);
+
rb_define_method(C_Float, "to_s", Fflo_to_s, 0);
rb_define_method(C_Float, "coerce", Fflo_coerce, 1);
rb_define_method(C_Float, "-@", Fflo_uminus, 0);
diff --git a/object.c b/object.c
index e7e4539..5a60b79 100644
--- a/object.c
+++ b/object.c
@@ -17,7 +17,6 @@
#include <stdio.h>
VALUE C_Kernel;
-VALUE C_Builtin;
VALUE C_Object;
VALUE C_Module;
VALUE C_Class;
@@ -27,15 +26,10 @@ VALUE C_Data;
struct st_table *new_idhash();
VALUE Fsprintf();
-VALUE Fexit();
-VALUE Feval();
-VALUE Fapply();
VALUE Fdefined();
-VALUE Fcaller();
VALUE obj_responds_to();
VALUE obj_alloc();
-VALUE Ffix_clone();
static ID eq, match;
@@ -62,13 +56,6 @@ Fkrn_equal(obj, other)
}
static VALUE
-Fkrn_hash(obj)
- VALUE obj;
-{
- return obj;
-}
-
-static VALUE
Fkrn_to_a(obj)
VALUE obj;
{
@@ -228,13 +215,6 @@ Fobj_clone(obj)
}
static VALUE
-Fiterator_p()
-{
- if (the_env->iterator > 1 && the_env->iterator < 4) return TRUE;
- return FALSE;
-}
-
-static VALUE
Fnil_to_s(obj)
VALUE obj;
{
@@ -317,6 +297,45 @@ Fcls_attr(class, args)
}
static VALUE
+Fcls_export_internal(argc, argv, ex)
+ int argc;
+ VALUE *argv;
+ int ex;
+{
+ VALUE self = Qself;
+ int i;
+ ID id;
+
+ for (i=0; i<argc; i++) {
+ if (FIXNUM_P(argv[i])) {
+ id = FIX2INT(argv[i]);
+ }
+ else {
+ Check_Type(argv[i], T_STRING);
+ id = rb_intern(RSTRING(argv[i])->ptr);
+ }
+ rb_export_method(self, id, ex);
+ }
+ return Qnil;
+}
+
+static VALUE
+Fcls_export(argc, argv)
+ int argc;
+ VALUE *argv;
+{
+ Fcls_export_internal(argc, argv, 0);
+}
+
+static VALUE
+Fcls_unexport(argc, argv)
+ int argc;
+ VALUE *argv;
+{
+ Fcls_export_internal(argc, argv, 1);
+}
+
+static VALUE
Fcant_clone(obj)
VALUE obj;
{
@@ -348,13 +367,11 @@ Init_Object()
VALUE metaclass;
C_Kernel = boot_defclass("Kernel", Qnil);
- C_Builtin = boot_defclass("Builtin", C_Kernel);
- C_Object = boot_defclass("Object", C_Builtin);
+ C_Object = boot_defclass("Object", C_Kernel);
C_Module = boot_defclass("Module", C_Object);
C_Class = boot_defclass("Class", C_Module);
metaclass = RBASIC(C_Kernel)->class = single_class_new(C_Class);
- metaclass = RBASIC(C_Builtin)->class = single_class_new(metaclass);
metaclass = RBASIC(C_Object)->class = single_class_new(metaclass);
metaclass = RBASIC(C_Module)->class = single_class_new(metaclass);
metaclass = RBASIC(C_Class)->class = single_class_new(metaclass);
@@ -368,13 +385,10 @@ Init_Object()
* | Kernel----->(Kernel) |
* | ^ ^ ^ ^ |
* | | | | | |
- * | +---+ +-----+ | +---+ |
- * | | +------|---+ | |
- * | | | | | |
- * +->Nil->(Nil) Builtin--->(Builtin) |
- * ^ ^ |
- * | | |
- * Object---->(Object) |
+ * | +---+ +----+ | +---+ |
+ * | | +-----|----+ | |
+ * | | | | | |
+ * +->Nil->(Nil) Object---->(Object) |
* ^ ^ ^ ^ |
* | | | | |
* | | +-------+ | |
@@ -396,7 +410,7 @@ Init_Object()
rb_define_method(C_Kernel, "!", P_false, 0);
rb_define_method(C_Kernel, "==", Fkrn_equal, 1);
rb_define_alias(C_Kernel, "equal", "==");
- rb_define_method(C_Kernel, "hash", Fkrn_hash, 0);
+ rb_define_method(C_Kernel, "hash", rb_self, 0);
rb_define_method(C_Kernel, "id", Fkrn_id, 0);
rb_define_method(C_Kernel, "class", Fkrn_class, 0);
rb_define_method(C_Kernel, "!=", Fkrn_noteq, 1);
@@ -407,17 +421,9 @@ Init_Object()
rb_define_method(C_Kernel, "to_s", Fkrn_to_s, 0);
rb_define_method(C_Kernel, "_inspect", Fkrn_inspect, 0);
-#ifdef USE_CALLER
- rb_define_method(C_Builtin, "caller", Fcaller, -2);
-#endif
- rb_define_method(C_Builtin, "exit", Fexit, -2);
- rb_define_method(C_Builtin, "eval", Feval, 1);
- rb_define_method(C_Builtin, "defined", Fdefined, 1);
- rb_define_method(C_Builtin, "sprintf", Fsprintf, -1);
- rb_define_alias(C_Builtin, "format", "sprintf");
- rb_define_method(C_Builtin, "iterator_p", Fiterator_p, 0);
-
- rb_define_method(C_Builtin, "apply", Fapply, -2);
+ rb_define_private_method(C_Kernel, "defined", Fdefined, 1);
+ rb_define_private_method(C_Kernel, "sprintf", Fsprintf, -1);
+ rb_define_alias(C_Kernel, "format", "sprintf");
rb_define_method(C_Object, "_inspect", Fobj_inspect, 0);
@@ -428,13 +434,15 @@ Init_Object()
rb_define_method(C_Module, "to_s", Fcls_to_s, 0);
rb_define_method(C_Module, "clone", Fcant_clone, 0);
- rb_define_method(C_Module, "attr", Fcls_attr, -2);
+ rb_define_private_method(C_Module, "attr", Fcls_attr, -2);
+ rb_define_method(C_Module, "export", Fcls_export, -1);
+ rb_define_method(C_Module, "unexport", Fcls_unexport, -1);
rb_define_method(C_Class, "new", Fcls_new, -2);
C_Nil = rb_define_class("Nil", C_Kernel);
rb_define_method(C_Nil, "to_s", Fnil_to_s, 0);
- rb_define_method(C_Nil, "clone", Ffix_clone, 0);
+ rb_define_method(C_Nil, "clone", rb_self, 0);
rb_define_method(C_Nil, "class", Fnil_class, 0);
rb_define_method(C_Nil, "is_nil", P_true, 0);
@@ -455,7 +463,7 @@ Init_Object()
TRUE = obj_alloc(C_Object);
rb_define_single_method(TRUE, "to_s", Ftrue_to_s, 0);
- rb_define_const(C_Builtin, "%TRUE", TRUE);
- rb_define_const(C_Builtin, "%FALSE", FALSE);
+ rb_define_const(C_Kernel, "%TRUE", TRUE);
+ rb_define_const(C_Kernel, "%FALSE", FALSE);
}
diff --git a/parse.y b/parse.y
index 18ab233..a4122de 100644
--- a/parse.y
+++ b/parse.y
@@ -29,7 +29,7 @@
#define is_const_id(id) (is_id_nonop(id)&&((id)&ID_SCOPE_MASK)==ID_CONST)
struct op_tbl {
- ID tok;
+ ID token;
char *name;
};
@@ -133,7 +133,7 @@ static void setup_top_local();
%type <node> f_arglist f_args f_arg assoc_list assocs assoc
%type <node> mlhs mlhs_head mlhs_tail lhs iter_var opt_iter_var
%type <id> superclass variable symbol
-%type <id> fname fname0 op rest_arg
+%type <id> fname op rest_arg
%token UPLUS /* unary+ */
%token UMINUS /* unary- */
@@ -244,10 +244,11 @@ stmt : CLASS IDENTIFIER superclass
cur_mid = $2;
push_local();
}
- f_arglist compstmts
+ f_arglist
+ compstmts
END
{
- $$ = NEW_DEFN($2, NEW_RFUNC($4, $5));
+ $$ = NEW_DEFN($2, NEW_RFUNC($4, $5), cur_class?0:1);
pop_local();
cur_mid = Qnil;
}
@@ -271,7 +272,7 @@ stmt : CLASS IDENTIFIER superclass
}
| DEF fname fname
{
- $$ = NEW_ALIAS($2, $3);
+ $$ = NEW_ALIAS($2, $3);
}
| INCLUDE inc_list
{
@@ -438,10 +439,7 @@ inc_list : IDENTIFIER
$$ = $1;
}
-fname : fname0
- | IVAR
-
-fname0 : IDENTIFIER
+fname : IDENTIFIER
| op
{
lex_state = EXPR_END;
@@ -844,10 +842,6 @@ expr0 : literal
{
$$ = NEW_CALL(Qnil, $1, $3);
}
- | IVAR '(' call_args rparen
- {
- $$ = NEW_CALL(Qnil, $1, $3);
- }
| SUPER '(' call_args rparen
{
if (!cur_mid && !in_single)
@@ -906,7 +900,7 @@ expr0 : literal
}
| expr0 lbrace opt_iter_var '|' compstmts rbrace
{
- $$ = NEW_DO($3, $1, $5);
+ $$ = NEW_ITER($3, $1, $5);
}
| expr0 '.' IDENTIFIER '(' call_args rparen
{
@@ -1002,7 +996,7 @@ opt_iter_var : /* none */
| iter_var
cases : opt_else
- | WHEN args term
+ | WHEN args then
compstmts
cases
{
@@ -1039,7 +1033,7 @@ literal : numeric
| GLOB
-symbol : fname0
+symbol : fname
| IVAR
| GVAR
| CONSTANT
@@ -1856,6 +1850,9 @@ retry:
case '.': /* $.: last read line number */
case '_': /* $_: last read line string */
case '&': /* $&: last match */
+ case '`': /* $&: string before last match */
+ case '\'': /* $&: string after last match */
+ case '+': /* $&: string matches last paren. */
case '~': /* $~: match-data */
case '=': /* $=: ignorecase */
tokadd(c);
@@ -2286,6 +2283,11 @@ void freenode(node)
if (node == Qnil) return;
switch (node->type) {
+ case NODE_FBODY:
+ node->nd_cnt--;
+ if (node->nd_cnt > 0) return;
+ freenode(node->nd_head);
+ break;
case NODE_BLOCK:
case NODE_ARRAY:
freenode(node->nd_head);
@@ -2317,7 +2319,7 @@ void freenode(node)
freenode(node->nd_head);
freenode(node->nd_body);
break;
- case NODE_DO:
+ case NODE_ITER:
case NODE_FOR:
freenode(node->nd_var);
freenode(node->nd_ibdy);
@@ -2377,6 +2379,7 @@ void freenode(node)
break;
case NODE_CLASS:
case NODE_MODULE:
+ case NODE_METHOD:
freenode(node->nd_body);
break;
case NODE_CONST:
@@ -2670,7 +2673,7 @@ push_local()
lvtbl = local;
}
-void
+static void
pop_local()
{
struct local_vars *local = lvtbl;
@@ -2726,42 +2729,42 @@ init_top_local()
if (lvtbl == Qnil) {
push_local();
}
- else if (the_env->local_tbl) {
- lvtbl->cnt = the_env->local_tbl[0];
+ else if (the_scope->local_tbl) {
+ lvtbl->cnt = the_scope->local_tbl[0];
}
else {
lvtbl->cnt = 0;
}
- lvtbl->tbl = the_env->local_tbl;
+ lvtbl->tbl = the_scope->local_tbl;
}
static void
setup_top_local()
{
if (lvtbl->cnt > 0) {
- if (the_env->local_vars == Qnil) {
- the_env->local_vars = ALLOC_N(VALUE, lvtbl->cnt);
- memset(the_env->local_vars, 0, lvtbl->cnt * sizeof(VALUE));
+ if (the_scope->local_vars == Qnil) {
+ the_scope->local_vars = ALLOC_N(VALUE, lvtbl->cnt);
+ memset(the_scope->local_vars, 0, lvtbl->cnt * sizeof(VALUE));
}
else if (lvtbl->tbl[0] < lvtbl->cnt) {
int i;
- if (the_env->flags&VARS_MALLOCED) {
- REALLOC_N(the_env->local_vars, VALUE, lvtbl->cnt);
+ if (the_scope->flags&VARS_MALLOCED) {
+ REALLOC_N(the_scope->local_vars, VALUE, lvtbl->cnt);
}
else {
- VALUE *vars = the_env->local_vars;
- the_env->local_vars = ALLOC_N(VALUE, lvtbl->cnt);
- memcpy(the_env->local_vars, vars, sizeof(VALUE)*lvtbl->cnt);
- the_env->flags |= VARS_MALLOCED;
+ VALUE *vars = the_scope->local_vars;
+ the_scope->local_vars = ALLOC_N(VALUE, lvtbl->cnt);
+ memcpy(the_scope->local_vars, vars, sizeof(VALUE)*lvtbl->cnt);
+ the_scope->flags |= VARS_MALLOCED;
}
- memset(the_env->local_vars+i, 0, lvtbl->cnt-i);
+ memset(the_scope->local_vars+i, 0, lvtbl->cnt-i);
}
lvtbl->tbl[0] = lvtbl->cnt;
- the_env->local_tbl = lvtbl->tbl;
+ the_scope->local_tbl = lvtbl->tbl;
}
else {
- the_env->local_vars = Qnil;
+ the_scope->local_vars = Qnil;
}
}
@@ -2879,9 +2882,9 @@ rb_intern(name)
int i;
id = Qnil;
- for (i=0; rb_op_tbl[i].tok; i++) {
+ for (i=0; rb_op_tbl[i].token; i++) {
if (strcmp(rb_op_tbl[i].name, name) == 0) {
- id = rb_op_tbl[i].tok;
+ id = rb_op_tbl[i].token;
break;
}
}
@@ -2931,8 +2934,8 @@ rb_id2name(id)
if (id < LAST_TOKEN) {
int i = 0;
- for (i=0; rb_op_tbl[i].tok; i++) {
- if (rb_op_tbl[i].tok == id)
+ for (i=0; rb_op_tbl[i].token; i++) {
+ if (rb_op_tbl[i].token == id)
return rb_op_tbl[i].name;
}
}
@@ -2966,9 +2969,11 @@ rb_class2name(class)
find_ok = Qnil;
switch (TYPE(class)) {
+ case T_ICLASS:
+ class = (struct RClass*)RBASIC(class)->class;
+ break;
case T_CLASS:
case T_MODULE:
- case T_ICLASS:
break;
default:
Fail("0x%x is not a class/module", class);
diff --git a/process.c b/process.c
index 15f101e..0f36bf7 100644
--- a/process.c
+++ b/process.c
@@ -693,7 +693,7 @@ Fsleep(argc, argv)
int beg, end;
beg = time(0);
- if (argc == 1) {
+ if (argc == 0) {
sleep((32767<<16)+32767);
}
else if (argc == 1) {
@@ -832,19 +832,19 @@ VALUE M_Process;
Init_process()
{
- extern VALUE C_Builtin;
+ extern VALUE C_Kernel;
- rb_define_variable("$$", Qnil, get_pid, rb_readonly_hook);
+ rb_define_variable("$$", Qnil, get_pid, Qnil);
rb_define_variable("$?", &status, Qnil, rb_readonly_hook);
- rb_define_method(C_Builtin, "exec", Fexec, 1);
- rb_define_method(C_Builtin, "fork", Ffork, 0);
- rb_define_method(C_Builtin, "_exit", Ffork, 1);
- rb_define_method(C_Builtin, "wait", Fwait, 0);
- rb_define_method(C_Builtin, "waitpid", Fwaitpid, 2);
- rb_define_method(C_Builtin, "system", Fsystem, 1);
- rb_define_method(C_Builtin, "kill", Fkill, -1);
- rb_define_method(C_Builtin, "trap", Ftrap, -1);
- rb_define_method(C_Builtin, "sleep", Fsleep, -1);
+ rb_define_private_method(C_Kernel, "exec", Fexec, 1);
+ rb_define_private_method(C_Kernel, "fork", Ffork, 0);
+ rb_define_private_method(C_Kernel, "_exit", Ffork, 1);
+ rb_define_private_method(C_Kernel, "wait", Fwait, 0);
+ rb_define_private_method(C_Kernel, "waitpid", Fwaitpid, 2);
+ rb_define_private_method(C_Kernel, "system", Fsystem, 1);
+ rb_define_private_method(C_Kernel, "kill", Fkill, -1);
+ rb_define_private_method(C_Kernel, "trap", Ftrap, -1);
+ rb_define_private_method(C_Kernel, "sleep", Fsleep, -1);
M_Process = rb_define_module("Process");
@@ -854,27 +854,21 @@ Init_process()
rb_define_single_method(M_Process, "waitpid", Fwaitpid, 2);
rb_define_single_method(M_Process, "kill", Fkill, -1);
- rb_define_method(M_Process, "pid", get_pid, 0);
- rb_define_method(M_Process, "ppid", get_ppid, 0);
+ rb_define_module_function(M_Process, "pid", get_pid, 0);
+ rb_define_module_function(M_Process, "ppid", get_ppid, 0);
- rb_define_method(M_Process, "getpgrp", Fproc_getpgrp, -2);
- rb_define_method(M_Process, "setpgrp", Fproc_setpgrp, 2);
+ rb_define_module_function(M_Process, "getpgrp", Fproc_getpgrp, -2);
+ rb_define_module_function(M_Process, "setpgrp", Fproc_setpgrp, 2);
- rb_define_method(M_Process, "getpriority", Fproc_getpriority, 2);
- rb_define_method(M_Process, "setpriority", Fproc_setpriority, 3);
+ rb_define_module_function(M_Process, "getpriority", Fproc_getpriority, 2);
+ rb_define_module_function(M_Process, "setpriority", Fproc_setpriority, 3);
rb_define_const(M_Process, "%PRIO_PROCESS", INT2FIX(PRIO_PROCESS));
rb_define_const(M_Process, "%PRIO_PGRP", INT2FIX(PRIO_PGRP));
rb_define_const(M_Process, "%PRIO_USER", INT2FIX(PRIO_USER));
- rb_define_single_method(M_Process, "uid", Fproc_getuid, 0);
- rb_define_method(M_Process, "uid", Fproc_getuid, 0);
- rb_define_single_method(M_Process, "uid=", Fproc_setuid, 1);
- rb_define_method(M_Process, "uid=", Fproc_setuid, 1);
- rb_define_single_method(M_Process, "euid", Fproc_geteuid, 0);
- rb_define_method(M_Process, "euid", Fproc_geteuid, 0);
- rb_define_single_method(M_Process, "euid=", Fproc_seteuid, 1);
- rb_define_method(M_Process, "euid=", Fproc_seteuid, 1);
-
- rb_include_module(CLASS_OF(M_Process), M_Process);
+ rb_define_module_function(M_Process, "uid", Fproc_getuid, 0);
+ rb_define_module_function(M_Process, "uid=", Fproc_setuid, 1);
+ rb_define_module_function(M_Process, "euid", Fproc_geteuid, 0);
+ rb_define_module_function(M_Process, "euid=", Fproc_seteuid, 1);
}
diff --git a/random.c b/random.c
index 7b663b2..a8344fa 100644
--- a/random.c
+++ b/random.c
@@ -73,8 +73,8 @@ Frand(obj, max)
Init_Random()
{
- extern VALUE C_Builtin;
+ extern VALUE C_Kernel;
- rb_define_method(C_Builtin, "srand", Fsrand, -2);
- rb_define_method(C_Builtin, "rand", Frand, 1);
+ rb_define_private_method(C_Kernel, "srand", Fsrand, -2);
+ rb_define_private_method(C_Kernel, "rand", Frand, 1);
}
diff --git a/re.c b/re.c
index 0d314c9..5523df6 100644
--- a/re.c
+++ b/re.c
@@ -153,17 +153,13 @@ research(reg, str, start, ignorecase)
OBJSETUP(obj, C_Data, T_DATA);
obj->dfree = free_match;
data = (struct match*)DATA_PTR(obj);
- memset(data, 0, sizeof(struct match));
- beg = reg->ptr->regs.start[0];
- data->len = reg->ptr->regs.end[0] - beg;
- data->ptr = ALLOC_N(char, data->len+1);
- memcpy(data->ptr, str->ptr + beg, data->len);
+
+ data->len = str->len;
+ data->ptr = ALLOC_N(char, str->len+1);
+ memcpy(data->ptr, str->ptr, data->len);
data->ptr[data->len] = '\0';
- for (i=0; i<RE_NREGS; i++) {
- if (reg->ptr->regs.start[i] == -1) break;
- data->regs.start[i] = reg->ptr->regs.start[i] - beg;
- data->regs.end[i] = reg->ptr->regs.end[i] - beg;
- }
+ data->regs = reg->ptr->regs;
+
last_match_data = (VALUE)obj;
}
@@ -182,7 +178,6 @@ nth_match(nth)
struct match *match;
match = (struct match*)DATA_PTR(last_match_data);
- if (nth == 0) return str_new(match->ptr, match->len);
start = match->regs.start[nth];
if (start == -1) return Qnil;
end = match->regs.end[nth];
@@ -199,6 +194,44 @@ re_last_match(id)
return nth_match(0);
}
+static VALUE
+re_match_pre()
+{
+ struct match *match;
+
+ if (!last_match_data) return Qnil;
+
+ match = (struct match*)DATA_PTR(last_match_data);
+ return str_new(match->ptr, match->regs.start[0]);
+}
+
+static VALUE
+re_match_post()
+{
+ struct match *match;
+
+ if (!last_match_data) return Qnil;
+
+ match = (struct match*)DATA_PTR(last_match_data);
+ return str_new(match->ptr+match->regs.end[0], match->ptr+match->len);
+}
+
+static VALUE
+re_match_last()
+{
+ struct match *match;
+ int i;
+
+ if (!last_match_data) return Qnil;
+
+ match = (struct match*)DATA_PTR(last_match_data);
+ for (i=0; i<RE_NREGS; i++) {
+ if (match->regs.start[i] == -1) break;
+ }
+ i--;
+ return nth_match(i);
+}
+
#ifdef __STDC__
#define CONCAT(a,b) a##b
#else
@@ -405,7 +438,54 @@ re_regsub(str)
return val;
}
-VALUE rb_readonly_hook();
+void
+rb_set_kanjicode(code)
+ char *code;
+{
+ if (code == Qnil) goto set_no_conversion;
+
+ switch (code[0]) {
+ case 'E':
+ case 'e':
+ obscure_syntax &= ~RE_MBCTYPE_MASK;
+ obscure_syntax |= RE_MBCTYPE_EUC;
+ break;
+ case 'S':
+ case 's':
+ obscure_syntax &= ~RE_MBCTYPE_MASK;
+ obscure_syntax |= RE_MBCTYPE_SJIS;
+ break;
+ default:
+ case 'N':
+ case 'n':
+ set_no_conversion:
+ obscure_syntax &= ~RE_MBCTYPE_MASK;
+ break;
+ }
+ re_set_syntax(obscure_syntax);
+}
+
+static VALUE
+kanji_var_get()
+{
+ switch (obscure_syntax & RE_MBCTYPE_MASK) {
+ case RE_MBCTYPE_SJIS:
+ return str_new2("SJIS");
+ case RE_MBCTYPE_EUC:
+ return str_new2("EUC");
+ default:
+ return Qnil;
+ }
+}
+
+static void
+kanji_var_set(val)
+ struct RString *val;
+{
+ if (val == Qnil) rb_set_kanjicode(Qnil);
+ Check_Type(val, T_STRING);
+ rb_set_kanjicode(val->ptr);
+}
void
Init_Regexp()
@@ -417,17 +497,22 @@ Init_Regexp()
rb_define_variable("$~", last_match_data, Qnil, store_match_data);
- rb_define_variable("$&", Qnil, re_last_match, rb_readonly_hook);
-
- rb_define_variable("$1", Qnil, GET_MATCH(1), rb_readonly_hook);
- rb_define_variable("$2", Qnil, GET_MATCH(2), rb_readonly_hook);
- rb_define_variable("$3", Qnil, GET_MATCH(3), rb_readonly_hook);
- rb_define_variable("$4", Qnil, GET_MATCH(4), rb_readonly_hook);
- rb_define_variable("$5", Qnil, GET_MATCH(5), rb_readonly_hook);
- rb_define_variable("$6", Qnil, GET_MATCH(6), rb_readonly_hook);
- rb_define_variable("$7", Qnil, GET_MATCH(7), rb_readonly_hook);
- rb_define_variable("$8", Qnil, GET_MATCH(8), rb_readonly_hook);
- rb_define_variable("$9", Qnil, GET_MATCH(9), rb_readonly_hook);
+ rb_define_variable("$&", Qnil, re_last_match, Qnil);
+ rb_define_variable("$`", Qnil, re_match_pre, Qnil);
+ rb_define_variable("$'", Qnil, re_match_post, Qnil);
+ rb_define_variable("$+", Qnil, re_match_last, Qnil);
+
+ rb_define_variable("$1", Qnil, GET_MATCH(1), Qnil);
+ rb_define_variable("$2", Qnil, GET_MATCH(2), Qnil);
+ rb_define_variable("$3", Qnil, GET_MATCH(3), Qnil);
+ rb_define_variable("$4", Qnil, GET_MATCH(4), Qnil);
+ rb_define_variable("$5", Qnil, GET_MATCH(5), Qnil);
+ rb_define_variable("$6", Qnil, GET_MATCH(6), Qnil);
+ rb_define_variable("$7", Qnil, GET_MATCH(7), Qnil);
+ rb_define_variable("$8", Qnil, GET_MATCH(8), Qnil);
+ rb_define_variable("$9", Qnil, GET_MATCH(9), Qnil);
+
+ rb_define_variable("$KANJI", Qnil, kanji_var_get, kanji_var_set);
rb_define_variable("$=", &ignorecase, Qnil, Qnil);
diff --git a/ruby.c b/ruby.c
index d0ad1e2..88e76b9 100644
--- a/ruby.c
+++ b/ruby.c
@@ -176,24 +176,7 @@ proc_options(argcp, argvp)
break;
case 'C':
- switch (optarg[0]) {
- case 'E':
- case 'e':
- obscure_syntax &= ~RE_MBCTYPE_MASK;
- obscure_syntax |= RE_MBCTYPE_EUC;
- break;
- case 'S':
- case 's':
- obscure_syntax &= ~RE_MBCTYPE_MASK;
- obscure_syntax |= RE_MBCTYPE_SJIS;
- break;
- default:
- case 'N':
- case 'n':
- obscure_syntax &= ~RE_MBCTYPE_MASK;
- break;
- }
- re_set_syntax(obscure_syntax);
+ rb_set_kanjicode(optarg);
break;
case 'S':
diff --git a/sample/caller.rb b/sample/caller.rb
deleted file mode 100644
index 8988733..0000000
--- a/sample/caller.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-def test
- for i in 1..2
- for j in 1..5
- print(j, ": ", caller(j).join(':'), "\n")
- end
- end
-end
-
-def test2
- print(1, ": ", caller(1).join(':'), "\n")
- test()
-end
-
-test2()
-caller()
diff --git a/sample/dbm.rb b/sample/dbm.rb
index 1f2886e..128391f 100644
--- a/sample/dbm.rb
+++ b/sample/dbm.rb
@@ -1,6 +1,6 @@
# ruby
#
-d = Dbm.open("test")
+d = DBM.open("test")
for k in d.keys; print(k, "\n"); end
for v in d.values; print(v, "\n"); end
diff --git a/sample/export.rb b/sample/export.rb
new file mode 100644
index 0000000..3a6a819
--- /dev/null
+++ b/sample/export.rb
@@ -0,0 +1,13 @@
+class foo
+ export(\printf)
+end
+
+def foobar
+ print "foobar\n"
+end
+
+f = foo.new
+#foo.unexport(\printf)
+foo.export(\foobar)
+f.foobar
+f.printf "%s\n", foo
diff --git a/sample/fib.rb b/sample/fib.rb
index c72f91f..9fb8b24 100644
--- a/sample/fib.rb
+++ b/sample/fib.rb
@@ -1,4 +1,4 @@
-def fib (n)
+def fib(n)
if n<2
n
else
diff --git a/sample/fib.scm b/sample/fib.scm
new file mode 100644
index 0000000..8eba75b
--- /dev/null
+++ b/sample/fib.scm
@@ -0,0 +1,6 @@
+(define (fib n)
+ (if (< n 2)
+ n
+ (+ (fib (- n 2)) (fib (- n 1)))))
+
+(fib 20)
diff --git a/sample/list3.rb b/sample/list3.rb
new file mode 100644
index 0000000..c38e5bf
--- /dev/null
+++ b/sample/list3.rb
@@ -0,0 +1,20 @@
+# Linked list program -- short version
+class Point
+ def Point.new(x, y)
+ super.init(x, y)
+ end
+
+ def init(x, y)
+ @x = x; @y = y
+ self
+ end
+
+ def to_s
+ sprintf("%d@%d", @x, @y)
+ end
+end
+
+list1 = [10, 20, Point.new(2, 3), Point.new(4, 5)]
+list2 = [20, Point.new(4, 5), list1]
+print("list1: ", list1._inspect, "\n")
+print("list2: ", list2._inspect, "\n")
diff --git a/sample/ruby-mode.el b/sample/ruby-mode.el
index 8f864d3..7f97e71 100644
--- a/sample/ruby-mode.el
+++ b/sample/ruby-mode.el
@@ -18,7 +18,7 @@
(defconst ruby-block-end-re "end")
(defconst ruby-delimiter
- (concat "[/<(){}#\"'`]\\|\\[\\|\\]\\|\\b\\("
+ (concat "[$/<(){}#\"'`]\\|\\[\\|\\]\\|\\b\\("
ruby-block-beg-re "\\|" ruby-block-end-re "\\)\\b")
)
@@ -55,6 +55,7 @@
;;(modify-syntax-entry ?\n ">" ruby-mode-syntax-table)
;;(modify-syntax-entry ?\f ">" ruby-mode-syntax-table)
(modify-syntax-entry ?# "<" ruby-mode-syntax-table)
+ (modify-syntax-entry ?$ "/" ruby-mode-syntax-table)
(modify-syntax-entry ?\\ "'" ruby-mode-syntax-table)
(modify-syntax-entry ?_ "w" ruby-mode-syntax-table)
(modify-syntax-entry ?< "." ruby-mode-syntax-table)
@@ -193,6 +194,8 @@ The variable ruby-indent-level controls the amount of indentation.
nil
(goto-char indent-point)
(setq in-string t))))))
+ ((string= "$" w) ;skip $char
+ (forward-char 1))
((string= "#" w) ;skip comment
(forward-line 1))
((string= "(" w) ;skip to matching paren
diff --git a/sample/time.rb b/sample/time.rb
new file mode 100755
index 0000000..b0ef065
--- /dev/null
+++ b/sample/time.rb
@@ -0,0 +1,8 @@
+#! /usr/local/bin/ruby
+cmd = $ARGV.join(" ")
+b = Time.now
+system(cmd)
+e = Time.now
+ut, st, cut, cst = Time.times
+total = (e - b).to_f
+printf $stderr, "%11.1f real %11.1f user %11.1f sys\n", total, cut, cst
diff --git a/sample/uumerge.rb b/sample/uumerge.rb
new file mode 100755
index 0000000..420a392
--- /dev/null
+++ b/sample/uumerge.rb
@@ -0,0 +1,27 @@
+#!/usr/local/bin/ruby
+
+while gets()
+ if /^begin\s*(\d*)\s*(\S*)/
+ $mode, $file = $1, $2
+ $sawbegin+=1
+ break
+ end
+end
+
+fail "missing begin" unless $sawbegin;
+OUT = open($file, "w") if $file != "";
+
+while gets()
+ if /^end/
+ $sawend+=1
+ break
+ end
+ sub(/[a-z]+$/, ""); # handle stupid trailing lowercase letters
+ continue if /[a-z]/
+ continue unless ((($_[0] - 32) & 077) + 2) / 3 == $_.length / 4
+ OUT << $_.unpack("u");
+end
+
+fail "missing end" unless $sawend;
+File.chmod $mode.oct, $file;
+exit 0;
diff --git a/socket.c b/socket.c
index 7d55d0d..57be073 100644
--- a/socket.c
+++ b/socket.c
@@ -608,15 +608,13 @@ Fsock_accept(sock)
{
OpenFile *fptr;
VALUE addr, sock2;
- int fd;
char buf[1024];
int len = sizeof buf;
GetOpenFile(sock, fptr);
- if ((fd = accept(fileno(fptr->f), (struct sockaddr*)buf, &len)) < 0)
- rb_sys_fail("listen(2)");
+ sock2 = sock_accept(C_Socket,fileno(fptr->f),(struct sockaddr*)buf,&len);
- return sock_new(C_Socket, fd);
+ return assoc_new(sock2, str_new(buf, len));
}
static VALUE
@@ -651,24 +649,50 @@ Fsock_send(sock, args)
}
static VALUE
-Fsock_recv(sock, len, flags)
- VALUE sock, len, flags;
+sock_recv(sock, args, from)
+ VALUE sock, args;
+ int from;
{
OpenFile *fptr;
FILE f;
struct RString *str;
char buf[1024];
int fd, alen = sizeof buf;
+ VALUE len, flg;
+ int flags;
+
+ rb_scan_args(args, "11", &len, &flg);
+
+ if (flg == Qnil) flags = 0;
+ else flags = NUM2INT(flg);
str = (struct RString*)str_new(0, NUM2INT(len));
GetOpenFile(sock, fptr);
fd = fileno(fptr->f);
- if (recvfrom(fd, str->ptr, str->len, NUM2INT(flags),
- (struct sockaddr*)buf, &alen) < 0) {
- rb_sys_fail("recv(2)");
+ if ((str->len = recvfrom(fd, str->ptr, str->len, flags,
+ (struct sockaddr*)buf, &alen)) < 0) {
+ rb_sys_fail("recvfrom(2)");
}
- return assoc_new(str, str_new(buf, alen));
+
+ if (from)
+ return assoc_new(str, str_new(buf, alen));
+ else
+ return (VALUE)str;
+}
+
+static VALUE
+Fsock_recv(sock, args)
+ VALUE sock, args;
+{
+ return sock_recv(sock, args, 0);
+}
+
+static VALUE
+Fsock_recvfrom(sock, args)
+ VALUE sock, args;
+{
+ return sock_recv(sock, args, 1);
}
Init_Socket ()
@@ -715,7 +739,8 @@ Init_Socket ()
rb_define_method(C_Socket, "accept", Fsock_accept, 0);
rb_define_method(C_Socket, "send", Fsock_send, -2);
- rb_define_method(C_Socket, "recv", Fsock_recv, 2);
+ rb_define_method(C_Socket, "recv", Fsock_recv, -2);
+ rb_define_method(C_Socket, "recvfrom", Fsock_recv, -2);
rb_define_single_method(C_Socket, "socketpair", Fsock_socketpair, 3);
}
diff --git a/spec b/spec
index d22a970..4e8becc 100644
--- a/spec
+++ b/spec
@@ -270,11 +270,9 @@ Rubyの変数はスコープ(有効範囲)と寿命(有効期限)によって4種類に分類され,
ミング言語における関数のような形式でメソッドを呼び出すことができる. こ
の場合引数が1つもない時でも括弧の省略はできない.
-関数形式では`@'で始まる名前を持つメソッドを呼び出すことができる. `@'で
-始まるメソッドは関数形式でしか呼び出すことができないため, 該当するクラ
-スまたはそのサブクラスからしか呼ばれないので, プライベートメソッドと呼
-ばれる. プライベートメソッドはC++におけるprotected member functionに該
-当する.
+クラス定義文の外で指定されたメソッドとクラスModuleのnoexportメソッドで
+指定されたメソッドは関数的メソッドと呼ばれ, 関数形式でしか呼び出すこと
+ができない.
*** スーパークラスのメソッド呼び出し
@@ -458,7 +456,7 @@ unless式
case式
case 式0
- [when 式1 [, 式2]...
+ [when 式1 [, 式2]... [then]
文1 ]...
[else
文n ]
@@ -603,10 +601,10 @@ Enumerableモジュールのgrepメソッドのようにイテレータとして呼ばれた時と
protect
文1
- [ resque
+ [resque
文2 ]
- [ ensure
- 文3 ]
+ [ensure
+ 文3]
end
文1を実行し, その実行中に例外が発生すればresque節で指定された文2を実行
@@ -712,12 +710,12 @@ yield文
*** メソッド呼び出し文
-1つ以上引数を持つメソッドを文として呼び出す場合には引数を括弧で括る必
-要はない. その形式は以下の通りである.
+1つ以上の引数を持つメソッド呼び出す場合には曖昧さがなければ, 引数を括
+弧で括る必要はない. その形式は以下の通りである.
- 式 '.' メソッド名 引数1 ',' [ 引数2... ][ '*' 引数n ]
- メソッド名 引数1 ',' [ 引数2... ][ '*' 引数n ]
- super 引数1 ',' [ 引数2... ][ '*' 引数n ]
+ 式 '.' メソッド名 引数1 ',' [引数2...]['*' 引数n]
+ メソッド名 引数1 ',' [引数2...]['*' 引数n]
+ super 引数1 ',' [引数2... ]['*' 引数n]
構文解析時に, 式のように解釈できる場合は式としての解釈が優先される.
@@ -726,7 +724,7 @@ yield文
foo 1 # メソッド呼び出しfoo(1)
foo -1 # ローカル変数foo - 1
-メソッド呼び出し文は単純文である.
+括弧のないメソッド呼び出し文は単純文である.
*** 制御修飾子
@@ -786,7 +784,7 @@ yield文
ド定義はネストできないので, メソッド定義文中ではメソッド定義文を再び呼
び出せない.
- def メソッド名 [ '(' 引数 [',' 引数...][',' '*'引数 ] ')' ]
+ def メソッド名 ['(' 引数 [',' 引数...][',' '*'引数 ] ')']
定義実体
end
@@ -794,12 +792,19 @@ yield文
で指定する. 仮引数並びの最後に`*'がある場合, 仮引数より多く与えられた
実引数は, 最後の引数に配列として与えられる(足りない時にはエラー).
+メソッドには関数的メソッドと通常メソッドがある. 関数的メソッドは関数形
+式でしか呼び出すことができず, よって該当するクラスとそのサブクラスのメ
+ソッドからしか呼び出すことができない. クラス定義文の外にあるdef文は関
+数的メソッドを定義し, クラス定義文の中にあるdef文は通常のメソッドを定
+義する. メソッドの可視性はModuleクラスのexport/noexportメソッドを使っ
+て変更する.
+
** 特異メソッド定義文
メソッド定義にはもう一つ特異メソッドの定義がある. 特異メソッドとはある
特定のオブジェクトに固有のメソッドである. 形式は以下の通りである.
- def 式 '.' メソッド名 [ '(' 引数 [',' 引数...][',' '*'引数 ] ')' ]
+ def 式 '.' メソッド名 ['(' 引数 [',' 引数...][',' '*'引数 ] ')']
定義実体
end
@@ -845,10 +850,10 @@ Rubyには処理系そのものに以下の機能が組み込まれている. ライブラリをロー
** 関数
-Rubyには厳密な意味では関数はないがBuiltinクラスのメソッドは(全ての通常
-クラスから関数形式で呼び出せるので), 関数的に用いられる. 関数的に用い
-られるメソッドを以下にあげる. これらのメソッドを再定義する際には互換性
-を考えて行なうべきである.
+Rubyには厳密な意味では関数はないがKernelクラスの関数メソッドは(全ての
+通常クラスから関数形式で呼び出せるので), 関数的に用いられる. 関数的に
+用いられるメソッドを以下にあげる. これらのメソッドを再定義する際には互
+換性を考えて行なうべきである.
_exit(status)
@@ -1116,8 +1121,7 @@ Rubyには厳密な意味では関数はないがBuiltinクラスのメソッドは(全ての通常
$ARGV $*と同じ.
- $ENV 環境変数にアクセスする連想配列(EnvDict). この変数に対
- して `for'を行なうと変数名と値のペアを与える.
+ $ENV 環境変数にアクセスする連想配列.
$FILENAME 仮想ファイル$ARGFで現在読み込み中のファイル名. メソッ
ドgets()が今読んでいるファイル名.
@@ -1163,67 +1167,6 @@ Rubyには厳密な意味では関数はないがBuiltinクラスのメソッドは(全ての通常
** クラス/モジュール
-*** ARGFILE(クラス)
-
-引数で指定されたファイル(引数が与えられていない時には標準入力)で構成さ
-れる仮想ファイルをアクセスするためのクラス. ただしこのクラスは特異メソッ
-ドしか持たず, モジュール的な使い方をされる. クラス名だけでなくシステム
-変数$ARGFでも参照できる.
-
- while gets()
- ...
- end
-
-と
-
- for $_ in $ARGF
- ...
- end
-
-は全く同じ意味だが, 後者の方がより美しく, 理解しやすく, そしてブロック
-生成のコストのため若干遅い.
-
-SuperClass: Object
-
-Included Modules: Enumerable
-
-Methods:
-
- each
-
- 各行毎に繰り返すイテレータ
-
- each_byte
-
- 各文字毎に繰り返すイテレータ
-
- eof
-
- 現在読み込んでいるファイル(仮想ファイル全体ではない)が終りに到
- 達した時に真を返す.
-
- getc
-
- 仮想ファイルから1文字読み込む. 戻り値は文字コードを表す整数で
- ある. ファイルの終りに到達した時にはnilを返す. このメソッドで
- 読み込んだ場合, システム変数`$.'は変化しない.
-
- gets
- readline
-
- 仮想ファイルから一行読み込んで, 読み込みに成功した時にはその文
- 字列を返す. ファイルの終りに到達した時にはnilを返す. 行の区切
- りはシステム変数`$/'によって変更できる. 読み込んだ文字列はシス
- テム変数`$_'にもセットされる.
-
- read
-
- 仮想ファイルの内容を全て文字列として読み込む.
-
- readlines
-
- 仮想ファイルを全て読み込んで, 各行を要素として持つ配列を返す.
-
*** Array(クラス)
数字を添字とした配列のクラスである. 生成は一般的には配列式``[...]''で
@@ -1431,17 +1374,6 @@ Methods:
商と剰余の2要素の配列を返す.
-*** Builtin(クラス)
-
-全ての通常クラスのスーパークラス. Ruby組み込みの全ての関数的に呼ばれるメソッド
-はこのクラスで定義されている.
-
-SuperClass: Kernel
-
-Methods:
-
- 「関数」の項目を参照のこと.
-
*** Class(クラス)
クラスのクラス. より厳密に説明するとクラスは特異メソッドを継承するため
@@ -1453,13 +1385,15 @@ Classはそのメタクラスのクラスである(分かったかな?). が, この解説が理解
SuperClass: Module
-Methods:
+Private Methods:
attr(name[, public])
そのクラスのインスタンスに対してnameで指定される属性を定義する.
詳しくはModuleのattrメソッドの項を参照のこと.
+Methods:
+
new(...)
クラスのインスタンスを生成する. 多くの場合このメソッドはサブク
@@ -1799,34 +1733,6 @@ Methods:
全ての要素をソートした配列を返す.
-*** EnvDict(クラス)
-
-環境変数を操作するためのクラス. システム変数$ENVに唯一のインスタンスが
-代入されている.
-
-SuperClass: Object
-
-Included Modules: Enumerable
-
-Methods:
-
- [name]
-
- 環境変数の値を返す.
-
- [name]= val
-
- 環境変数の値をvalに設定する. valとしてnilを指定した場合には,
- 該当する環境変数を削除する.
-
- delete(name)
-
- 環境変数を削除する.
-
- each
-
- 環境変数の名前と値のペアを与えるイテレータ.
-
*** Etc(モジュール)
/etcディレクトリ以下の情報を得るためのモジュール. クラスにインクルード
@@ -2463,7 +2369,8 @@ Single Methods:
*** Kernel(クラス)
-全てのクラスの基底クラス.
+全てのクラスの基底クラス. Ruby組み込みの全ての関数メソッドはこのクラス
+で定義されている. 関数メソッドについては「関数」の項目を参照のこと.
SuperClass: なし
@@ -2533,6 +2440,7 @@ Methods:
時は必ず「A.hash == B.hash」が成立する必要があるので, "=="を再
定義した時には必ずこちらもそれに合わせて再定義すること.
+
*** Math(モジュール)
浮動小数点演算をサポートするクラス. Mathモジュールは同じ定義のメソッド
@@ -2584,19 +2492,21 @@ Single Methods:
SuperClass: Object
-Methods:
+Private Methods:
attr(name[, public])
そのモジュールをインクルードしたクラスのインスタンスに対して
nameで指定される属性を付加し, 属性に対するアクセスメソッドを定
- 義する. attr("attr")は以下に示すコードとほぼ同義である.
+ 義する. attr("attr")はクラス定義に以下に示すコードを追加するの
+ とほぼ同義である.
def attr; @attr; end
省略可能な第2引数publicが与えられて, かつその値がnilでない時に
は, その属性には属性設定メソッドも用意され, 外部から代入可能に
- なる. attr("attr", %TRUE)は以下のコードとほぼ同義である.
+ なる. attr("attr", %TRUE)はクラス定義に以下のコードを追加する
+ のとほぼ同義である.
def attr; @attr; end
def attr=(val); @attr = val; end
@@ -2614,11 +2524,23 @@ Methods:
はアクセスメソッドがすでに定義されている場合は, デフォルトのア
クセスメソッドを定義しない.
+Methods:
+
+ export(name[, name..])
+
+ nameで指定されたメソッドを通常形式で呼び出し可能にする. すでに
+ 通常メソッドである場合には何もしない.
+
to_s
モジュールの文字列表現を返す. モジュールの場合の文字列表現はモ
ジュール名である.
+ unexport(name[, name..])
+
+ nameで指定されたメソッドを関数形式でだけ呼び出し可能にする. す
+ でに関数メソッドである場合には何もしない.
+
*** Nil(クラス)
偽を表すオブジェクトnilのクラス. 偽変数(の値)nilはNilクラスの唯一のイ
@@ -2829,8 +2751,8 @@ Methods:
accept
- 新しい接続を受け付けて, 新しい接続に対するソケットを返す.
- accept(2)を参照.
+ 新しい接続を受け付けて, 新しい接続に対するソケットとアドレスの
+ ペアを返す. accept(2)を参照.
bind(addr)
@@ -2846,9 +2768,22 @@ Methods:
listen(2)と同じ働きをする.
- recv(len, flags)
+ recv(len[, flags])
+
+ ソケットからデータを受け取り, 文字列として返す. lenは受け取る
+ 最大の長さを指定する. flagsについてはrecv(2)を参照. flagsのデ
+ フォルト値は0である.
+
+ recvfrom(len[, flags])
+
+ recvと同様にソケットからデータを受け取るが, 戻り値は文字列と相
+ 手ソケットのアドレスのペアである. 引数についてはrecvと同様.
+
send(mesg, flags[, to])
- sysread(len)
+
+ ソケットを介してデータを送る.flagsに関してはsend(2)を参照の事.
+ connectしていないソケットに対しては送り先であるtoを指定する必
+ 要がある.実際に送ったデータの長さを返す.
Single Methods:
@@ -3044,6 +2979,14 @@ Methods:
文字列の長さ(バイト数)を返す.
+ ljust(width)
+ rjust(width)
+ center(width)
+
+ 文字列をそれぞれ, 右詰め, 左詰め, 真中寄せした幅widthの文字列
+ を返す. 文字列長がwidthより長い場合は元の文字列を返し, 切り詰
+ めない.
+
next
selfからendまで「次の」文字列を返す. 次の文字列とは数字は数字
@@ -3117,6 +3060,12 @@ Methods:
end
sum %= 65536
+ swapcase
+
+ 文字列中のアルファベットのうち大文字を小文字に, 小文字を大文字
+ にに置き換える. 元の文字列が更新されることに注意. 動作としては
+ tr("a-zA-Z", "A-Za-z")より少し速い.
+
to_f
文字列をFloatに変換する.
@@ -3127,12 +3076,14 @@ Methods:
toupper
uc
+ upcase
文字列中のアルファベットを全て大文字に置き換える. 元の文字列が
更新されることに注意. tr("a-z", "A-Z")より少し速い.
tolower
lc
+ downcase
文字列中のアルファベットを全て小文字に置き換える. 元の文字列が
更新されることに注意. tr("A-Z", "a-z")より少し速い.
@@ -3495,7 +3446,7 @@ Single Methods:
end
時間の単位は秒であり, 浮動小数点数で与えられる. 詳細は
- times(3C)を参照のこと.
+ times(3)を参照のこと.
*** UNIXserver
diff --git a/string.c b/string.c
index 9025668..34ca5f1 100644
--- a/string.c
+++ b/string.c
@@ -1024,6 +1024,28 @@ Fstr_lcfirst(str)
return (VALUE)str;
}
+static VALUE
+Fstr_swapcase(str)
+ struct RString *str;
+{
+ char *s;
+ int i;
+
+ str_modify(str);
+ s = str->ptr;
+ for (i=0; i < str->len; i++) {
+ if (isupper(*s)) {
+ *s = tolower(*s);
+ }
+ else if (islower(*s)) {
+ *s = toupper(*s);
+ }
+ *s++;
+ }
+
+ return (VALUE)str;
+}
+
struct tr {
int last, max;
char *p, *pend;
@@ -1533,7 +1555,67 @@ Fstr_sum(str, args)
}
}
-extern VALUE C_Builtin;
+Fstr_ljust(str, w)
+ struct RString *str;
+ VALUE w;
+{
+ int width = NUM2INT(w);
+ struct RString *res;
+ char *p, *pend;
+
+ if (str->len >= width) return (VALUE)str;
+ res = (struct RString*)str_new(0, width);
+ memcpy(res->ptr, str->ptr, str->len);
+ p = res->ptr + str->len; pend = res->ptr + width;
+ while (p < pend) {
+ *p++ = ' ';
+ }
+ return (VALUE)res;
+}
+
+Fstr_rjust(str, w)
+ struct RString *str;
+ VALUE w;
+{
+ int width = NUM2INT(w);
+ struct RString *res;
+ char *p, *pend;
+
+ if (str->len >= width) return (VALUE)str;
+ res = (struct RString*)str_new(0, width);
+ p = res->ptr; pend = p + width - str->len;
+ while (p < pend) {
+ *p++ = ' ';
+ }
+ memcpy(pend, str->ptr, str->len);
+ return (VALUE)res;
+}
+
+Fstr_center(str, w)
+ struct RString *str;
+ VALUE w;
+{
+ int width = NUM2INT(w);
+ struct RString *res;
+ char *p, *pend;
+ int n;
+
+ if (str->len >= width) return (VALUE)str;
+ res = (struct RString*)str_new(0, width);
+ n = (width - str->len)/2;
+ p = res->ptr; pend = p + n;
+ while (p < pend) {
+ *p++ = ' ';
+ }
+ memcpy(pend, str->ptr, str->len);
+ p = pend + str->len; pend = res->ptr + width;
+ while (p < pend) {
+ *p++ = ' ';
+ }
+ return (VALUE)res;
+}
+
+extern VALUE C_Kernel;
extern VALUE M_Comparable;
extern VALUE M_Enumerable;
@@ -1567,11 +1649,15 @@ Init_String()
rb_define_method(C_String, "_inspect", Fstr_inspect, 0);
rb_define_method(C_String, "toupper", Fstr_toupper, 0);
+ rb_define_alias(C_String, "upcase", "toupper");
rb_define_alias(C_String, "uc", "toupper");
rb_define_method(C_String, "tolower", Fstr_tolower, 0);
+ rb_define_alias(C_String, "downcase", "tolower");
rb_define_alias(C_String, "lc", "tolower");
rb_define_method(C_String, "ucfirst", Fstr_ucfirst, 0);
rb_define_method(C_String, "lcfirst", Fstr_lcfirst, 0);
+ rb_define_method(C_String, "swapcase", Fstr_swapcase, 0);
+
rb_define_method(C_String, "hex", Fstr_hex, 0);
rb_define_method(C_String, "oct", Fstr_oct, 0);
rb_define_method(C_String, "split", Fstr_split, -2);
@@ -1580,6 +1666,10 @@ Init_String()
rb_define_method(C_String, "crypt", Fstr_crypt, 1);
rb_define_method(C_String, "intern", Fstr_intern, 0);
+ rb_define_method(C_String, "ljust", Fstr_ljust, 1);
+ rb_define_method(C_String, "rjust", Fstr_rjust, 1);
+ rb_define_method(C_String, "center", Fstr_center, 1);
+
rb_define_method(C_String, "sub", Fstr_sub, 2);
rb_define_method(C_String, "gsub", Fstr_gsub, 2);
rb_define_method(C_String, "chop", Fstr_chop, 0);
@@ -1595,8 +1685,8 @@ Init_String()
rb_define_method(C_String, "sum", Fstr_sum, -2);
- rb_define_method(C_Builtin, "sub", Fsub, 2);
- rb_define_method(C_Builtin, "gsub", Fgsub, 2);
+ rb_define_private_method(C_Kernel, "sub", Fsub, 2);
+ rb_define_private_method(C_Kernel, "gsub", Fgsub, 2);
pr_str = rb_intern("to_s");
}
diff --git a/time.c b/time.c
index 4289f35..eea9783 100644
--- a/time.c
+++ b/time.c
@@ -128,6 +128,7 @@ Ftime_at(class, time)
return time_new_internal(class, tp->tv_sec, tp->tv_usec);
}
+
static VALUE
Ftime_to_i(time)
VALUE time;
@@ -139,6 +140,16 @@ Ftime_to_i(time)
}
static VALUE
+Ftime_to_f(time)
+ VALUE time;
+{
+ struct time_object *tobj;
+
+ GetTimeval(time, tobj);
+ return float_new((double)tobj->tv.tv_sec+(double)tobj->tv.tv_usec/1000000);
+}
+
+static VALUE
Ftime_usec(time)
VALUE time;
{
@@ -516,6 +527,7 @@ Init_Time()
rb_define_single_method(C_Time, "times", Ftime_times, 0);
rb_define_method(C_Time, "to_i", Ftime_to_i, 0);
+ rb_define_method(C_Time, "to_f", Ftime_to_f, 0);
rb_define_method(C_Time, "<=>", Ftime_cmp, 1);
rb_define_method(C_Time, "hash", Ftime_hash, 0);
diff --git a/variable.c b/variable.c
index 70aa959..1a06def 100644
--- a/variable.c
+++ b/variable.c
@@ -260,8 +260,12 @@ rb_gvar_set(entry, val)
if (entry->set_hook)
(*entry->set_hook)(val, entry->id);
- if (entry->mode == GLOBAL_VAR && entry->v.var != Qnil)
+ if (entry->mode == GLOBAL_VAR) {
+ if (entry->v.var == Qnil) {
+ rb_readonly_hook(val, entry->id);
+ }
return *entry->v.var = val;
+ }
else {
if (entry->mode == GLOBAL_UNDEF)
entry->mode = GLOBAL_VAL;
@@ -319,8 +323,8 @@ const_bound(class, id)
return FALSE;
}
-static void
-rb_const_set_1(class, id, val)
+void
+rb_const_set(class, id, val)
struct RClass *class;
ID id;
VALUE val;
@@ -334,22 +338,13 @@ rb_const_set_1(class, id, val)
st_insert(class->c_tbl, id, val);
}
-VALUE
-rb_const_set(id, val)
- ID id;
- VALUE val;
-{
- rb_const_set_1(the_class, id, val);
- return val;
-}
-
void
rb_define_const(class, name, val)
struct RClass *class;
char *name;
VALUE val;
{
- rb_const_set_1(class, rb_intern(name), val);
+ rb_const_set(class, rb_intern(name), val);
}
VALUE
@@ -410,9 +405,9 @@ Fdefined(obj, name)
{
int i, max;
- if (the_env->local_tbl) {
- for (i=1, max=the_env->local_tbl[0]+1; i<max; i++) {
- if (the_env->local_tbl[i] == id) return TRUE;
+ if (the_scope->local_tbl) {
+ for (i=1, max=the_scope->local_tbl[0]+1; i<max; i++) {
+ if (the_scope->local_tbl[i] == id) return TRUE;
}
}
}
diff --git a/version.h b/version.h
index ff07233..d2d5a5a 100644
--- a/version.h
+++ b/version.h
@@ -1,2 +1,2 @@
-#define RUBY_VERSION "0.52"
-#define VERSION_DATE "14 Oct 94"
+#define RUBY_VERSION "0.54"
+#define VERSION_DATE "94/10/26"