Skip to content

Commit

Permalink
fix: pass arguments down to nested macro calls
Browse files Browse the repository at this point in the history
Fixes #2
  • Loading branch information
z80dev committed Nov 1, 2024
1 parent 2cd210d commit 0a8cf5d
Showing 1 changed file with 34 additions and 11 deletions.
45 changes: 34 additions & 11 deletions puff/phases/macros.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,59 @@

(define (is-macro-call code data)
(and (list? code)
(eq? 'fncall (car code))
(hash-has-key? data (cadr code))))
(eq? 'fncall (first code))
(hash-has-key? data (second code))))

(define (is-macro-arg code)
(and (list? code)
(eq? 'macro-arg (car code))))
(eq? 'macro-arg (first code))))

(define (fncall? code)
(and (list? code)
(eq? 'fncall (first code))))

;; iterate over every element in code
;; if its a '(macro-arg foo) then replace it with the value of foo
(define (insert-args-from-data code data)
(define (replace-arg element)
(if (is-macro-arg element)
(hash-ref data (second element))
element))
(map replace-arg code))

(define (insert-macroargs-to-fncall fncall data)
(list 'fncall (second fncall) (insert-args-from-data (third fncall) data)))

(define (insert-macro-args code data)
;; just calls self with rest of the code
(define (recurse)
(insert-macro-args (cdr code) data))
(insert-macro-args (rest code) data))

;; this leaves the first element unmodified and recurses
(define (continue code)
(cons (car code) (recurse)))
(cons (first code) (recurse)))

;; cons the value of the macro arg with the rest of the code
(define (handle-macro-arg code)
;; (cadar '((1 2 3) 4 5)) = 2, i.e. second element of first element in list
;; (cadar '((macro-arg foo))) = 'foo
(cons (hash-ref data (cadar code)) (recurse)))

(define (handle-fncall node)
(cons (insert-macroargs-to-fncall node data) (recurse)))

;; here we handle the base case, the macro-arg case, or continue
(cond
((empty? code) '())
((is-macro-arg (car code)) (handle-macro-arg code))
((fncall? (first code)) (handle-fncall (first code)))
((is-macro-arg (first code)) (handle-macro-arg code))
(else (continue code))))

(define (get-macro-body code data)
(let* ([name (cadr code)]
[args (caddr code)]
(let* ([name (second code)]
[args (third code)]
[macrodef (hash-ref data name)]
[argsdef (car macrodef)]
[argsdef (first macrodef)]
[argsmap (make-hash)])
(for ([k (rest argsdef)]
[v (rest args)])
Expand All @@ -54,11 +74,14 @@
(if (empty? code)
code
; For non-empty code, analyze the first element
(let ([first-element (car code)]
[rest-code (cdr code)])
(let ([first-element (first code)]
[rest-code (rest code)])

(if (is-macro-call first-element data)
; If it's a macro call, expand it and continue processing
;; NOTE: Figure out how to properly pass args to nested macros
;; right now they're ending up with the wrong values
;; if the arg itself is a macro-arg, we need to trickle that down somehow
(let ([expanded-code (process-macro-element first-element rest-code data)])
;; recursive call with expanded code
(insert-macro expanded-code data))
Expand Down

0 comments on commit 0a8cf5d

Please sign in to comment.