Fix macro expansion #9

Merged
alex-eg merged 3 commits from fix-macro-expansion into main 2025-09-29 14:56:51 +02:00
3 changed files with 55 additions and 7 deletions

4
.gitignore vendored
View File

@@ -1 +1,3 @@
*.o
*.o
sexc
sex-tests

View File

@@ -79,8 +79,35 @@
(cons (car module-public-forms)
pkulev commented 2025-09-29 14:29:26 +02:00 (Migrated from github.com)
Review
  "Walk the form recursively and expand all macros, until none is left."
```suggestion "Walk the form recursively and expand all macros, until none is left." ```
acc))))))
(define (semen-macro-expand form)
"Walk the form recursively and expand all macros, until none is left."
(semen-walk-form
form
(lambda (subform)
(if (sex-macro? subform)
(apply-macro subform)
subform))))
;;; TODO: for greater inspiration, see SBCL's walk.lisp
(define (semen-walk-form form walk-fn)
(if (atom? form) form
(let ((new-form (walk-fn form)))
(cond ((not (eq? form new-form))
(semen-walk-form new-form walk-fn))
(else (recons
new-form
(semen-walk-form (car new-form) walk-fn)
(semen-walk-form (cdr new-form) walk-fn)))))))
(define (recons old-cons new-car new-cdr)
(if (and (eq? new-car (car old-cons))
(eq? new-cdr (cdr old-cons)))
old-cons
(cons new-car new-cdr)))
(define (process-fn sex-fn acc)
(cons sex-fn acc))
(let ((expanded (semen-macro-expand sex-fn)))
(cons expanded acc)))
(define (process-struct sex-struct acc)
(cons sex-struct acc))

View File

@@ -23,12 +23,31 @@
(test '(pub fn float sum ((int a) (int b))) (sex-fn-prototype sum-fn))
(test '((return (cast float (+ a b)))) (sex-fn-body sum-fn))
(define sex-code
'((defmacro (sum-var name a b c)
`(var ,name ,(+ a b c)))
(let ((sex-code
'((defmacro (sum-var name a b c)
`(var ,name ,(+ a b c)))
(sum-var v 1 2 3)))
(sum-var v 1 2 3))))
(test '((var v 6)) (semen-process sex-code))
(test '((var v 6)) (semen-process sex-code)))
;;; Macro expansion
(test 'a (semen-walk-form 'a identity))
(test '(a b c) (semen-walk-form '(a b c) identity))
(test 'a (semen-macro-expand 'a))
(test '(a b c) (semen-macro-expand '(a b c)))
(let ((sex-code-macro
'((defmacro (x10 a)
`(* 10 ,a))
(fn void foo ((int a) (int b))
(return (+ a (x10 b)))))))
(test '((fn void foo ((int a) (int b))
(return (+ a (* 10 b)))))
(semen-process sex-code-macro)))
(test-end)