Builtin case construct evaluation before macro expansion issue pasted by patham9 on Mon Oct 2 17:40:32 2023
(define-syntax CaseMettaHelper (syntax-rules (else) ((_ else bi) (list else bi)) ((_ ai bi) (list (list ai) bi)))) (define-syntax CaseMettaClean (syntax-rules (else) ((_ var ((a1 else))) (case var (else b1))) ((_ var ((a1 b1))) (case var ((a1) b1))) ((_ var ((ai bi) ...)) (list var (CaseMettaHelper ai bi) ...)))) ;^^^^ ;expected would have been to be able to use directly ;case instead of list here, but case is so greedy that ;CaseMettaHelper won't be evaluated before it complains about it. (define-syntax CaseMetta (syntax-rules (else) ((_ var cases) (eval (let ((x (CaseMettaClean var cases))) (append (list 'case) x)))))) ;forces to have the CaseMettaClean evaluated before filling in "case". (display (CaseMetta 3 ((1 2) (3 4)))) ;4
Fixed version pasted by wasamasa on Mon Oct 2 18:04:04 2023
(import (chicken base)) (define-syntax CaseMetta (syntax-rules (else) ((_ var ((pat body ...) ...)) (case var ((pat) body ...) ...)))) (let ((x 1)) (print (case x ((1) 2) ((3) 4))) (print (CaseMetta x ((1 2) (3 4)))))
Not the solution unfortunately pasted by patham9 on Mon Oct 2 18:26:07 2023
Your macro does not consider the else case. My initial one also did not: (define-syntax CaseMetta (syntax-rules () ((_ var ((a1 b1))) (case var ((a1) b1))) ((_ var ((a1 b1) ...)) (case var ((a1) b1) ...)))) The complexity growth came from me trying to address the else case! :)
Error comes when else is tried to be considered pasted by patham9 on Mon Oct 2 18:40:40 2023
(define-syntax CaseMettaHelper (syntax-rules (else) ((_ else bi) (list else bi)) ((_ ai bi) (list (list ai) bi)))) (define-syntax CaseMetta (syntax-rules (else) ((_ var ((pat body ...) ...)) (case var (CaseMettaHelper pat body ...) ...)))) (display (CaseMetta 3 ((1 2) (else 4)))) ;bad argument type - not a list: CaseMettaHelper356
With support for else, cribbed from R7RS-small pasted by wasamasa on Mon Oct 2 18:54:13 2023
(import (chicken base)) (define-syntax CaseMetta (syntax-rules (else) ((_ key ((else result1 result2 ...))) (begin result1 result2 ...)) ((_ key ((atom result1 result2 ...))) (if (eqv? key atom) (begin result1 result2 ...))) ((_ key ((atom result1 result2 ...) clause clauses ...)) (if (eqv? key atom) (begin result1 result2 ...) (CaseMetta key (clause clauses ...)))))) (let ((x 1) (y 5)) (print (case x ((1) 2) ((3) 4) (else 999))) (print (case y ((1) 2) ((3) 4) (else 999))) (print (CaseMetta x ((1 2) (3 4) (else 999)))) (print (CaseMetta y ((1 2) (3 4) (else 999)))))
Also my solution for completeness added by patham9 on Mon Oct 2 19:13:28 2023
(define-syntax CaseMettaMatch (syntax-rules (else) ((_ var ((pat body) ...)) (case var ((pat) body) ...)))) (define-syntax CaseMettaNoMatch (syntax-rules () ((_ var ((p body1) ... (elsemaybe elsebody))) (if (eq? 'elsemaybe 'else) 'elsebody)))) (define-syntax CaseMetta (syntax-rules () ((_ var cases) (let ((z (CaseMettaMatch var cases))) (if (eq? (if #f 1) z) (CaseMettaNoMatch var cases) z))))) (display (CaseMetta 343 ((1 2) (3 4) (5 6) (else 42) ))) ;42 (display (CaseMetta 343 ((1 2) (3 4) (5 6) (asdasd 42) ))) ;unspecified (display (CaseMetta 3 ((1 2) (3 4) (5 6) (asdasd 42) ))) ;4