aminya / AcuteML.jl

Acute Markup Language - HTML/XML in Julia
https://aminya.github.io/AcuteML.jl/dev
MIT License
6 stars 4 forks source link

How to write a template type? #161

Open singularitti opened 3 years ago

singularitti commented 3 years ago

I have several types, they have the same fieldnames, but different names & tags in an XML file, i.e.,

@aml struct R "PP_R"
    type::String, att"type"
    size::UInt, att"size"
    columns::UN{UInt}, att"columns"
    text::String, txt""
end

@aml struct Rab "PP_RAB"
    type::String, att"type"
    size::UInt, att"size"
    columns::UN{UInt}, att"columns"
    text::String, txt""
end

where the only differences between R & Rab are their name & tags. I want to define a template type DataSection so that the following code

@aml struct DataSection{T} "tag"
    type::String, att"type"
    size::UInt, att"size"
    columns::UN{UInt}, att"columns"
    text::String, txt""
end

@aml struct DataSection{:R} "PP_R"
    type::String, att"type"
    size::UInt, att"size"
    columns::UN{UInt}, att"columns"
    text::String, txt""
end

@aml struct DataSection{:Rab} "PP_RAB"
    type::String, att"type"
    size::UInt, att"size"
    columns::UN{UInt}, att"columns"
    text::String, txt""
end

is automatically generated.

I tried to write an @amltag macro but it doesn't work:

macro amltag(T, t)
    return quote
        @aml struct DataSection{$T} $$t
            type::String, att"type"
            size::UInt, att"size"
            columns::UN{UInt}, att"columns"
            text::String, txt""
        end
    end
end

julia> @macroexpand1 @amltag(:R, "PP_R")
quote
    #= REPL[67]:3 =#
    #= REPL[67]:3 =# @aml struct DataSection{:R} $ "PP_R"
            #= REPL[67]:4 =#
            (type::String, att"type")
            #= REPL[67]:5 =#
            (size::UInt, att"size")
            #= REPL[67]:6 =#
            (columns::UN{UInt}, att"columns")
            #= REPL[67]:7 =#
            (text::String, txt"")
        end
end

As you see, there is an extra $ before "PP_R". I don't know if it is Julia's parsing mechanism causes this. If I put $$t the next line, it reduces to "PP_R" immediately

macro amltag(T, t)
     return quote
         @aml struct DataSection{$T}
             $t
             type::String, att"type"
             size::UInt, att"size"
             columns::UN{UInt}, att"columns"
             text::String, txt""
         end
     end
end

julia> @macroexpand1 @amltag(:R, "PP_R")
quote
    #= REPL[5]:3 =#
    #= REPL[5]:3 =# @aml struct DataSection{:R}
            #= REPL[5]:4 =#
            "PP_R"
            #= REPL[5]:5 =#
            (type::String, att"type")
            #= REPL[5]:6 =#
            (size::UInt, att"size")
            #= REPL[5]:7 =#
            (columns::UN{UInt}, att"columns")
            #= REPL[5]:8 =#
            (text::String, txt"")
        end
end
aminya commented 3 years ago

That extra $ was fixable somehow. I have forgotten how to do that.

aminya commented 3 years ago

I think you can use this function to remove that extra $. This is a bug in Julia. I applied a similar workaround in CompileBot.jl

toplevel_string(expr::Expr) = Meta.parse(replace(string(expr), r"^begin([\s\S]*)end$"=>s"\1"))
singularitti commented 3 years ago

I think you can use this function to remove that extra $. This is a bug in Julia. I applied a similar workaround in CompileBot.jl

toplevel_string(expr::Expr) = Meta.parse(replace(string(expr), r"^begin([\s\S]*)end$"=>s"\1"))

This is really a temporary workaround, could you please report this bug to the julia team? I'm afraid I am not able to make it clear to them.

singularitti commented 3 years ago

Is it possible we move the XML tag (e.g., "PP_R") before struct? It solves the problem pretty fine:

julia> macro amltag(T, t)
            return quote
                @aml $t struct DataSection{$T}
                    type::String, att"type"
                    size::UInt, att"size"
                    columns::UN{UInt}, att"columns"
                    text::String, txt""
                end
            end
       end
@amltag (macro with 1 method)

julia> @macroexpand1 @amltag(:R, "PP_R")
quote
    #= REPL[3]:3 =#
    #= REPL[3]:3 =# @aml "PP_R" struct DataSection{:R}
            #= REPL[3]:5 =#
            (type::String, att"type")
            #= REPL[3]:6 =#
            (size::UInt, att"size")
            #= REPL[3]:7 =#
            (columns::UN{UInt}, att"columns")
            #= REPL[3]:8 =#
            (text::String, txt"")
        end
end

I know this is a breaking change, but can we leave it to AcuteML v1.0?

aminya commented 3 years ago

Yeah, this is a breaking change, but I am fine with it if it solves the issue.