11const JS = JuliaSyntax
22
3- function _insert_tree_node (graph:: SyntaxGraph , k:: JS.Kind ,
4- src :: SourceAttrType , flags:: UInt16 = 0x0000 )
3+ function _insert_tree_node (graph:: SyntaxGraph , k:: JS.Kind , src :: SourceAttrType ,
4+ flags:: UInt16 = 0x0000 ; attrs ... )
55 id = newnode! (graph)
66 sethead! (graph, id, k)
7- setattr! (graph, id, source= src)
87 setflags! (graph, id, flags)
8+ setattr! (graph, id; source= src, attrs... )
99 return id
1010end
1111
@@ -156,51 +156,47 @@ function _insert_convert_expr(@nospecialize(e), graph::SyntaxGraph, src::SourceA
156156 # ---------------------------------------------------------------------------
157157 # Non-expr types
158158 if isnothing (e)
159- st_id = _insert_tree_node (graph, K " core" , src)
160- setattr! (graph, st_id, name_val= " nothing" )
161- return (st_id, src)
159+ st_id = _insert_tree_node (graph, K " core" , src; name_val= " nothing" )
160+ return st_id, src
162161 elseif e isa Symbol
163- st_id = _insert_tree_node (graph, K " Identifier" , src)
164- setattr! (graph, st_id; name_val= String (e))
162+ st_id = _insert_tree_node (graph, K " Identifier" , src; name_val= String (e))
165163 if ! Base. isoperator (e) && ! Base. is_valid_identifier (e)
166164 return _insert_var_str (st_id, graph, src)
167165 end
168- return ( st_id, src)
166+ return st_id, src
169167 elseif e isa LineNumberNode
170- return ( nothing , e)
168+ return nothing , e
171169 elseif e isa QuoteNode && e. value isa Symbol
172170 # Undo special handling from st->expr
173171 return _insert_convert_expr (Expr (:quote , e. value), graph, src)
174172 # elseif e isa QuoteNode
175173 # st_id = _insert_tree_node(graph, K"inert", src)
176174 # quote_child, _ = _insert_convert_expr(e.value, graph, src)
177175 # setchildren!(graph, st_id, NodeId[quote_child])
178- # return ( st_id, src)
176+ # return st_id, src
179177 elseif e isa String
180- st_id = _insert_tree_node (graph, K " string" , src)
181- id_inner = _insert_tree_node (graph, K " String" , src)
182- setattr! (graph, id_inner, value= e)
183- setflags! (graph, st_id, JS. NON_TERMINAL_FLAG)
178+ st_id = _insert_tree_node (graph, K " string" , src, JS. NON_TERMINAL_FLAG)
179+ id_inner = _insert_tree_node (graph, K " String" , src; value= e)
184180 setchildren! (graph, st_id, [id_inner])
185- return ( st_id, src)
181+ return st_id, src
186182 elseif ! (e isa Expr)
187183 # There are other kinds we could potentially back-convert (e.g. Float),
188184 # but Value should work fine.
189185 st_k = e isa Integer ? K " Integer" : find_kind (string (typeof (e)))
190- st_id = _insert_tree_node (graph, isnothing (st_k) ? K " Value" : st_k, src)
191- setattr! (graph, st_id, value= e)
192- return (st_id, src)
186+ st_id = _insert_tree_node (graph, isnothing (st_k) ? K " Value" : st_k, src; value= e)
187+ return st_id, src
193188 end
194189
195190 # ---------------------------------------------------------------------------
196191 # `e` is an expr. In many cases, it suffices to
197192 # - guess that the kind name is the same as the expr head
198- # - add no syntax flags
193+ # - add no syntax flags or attrs
199194 # - map e.args to syntax tree children one-to-one
200195 nargs = length (e. args)
201196 maybe_kind = find_kind (string (e. head))
202197 st_k = isnothing (maybe_kind) ? K " None" : maybe_kind
203198 st_flags = 0x0000
199+ st_attrs = Dict {Symbol, Any} ()
204200 # Note that SyntaxTree/Node differentiate 0-child non-terminals and leaves
205201 child_exprs:: Union{Nothing, Vector{Any}} = copy (e. args)
206202
@@ -394,9 +390,8 @@ function _insert_convert_expr(@nospecialize(e), graph::SyntaxGraph, src::SourceA
394390 # upstream for consistency.
395391 if nargs === 0
396392 child_exprs = nothing
397- st_id = _insert_tree_node (graph, st_k, src, st_flags)
398- setattr! (graph, st_id, value= JS. ErrorVal ())
399- return st_id, src
393+ st_attrs[:value ] = JS. ErrorVal ()
394+ st_flags |= JS. TRIVIA_FLAG
400395 end
401396 end
402397
@@ -427,46 +422,50 @@ function _insert_convert_expr(@nospecialize(e), graph::SyntaxGraph, src::SourceA
427422 elseif e. head === :symbolicgoto || e. head === :symboliclabel
428423 @assert nargs === 1
429424 st_k = e. head === :symbolicgoto ? K " symbolic_label" : K " symbolic_goto"
430- st_id = _insert_tree_node (graph, st_k, src)
431- setattr! (graph, st_id, name_val= string (e. args[1 ]))
432- return st_id, src
425+ st_attrs[:name_val ] = string (e. args[1 ])
426+ child_exprs = nothing
433427 elseif e. head === :inline || e. head === :noinline
434428 @assert nargs === 1 && e. args[1 ] isa Bool
435429 # TODO : JuliaLowering doesn't accept this (non-:meta) form yet
436- return ( nothing , src)
430+ return nothing , src
437431 elseif e. head === :core
438432 @assert nargs === 1
439433 @assert e. args[1 ] isa Symbol
440- coreref_name = string (e. args[1 ])
441- st_id = _insert_tree_node (graph, K " core" , src)
442- setattr! (graph, st_id; name_val= coreref_name)
443- return st_id, src
434+ st_attrs[:name_val ] = string (e. args[1 ])
435+ child_exprs = nothing
444436 elseif e. head === :islocal || e. head === :isglobal
445437 st_k = K " extension"
446438 child_exprs = [Expr (:sym_not_identifier , e. head), e. args[1 ]]
439+ elseif e. head === :block && nargs >= 1 &&
440+ e. args[1 ] isa Expr && e. args[1 ]. head === :softscope
441+ # (block (softscope true) ex) produced with every REPL prompt.
442+ # :hardscope exists too, but should just be a let, and appears to be
443+ # unused in the wild.
444+ ensure_attributes! (graph; scope_type= Symbol)
445+ st_k = K " scope_block"
446+ st_attrs[:scope_type ] = :soft
447+ child_exprs = e. args[2 : end ]
447448 end
448449
449450 # ---------------------------------------------------------------------------
450451 # Temporary heads introduced by us converting the parent expr
451452 if e. head === :MacroName
452453 @assert nargs === 1
453- st_id = _insert_tree_node (graph, K " MacroName" , src, st_flags)
454454 mac_name = string (e. args[1 ])
455- setattr! (graph, st_id, name_val= mac_name == " @__dot__" ? " @." : mac_name)
455+ mac_name = mac_name == " @__dot__" ? " @." : mac_name
456+ st_id = _insert_tree_node (graph, K " MacroName" , src, st_flags; name_val= mac_name)
456457 if ! Base. is_valid_identifier (mac_name[2 : end ])
457458 return _insert_var_str (st_id, graph, src)
458459 end
459460 return st_id, src
460461 elseif e. head === :catch_var_placeholder
461- st_id = _insert_tree_node (graph, K " Placeholder" , src, st_flags)
462- setattr! (graph, st_id, name_val= " " )
463- return st_id, src
462+ st_k = K " Placeholder"
463+ st_attrs[ : name_val] = " "
464+ child_exprs = nothing
464465 elseif e. head === :sym_not_identifier
465- estr = String (e. args[1 ])
466466 st_k = K " Symbol"
467- st_id = _insert_tree_node (graph, st_k, src)
468- setattr! (graph, st_id, name_val= estr)
469- return st_id, src
467+ st_attrs[:name_val ] = String (e. args[1 ])
468+ child_exprs = nothing
470469 elseif e. head === :do_lambda
471470 st_k = K " do"
472471 end
@@ -478,21 +477,22 @@ function _insert_convert_expr(@nospecialize(e), graph::SyntaxGraph, src::SourceA
478477 error (" Unknown expr head `$(e. head) `\n $(sprint (dump, e)) " )
479478 end
480479
481- st_flags |= JS. NON_TERMINAL_FLAG
482- st_id = _insert_tree_node (graph, st_k, src, st_flags)
480+ st_id = _insert_tree_node (graph, st_k, src, st_flags; st_attrs... )
483481
484482 # child_exprs === nothing means we want a leaf. Note that setchildren! with
485483 # an empty list makes a node non-leaf.
486484 if isnothing (child_exprs)
487485 return st_id, src
488486 else
489- st_child_ids, last_src = _insert_expr_children (child_exprs, graph, src)
487+ st_flags |= JS. NON_TERMINAL_FLAG
488+ setflags! (graph, st_id, st_flags)
489+ st_child_ids, last_src = _insert_child_expr (child_exprs, graph, src)
490490 setchildren! (graph, st_id, st_child_ids)
491491 return st_id, last_src
492492 end
493493end
494494
495- function _insert_expr_children (child_exprs:: Vector{Any} , graph:: SyntaxGraph ,
495+ function _insert_child_expr (child_exprs:: Vector{Any} , graph:: SyntaxGraph ,
496496 src:: SourceAttrType )
497497 st_child_ids = NodeId[]
498498 last_src = src
0 commit comments