Reputation: 10386
I have a need to partially expand scheme code without completely evaluated. I'd like a function that takes something like this:
'(let [(my-number 8)
(my-function (lambda args 'value))]
(cond
((> my-number 10) (my-function 'x 'y 'z))
((= my-number 10) (my-function 'a 'b 'c))
(else my-number)))
and turns it into this:
'(cond
((> 8 10) 'value)
((= 8 10) 'value)
(else 8))
In other words, I want something that expands definitions, lets, letrecs, etc. without doing any dangerous evaluation. I plan to do some static analysis on some varied scheme code, and it would be nice if all the code is in a relatively normalized form. I'd like to do as much expansion as possible without risking any I/O.
What this entails is basically writing a scheme evaluator. I'd rather not. Is there any scheme functions that help me do this out of the box?
I should clarify that I don't have control over the input. I'm given the input as-is and I've got to analyze it; I'd prefer to normalize it before doing my analysis. That's what I'm trying to achieve here. It's not possible for me to re-write the input by hand to make life easier.
I'm using racket, but unfortunately my code has to run with #lang scheme
.
Upvotes: 3
Views: 234
Reputation: 236122
Perhaps expand
is what you're looking for? It will not produce an output as the one in the question, but it will:
Expand all non-primitive syntax in top-level-form, and return a syntax object for the expanded form that contains only core forms, matching the grammar specified by Fully Expanded Programs
Here's an usage example:
(define src
'(let [(my-number 8)
(my-function (lambda args 'value))]
(cond
((> my-number 10) (my-function 'x 'y 'z))
((= my-number 10) (my-function 'a 'b 'c))
(else my-number))))
(syntax->datum
(parameterize ([current-namespace (make-base-namespace)])
(expand (datum->syntax #f src))))
With this output:
(let-values (((my-number) '8) ((my-function) (lambda args 'value)))
(if (#%app > my-number '10)
(let-values () (#%app my-function 'x 'y 'z))
(if (#%app = my-number '10)
(let-values () (#%app my-function 'a 'b 'c))
(let-values () my-number))))
Notice that if we remove the syntax->datum
conversion, the value returned by expand
will be a syntax object, which could be more useful for performing the analysis you have in mind.
Upvotes: 1