diff --git a/doc/lib/chibi/match.html b/doc/lib/chibi/match.html index 1a073107..2219e521 100755 --- a/doc/lib/chibi/match.html +++ b/doc/lib/chibi/match.html @@ -43,7 +43,7 @@ where the result of expr is matched against each pattern in turn, and the corresponding body is evaluated for the first to succeed. Thus, a list of three elements matches a list of three elements. -

(let ((ls (list 1 2 3))) (match ls ((1 2 3) #)))
=> #t

+

(let ((ls (list 1 2 3))) (match ls ((1 2 3) #t)))
=> #t

If no patterns match an error is signalled. Identifiers will match anything, and make the corresponding binding available in the body. @@ -65,9 +65,9 @@ parts unquoted. Often you want to match any number of a repeated pattern. Inside a list pattern you can append ... after an element to match zero or more of that pattern (like a regexp Kleene star). -

(match (list 1 2) ((1 2 3 ...) #))
=> #t

-

(match (list 1 2 3) ((1 2 3 ...) #))
=> #t

-

(match (list 1 2 3 3 3) ((1 2 3 ...) #))
=> #t

+

(match (list 1 2) ((1 2 3 ...) #t))
=> #t

+

(match (list 1 2 3) ((1 2 3 ...) #t))
=> #t

+

(match (list 1 2 3 3 3) ((1 2 3 ...) #t))
=> #t

Pattern variables matched inside the repeated pattern are bound to a list of each matching instance in the body.

(match (list 1 2) ((a b c ...) c))
=> ()

@@ -96,7 +96,7 @@ bind x to the entire value that matches pat (c.f. "as-patterns" in ML or Haskell). Another common use is in conjunction with not patterns to match a general case with certain exceptions. -

(match 1 ((and) #))
=> #t

+

(match 1 ((and) #t))
=> #t

(match 1 ((and x) x))
=> 1

(match 1 ((and x 1) x))
=> 1

The or operator ensures that at least one subpattern @@ -104,12 +104,12 @@ matches. If the same identifier occurs in different subpatterns, it is matched independently. All identifiers from all subpatterns are bound if the or operator matches, but the binding is only defined for identifiers from the subpattern which matched. -

(match 1 ((or) #) (else #))
=> #f

+

(match 1 ((or) #t) (else #f))
=> #f

(match 1 ((or x) x))
=> 1

(match 1 ((or x 2) x))
=> 1

The not operator succeeds if the given pattern doesn't match. None of the identifiers used are available in the body. -

(match 1 ((not 2) #))
=> #t

+

(match 1 ((not 2) #t))
=> #t

The more general operator ? can be used to provide a predicate. The usage is (? predicate pat ...) where predicate is a Scheme expression evaluating to a predicate diff --git a/lib/srfi/69/hash.c b/lib/srfi/69/hash.c index 42d1e864..7f39eb14 100644 --- a/lib/srfi/69/hash.c +++ b/lib/srfi/69/hash.c @@ -117,6 +117,8 @@ static sexp sexp_get_bucket (sexp ctx, sexp buckets, sexp hash_fn, sexp obj) { args = sexp_eval_string(ctx, "(current-error-port)", -1, sexp_context_env(ctx)); sexp_print_exception(ctx, res, args); res = sexp_make_fixnum(0); + } else if (sexp_unbox_fixnum(res) >= len) { + res = SEXP_ZERO; } sexp_gc_release1(ctx); } diff --git a/lib/srfi/69/interface.scm b/lib/srfi/69/interface.scm index edd752f1..bc7501c0 100644 --- a/lib/srfi/69/interface.scm +++ b/lib/srfi/69/interface.scm @@ -112,4 +112,3 @@ (let ((res (make-hash-table (hash-table-equivalence-function table)))) (hash-table-merge! res table) res)) - diff --git a/vm.c b/vm.c index aad431ef..fff0415a 100644 --- a/vm.c +++ b/vm.c @@ -616,10 +616,9 @@ static int sexp_check_type(sexp ctx, sexp a, sexp b) { #include "opt/fcall.c" #endif -sexp sexp_vm (sexp ctx, sexp proc) { - sexp bc = sexp_procedure_code(proc), cp = sexp_procedure_vars(proc); - sexp *stack = sexp_stack_data(sexp_context_stack(ctx)); - unsigned char *ip = sexp_bytecode_data(bc); +sexp sexp_vm (sexp ctx, sexp proc, sexp args) { + unsigned char *ip; + sexp bc, cp, *stack = sexp_stack_data(sexp_context_stack(ctx)); sexp_sint_t i, j, k, fp, top = sexp_stack_top(sexp_context_stack(ctx)); #if SEXP_USE_GREEN_THREADS sexp root_thread = ctx; @@ -631,7 +630,12 @@ sexp sexp_vm (sexp ctx, sexp proc) { sexp_gc_var3(self, tmp1, tmp2); sexp_gc_preserve3(ctx, self, tmp1, tmp2); fp = top - 4; - self = proc; + self = sexp_global(ctx, SEXP_G_FINAL_RESUMER); + bc = sexp_procedure_code(self); + cp = sexp_procedure_vars(self); + ip = sexp_bytecode_data(bc); + tmp1 = proc, tmp2 = args; + goto apply1; loop: #if SEXP_USE_GREEN_THREADS @@ -727,8 +731,10 @@ sexp sexp_vm (sexp ctx, sexp proc) { case SEXP_OP_APPLY1: tmp1 = _ARG1; tmp2 = _ARG2; + top -= 2; + apply1: i = sexp_unbox_fixnum(sexp_length(ctx, tmp2)); - top += (i-2); + top += i; for ( ; sexp_pairp(tmp2); tmp2=sexp_cdr(tmp2), top--) _ARG1 = sexp_car(tmp2); top += i+1; @@ -1593,26 +1599,16 @@ sexp sexp_apply1 (sexp ctx, sexp f, sexp x) { } sexp sexp_apply (sexp ctx, sexp proc, sexp args) { - sexp res, ls, *stack = sexp_stack_data(sexp_context_stack(ctx)); - sexp_sint_t top = sexp_context_top(ctx), len, offset; + sexp res; sexp_gc_var1(tmp); sexp_gc_preserve1(ctx, tmp); - len = sexp_unbox_fixnum(sexp_length(ctx, args)); if (sexp_opcodep(proc)) - proc = tmp = make_opcode_procedure(ctx, proc, len); + proc = tmp = make_opcode_procedure(ctx, proc, sexp_unbox_fixnum(sexp_length(ctx, args))); if (! sexp_procedurep(proc)) { res = sexp_exceptionp(proc) ? proc : sexp_type_exception(ctx, NULL, SEXP_PROCEDURE, proc); } else { - offset = top + len; - for (ls=args; sexp_pairp(ls); ls=sexp_cdr(ls), top++) - stack[--offset] = sexp_car(ls); - stack[top++] = sexp_make_fixnum(len); - stack[top++] = SEXP_ZERO; - stack[top++] = sexp_global(ctx, SEXP_G_FINAL_RESUMER); - stack[top++] = SEXP_ZERO; - sexp_context_top(ctx) = top; - res = sexp_vm(ctx, proc); + res = sexp_vm(ctx, proc, args); if (! res) res = SEXP_VOID; /* shouldn't happen */ } sexp_gc_release1(ctx);