Skip to content

Commit

Permalink
Documentation binding for structs + test const/atomic struct fields
Browse files Browse the repository at this point in the history
  • Loading branch information
c42f committed Oct 7, 2024
1 parent 3d1e887 commit 90d1b2a
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 5 deletions.
21 changes: 20 additions & 1 deletion src/desugaring.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1611,8 +1611,8 @@ function _collect_struct_fields(ctx, field_names, field_types, field_attrs, fiel
m = _match_struct_field(e)
if !isnothing(m)
# Struct field
n = length(field_names)
push!(field_names, @ast ctx m.name m.name=>K"Symbol")
n = length(field_names)
push!(field_types, isnothing(m.type) ? @ast(ctx, e, "Any"::K"core") : m.type)
if m.atomic
push!(field_attrs, @ast ctx e n::K"Integer")
Expand Down Expand Up @@ -1733,6 +1733,25 @@ function expand_struct_def(ctx, ex, docs)
]
]
]
# Inner constructors
# TODO
# [K"scope_block"(scope_type=:hard)
# [K"block"
# [K"global" struct_name]
# ]
# ]
if !isnothing(docs) || !isempty(field_docs)
[K"call"(isnothing(docs) ? ex : docs)
bind_docs!::K"Value"
struct_name
isnothing(docs) ? nothing_(ctx, ex) : docs[1]
QuoteNode(source_location(LineNumberNode, ex))::K"Value"
[K"="
"field_docs"::K"Identifier"
[K"call" "svec"::K"core" field_docs...]
]
]
end
nothing_(ctx, ex)
]
end
Expand Down
29 changes: 25 additions & 4 deletions src/runtime.jl
Original file line number Diff line number Diff line change
Expand Up @@ -170,17 +170,38 @@ function bind_docs!(f::Function, docstr, method_metadata)
bind = Base.Docs.Binding(mod, nameof(f))
full_sig = method_metadata[1]
arg_sig = Tuple{full_sig[2:end]...}
linenum = method_metadata[3]
lineno = method_metadata[3]
metadata = Dict{Symbol, Any}(
:linenumber => linenum.line,
:linenumber => lineno.line,
:module => mod,
)
if !isnothing(linenum.file)
push!(metadata, :path => string(linenum.file))
if !isnothing(lineno.file)
push!(metadata, :path => string(lineno.file))
end
Docs.doc!(mod, bind, Base.Docs.docstr(docstr, metadata), arg_sig)
end

function bind_docs!(type::Type, docstr, lineno; field_docs=Core.svec())
mod = parentmodule(type)
bind = Base.Docs.Binding(mod, nameof(type))
metadata = Dict{Symbol, Any}(
:linenumber => lineno,
:module => mod,
)
if !isnothing(lineno.file)
push!(metadata, :path => string(lineno.file))
end
if !isempty(field_docs)
fd = Dict{Symbol, Any}()
fns = fieldnames(type)
for i = 1:2:length(field_docs)
fd[fns[field_docs[i]]] = field_docs[i+1]
end
metadata[:fields] = fd
end
Docs.doc!(mod, bind, Base.Docs.docstr(docstr, metadata), Union{})
end

#-------------------------------------------------------------------------------
# The following functions are used by lowering to inspect Julia's state.

Expand Down
80 changes: 80 additions & 0 deletions test/typedefs_ir.jl
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,86 @@ end
41 (call core._typebody! %₃₉ %₄₀)
42 (return core.nothing)

########################################
# Struct with const and atomic fields
struct X
const a
@atomic b
const @atomic c
end
#---------------------
1 (global TestMod.X)
2 (const TestMod.X)
3 (call core.svec)
4 (call core.svec :a :b :c)
5 (call core.svec 1 :const 2 :atomic 3 :atomic 3 :const)
6 (call core._structtype TestMod :X %%%false 3)
7 (= slot₁/X %₆)
8 (call core._setsuper! %₆ core.Any)
9 (isdefined TestMod.X)
10 (gotoifnot %₉ label₂₀)
11 TestMod.X
12 (call core._equiv_typedef %₁₁ %₆)
13 (gotoifnot %₁₂ label₁₇)
14 TestMod.X
15 (= slot₁/X %₁₄)
16 (goto label₁₉)
17 slot₁/X
18 (= TestMod.X %₁₇)
19 (goto label₂₂)
20 slot₁/X
21 (= TestMod.X %₂₀)
22 slot₁/X
23 (call core.svec core.Any core.Any core.Any)
24 (call core._typebody! %₂₂ %₂₃)
25 (return core.nothing)

########################################
# Documented struct
"""
X docs
"""
struct X
"field a docs"
a
"field b docs"
b
end
#---------------------
1 (global TestMod.X)
2 (const TestMod.X)
3 (call core.svec)
4 (call core.svec :a :b)
5 (call core.svec)
6 (call core._structtype TestMod :X %%%false 2)
7 (= slot₁/X %₆)
8 (call core._setsuper! %₆ core.Any)
9 (isdefined TestMod.X)
10 (gotoifnot %₉ label₂₀)
11 TestMod.X
12 (call core._equiv_typedef %₁₁ %₆)
13 (gotoifnot %₁₂ label₁₇)
14 TestMod.X
15 (= slot₁/X %₁₄)
16 (goto label₁₉)
17 slot₁/X
18 (= TestMod.X %₁₇)
19 (goto label₂₂)
20 slot₁/X
21 (= TestMod.X %₂₀)
22 slot₁/X
23 (call core.svec core.Any core.Any)
24 (call core._typebody! %₂₂ %₂₃)
25 JuliaLowering.bind_docs!
26 (call core.tuple :field_docs)
27 (call core.apply_type core.NamedTuple %₂₆)
28 (call core.svec 1 "field a docs" 2 "field b docs")
29 (call core.tuple %₂₈)
30 (call %₂₇ %₂₉)
31 TestMod.X
32 (call core.kwcall %₃₀ %₂₅ %₃₁ "X docs\n" :($(QuoteNode(:(#= line 4 =#)))))
33 (return core.nothing)

########################################
# Error: Struct not at top level
function f()
Expand Down

0 comments on commit 90d1b2a

Please sign in to comment.