On 08/25/2012 10:53 AM, Ryan Culpepper wrote:
On 08/25/2012 12:19 PM, Neil Toronto wrote:
I've reordered these a bit:
number
string
bytes
character
regexp
In other words, "literal data". But did you check that the '#%datum'
macro associated with them has the standard meaning? If not, they could
expand into arbitrary expressions (possibly with side effects)!
A number can expand to an arbitrary expression? How?
And what do you mean by "the '#%datum' macro associated with them"?
Applied to them?
symbol
Do you mean identifier, as in "it's just a variable reference"? But it
could be an identifier macro. Or it could be a variable that other parts
of the code could concurrently mutate. For example, suppose 'match'
expanded less cautiously than it actually does:
(match x [(cons a b) a])
=>
(if (pair? x) (unsafe-car x) (match-error ....))
Now suppose that x is a module-level variable that some other thread
mutates between the 'pair?' check and the 'unsafe-car'.
Right. Typed Racket would actually catch these at compile time, but
mutation would still break my macros. *sigh*
If you must do such things, the safest way in general is to fully
local-expand the expression you want to analyze; that gives you
something with a known grammar. Now it's feasible to identify literal
data: it's any 'quote' expression. You don't have to worry about
identifier macros, but the 'set!' danger remains for any variables that
you don't completely control the scope of.
In your specific case, it would also be safe to check whether the
comparison expression is an identifier free-identifier=? to one of a
fixed list of known (immutable) variables; if so, it's safe to duplicate.
I think I'll have to go that route.
Thanks for the explanations!
Neil ⊥
_________________________
Racket Developers list:
http://lists.racket-lang.org/dev