102102
103103# Parse whole struct definition for the @concrete macro
104104function _concretize (expr)
105- expr isa Expr && expr. head == :struct || error ( " Invalid usage of @concrete " )
106-
105+ original_expr, expr = _find_struct_def (expr )
106+
107107 is_mutable = expr. args[1 ]
108108 struct_name, type_params, super = _parse_head (expr. args[2 ])
109109 line_tuples = _parse_line .(expr. args[3 ]. args)
@@ -121,6 +121,8 @@ function _concretize(expr)
121121 body = Expr (:block , lines... , constructor_expr)
122122 struct_expr = Expr (:struct , is_mutable, head, body)
123123
124+ struct_expr = _apply_original_expr (original_expr, struct_expr)
125+
124126 return struct_expr, struct_name, type_params
125127end
126128
@@ -239,5 +241,27 @@ function _parse_line(line::Symbol)
239241 return (:($ line:: $T ), T)
240242end
241243
244+ # find the struct def in case its encapsuled in other macros
245+ # returns full_original_expression, struct_definition_expr
246+ function _find_struct_def (expr; tl_expr = expr)
247+ if expr. head == :struct
248+ return tl_expr, expr
249+ elseif expr. head == :macrocall
250+ return _find_struct_def (expr. args[3 ]; tl_expr = tl_expr)
251+ end
252+ return nerror (" Invalid usage of @concrete." )
253+ end
254+
255+ # finds where the struct is defined in original_expr and plugs in struct_expr
256+ function _apply_original_expr (original_expr, struct_expr)
257+ if original_expr. head == :struct
258+ original_expr. args = struct_expr. args
259+ elseif original_expr. head == :macrocall
260+ original_expr. args[3 ] = _apply_original_expr (original_expr. args[3 ], struct_expr)
261+ else
262+ error (" Unsupported expression." )
263+ end
264+ return original_expr
265+ end
242266
243267end
0 commit comments