From 322a357e05d858ef7e2bc988dd9a5c1fe64c44e9 Mon Sep 17 00:00:00 2001 From: alex-eg Date: Fri, 26 Sep 2025 11:53:10 +0300 Subject: [PATCH 1/3] add binaries to .gitignore --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 1530978..b53963d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ -*.o \ No newline at end of file +*.o +sexc +sex-tests -- 2.52.0 From 9833e12777687a98e071a3d66503b6849c7dcfad Mon Sep 17 00:00:00 2001 From: alex-eg Date: Fri, 26 Sep 2025 14:33:23 +0300 Subject: [PATCH 2/3] implement semantic code walking framework --- semen.scm | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/semen.scm b/semen.scm index 92e3919..2462819 100644 --- a/semen.scm +++ b/semen.scm @@ -79,6 +79,23 @@ (cons (car module-public-forms) acc)))))) +;;; 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)) -- 2.52.0 From b80b7c960ed49afa06a78f75945d72a62b6126f8 Mon Sep 17 00:00:00 2001 From: alex-eg Date: Fri, 26 Sep 2025 14:33:47 +0300 Subject: [PATCH 3/3] re-implement macro-expansion using new semantic walker --- semen.scm | 12 +++++++++++- tests/semen.scm | 29 ++++++++++++++++++++++++----- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/semen.scm b/semen.scm index 2462819..afdff0f 100644 --- a/semen.scm +++ b/semen.scm @@ -79,6 +79,15 @@ (cons (car module-public-forms) 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 @@ -97,7 +106,8 @@ (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)) diff --git a/tests/semen.scm b/tests/semen.scm index 63e88a7..b29f6a5 100644 --- a/tests/semen.scm +++ b/tests/semen.scm @@ -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) -- 2.52.0