[Anthy-dev 2295] Re: r5rs: 訂正

Back to archive index

Jun Inoue jun.l****@gmail*****
2005年 8月 26日 (金) 17:53:25 JST


On Fri, 26 Aug 2005 12:53:51 +0900
Kazuki Ohta <mover****@hct*****> wrote:

> > ります。文字列長を int で管理して COW にすると、string-set! が無い限り最
> > 初の文字列を切り取り次第に使いまわせます。
> なるほど、いいですね。是非実装したいです。ただし、SigSchemeの機能拡張自
> 体はスケジュール的にもう少し後かなぁと思っています。

ただ、小さい(≦数十 bytes) string オブジェクトをたくさん扱うときや、C
string に変換←→戻す、をしまくる場合は逆にメモリ使用量が増えたり、オー
バーヘッドがバカにならなかったりする可能性があります。実装するときにはこ
のへんをしっかり詰めましょう。


> * SIOD compatible で uim を動かす
> * 速度&メモリ使用量最適化
> * not SIOD compatible で uim を動かす
> * SigSchemeの機能拡張(GC, string等)
> 
> 一応10月に中間報告会なるものが有るので、少なくとも安定版と同程度の動作
> を確保しておきたいという事が有ります。

なるほど。そういうスケジュールで動いてたんですね。じゃあ私も port 周りを
弄ってたんですがそれを一旦置いて uim への組み込みに注力しますね。
今までの作業中のとりあえずの成果物を添付しておきます。

* sigscheme/eval.c
  - (ScmOp_eval) 事実に即さなくなっているコメントを削除
  - (ScmExp_cond) (() expr) という clause をエラーにしてたのをフィックス。
    siod 互換モードでは、どのみち正しくない動作なのであんまり意味なし。
* sigscheme/operations.c
  - (ScmOp_make_vector) (make-vector n ()) が通るようにした
  - (ScmOp_force) 無駄な中間生成物排除。
* sigscheme/read.c
  - 括弧の内側の謎スペース削除×2
  - (read_sexpression) merge duplicated code
  - 進数表現に対応 (#xff とか)
  - .で始まる symbol を扱うコードの省力化

最後の二つは peek_char を実装すればもっとエレガントに書けそうです。(とい
うかそれが port を弄ってた理由)

-- 
Jun Inoue
jun.l****@gmail*****
-------------- next part --------------
diff -ur sigscheme/eval.c ../.r5rs/sigscheme/eval.c
--- sigscheme/eval.c	2005-08-25 22:03:28.000000000 -0700
+++ ../.r5rs/sigscheme/eval.c	2005-08-26 00:02:24.000000000 -0700
@@ -260,7 +260,6 @@
             tmp = ScmOp_eval(tmp, env);
             break;
         case ScmEtc:
-            /* QUOTE case */
             break;
         default:
             SigScm_ErrorObj("eval : invalid operation ", obj);
@@ -1038,12 +1037,13 @@
     /* looping in each clause */
     for (; !NULLP(arg); arg = CDR(arg)) {
         clause = CAR(arg);
+
+        if (!CONSP(clause))
+            SigScm_ErrorObj("cond : bad clause: ", clause);
+
         test   = CAR(clause);
         exps   = CDR(clause);
 
-        if (NULLP(clause) || NULLP(test))
-            SigScm_Error("cond : syntax error\n");
-
         /* evaluate test */
         test = ScmOp_eval(test, env);
 
diff -ur sigscheme/operations.c ../.r5rs/sigscheme/operations.c
--- sigscheme/operations.c	2005-08-25 22:03:28.000000000 -0700
+++ ../.r5rs/sigscheme/operations.c	2005-08-25 22:30:56.000000000 -0700
@@ -1738,7 +1738,7 @@
 
     /* fill vector */
     fill = SCM_UNDEF;
-    if (!NULLP(CDR(arg)) && !NULLP(CAR(CDR(arg))))
+    if (!NULLP(CDR(arg)))
         fill = CAR(CDR(arg));
 
     for (i = 0; i < c_k; i++) {
@@ -1954,8 +1954,8 @@
     if (!CLOSUREP(CAR(arg)))
         SigScm_Error("force : not proper delayed object\n");
 
-    /* evaluated exp = ( CAR(arg) ) */
-    return ScmOp_eval(Scm_NewCons(CAR(arg), SCM_NULL), env);
+    /* the caller's already wrapped arg in a list for us */
+    return ScmOp_eval(arg, env);
 }
 
 ScmObj ScmOp_call_with_current_continuation(ScmObj arg, ScmObj env)
diff -ur sigscheme/read.c ../.r5rs/sigscheme/read.c
--- sigscheme/read.c	2005-08-25 22:03:28.000000000 -0700
+++ ../.r5rs/sigscheme/read.c	2005-08-26 00:23:20.000000000 -0700
@@ -73,7 +73,7 @@
         }                                                                     \
     } while (0);
 
-#define SCM_PORT_UNGETC(port,c )        \
+#define SCM_PORT_UNGETC(port,c)         \
     SCM_PORTINFO_UNGOTTENCHAR(port) = c;
 
 /*=======================================
@@ -92,6 +92,7 @@
 static ScmObj read_char(ScmObj port);
 static ScmObj read_string(ScmObj port);
 static ScmObj read_symbol(ScmObj port);
+static ScmObj parse_number(const char *str);
 static ScmObj read_number_or_symbol(ScmObj port);
 static ScmObj read_quote(ScmObj port, ScmObj quoter);
 
@@ -131,7 +132,7 @@
                 if (c == '\n') {
                     break;
                 }
-                if (c == EOF ) return c;
+                if (c == EOF) return c;
             }
             continue;
         } else if(isspace(c)) {
@@ -165,8 +166,6 @@
             return read_string(port);
         case '0': case '1': case '2': case '3': case '4':
         case '5': case '6': case '7': case '8': case '9':
-            SCM_PORT_UNGETC(port, c);
-            return read_number_or_symbol(port);
         case '+': case '-':
             SCM_PORT_UNGETC(port, c);
             return read_number_or_symbol(port);
@@ -196,6 +195,9 @@
                 return ScmOp_list2vector(read_list(port, ')'));
             case '\\':
                 return read_char(port);
+            case 'b': case 'o': case 'd': case 'x':
+                SCM_PORT_UNGETC(port, c1);
+                return parse_number(read_word(port));
             case EOF:
                 SigScm_Error("end in #\n");
             default:
@@ -225,7 +227,6 @@
     int    c      = 0;
     int    c2     = 0;
     char  *token  = NULL;
-    char  *dotsym = NULL;
 
 #if DEBUG_PARSER
     printf("read_list\n");
@@ -272,11 +273,10 @@
              */
             SCM_PORT_UNGETC(port, c2);
             token  = read_word(port);
-            dotsym = (char*)malloc(sizeof(char) * (strlen(token) + 1 + 1));
-            memmove (dotsym + 1, token, strlen(token)+1);
-            dotsym[0] = '.';
-            item = Scm_Intern(dotsym);
-            free(dotsym);
+            token  = (char*)realloc(token, strlen(token) + 1 + 1);
+            memmove (token + 1, token, strlen(token)+1);
+            token[0] = '.';
+            item = Scm_Intern(token);
             free(token);
         } else {
             SCM_PORT_UNGETC(port, c);
@@ -358,6 +358,7 @@
             case 'r':  stringbuf[stringlen] = '\r'; break;
             case 'f':  stringbuf[stringlen] = '\f'; break;
             case 't':  stringbuf[stringlen] = '\t'; break;
+            case '\\': stringbuf[stringlen] = '\\'; break;
             default:
                 stringbuf[stringlen] = '\\';
                 stringbuf[++stringlen] = c;
@@ -389,11 +390,10 @@
 
 static ScmObj read_number_or_symbol(ScmObj port)
 {
-    int i = 0;
-    int is_str  = 0;
+    int number = 0;
     int str_len = 0;
     char  *str = NULL;
-    ScmObj obj = SCM_NULL;
+    char  *first_nondigit = NULL;
 
 #if DEBUG_PARSER
     printf("read_number_or_symbol\n");
@@ -403,44 +403,13 @@
     str = read_word(port);
     str_len = strlen(str);
 
-    if (strlen(str) == 1
-        && (strcmp(str, "+") == 0 || strcmp(str, "-") == 0))
-    {
-#if DEBUG_PARSER
-        printf("determined as symbol : %s\n", str);
-#endif
+    /* see if it's a decimal integer */
+    number = (int)strtol(str, &first_nondigit, 10);
 
-        obj = Scm_Intern(str);
-        free(str);
-        return obj;
-    }
+    if (*first_nondigit)
+        return Scm_Intern(str);
 
-    /* check whether each char is the digit */
-    for (i = 0; i < str_len; i++) {
-        if (i == 0 && (str[i] == '+' || str[i] == '-'))
-            continue;
-
-        if (!isdigit(str[i])) {
-            is_str = 1;
-            break;
-        }
-    }
-
-    /* if symbol, then intern it. if number, return new int obj */
-    if (is_str) {
-#if DEBUG_PARSER
-        printf("determined as symbol : %s\n", str);
-#endif
-        obj = Scm_Intern(str);
-    } else {
-#if DEBUG_PARSER
-        printf("determined as num : %s\n", str);
-#endif
-        obj = Scm_NewInt((int)atof(str));
-    }
-    free(str);
-
-    return obj;
+    return Scm_NewInt(number);
 }
 
 
@@ -518,5 +487,30 @@
 
 static ScmObj read_quote(ScmObj port, ScmObj quoter)
 {
-    return Scm_NewCons(quoter, Scm_NewCons(read_sexpression(port), SCM_NULL));
+    return SCM_LIST_2(quoter, read_sexpression(port));
+}
+
+/* str should be what appeared right after a # */
+static ScmObj parse_number(const char *str)
+{
+    int radix  = 0;
+    int number = 0;
+    char *first_nondigit = NULL;
+    const char *p = str;
+
+    switch (str[0]) {
+    case 'b': radix = 2;  p++; break;
+    case 'o': radix = 8;  p++; break;
+    case 'd': radix = 10; p++; break;
+    case 'x': radix = 16; p++; break;
+    default:
+        SigScm_Error("ill-formatted number: #%s\n", str);
+    }
+
+    number = (int)strtol(p, &first_nondigit, radix);
+
+    if (*first_nondigit)
+        SigScm_Error("ill-formatted number: #%s\n", str);
+
+    return Scm_NewInt(number);
 }
diff -ur sigscheme/test/io.scm ../.r5rs/sigscheme/test/io.scm
--- sigscheme/test/io.scm	2005-08-21 04:48:30.000000000 -0700
+++ ../.r5rs/sigscheme/test/io.scm	2005-08-25 22:41:31.000000000 -0700
@@ -1,2 +1,2 @@
-(display "type an sexp:")
+(display "type a char:")
 (print (read-char))
diff -ur sigscheme/test/test-num.scm ../.r5rs/sigscheme/test/test-num.scm
--- sigscheme/test/test-num.scm	2005-08-22 13:04:10.000000000 -0700
+++ ../.r5rs/sigscheme/test/test-num.scm	2005-08-26 00:18:58.000000000 -0700
@@ -59,4 +59,14 @@
 (assert-equal? "string->number test2" 10  (string->number "10"))
 (assert-equal? "string->number test2" 100 (string->number "100"))
 
+; numbers in various radices
+(assert-true "binary number test1" (= #b1111 15))
+(assert-true "binary number test2" (= #b010  2))
+(assert-true "octal number test1"  (= #o077  63))
+(assert-true "octal number test2"  (= #o361  241))
+(assert-true "decimal number test1" (= #d3900 3900))
+(assert-true "decimal number test2" (= #d18782 18782))
+(assert-true "hexadecimal test1" (= #xffff 65535))
+(assert-true "hexadecimal test2" (= #x0A7b 2683))
+
 (total-report)


Anthy-dev メーリングリストの案内
Back to archive index