[uim-commit] r2173 - in branches/r5rs/sigscheme: . test

jun0 at freedesktop.org jun0 at freedesktop.org
Sat Nov 19 20:26:50 PST 2005


Author: jun0
Date: 2005-11-19 20:26:45 -0800 (Sat, 19 Nov 2005)
New Revision: 2173

Modified:
   branches/r5rs/sigscheme/eval.c
   branches/r5rs/sigscheme/sigschemeinternal.h
   branches/r5rs/sigscheme/sigschemetype.h
   branches/r5rs/sigscheme/test/test-quote.scm
Log:
This commit refactors quasiquote handling.  It also fixes some bugs
and adds tests for them.

* sigscheme/sigschemeinternal.h
  - (REF_OFF_HEAP): New macro.
  - (ScmQueue): New type.
  - (SCM_QUEUE_INVALIDATE, SCM_QUEUE_VALIDP, SCM_QUEUE_POINT_TO,
    SCM_QUEUE_ADD, SCM_QUEUE_APPEND, SCM_QUEUE_TERMINATOR,
    SCM_QUEUE_SLOPPY_APPEND): New macros.

* sigscheme/eval.c
  - (SCM_REF_OFF_HEAP): New macro.
  - (qquote_internal, qquote_vector): Update prototype.  Move
    definition closer to that of ScmExp_quasiquote().
  - (list_translator, tr_msg, qquote_result): New types.
  - (LISTRAN_INIT, LISTRAN_CURPOS, LISTRAN_NEXT, LISTRAN_EXTRACT): New macros.
  - (listran): New function.

* sigscheme/test/test-quote.scm
  - Add new tests.

Modified: branches/r5rs/sigscheme/eval.c
===================================================================
--- branches/r5rs/sigscheme/eval.c	2005-11-20 04:25:27 UTC (rev 2172)
+++ branches/r5rs/sigscheme/eval.c	2005-11-20 04:26:45 UTC (rev 2173)
@@ -83,10 +83,13 @@
 static ScmObj call(ScmObj proc, ScmObj args, ScmEvalState *eval_state,
                    int suppress_eval);
 static ScmObj map_eval(ScmObj args, ScmObj env);
-static ScmObj qquote_internal(ScmObj expr, ScmObj env, int nest);
-static ScmObj qquote_vector(ScmObj vec, ScmObj env, int nest);
 static void define_internal(ScmObj var, ScmObj exp, ScmObj env);
 
+/* Quasiquotation. */
+typedef struct _qquote_result qquote_result;
+static qquote_result qquote_internal(ScmObj input, ScmObj env, int nest);
+static qquote_result qquote_vector(ScmObj vec, ScmObj env, int nest);
+
 /*=======================================
   Function Implementations
 =======================================*/
@@ -600,243 +603,96 @@
     return result;
 }
 
+/*===========================================================================
+  Utilities: Compound Data Translators
+===========================================================================*/
 
+/* Providing also a vector translator would make sense, but currently
+ * there's no compelling reason to take the trouble of designing a
+ * clean interface for it. */
+
 /**
- * The big bad full-implementation of quasiquote.
+ * This structure aids in copying a list with modifications to some
+ * parts of it.  It's currently used for handling quasiquotation, and
+ * planned to be used to implement run-time macro expansion.
  *
- * @param qexpr The expression given to quasiquote.
- * @param env The effective environment.
- * @param nest Nesting level of quasiquote.  This function is recursive.
+ * The translator has an input, an output, and a current position.
+ * Only the input is supplied by the user.  Conceptually, the
+ * translator replicates the input list and places it at the output.
+ * The user then CDRs down the input by successively calling
+ * TRL_NEXT().  When an element is encountered that shall be modified,
+ * the user calls listrans() with a suitable message (of type tr_msg)
+ * along with the modified object.
  *
- * @return If qexpr or any of its subexpressions was evaluated, then
- * (do-unquotes qexpr) is returned.  Otherwise, the return
- * value will test true for QQUOTE_IS_VERBATIM().
- *
- * @see qquote_vector()
+ * @see tr_msg
  */
-static ScmObj qquote_internal(ScmObj qexpr, ScmObj env, int nest)
-{
-    ScmObj ls        = SCM_NULL;
-    ScmObj obj       = SCM_NULL;
-    ScmObj car       = SCM_NULL;
-    ScmObj args      = SCM_NULL;
-    ScmObj result    = SCM_NULL;
-    ScmObj ret_lst   = SCM_NULL;
-    ScmRef ret_tail  = SCM_REF_NULL;
-    int splice_flag  = 0;
-    DECLARE_INTERNAL_FUNCTION("qquote_internal");
+typedef struct {
+    ScmObj output;
+    ScmObj src;                 /* Uncopied portion of input. */
+    ScmObj ptr;                 /* Current position. */
+    ScmQueue q;
+} list_translator;
 
-    /* local "functions" */
-#define qquote_copy_delayed()   (QQUOTE_IS_VERBATIM(ret_lst))
-#define qquote_force_copy_upto(end)                             \
-    do {                                                        \
-        ScmObj src = qexpr;                                     \
-        ret_tail = SCM_REF(ret_lst);                            \
-        while (!EQ(src, end)) {                                 \
-            SCM_SET(ret_tail, CONS(CAR(src), SCM_NULL));        \
-            ret_tail = SCM_REF_CDR(SCM_DEREF(ret_tail));        \
-            src = CDR(src);                                     \
-        }                                                       \
-    } while (0)
+typedef enum {
+    TR_MSG_NOP,
 
+    /** Substitute OBJ for all the cons cells at or after the current
+     * position. */
+    TR_MSG_SET_TAIL,
 
-    QQUOTE_SET_VERBATIM(ret_lst); /* default return value */
+    /** Put OBJ in place of the current element. */
+    TR_MSG_REPLACE_CAR,
 
-    if (CONSP(qexpr)) {
-        car = CAR(qexpr);
-        args = CDR(qexpr);
+    /** Splice OBJ into the current position. */
+    TR_MSG_SPLICE,
 
-        if (EQ(car, SYM_UNQUOTE_SPLICING)) {
-            if (!IS_LIST_LEN_1(args))
-                ERR_OBJ("syntax error", qexpr);
-            if (--nest == 0)
-                return EVAL(CAR(args), env);
-        } else if (EQ(car, SYM_QUASIQUOTE)) {
-            if (!IS_LIST_LEN_1(args))
-                ERR_OBJ("syntax error", qexpr);
-            if (++nest <= 0)
-                SigScm_Error("quasiquote: nesting too deep (circular list?)");
-        }
-    }
+    /* Aliases. */
+    TR_MSG_REUSE_CAR = TR_MSG_NOP,
+    TR_MSG_CURTAIL = TR_MSG_NOP,
+    TR_MSG_REPLACE_CONS = TR_MSG_SPLICE
+} tr_msg;
 
-    for (ls = qexpr; CONSP(ls); ls = CDR(ls)) {
-        obj = CAR(ls);
-        splice_flag = 0;
+#define LISTRAN_INIT(_t, _in)  ((_t).output = SCM_INVALID,               \
+                                SCM_QUEUE_POINT_TO((_t).q, (_t).output), \
+                                (_t).src = (_t).ptr = (_in))
+#define LISTRAN_CURPOS(_t)     ((_t).ptr)
+#define LISTRAN_NEXT(_t)       ((_t).ptr = CDR((_t).ptr))
+#define LISTRAN_EXTRACT(_t)    ((_t).output)
 
-        if (CONSP(obj)) {
-            result = qquote_internal(obj, env, nest);
-
-            if (EQ(CAR(obj), SYM_UNQUOTE_SPLICING) && nest == 1) {
-                /* , at x */
-                splice_flag = 1;
-            }
-        } else if (VECTORP(obj)) {
-            /* #(x) */
-            result = qquote_vector(obj, env, nest);
-        } else if (EQ(obj, SYM_UNQUOTE) && IS_LIST_LEN_1(CDR(ls))) {
-            /* we're at the comma in (x . ,y) or qexpr was ,z */
-            if (--nest == 0) {
-                result = EVAL(CADR(ls), env);
-                goto append_last_item;
-            }
-            QQUOTE_SET_VERBATIM(result);
-        } else {
-            /* atom */
-            QQUOTE_SET_VERBATIM(result);
-        }
-
-        if (QQUOTE_IS_VERBATIM(result)) {
-            if (!qquote_copy_delayed()) {
-                SCM_SET(ret_tail, CONS(obj, SCM_NULL));
-                ret_tail = SCM_REF_CDR(SCM_DEREF(ret_tail));
-            }
-        } else {
-            if (qquote_copy_delayed())
-                qquote_force_copy_upto(ls);
-
-            if (splice_flag) {
-                SCM_SET(ret_tail, result);
-                /* find the new tail (which may be the current pos) */
-                while (CONSP(SCM_DEREF(ret_tail)))
-                    ret_tail = SCM_REF_CDR(SCM_DEREF(ret_tail));
-                if (!NULLP(SCM_DEREF(ret_tail)))
-                    ERR_OBJ("unquote-splicing: bad list",
-                                    result);
-            } else {
-                SCM_SET(ret_tail, CONS(result, SCM_NULL));
-                ret_tail = SCM_REF_CDR(SCM_DEREF(ret_tail));
-            }
-        }
-    } /* foreach ls in qexpr */
-
-    /* Handle the leftover of an improper list; if qexpr is a proper
-     * list, all the following will be a no-op. */
-    if (VECTORP(ls))
-        result = qquote_vector(ls, env, nest);
-    else
-        QQUOTE_SET_VERBATIM(result);
-
-  append_last_item:
-    if (QQUOTE_IS_VERBATIM(result)) {
-        if (!qquote_copy_delayed())
-            SCM_SET(ret_tail, ls);
-    } else {
-        if (qquote_copy_delayed())
-            qquote_force_copy_upto(ls);
-        SCM_SET(ret_tail, result);
-    }
-
-    return ret_lst;
-#undef qquote_is_spliced
-#undef qquote_copy_delayed
-#undef qquote_force_copy_upto
-}
-
 /**
- * The semantics are the same as qquote_internal, except the first
- * argument should be a vector.  Adapted some ideas from Gauche,
- * another Scheme implementation by Shiro Kawai.
- *
- * @see qquote_internal()
+ * Performs (relatively) complex operations on a list translator.
+ * 
+ * @see list_translator, tr_msg
  */
-static ScmObj qquote_vector(ScmObj src, ScmObj env, int nest)
+static void listran(list_translator *t, tr_msg msg, ScmObj obj)
 {
-    ScmObj splices    = SCM_NULL;
-    ScmObj expr       = SCM_NULL;
-    ScmObj ret        = SCM_NULL;
-    ScmObj *copy_buf  = NULL;
-    ScmObj result     = SCM_NULL;
-    ScmObj splice_len = SCM_NULL;
-    int len = SCM_VECTOR_LEN(src);
-    int growth = 0;
-    int next_splice_index = -1;
-    int i = 0;
-    int j = 0;
-    DECLARE_INTERNAL_FUNCTION("qquote_vector");
+    DECLARE_INTERNAL_FUNCTION("(list translator)");
+    switch (msg) {
+    case TR_MSG_NOP:
+        break;
 
-    /* local "functions" */
-#define qquote_copy_delayed() (copy_buf == NULL)
-#define qquote_is_spliced(o)  \
-    (CONSP(o) && EQ(CAR(o), SYM_UNQUOTE_SPLICING))
-#define qquote_force_copy_upto(n) \
-    do { \
-        int k; \
-        copy_buf = (ScmObj*)malloc((len + growth) * sizeof(ScmObj)); \
-        memcpy(copy_buf, SCM_VECTOR_VEC(src), n*sizeof(ScmObj)); \
-        /* wrap it now, or a cont invocation can leak it */ \
-        ret = Scm_NewVector(copy_buf, len + growth); \
-        /* fill with something the garbage collector recognizes */ \
-        for (k=n; k < len + growth; k++) \
-            copy_buf[k] = SCM_NULL; \
-    } while(0)
+    case TR_MSG_REPLACE_CAR:
+        obj = LIST_1(obj);
+        /* Fall through. */
+    case TR_MSG_SET_TAIL:
+    case TR_MSG_SPLICE:
 
-    QQUOTE_SET_VERBATIM(ret);
-    copy_buf = NULL;
+        /* Let src cath up with ptr, copying elements in between. */
+        for (; !EQ(t->src, t->ptr); t->src = CDR(t->src))
+            SCM_QUEUE_ADD(t->q, CAR(t->src));
 
-    if (nest == 1) {
-        /* Evaluate all the splices first, in reverse order, and store
-         * them in a list ((ls . index) (ls . index)...). */
-        for (i = len - 1; i >= 0; i--) {
-            expr = SCM_VECTOR_CREF(src, i);
-            if (qquote_is_spliced(expr)) {
-                if (!IS_LIST_LEN_1(CDR(expr)))
-                    ERR_OBJ("syntax error: ", expr);
-
-                result = EVAL(CADR(expr), env);
-
-                splice_len = ScmOp_length(result);
-                if (SCM_INT_VALUE(splice_len) < 0)
-                    SigScm_Error("unquote-splicing: bad list");
-
-                growth += SCM_INT_VALUE(splice_len) - 1;
-                splices = CONS(CONS(result, Scm_NewInt(i)),
-                               splices);
-            }
+        if (msg != TR_MSG_SET_TAIL) {
+            SCM_QUEUE_APPEND(t->q, obj);
+#if SCM_STRICT_R5RS
+            if (!NULLP(SCM_QUEUE_TERMINATOR(t->q)))
+                ERR_OBJ("bad splice list", obj);
+#endif
+            obj = t->src = CDR(t->src);
         }
-        if (!NULLP(splices)) {
-            next_splice_index = SCM_INT_VALUE(CDAR(splices));
-            qquote_force_copy_upto(0);
-        }
+        SCM_QUEUE_SLOPPY_APPEND(t->q, obj);
+            
+        break;
     }
-
-    for (i = j = 0; i < len; i++) {
-        /* j will be the index for copy_buf */
-        if (i == next_splice_index) {
-            /* spliced */
-            for (expr=CAAR(splices); !NULLP(expr); expr=CDR(expr))
-                copy_buf[j++] = CAR(expr);
-            splices = CDR(splices);
-
-            if (NULLP(splices))
-                next_splice_index = -1;
-            else
-                next_splice_index = SCM_INT_VALUE(CDAR(splices));
-            /* continue; */
-        } else {
-            expr = SCM_VECTOR_CREF(src, i);
-            if (CONSP(expr))
-                result = qquote_internal(expr, env, nest);
-            else if (VECTORP(expr))
-                result = qquote_vector(expr, env, nest);
-            else
-                QQUOTE_SET_VERBATIM(result);
-
-            if (!QQUOTE_IS_VERBATIM(result)) {
-                if (qquote_copy_delayed())
-                    qquote_force_copy_upto(i);
-
-                copy_buf[j] = result;
-            } else if (!qquote_copy_delayed()) {
-                copy_buf[j] = expr;
-            }
-
-            j++;
-        }
-    }
-
-    return ret;
-#undef qquote_copy_delayed
-#undef qquote_force_copy_upto
 }
 
 /*=======================================
@@ -1405,14 +1261,191 @@
 /*===========================================================================
   R5RS : 4.2 Derived expression types : 4.2.6 Quasiquotation
 ===========================================================================*/
+
+struct _qquote_result {
+    ScmObj obj;
+    tr_msg insn;
+};
+
+static qquote_result qquote_vector(ScmObj input, ScmObj env, int nest)
+{
+    ScmObj replacements;
+    ScmObj obj;
+    ScmObj *copy_buf;
+    int splice_len;
+    int growth;
+    int len;
+    int i, cpi;
+    int next_rindex;
+    qquote_result tmp;
+    qquote_result my_result;
+    DECLARE_INTERNAL_FUNCTION("(quasiquote:vector)");
+
+    len          = SCM_VECTOR_LEN(input);
+    replacements = SCM_NULL;
+    obj          = SCM_INVALID;
+    copy_buf     = NULL;
+    growth       = 0;
+
+    for (i = len - 1; i >= 0; i--) {
+        obj = SCM_VECTOR_CREF(input, i);
+        tmp = qquote_internal(obj, env, nest);
+        switch (tmp.insn) {
+        case TR_MSG_REPLACE_CAR:
+            replacements = CONS(CONS(Scm_NewInt(i),
+                                     tmp.obj),
+                                replacements);
+            break;
+        case TR_MSG_SPLICE:
+            replacements = CONS(CONS(Scm_NewInt(-i-1), /* Mark as splice. */
+                                     tmp.obj),
+                                replacements);
+            splice_len = ScmOp_c_length(tmp.obj);
+#if SCM_STRICT_R5RS
+            if (splice_len < 0)
+                ERR_OBJ("got bad splice list from", obj);
+#endif
+            growth += splice_len - 1;
+            break;
+        default:
+            break;
+        }
+    }
+
+    if (NULLP(replacements)) {
+        my_result.obj = SCM_INVALID;
+        my_result.insn = TR_MSG_REUSE_CAR;
+        return my_result;
+    }
+
+    copy_buf = malloc((len + growth) * sizeof(ScmObj));
+
+    /* i indexes input and cpi indexes copy_buf. */
+    next_rindex = SCM_INT_VALUE(CAAR(replacements));
+    for (i = cpi = 0; i < len; i++) {
+        if (i == next_rindex) {
+            copy_buf[cpi++] = CDAR(replacements);
+        } else if (-i-1 == next_rindex) {
+            ScmObj tmp;
+            for (tmp = CDAR(replacements); CONSP(tmp); tmp = CDR(tmp))
+                copy_buf[cpi++] = CAR(tmp);
+        } else {
+            copy_buf[cpi++] = SCM_VECTOR_CREF(input, i);
+            continue;
+        }
+        replacements = CDR(replacements);
+        if (NULLP(replacements))
+            next_rindex = len;   /* Invalidate. */
+        else
+            next_rindex = SCM_INT_VALUE(CAAR(replacements));
+    }
+
+    my_result.obj = Scm_NewVector(copy_buf, len + growth);
+    my_result.insn = TR_MSG_REPLACE_CAR;
+    return my_result;
+}
+
+/**
+ * Interpret a quasiquoted expression.
+ *
+ * @see qquote_vector()
+ */
+static qquote_result qquote_internal(ScmObj input, ScmObj env, int nest)
+{
+    ScmObj ptr;
+    list_translator tr;
+    qquote_result tmp_result;
+    qquote_result my_result;
+    DECLARE_INTERNAL_FUNCTION("(quasiquote)");
+
+    LISTRAN_INIT(tr, input);
+    ptr = LISTRAN_CURPOS(tr);        /* This will be our traverser. */
+
+    if (VECTORP(input))
+        return qquote_vector(input, env, nest);
+
+    if (!CONSP(input))
+        goto end;
+
+#define EXPAND(_datum)                                                  \
+        (tmp_result = qquote_internal((_datum), env, nest),             \
+         listran(&tr, tmp_result.insn, tmp_result.obj))
+
+#define SET_TAIL(_datum) \
+        listran(&tr, TR_MSG_SET_TAIL, (_datum))
+
+    /* INPUT can't be a syntactical expression if length < 2. */
+    if (!CONSP(CDR(ptr)))
+        goto one_cons;
+
+    /* Process up to the penultimate element (not counting the
+     * list terminator). */
+    for (; CONSP(CDDR(ptr)); ptr = LISTRAN_NEXT(tr))
+        EXPAND(CAR(ptr));
+
+    if (NULLP(CDDR(ptr))) {
+        if (EQ(CAR(ptr), SYM_QUASIQUOTE)) {
+            /* PTR == `x */
+            ++nest;
+        } else if (EQ(CAR(ptr), SYM_UNQUOTE)) {
+            /* PTR == ,x */
+            if (--nest == 0) {
+                SET_TAIL(EVAL(CADR(ptr), env));
+                my_result.obj = LISTRAN_EXTRACT(tr);
+                my_result.insn = TR_MSG_REPLACE_CAR;
+                return my_result;
+            }
+        } else if (EQ(CAR(ptr), SYM_UNQUOTE_SPLICING)) {
+            /* PTR == , at x */
+            if (!EQ(ptr, input)) /* (a . , at b) */
+                ERR_OBJ(",@ in wrong context", input);
+            if (--nest == 0) {
+                my_result.insn = TR_MSG_SPLICE;
+                my_result.obj  = EVAL(CADR(ptr), env);
+                return my_result;
+            }
+        }
+    }
+
+  one_cons:
+    do {
+        EXPAND(CAR(ptr));
+        ptr = LISTRAN_NEXT(tr);
+    } while (CONSP(ptr));
+
+    /* Handle list terminator; '() for proper lists. */
+    tmp_result = qquote_internal(ptr, env, nest);
+    if (tmp_result.insn != TR_MSG_REUSE_CAR)
+        SET_TAIL(tmp_result.obj);
+
+  end:
+    my_result.obj = LISTRAN_EXTRACT(tr);
+    my_result.insn = VALIDP(my_result.obj)
+        ? TR_MSG_REPLACE_CAR
+        : TR_MSG_REUSE_CAR;
+    return my_result;
+#undef EXPAND
+#undef SET_TAIL
+}
+
 ScmObj ScmExp_quasiquote(ScmObj datum, ScmObj env)
 {
-    ScmObj ret = qquote_internal(datum, env, 1);
+    qquote_result ret = qquote_internal(datum, env, 1);
     DECLARE_FUNCTION("quasiquote", SyntaxFixed1);
 
-    if (QQUOTE_IS_VERBATIM(ret))
+    switch (ret.insn) {
+    case TR_MSG_REUSE_CAR:
         return datum;
-    return ret;
+    case TR_MSG_SPLICE:
+#if SCM_STRICT_R5RS
+        ERR_OBJ("unquote-splicing in invalid context", datum);
+#endif
+        /* Otherwise fall through. */
+    case TR_MSG_REPLACE_CAR:
+        return ret.obj;
+    default:
+        ERR_OBJ("bug in quasiquote", datum);
+    }
 }
 
 ScmObj ScmExp_unquote(ScmObj dummy, ScmObj env)

Modified: branches/r5rs/sigscheme/sigschemeinternal.h
===================================================================
--- branches/r5rs/sigscheme/sigschemeinternal.h	2005-11-20 04:25:27 UTC (rev 2172)
+++ branches/r5rs/sigscheme/sigschemeinternal.h	2005-11-20 04:26:45 UTC (rev 2173)
@@ -149,6 +149,7 @@
 #define SET            SCM_SET
 #define REF_CAR        SCM_REF_CAR
 #define REF_CDR        SCM_REF_CDR
+#define REF_OFF_HEAP   SCM_REF_OFF_HEAP
 
 #define EVAL           SCM_EVAL
 
@@ -307,6 +308,23 @@
 #define NAMEHASH_SIZE 1024
 
 /*=======================================
+   List Constructor
+=======================================*/
+typedef ScmRef ScmQueue;
+#define SCM_QUEUE_INVALIDATE(_q) ((_q) = NULL)
+#define SCM_QUEUE_VALIDP(_q)     (_q)
+#define SCM_QUEUE_POINT_TO(_q, _out) ((_q) = SCM_REF_OFF_HEAP(_out))
+#define SCM_QUEUE_ADD(_q, _dat) (SET((_q), LIST_1(_dat)),       \
+                                 (_q) = REF_CDR(DEREF(_q)))
+#define SCM_QUEUE_APPEND(_q, _lst)              \
+    do {                                        \
+        DEREF(_q) = (_lst);                     \
+        while (CONSP(DEREF(_q)))                \
+            (_q) = REF_CDR(DEREF(_q));          \
+    } while (0)
+#define SCM_QUEUE_TERMINATOR(_q)          (DEREF(_q))
+#define SCM_QUEUE_SLOPPY_APPEND(_q, _lst) (DEREF(_q) = (_lst))
+/*=======================================
    Function Declarations
 =======================================*/
 /* datas.c */

Modified: branches/r5rs/sigscheme/sigschemetype.h
===================================================================
--- branches/r5rs/sigscheme/sigschemetype.h	2005-11-20 04:25:27 UTC (rev 2172)
+++ branches/r5rs/sigscheme/sigschemetype.h	2005-11-20 04:26:45 UTC (rev 2173)
@@ -401,6 +401,7 @@
 #define SCM_REF(obj)      (&(obj))
 #define SCM_REF_CAR(cons) (SCM_REF(SCM_CAR(cons)))
 #define SCM_REF_CDR(cons) (SCM_REF(SCM_CDR(cons)))
+#define SCM_REF_OFF_HEAP(cons) (&(cons))
 #define SCM_DEREF(ref)    (*(ref))
 /* RFC: Is there a better name? */
 #define SCM_SET(ref, obj) (*(ref) = (obj))

Modified: branches/r5rs/sigscheme/test/test-quote.scm
===================================================================
--- branches/r5rs/sigscheme/test/test-quote.scm	2005-11-20 04:25:27 UTC (rev 2172)
+++ branches/r5rs/sigscheme/test/test-quote.scm	2005-11-20 04:26:45 UTC (rev 2173)
@@ -4,14 +4,32 @@
 (assert-true "unquote check" (equal? `(1 2 3) `(1 ,(+ 1 1) ,(+ 1 2))))
 (assert-true "unquote-splicing check" (equal? `(1 2 3) `(1 ,@(cdr '(1 2)) 3)))
 (assert-true "mixed check" (equal? '(a 3 c 7 8 9) `(a ,(+ 1 2) c ,@(cdr '(6 7 8 9)))))
-(assert-true "nested quasiquote check"
-	(equal?
-	 '(a `(b c ,() 0) 1)
-	 `(a `(b c ,(,@() ,@()) 0) 1)))
+(assert-equal? "nested quasiquote check #1"
+               '(a `(b c ,() 0) 1)
+               `(a `(b c ,(,@() ,@()) 0) 1))
 
-(assert-true "vector quasiquote check"
+(assert-equal? "nested quasiquote check #2"
+               '(0 1)
+               `(0 . ,(list 1)))
+
+(assert-equal? "nested quasiquote check #3"
+               '(0 . 1)
+               `(0 . ,'1))
+
+(assert-equal? "nested quasiquote check #4"
+               '(0 quasiquote (unquote 1))
+               `(0 . `,,(+ 1)))
+
+(assert-true "vector quasiquote check #1"
 	(equal?
 	 '#(#(a b c d) e)
 	 `#(,@() #(a ,@(list 'b 'c) d) e)))
+(assert-equal? "vector quasiquote check #2" '(1 . #(2 3)) `(1 . #(,(+ 1 1) 3)))
+(assert-equal? "vector quasiquote check #3"
+               '(0 . #(1 2 3 4 5 6))
+               `(0 . #(1 ,2 ,@(list 3 4) 5 ,6 ,@())))
+(assert-equal? "vector quasiquote check #3"
+               '#(a b)
+               `#(,@(list 'a 'b)))
 
 (total-report)



More information about the uim-commit mailing list