From 578a46ac53d7bc9365091d81d77bfbe139ab4333 Mon Sep 17 00:00:00 2001 From: serenity4 Date: Sun, 27 Jun 2021 18:46:50 +0200 Subject: [PATCH 1/3] Generate constructors for union and struct records --- src/generator/codegen.jl | 69 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/src/generator/codegen.jl b/src/generator/codegen.jl index 11b96b30..d46e89d7 100644 --- a/src/generator/codegen.jl +++ b/src/generator/codegen.jl @@ -320,6 +320,73 @@ function emit_setproperty!(dag, node, options) return dag end +function get_names_types(root_cursor, cursor, options) + field_cursors = fields(getCursorType(cursor)) + field_cursors = isempty(field_cursors) ? children(cursor) : field_cursors + tys = [] + fsyms = [] + for field_cursor in field_cursors + n = name(field_cursor) + if isempty(n) + _emit_getproperty_ptr!(root_cursor, field_cursor, options) + continue + end + fsym = make_symbol_safe(n) + fty = getCursorType(field_cursor) + ty = translate(tojulia(fty), options) + push!(tys, ty) + push!(fsyms, fsym) + end + fsyms, tys +end + +function emit_constructor!(dag, node::ExprNode{<:AbstractUnionNodeType}, options) + sym = make_symbol_safe(node.id) + fsyms, tys = get_names_types(node.cursor, node.cursor, options) + union_sym = Symbol(:__U_, sym) + push!(node.exprs, :(const $union_sym = Union{$(tys...)})) + body = Expr(:block, + :(ref = Ref{$sym}()), + :(ptr = Base.unsafe_convert(Ptr{$sym}, ref)), + ) + + branch_args = map(zip(fsyms, tys)) do (fsym, ty) + cond = :(val isa $ty) + assign = :(ptr.$fsym = val) + (cond, assign) + end + + first_args, rest = Iterators.peel(branch_args) + ex = Expr(:if, first_args...) + push!(body.args, ex) + foreach(rest) do (cond, assign) + _ex = Expr(:elseif, cond, assign) + push!(ex.args, _ex) + ex = _ex + end + + push!(body.args, :(ref[])) + + push!(node.exprs, Expr(:function, Expr(:call, sym, :(val::$union_sym)), body)) +end + +function emit_constructor!(dag, node::ExprNode{<:StructLayout}, options) + sym = make_symbol_safe(node.id) + fsyms, tys = get_names_types(node.cursor, node.cursor, options) + body = quote + ref = Ref{$sym}() + ptr = Base.unsafe_convert(Ptr{$sym}, ref) + $((:(ptr.$fsym = $fsym) for fsym in fsyms)...) + ref[] + end + + rm_line_num_node!(body) + + push!(body.args, ) + func = Expr(:function, Expr(:call, sym, (:($fsym::$ty) for (fsym, ty) in zip(fsyms, tys))...), body) + push!(node.exprs, func) +end + function emit!(dag::ExprDAG, node::ExprNode{<:AbstractStructNodeType}, options::Dict; args...) struct_sym = make_symbol_safe(node.id) block = Expr(:block) @@ -435,6 +502,8 @@ function emit!(dag::ExprDAG, node::ExprNode{<:RecordLayouts}, options::Dict; arg emit_getproperty!(dag, node, options) emit_setproperty!(dag, node, options) + emit_constructor!(dag, node, options) + return dag end From 1f32f5d7d757afa963b50be8a06c2a629f18f335 Mon Sep 17 00:00:00 2001 From: serenity4 Date: Mon, 28 Jun 2021 12:19:37 +0200 Subject: [PATCH 2/3] Remove typo --- src/generator/codegen.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/generator/codegen.jl b/src/generator/codegen.jl index d46e89d7..5962aecf 100644 --- a/src/generator/codegen.jl +++ b/src/generator/codegen.jl @@ -382,7 +382,6 @@ function emit_constructor!(dag, node::ExprNode{<:StructLayout}, options) rm_line_num_node!(body) - push!(body.args, ) func = Expr(:function, Expr(:call, sym, (:($fsym::$ty) for (fsym, ty) in zip(fsyms, tys))...), body) push!(node.exprs, func) end From 9582b91eb585d93b95e44c83a5a536b17b45befd Mon Sep 17 00:00:00 2001 From: serenity4 Date: Mon, 28 Jun 2021 18:29:37 +0200 Subject: [PATCH 3/3] Add more codegen options --- src/generator/codegen.jl | 50 ++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/src/generator/codegen.jl b/src/generator/codegen.jl index 5962aecf..3ee732cf 100644 --- a/src/generator/codegen.jl +++ b/src/generator/codegen.jl @@ -350,24 +350,37 @@ function emit_constructor!(dag, node::ExprNode{<:AbstractUnionNodeType}, options :(ptr = Base.unsafe_convert(Ptr{$sym}, ref)), ) - branch_args = map(zip(fsyms, tys)) do (fsym, ty) - cond = :(val isa $ty) - assign = :(ptr.$fsym = val) - (cond, assign) - end - - first_args, rest = Iterators.peel(branch_args) - ex = Expr(:if, first_args...) - push!(body.args, ex) - foreach(rest) do (cond, assign) - _ex = Expr(:elseif, cond, assign) - push!(ex.args, _ex) - ex = _ex - end + if get(options, "union_single_constructor", false) + branch_args = map(zip(fsyms, tys)) do (fsym, ty) + cond = :(val isa $ty) + assign = :(ptr.$fsym = val) + (cond, assign) + end - push!(body.args, :(ref[])) + first_args, rest = Iterators.peel(branch_args) + ex = Expr(:if, first_args...) + push!(body.args, ex) + foreach(rest) do (cond, assign) + _ex = Expr(:elseif, cond, assign) + push!(ex.args, _ex) + ex = _ex + end - push!(node.exprs, Expr(:function, Expr(:call, sym, :(val::$union_sym)), body)) + push!(body.args, :(ref[])) + push!(node.exprs, Expr(:function, Expr(:call, sym, :(val::$union_sym)), body)) + else + foreach(zip(fsyms, tys)) do (fsym, ty) + _body = copy(body) + append!(_body.args, + [ + :(ptr.$fsym = $fsym), + :(ref[]), + ] + ) + func = Expr(:function, :($sym($fsym::$ty)), _body) + push!(node.exprs, func) + end + end end function emit_constructor!(dag, node::ExprNode{<:StructLayout}, options) @@ -501,7 +514,10 @@ function emit!(dag::ExprDAG, node::ExprNode{<:RecordLayouts}, options::Dict; arg emit_getproperty!(dag, node, options) emit_setproperty!(dag, node, options) - emit_constructor!(dag, node, options) + opt = get(options, "add_record_constructors", []) + if (opt isa Bool && opt) || sym in opt + emit_constructor!(dag, node, options) + end return dag end