red / REP

Red Enhancement Process
BSD 3-Clause "New" or "Revised" License
10 stars 4 forks source link

WISH: preprocessor to process the inside of literal maps #111

Open hiiamboris opened 2 years ago

hiiamboris commented 2 years ago

What do you expect this code to produce?

Red []

;; macro that evaluates ((double parens)) during preprocessing
;; kind of something that could imitate the construction syntax and even be more general
#macro [ahead paren! into [paren! end]] func [[manual] s e] [
    change/only s do as [] s/1/1
    s
]

probe b: [
    ((skip "it should work" 3))
    #(
        a ((next "123"))
        b [((next "234"))]
        c "345"
    )
]
probe head b/1

Turns out only 1 of 3 macros is expanded:

["should work" 
    #(
        a: ((next "123"))
        b: [((next "234"))]
        c: "345"
    )
]
"it should work"

The reason for that being that Parse does not define into map! operation - it only works on series. Which is understandable. But from the POV of code writer/reader, why should it matter if I write my macro inside a map body or outside of it? Why should this detail stop it from working?

It is possible to do all the work inside the macro: visit every key and value of the map and expand them. But then it will have to be done in every macro.

Thus I think that the preprocessor should be smart enough to visit maps on it's own. It can be a foreach loop, or it can convert maps to blocks, process, and convert back (which is way more flexible).

hiiamboris commented 2 years ago

Tried adding this but preprocessor is bugged:

#macro [map!] func [[manual] s e] [
    change s to map! expand-directives to [] s/1
    s
]

This works but only by reimplementing the macro and preprocessor's work in regard to it:

Red []

#macro [ahead paren! into [paren! end]] func [[manual] s e] [
    change/only s do as [] s/1/1
    s
]

#macro [map!] func [[manual] s e /local m p rule] [
    parse m: to [] s/1 rule: [
        any [
            ahead paren! p: change only into [paren! end] (do as [] p/1/1)
        |   ahead any-block! into rule
        |   skip
        ]
    ]
    change s to map! m 
    e
]

probe b: [
    ((skip "it should work" 3))
    #(
        a ((next "123"))
        b [((next "234"))]
        c "345"
    )
]
probe head b/1