diff --git a/JuliaLowering/src/ast.jl b/JuliaLowering/src/ast.jl index 3f5533f8b773a..4588517906b88 100644 --- a/JuliaLowering/src/ast.jl +++ b/JuliaLowering/src/ast.jl @@ -126,48 +126,53 @@ function _append_nodeids!(graph::SyntaxGraph, ids::Vector{NodeId}, vals::SyntaxL append!(ids, vals.ids) end -function makeleaf(graph::SyntaxGraph, srcref, proto; attrs...) +# TODO: "proto", if SyntaxTree, is rarely different from srcref. reorganize to: +# newnode/newleaf(ctx, srcref, k::Kind[, attrs]) +# makenode/makeleaf(ctx, old::SyntaxTree[, attrs]) + +function makeleaf(graph::SyntaxGraph, srcref, proto::Union{Kind, SyntaxTree}) id = newnode!(graph) ex = SyntaxTree(graph, id) copy_attrs!(ex, proto, true) - setattr!(graph, id; source=_unpack_srcref(graph, srcref), attrs...) + ex.source = _unpack_srcref(graph, srcref) return ex end -function _makenode(graph::SyntaxGraph, srcref, proto, children; attrs...) - id = newnode!(graph) - setchildren!(graph, id, children) - ex = SyntaxTree(graph, id) - copy_attrs!(ex, proto, true) - setattr!(graph, id; source=_unpack_srcref(graph, srcref), attrs...) - return SyntaxTree(graph, id) -end -function _makenode(ctx, srcref, proto, children; attrs...) - _makenode(syntax_graph(ctx), srcref, proto, children; attrs...) +function makeleaf(ctx::AbstractLoweringContext, srcref, proto) + makeleaf(syntax_graph(ctx), srcref, proto) end -function makenode(ctx, srcref, proto, children...; attrs...) - _makenode(ctx, srcref, proto, _node_ids(syntax_graph(ctx), children...); attrs...) +function makeleaf(ctx, srcref, proto, @nospecialize(attrs::AbstractVector)) + graph = syntax_graph(ctx) + ex = makeleaf(graph, srcref, proto) + for (k, v) in attrs + setattr!(graph, ex._id, k, v) + end + return ex end -function makeleaf(ctx, srcref, proto; kws...) - makeleaf(syntax_graph(ctx), srcref, proto; kws...) +function makenode(ctx, srcref, proto, children, attrs=nothing) + graph = syntax_graph(ctx) + ex = isnothing(attrs) ? makeleaf(graph, srcref, proto) : + makeleaf(graph, srcref, proto, attrs) + setchildren!(graph, ex._id, children isa SyntaxList ? children.ids : children) + return ex end -function makeleaf(ctx, srcref, k::Kind, value; kws...) - graph = syntax_graph(ctx) +function newleaf(ctx, srcref, k::Kind, @nospecialize(value)) + leaf = makeleaf(ctx, srcref, k) if k == K"Identifier" || k == K"core" || k == K"top" || k == K"Symbol" || k == K"globalref" || k == K"Placeholder" || k == K"StrMacroName" || k == K"CmdMacroName" - makeleaf(graph, srcref, k; name_val=value, kws...) + setattr!(leaf._graph, leaf._id, :name_val, value) elseif k == K"BindingId" - makeleaf(graph, srcref, k; var_id=value, kws...) + setattr!(leaf._graph, leaf._id, :var_id, value) elseif k == K"label" - makeleaf(graph, srcref, k; id=value, kws...) + setattr!(leaf._graph, leaf._id, :id, value) elseif k == K"symbolic_label" - makeleaf(graph, srcref, k; name_val=value, kws...) + setattr!(leaf._graph, leaf._id, :name_val, value) elseif k in KSet"TOMBSTONE SourceLocation latestworld latestworld_if_toplevel" - makeleaf(graph, srcref, k; kws...) + # no attributes else val = k == K"Integer" ? convert(Int, value) : k == K"Float" ? convert(Float64, value) : @@ -177,8 +182,9 @@ function makeleaf(ctx, srcref, k::Kind, value; kws...) k == K"Bool" ? value : k == K"VERSION" ? value : error("Unexpected leaf kind `$k`") - makeleaf(graph, srcref, k; value=val, kws...) + setattr!(leaf._graph, leaf._id, :value, val) end + leaf end # TODO: Replace this with makeleaf variant? @@ -192,7 +198,7 @@ end # Convenience functions to create leaf nodes referring to identifiers within # the Core and Top modules. -core_ref(ctx, ex, name) = makeleaf(ctx, ex, K"core", name) +core_ref(ctx, ex, name) = newleaf(ctx, ex, K"core", name) svec_type(ctx, ex) = core_ref(ctx, ex, "svec") nothing_(ctx, ex) = core_ref(ctx, ex, "nothing") @@ -202,7 +208,7 @@ top_ref(ctx, ex, name) = makeleaf(ctx, ex, K"top", name) # Return (variable, assignment_node) function assign_tmp(ctx::AbstractLoweringContext, ex, name="tmp") var = ssavar(ctx, ex, name) - assign_var = makenode(ctx, ex, K"=", var, ex) + assign_var = makenode(ctx, ex, K"=", NodeId[var._id, ex._id]) var, assign_var end @@ -211,7 +217,7 @@ function emit_assign_tmp(stmts::SyntaxList, ctx, ex, name="tmp") return ex end var = ssavar(ctx, ex, name) - push!(stmts, makenode(ctx, ex, K"=", var, ex)) + push!(stmts, makenode(ctx, ex, K"=", NodeId[var._id, ex._id])) var end @@ -225,31 +231,38 @@ function _match_srcref(ex) end end -function _match_kind(f::Function, srcref, ex) +function _kw_to_pair(ex) + if ex isa Expr && ex.head === :kw && ex.args[1] isa Symbol + (QuoteNode(ex.args[1]), esc(ex.args[2])) + elseif ex isa Symbol + (QuoteNode(ex), esc(ex)) + else + @assert false "invalid keyword form in @ast $ex" + end +end + +function _match_kind(srcref, ex) kws = [] if Meta.isexpr(ex, :call) kind = esc(ex.args[1]) args = ex.args[2:end] if Meta.isexpr(args[1], :parameters) - kws = map(esc, args[1].args) + kws = map(_kw_to_pair, args[1].args) popfirst!(args) end while length(args) >= 1 && Meta.isexpr(args[end], :kw) - pushfirst!(kws, esc(pop!(args))) + pushfirst!(kws, _kw_to_pair(pop!(args))) end if length(args) == 1 srcref_tmp = gensym("srcref") - return quote - $srcref_tmp = $(_match_srcref(args[1])) - $(f(kind, srcref_tmp, kws)) - end + return (kind, _match_srcref(args[1]), kws) elseif length(args) > 1 error("Unexpected: extra srcref argument in `$ex`?") end else kind = esc(ex) end - f(kind, srcref, kws) + return (kind, srcref, kws) end function _expand_ast_tree(ctx, srcref, tree) @@ -262,8 +275,12 @@ function _expand_ast_tree(ctx, srcref, tree) val = nothing kindspec = tree.args[1] end - _match_kind(srcref, kindspec) do kind, srcref, kws - :(makeleaf($ctx, $srcref, $kind, $(val), $(kws...))) + let (kind, srcref, kws) = _match_kind(srcref, kindspec) + n = :(newleaf($ctx, $srcref, $kind, $val)) + for (attr, val) in kws + n = :(setattr!($n, $attr, $val)) + end + n end elseif Meta.isexpr(tree, :call) && tree.args[1] === :(=>) # Leaf node with copied attributes @@ -292,8 +309,12 @@ function _expand_ast_tree(ctx, srcref, tree) end end push!(child_stmts, :(child_ids)) - _match_kind(srcref, flatargs[1]) do kind, srcref, kws - :(_makenode($ctx, $srcref, $kind, $children_ex; $(kws...))) + let (kind, srcref, kws) = _match_kind(srcref, flatargs[1]) + n = :(makenode($ctx, $srcref, $kind, $children_ex)) + for (attr, val) in kws + n = :(setattr!($n, $attr, $val)) + end + n end elseif Meta.isexpr(tree, :(:=)) lhs = tree.args[1] @@ -389,17 +410,17 @@ end function copy_attrs!(dest, head::Union{Kind,JuliaSyntax.SyntaxHead}, all=false) if all - sethead!(dest._graph, dest._id, head) + setattr!(dest._graph, dest._id, :kind, kind(head)) + !(head isa Kind) && setattr!(dest._graph, dest._id, :syntax_flags, flags(head)) end end -function mapchildren(f::Function, ctx, ex::SyntaxTree, do_map_child::Function; - extra_attrs...) +function mapchildren(f::Function, ctx, ex::SyntaxTree, do_map_child::Function) if is_leaf(ex) return ex end orig_children = children(ex) - cs = isempty(extra_attrs) ? nothing : SyntaxList(ctx) + cs = nothing for (i,e) in enumerate(orig_children) newchild = do_map_child(i) ? f(e) : e if isnothing(cs) @@ -418,14 +439,12 @@ function mapchildren(f::Function, ctx, ex::SyntaxTree, do_map_child::Function; return ex end cs::SyntaxList - ex2 = makenode(ctx, ex, head(ex), cs) - copy_attrs!(ex2, ex) - setattr!(ex2; extra_attrs...) + ex2 = makenode(ctx, ex, ex, cs) return ex2 end -function mapchildren(f::Function, ctx, ex::SyntaxTree, mapped_children::AbstractVector{<:Integer}; - extra_attrs...) +function mapchildren(f::Function, ctx, ex::SyntaxTree, + mapped_children::AbstractVector{<:Integer}) j = Ref(firstindex(mapped_children)) function do_map_child(i) ind = j[] @@ -436,11 +455,11 @@ function mapchildren(f::Function, ctx, ex::SyntaxTree, mapped_children::Abstract false end end - mapchildren(f, ctx, ex, do_map_child; extra_attrs...) + mapchildren(f, ctx, ex, do_map_child) end -function mapchildren(f::Function, ctx, ex::SyntaxTree; extra_attrs...) - mapchildren(f, ctx, ex, i->true; extra_attrs...) +function mapchildren(f::Function, ctx, ex::SyntaxTree) + mapchildren(f, ctx, ex, i->true) end @@ -477,7 +496,7 @@ function _copy_ast(graph2::SyntaxGraph, graph1::SyntaxGraph, src1 end copy_attrs!(SyntaxTree(graph2, id2), SyntaxTree(graph1, id1), true) - setattr!(graph2, id2; source=src2) + setattr!(graph2, id2, :source, src2) if !is_leaf(graph1, id1) cs = NodeId[] for cid in children(graph1, id1) @@ -491,20 +510,19 @@ end #------------------------------------------------------------------------------- function set_scope_layer(ctx, ex, layer_id, force) k = kind(ex) - scope_layer = force ? layer_id : get(ex, :scope_layer, layer_id) - if k == K"module" || k == K"toplevel" || k == K"inert" - makenode(ctx, ex, ex, children(ex); - scope_layer=scope_layer) + new_layer = force ? layer_id : get(ex, :scope_layer, layer_id) + + ex2 = if k == K"module" || k == K"toplevel" || k == K"inert" + makenode(ctx, ex, ex, children(ex)) elseif k == K"." - makenode(ctx, ex, ex, set_scope_layer(ctx, ex[1], layer_id, force), ex[2], - scope_layer=scope_layer) + children = NodeId[set_scope_layer(ctx, ex[1], layer_id, force), ex[2]] + makenode(ctx, ex, ex, children) elseif !is_leaf(ex) - mapchildren(e->set_scope_layer(ctx, e, layer_id, force), ctx, ex; - scope_layer=scope_layer) + mapchildren(e->set_scope_layer(ctx, e, layer_id, force), ctx, ex) else - makeleaf(ctx, ex, ex; - scope_layer=scope_layer) + makeleaf(ctx, ex, ex) end + setattr!(ex2, :scope_layer, new_layer) end """ @@ -513,7 +531,7 @@ end Copy `ex`, adopting the scope layer of `ref`. """ function adopt_scope(ex::SyntaxTree, scope_layer::LayerId) - set_scope_layer(ex, ex, scope_layer, true) + set_scope_layer(ex._graph, ex, scope_layer, true) end function adopt_scope(ex::SyntaxTree, layer::ScopeLayer) @@ -539,19 +557,17 @@ end # the middle of a pass. const CompileHints = Base.ImmutableDict{Symbol,Any} -function setmeta!(ex::SyntaxTree; kws...) - @assert length(kws) == 1 # todo relax later ? - key = first(keys(kws)) - value = first(values(kws)) +function setmeta!(ex::SyntaxTree, key::Symbol, @nospecialize(val)) meta = begin m = get(ex, :meta, nothing) - isnothing(m) ? CompileHints(key, value) : CompileHints(m, key, value) + isnothing(m) ? CompileHints(key, val) : CompileHints(m, key, val) end - setattr!(ex; meta=meta) + setattr!(ex, :meta, meta) ex end -setmeta(ex::SyntaxTree; kws...) = setmeta!(copy_node(ex); kws...) +setmeta(ex::SyntaxTree, k::Symbol, @nospecialize(v)) = + setmeta!(copy_node(ex), k, v) function getmeta(ex::SyntaxTree, name::Symbol, default) meta = get(ex, :meta, nothing) diff --git a/JuliaLowering/src/bindings.jl b/JuliaLowering/src/bindings.jl index 286e67ecbeb14..f07eb166beb15 100644 --- a/JuliaLowering/src/bindings.jl +++ b/JuliaLowering/src/bindings.jl @@ -151,14 +151,16 @@ end # Create a new SSA binding function ssavar(ctx::AbstractLoweringContext, srcref, name="tmp") - nameref = makeleaf(ctx, srcref, K"Identifier", name_val=name) + nameref = makeleaf(ctx, srcref, K"Identifier") + nameref.name_val = name new_binding(ctx, nameref, name, :local; is_ssa=true, is_internal=true) end # Create a new local mutable binding or lambda argument function new_local_binding(ctx::AbstractLoweringContext, srcref, name; kind=:local, kws...) @assert kind === :local || kind === :argument - nameref = makeleaf(ctx, srcref, K"Identifier", name_val=name) + nameref = makeleaf(ctx, srcref, K"Identifier") + nameref.name_val = name ex = new_binding(ctx, nameref, name, kind; is_internal=true, kws...) lbindings = current_lambda_bindings(ctx) if !isnothing(lbindings) @@ -168,7 +170,8 @@ function new_local_binding(ctx::AbstractLoweringContext, srcref, name; kind=:loc end function new_global_binding(ctx::AbstractLoweringContext, srcref, name, mod; kws...) - nameref = makeleaf(ctx, srcref, K"Identifier", name_val=name) + nameref = makeleaf(ctx, srcref, K"Identifier") + nameref.name_val = name new_binding(ctx, nameref, name, :global; is_internal=true, mod=mod, kws...) end diff --git a/JuliaLowering/src/closure_conversion.jl b/JuliaLowering/src/closure_conversion.jl index 1dc4ca2bc8d9d..1cf199066a370 100644 --- a/JuliaLowering/src/closure_conversion.jl +++ b/JuliaLowering/src/closure_conversion.jl @@ -593,7 +593,7 @@ function closure_convert_lambda(ctx, ex) push!(lambda_children, _convert_closures(ctx2, ex[4])) end - lam = makenode(ctx, ex, ex, lambda_children; lambda_bindings=lambda_bindings) + lam = makenode(ctx, ex, ex, lambda_children, [:lambda_bindings=>lambda_bindings]) if !isnothing(interpolations) && !isempty(interpolations) @ast ctx ex [K"call" replace_captured_locals!::K"Value" diff --git a/JuliaLowering/src/compat.jl b/JuliaLowering/src/compat.jl index bb405abeaa242..25b73e08fde66 100644 --- a/JuliaLowering/src/compat.jl +++ b/JuliaLowering/src/compat.jl @@ -1,11 +1,14 @@ const JS = JuliaSyntax function _insert_tree_node(graph::SyntaxGraph, k::Kind, src::SourceAttrType, - flags::UInt16=0x0000; attrs...) + attrs=[], flags::UInt16=0x0000) id = newnode!(graph) - sethead!(graph, id, k) - flags !== 0 && setflags!(graph, id, flags) - setattr!(graph, id; source=src, attrs...) + setattr!(graph, id, :kind, k) + flags !== 0 && setattr!(graph, id, :syntax_flags, flags) + setattr!(graph, id, :source, src) + for (k,v) in attrs + setattr!(graph, id, k, v) + end return id end @@ -184,14 +187,14 @@ function _insert_convert_expr(@nospecialize(e), graph::SyntaxGraph, src::SourceA #--------------------------------------------------------------------------- # Non-expr types if isnothing(e) - st_id = _insert_tree_node(graph, K"core", src; name_val="nothing") + st_id = _insert_tree_node(graph, K"core", src, [:name_val=>"nothing"]) return st_id, src elseif e isa LineNumberNode # A LineNumberNode in value position evaluates to nothing - st_id = _insert_tree_node(graph, K"core", src; name_val="nothing") + st_id = _insert_tree_node(graph, K"core", src, [:name_val=>"nothing"]) return st_id, e elseif e isa Symbol - st_id = _insert_tree_node(graph, K"Identifier", src; name_val=String(e)) + st_id = _insert_tree_node(graph, K"Identifier", src, [:name_val=>String(e)]) return st_id, src elseif e isa QuoteNode if e.value isa Symbol @@ -199,13 +202,13 @@ function _insert_convert_expr(@nospecialize(e), graph::SyntaxGraph, src::SourceA elseif e.value isa Expr return _insert_convert_expr(Expr(:inert, e.value), graph, src) elseif e.value isa LineNumberNode - return _insert_tree_node(graph, K"Value", src; value=e.value), src + return _insert_tree_node(graph, K"Value", src, [:value=>e.value]), src else return _insert_convert_expr(e.value, graph, src) end elseif e isa String st_id = _insert_tree_node(graph, K"string", src) - id_inner = _insert_tree_node(graph, K"String", src; value=e) + id_inner = _insert_tree_node(graph, K"String", src, [:value=>e]) setchildren!(graph, st_id, [id_inner]) return st_id, src elseif !(e isa Expr) @@ -214,7 +217,7 @@ function _insert_convert_expr(@nospecialize(e), graph::SyntaxGraph, src::SourceA st_k = e isa Bool ? K"Bool" : e isa Integer ? K"Integer" : find_kind(string(typeof(e))) - st_id = _insert_tree_node(graph, isnothing(st_k) ? K"Value" : st_k, src; value=e) + st_id = _insert_tree_node(graph, isnothing(st_k) ? K"Value" : st_k, src, [:value=>e]) return st_id, src end @@ -497,7 +500,7 @@ function _insert_convert_expr(@nospecialize(e), graph::SyntaxGraph, src::SourceA @assert e.args[1] isa Symbol @assert e.args[2] isa LayerId st_id, src = _insert_convert_expr(e.args[1], graph, src) - setattr!(graph, st_id, scope_layer=e.args[2]) + setattr!(graph, st_id, :scope_layer, e.args[2]) return st_id, src elseif e.head === :symbolicgoto || e.head === :symboliclabel @assert nargs === 1 @@ -576,7 +579,7 @@ function _insert_convert_expr(@nospecialize(e), graph::SyntaxGraph, src::SourceA return nothing, src end - st_id = _insert_tree_node(graph, st_k, src, st_flags; st_attrs...) + st_id = _insert_tree_node(graph, st_k, src, collect(st_attrs), st_flags) # child_exprs === nothing means we want a leaf. Note that setchildren! with # an empty list makes a node non-leaf. diff --git a/JuliaLowering/src/desugaring.jl b/JuliaLowering/src/desugaring.jl index 98969a9043a55..16f2c929d1ef2 100644 --- a/JuliaLowering/src/desugaring.jl +++ b/JuliaLowering/src/desugaring.jl @@ -2166,9 +2166,9 @@ function make_lhs_decls(ctx, stmts, declkind, declmeta, ex, type_decls=true) # other Exprs that cannot be produced by the parser (tested by # test/precompile.jl #50538). if !isnothing(declmeta) - push!(stmts, makenode(ctx, ex, declkind, ex; meta=declmeta)) + push!(stmts, makenode(ctx, ex, declkind, NodeId[ex._id], [:meta=>declmeta])) else - push!(stmts, makenode(ctx, ex, declkind, ex)) + push!(stmts, makenode(ctx, ex, declkind, NodeId[ex._id])) end elseif k == K"Placeholder" nothing @@ -2177,7 +2177,7 @@ function make_lhs_decls(ctx, stmts, declkind, declmeta, ex, type_decls=true) @chk numchildren(ex) == 2 name = ex[1] if kind(name) == K"Identifier" - push!(stmts, makenode(ctx, ex, K"decl", name, ex[2])) + push!(stmts, makenode(ctx, ex, K"decl", NodeId[name._id, ex[2]._id])) else # TODO: Currently, this ignores the LHS in `_::T = val`. # We should probably do one of the following: @@ -2516,7 +2516,7 @@ function expand_function_generator(ctx, srcref, callex_srcref, func_name, func_n # Apply nospecialize to all arguments to prevent so much codegen and add # Core.Any type for them for i in first_trailing_arg:length(gen_arg_names) - gen_arg_names[i] = setmeta(gen_arg_names[i]; nospecialize=true) + gen_arg_names[i] = setmeta(gen_arg_names[i], :nospecialize, true) push!(gen_arg_types, @ast ctx gen_arg_names[i] "Any"::K"core") end # Code generator definition diff --git a/JuliaLowering/src/eval.jl b/JuliaLowering/src/eval.jl index 4d544ca783267..73f88d0b23d0b 100644 --- a/JuliaLowering/src/eval.jl +++ b/JuliaLowering/src/eval.jl @@ -532,3 +532,5 @@ function include_string(mod::Module, code::AbstractString, filename::AbstractStr expr_compat_mode=false) eval(mod, parseall(SyntaxTree, code; filename=filename); expr_compat_mode) end + +include(path::AbstractString) = include(JuliaLowering, path) diff --git a/JuliaLowering/src/linear_ir.jl b/JuliaLowering/src/linear_ir.jl index 974c51902caf5..a2448cb297107 100644 --- a/JuliaLowering/src/linear_ir.jl +++ b/JuliaLowering/src/linear_ir.jl @@ -173,10 +173,6 @@ function emit(ctx::LinearIRContext, ex) return ex end -function emit(ctx::LinearIRContext, srcref, k, args...) - emit(ctx, makenode(ctx, srcref, k, args...)) -end - # Emit computation of ex, assigning the result to an ssavar and returning that function emit_assign_tmp(ctx::LinearIRContext, ex, name="tmp") tmp = ssavar(ctx, ex, name) @@ -328,7 +324,7 @@ function emit_simple_assignment(ctx, srcref, lhs, rhs, op=K"=") rhs ]) else - emit(ctx, srcref, op, lhs, rhs) + emit(ctx, @ast ctx srcref [op lhs rhs]) end end @@ -351,7 +347,7 @@ end function make_label(ctx, srcref) id = ctx.next_label_id[] ctx.next_label_id[] += 1 - makeleaf(ctx, srcref, K"label", id=id) + makeleaf(ctx, srcref, K"label", [:id=>id]) end # flisp: make&mark-label @@ -773,7 +769,7 @@ function compile(ctx::LinearIRContext, ex, needs_value, in_tail_pos) else lam = emit_assign_tmp(ctx, compile(ctx, lam, true, false)) end - emit(ctx, ex, K"method", fname, sig, lam) + emit(ctx, @ast ctx ex [K"method" fname sig lam]) @assert !needs_value && !in_tail_pos nothing end @@ -970,7 +966,7 @@ function _renumber(ctx, ssa_rewrites, slot_rewrites, label_table, ex) if k == K"BindingId" id = ex.var_id if haskey(ssa_rewrites, id) - makeleaf(ctx, ex, K"SSAValue"; var_id=ssa_rewrites[id]) + makeleaf(ctx, ex, K"SSAValue", [:var_id=>ssa_rewrites[id]]) else new_id = get(slot_rewrites, id, nothing) binfo = lookup_binding(ctx, id) @@ -978,12 +974,13 @@ function _renumber(ctx, ssa_rewrites, slot_rewrites, label_table, ex) sk = binfo.kind == :local || binfo.kind == :argument ? K"slot" : binfo.kind == :static_parameter ? K"static_parameter" : throw(LoweringError(ex, "Found unexpected binding of kind $(binfo.kind)")) - makeleaf(ctx, ex, sk; var_id=new_id) + makeleaf(ctx, ex, sk, [:var_id=>new_id]) else if binfo.kind !== :global throw(LoweringError(ex, "Found unexpected binding of kind $(binfo.kind)")) end - makeleaf(ctx, ex, K"globalref", binfo.name, mod=binfo.mod) + makeleaf(ctx, ex, K"globalref", + [:name_val=>binfo.name, :mod=>binfo.mod]) end end elseif k == K"meta" || k == K"static_eval" diff --git a/JuliaLowering/src/macro_expansion.jl b/JuliaLowering/src/macro_expansion.jl index 28b36c2f6dfc0..61d76719d4fa6 100644 --- a/JuliaLowering/src/macro_expansion.jl +++ b/JuliaLowering/src/macro_expansion.jl @@ -143,7 +143,8 @@ function fixup_macro_name(ctx::MacroExpansionContext, ex::SyntaxTree) if k == K"StrMacroName" || k == K"CmdMacroName" layerid = get(ex, :scope_layer, current_layer_id(ctx)) newname = JuliaSyntax.lower_identifier_name(ex.name_val, k) - makeleaf(ctx, ex, ex, kind=K"Identifier", scope_layer=layerid, name_val=newname) + makeleaf(ctx, ex, ex, [:kind=>K"Identifier", :scope_layer=>layerid, + :name_val=>newname]) elseif k == K"macro_name" @chk numchildren(ex) === 1 if kind(ex[1]) === K"." @@ -151,7 +152,7 @@ function fixup_macro_name(ctx::MacroExpansionContext, ex::SyntaxTree) else layerid = get(ex, :scope_layer, current_layer_id(ctx)) newname = JuliaSyntax.lower_identifier_name(ex[1].name_val, K"macro_name") - makeleaf(ctx, ex[1], ex[1], kind=kind(ex[1]), name_val=newname) + makeleaf(ctx, ex[1], ex[1], [:kind=>kind(ex[1]), :name_val=>newname]) end else mapchildren(e->fixup_macro_name(ctx,e), ctx, ex) @@ -215,7 +216,7 @@ function set_macro_arg_hygiene(ctx, ex, layer_ids, layer_idx) k = kind(ex) scope_layer = get(ex, :scope_layer, layer_ids[layer_idx]) if is_leaf(ex) - makeleaf(ctx, ex, ex; scope_layer=scope_layer) + makeleaf(ctx, ex, ex, [:scope_layer=>scope_layer]) else inner_layer_idx = layer_idx if k == K"escape" @@ -229,8 +230,9 @@ function set_macro_arg_hygiene(ctx, ex, layer_ids, layer_idx) throw(MacroExpansionError(ex, "`escape` node in outer context")) end end - mapchildren(e->set_macro_arg_hygiene(ctx, e, layer_ids, inner_layer_idx), - ctx, ex; scope_layer=scope_layer) + node = mapchildren(e->set_macro_arg_hygiene( + ctx, e, layer_ids, inner_layer_idx), ctx, ex) + setattr!(node, :scope_layer, scope_layer) end end @@ -380,10 +382,10 @@ function append_sourceref(ctx, ex, secondary_prov) srcref = (ex, secondary_prov) if !is_leaf(ex) if kind(ex) == K"macrocall" - makenode(ctx, srcref, ex, children(ex)...) + makenode(ctx, srcref, ex, children(ex)) else - makenode(ctx, srcref, ex, - map(e->append_sourceref(ctx, e, secondary_prov), children(ex))...) + cs = map(e->append_sourceref(ctx, e, secondary_prov)._id, children(ex)) + makenode(ctx, srcref, ex, cs) end else makeleaf(ctx, srcref, ex) @@ -429,7 +431,7 @@ function expand_forms_1(ctx::MacroExpansionContext, ex::SyntaxTree) else k = all(==('_'), name_str) ? K"Placeholder" : K"Identifier" scope_layer = get(ex, :scope_layer, current_layer_id(ctx)) - makeleaf(ctx, ex, ex; kind=k, scope_layer) + makeleaf(ctx, ex, ex, [:kind=>k, :scope_layer=>scope_layer]) end elseif k == K"StrMacroName" || k == K"CmdMacroName" || k == K"macro_name" # These can appear outside of a macrocall, e.g. in `import` @@ -567,7 +569,8 @@ function expand_forms_1(ctx::MacroExpansionContext, ex::SyntaxTree) # TODO: Should every form get layerid systematically? Or only the ones # which expand_forms_2 needs? layerid = get(ex, :scope_layer, current_layer_id(ctx)) - mapchildren(e->expand_forms_1(ctx,e), ctx, ex; scope_layer=layerid) + setattr(mapchildren(e->expand_forms_1(ctx,e), ctx, ex), + :scope_layer, layerid) else mapchildren(e->expand_forms_1(ctx,e), ctx, ex) end diff --git a/JuliaLowering/src/runtime.jl b/JuliaLowering/src/runtime.jl index 377934a234b2e..50faef169e96f 100644 --- a/JuliaLowering/src/runtime.jl +++ b/JuliaLowering/src/runtime.jl @@ -63,9 +63,9 @@ function _interpolated_value(ctx::InterpolationContext, srcref, ex) # Plain symbols become identifiers. This is an accommodation for # compatibility to allow `:x` (a Symbol) and `:(x)` (a SyntaxTree) to # be used interchangeably in macros. - makeleaf(ctx, srcref, K"Identifier", string(ex)) + newleaf(ctx, srcref, K"Identifier", string(ex)) else - makeleaf(ctx, srcref, K"Value", ex) + newleaf(ctx, srcref, K"Value", ex) end end diff --git a/JuliaLowering/src/syntax_graph.jl b/JuliaLowering/src/syntax_graph.jl index 2630825197e55..2e16877aee70c 100644 --- a/JuliaLowering/src/syntax_graph.jl +++ b/JuliaLowering/src/syntax_graph.jl @@ -104,11 +104,8 @@ function newnode!(graph::SyntaxGraph) return length(graph.edge_ranges) end -function setchildren!(graph::SyntaxGraph, id, children::NodeId...) - setchildren!(graph, id, children) -end - -function setchildren!(graph::SyntaxGraph, id, children) +function setchildren!(graph::SyntaxGraph, id::NodeId, + children::AbstractVector{NodeId}) n = length(graph.edges) graph.edge_ranges[id] = n+1:(n+length(children)) # TODO: Reuse existing edges if possible @@ -152,12 +149,11 @@ function hasattr(graph::SyntaxGraph, name::Symbol) end # TODO: Probably terribly non-inferable? -function setattr!(graph::SyntaxGraph, id; attrs...) - for (k,v) in pairs(attrs) - if !isnothing(v) - getattr(graph, k)[id] = v - end +function setattr!(graph::SyntaxGraph, id::NodeId, k::Symbol, @nospecialize(v)) + if !isnothing(v) + getattr(graph, k)[id] = v end + id end function deleteattr!(graph::SyntaxGraph, id::NodeId, name::Symbol) @@ -172,19 +168,6 @@ function Base.getproperty(graph::SyntaxGraph, name::Symbol) return getattr(graph, name) end -function sethead!(graph, id::NodeId, h::JuliaSyntax.SyntaxHead) - sethead!(graph, id, kind(h)) - setflags!(graph, id, flags(h)) -end - -function sethead!(graph, id::NodeId, k::Kind) - graph.kind[id] = k -end - -function setflags!(graph, id::NodeId, f::UInt16) - graph.syntax_flags[id] = f -end - """ syntax_graph(ctx) @@ -225,8 +208,9 @@ function Base.getproperty(ex::SyntaxTree, name::Symbol) end end -function Base.setproperty!(ex::SyntaxTree, name::Symbol, val) - return setattr!(ex._graph, ex._id; name=>val) +function Base.setproperty!(ex::SyntaxTree, name::Symbol, @nospecialize(val)) + setattr!(ex._graph, ex._id, name, val) + val end function Base.propertynames(ex::SyntaxTree) @@ -264,22 +248,19 @@ function copy_node(ex::SyntaxTree) graph = syntax_graph(ex) id = newnode!(graph) if !is_leaf(ex) - setchildren!(graph, id, _node_ids(graph, children(ex)...)) + setchildren!(graph, id, children(ex._graph, ex._id)) end ex2 = SyntaxTree(graph, id) copy_attrs!(ex2, ex, true) ex2 end -function setattr(ex::SyntaxTree; extra_attrs...) - ex2 = copy_node(ex) - setattr!(ex2; extra_attrs...) - ex2 -end - -function setattr!(ex::SyntaxTree; attrs...) - setattr!(ex._graph, ex._id; attrs...) +function setattr!(ex::SyntaxTree, name::Symbol, @nospecialize(val)) + setattr!(ex._graph, ex._id, name, val) + ex end +setattr(ex::SyntaxTree, name::Symbol, @nospecialize(val)) = + setattr!(copy_node(ex), name, val) function deleteattr!(ex::SyntaxTree, name::Symbol) deleteattr!(ex._graph, ex._id, name) @@ -709,9 +690,14 @@ end SyntaxList(graph::SyntaxGraph) = SyntaxList(graph, Vector{NodeId}()) SyntaxList(ctx) = SyntaxList(syntax_graph(ctx)) +SyntaxList(ctx, v::Vector{SyntaxTree}) = + SyntaxList(syntax_graph(ctx), NodeId[x._id for x in v]) syntax_graph(lst::SyntaxList) = lst.graph +setchildren!(graph::SyntaxGraph, id::NodeId, children::SyntaxList) = + setchildren!(graph, id, children.ids) + Base.size(v::SyntaxList) = size(v.ids) Base.IndexStyle(::Type{<:SyntaxList}) = IndexLinear() @@ -853,8 +839,9 @@ function _insert_green(graph::SyntaxGraph, sf::SourceFile, txtbuf::Vector{UInt8}, offset::Int, cursor::RedTreeCursor) id = newnode!(graph) - sethead!(graph, id, head(cursor)) - setattr!(graph, id, source=SourceRef(sf, first_byte(cursor), last_byte(cursor))) + setattr!(graph, id, :kind, kind(cursor)) + setattr!(graph, id, :syntax_flags, flags(cursor)) + setattr!(graph, id, :source, SourceRef(sf, first_byte(cursor), last_byte(cursor))) if !is_leaf(cursor) cs = NodeId[] for c in reverse(cursor) @@ -865,9 +852,9 @@ function _insert_green(graph::SyntaxGraph, sf::SourceFile, v = parse_julia_literal(txtbuf, head(cursor), byte_range(cursor) .+ offset) if v isa Symbol # TODO: Fixes in JuliaSyntax to avoid ever converting to Symbol - setattr!(graph, id, name_val=string(v)) + setattr!(graph, id, :name_val, string(v)) elseif !isnothing(v) - setattr!(graph, id, value=v) + setattr!(graph, id, :value, v) end end return id @@ -902,7 +889,8 @@ function _green_to_ast(parent::Kind, ex::SyntaxTree; eq_to_kw=false) @assert length(cs) === 1 cs[1] elseif k === K"=" && eq_to_kw - makenode(graph, ex, ex, _map_green_to_ast(k, children(ex)); kind=K"kw") + setattr!(makenode(graph, ex, ex, _map_green_to_ast(k, children(ex))), + :kind, K"kw") elseif is_leaf(ex) return ex else diff --git a/JuliaLowering/src/syntax_macros.jl b/JuliaLowering/src/syntax_macros.jl index 00b5d12155469..f8ff00600525b 100644 --- a/JuliaLowering/src/syntax_macros.jl +++ b/JuliaLowering/src/syntax_macros.jl @@ -18,7 +18,7 @@ function _apply_nospecialize(ctx, ex) k = kind(ex) if k == K"Identifier" || k == K"Placeholder" || k == K"tuple" - setmeta(ex; nospecialize=true) + setmeta(ex, :nospecialize, true) elseif k == K"..." || k == K"::" || k == K"=" || k == K"kw" # The @nospecialize macro is responsible for converting K"=" to K"kw". # Desugaring uses this helper internally, so we may see K"kw" too. diff --git a/JuliaLowering/test/compat.jl b/JuliaLowering/test/compat.jl index a39f096746193..9e625a62fe265 100644 --- a/JuliaLowering/test/compat.jl +++ b/JuliaLowering/test/compat.jl @@ -95,7 +95,7 @@ const JL = JuliaLowering end pre_st_flags = (JS.flags(st) & ~JS.INFIX_FLAG) | JS.PREFIX_CALL_FLAG JL.setchildren!(st._graph, st._id, pre_st_args) - JL.setflags!(st._graph, st._id, pre_st_flags) + JL.setattr!(st._graph, st._id, :syntax_flags, pre_st_flags) elseif JS.is_postfix_op_call(st) && (k === K"call" || k === K"dotcall") pre_st_args = JL.NodeId[st[end]._id] for c in st[1:end-1] @@ -103,23 +103,23 @@ const JL = JuliaLowering end pre_st_flags = (JS.flags(st) & ~JS.POSTFIX_OP_FLAG) | JS.PREFIX_CALL_FLAG JL.setchildren!(st._graph, st._id, pre_st_args) - JL.setflags!(st._graph, st._id, pre_st_flags) + JL.setattr!(st._graph, st._id, :syntax_flags, pre_st_flags) elseif k in JS.KSet"tuple block macrocall" - JL.setflags!(st._graph, st._id, JS.flags(st) & ~JS.PARENS_FLAG) + JL.setattr!(st._graph, st._id, :syntax_flags, JS.flags(st) & ~JS.PARENS_FLAG) elseif k === K"toplevel" - JL.setflags!(st._graph, st._id, JS.flags(st) & ~JS.TOPLEVEL_SEMICOLONS_FLAG) + JL.setattr!(st._graph, st._id, :syntax_flags, JS.flags(st) & ~JS.TOPLEVEL_SEMICOLONS_FLAG) end if k in JS.KSet"tuple call dotcall macrocall vect curly braces <: >:" - JL.setflags!(st._graph, st._id, JS.flags(st) & ~JS.TRAILING_COMMA_FLAG) + JL.setattr!(st._graph, st._id, :syntax_flags, JS.flags(st) & ~JS.TRAILING_COMMA_FLAG) end - k === K"quote" && JL.setflags!(st._graph, st._id, JS.flags(st) & ~JS.COLON_QUOTE) - k === K"wrapper" && JL.sethead!(st._graph, st._id, K"block") + k === K"quote" && JL.setattr!(st._graph, st._id, :syntax_flags, JS.flags(st) & ~JS.COLON_QUOTE) + k === K"wrapper" && JL.setattr!(st._graph, st._id, :kind, K"block") # All ops are prefix ops in an expr. # Ignore trivia (shows up on some K"error"s) - JL.setflags!(st._graph, st._id, JS.flags(st) & + JL.setattr!(st._graph, st._id, :syntax_flags, JS.flags(st) & ~JS.PREFIX_OP_FLAG & ~JS.INFIX_FLAG & ~JS.TRIVIA_FLAG & ~JS.NON_TERMINAL_FLAG) for c in JS.children(st) diff --git a/JuliaLowering/test/scopes.jl b/JuliaLowering/test/scopes.jl index e327343eb03e6..d781ff66ad3d6 100644 --- a/JuliaLowering/test/scopes.jl +++ b/JuliaLowering/test/scopes.jl @@ -62,7 +62,7 @@ end function wrapscope(ex, scope_type) g = JuliaLowering.ensure_attributes(ex._graph, scope_type=Symbol) ex = JuliaLowering.reparent(g, ex) - makenode(ex, ex, K"scope_block", ex; scope_type=scope_type) + makenode(g, ex, K"scope_block", [ex._id], [:scope_type=>scope_type]) end assign_z_2 = parsestmt(SyntaxTree, "begin z = 2 end", filename="foo.jl") diff --git a/JuliaLowering/test/utils.jl b/JuliaLowering/test/utils.jl index 16f2f30294ffe..e82e524e13342 100644 --- a/JuliaLowering/test/utils.jl +++ b/JuliaLowering/test/utils.jl @@ -17,7 +17,7 @@ using .JuliaSyntax: sourcetext, set_numeric_flags using .JuliaLowering: SyntaxGraph, newnode!, ensure_attributes!, Kind, SourceRef, SyntaxTree, NodeId, - makenode, makeleaf, setattr!, sethead!, + makenode, makeleaf, setattr!, is_leaf, numchildren, children, @ast, flattened_provenance, showprov, LoweringError, MacroExpansionError, syntax_graph, Bindings, ScopeLayer, mapchildren @@ -33,8 +33,8 @@ end function _source_node(graph, src) id = newnode!(graph) - sethead!(graph, id, K"None") - setattr!(graph, id, source=src) + setattr!(graph, id, :kind, K"None") + setattr!(graph, id, :source, src) SyntaxTree(graph, id) end