diff --git a/README.md b/README.md index 789e1ce7..47ea97db 100644 --- a/README.md +++ b/README.md @@ -28,8 +28,8 @@ This work is intended to Note this is a work in progress; many types of syntax are not yet handled. -1. You need a 1.12-DEV build of Julia: At least 1.12.0-DEV.512. Commit `263928f9ad4` is currentl known to work. Note that JuliaLowering relies on Julia internals and may be broken on the latest Julia dev version from time to time. (In fact it is currently broken on the latest `1.12-DEV`.) -2. Check out the main branch of [JuliaSyntax](https://github.com/JuliaLang/JuliaSyntax.jl) +1. You need a 1.13.0-DEV build of Julia: At least 1.13.0-DEV.880. Commit `5ebc5b463ea` is currently known to work. Note that JuliaLowering relies on Julia internals and may be broken on the latest Julia dev version from time to time. +2. Use commit `46723f0` of [JuliaSyntax](https://github.com/JuliaLang/JuliaSyntax.jl) 3. Get the latest version of [JuliaSyntaxFormatter](https://github.com/c42f/JuliaSyntaxFormatter.jl) 4. Run the demo `include("test/demo.jl")` diff --git a/src/JuliaLowering.jl b/src/JuliaLowering.jl index a365a9e6..2f614c25 100644 --- a/src/JuliaLowering.jl +++ b/src/JuliaLowering.jl @@ -13,7 +13,7 @@ using JuliaSyntax: highlight, Kind, @KSet_str using JuliaSyntax: is_leaf, children, numchildren, head, kind, flags, has_flags, numeric_flags using JuliaSyntax: filename, first_byte, last_byte, byte_range, sourcefile, source_location, span, sourcetext -using JuliaSyntax: is_literal, is_number, is_operator, is_prec_assignment, is_prefix_call, is_infix_op_call, is_postfix_op_call, is_error, is_dotted +using JuliaSyntax: is_literal, is_number, is_operator, is_prec_assignment, is_prefix_call, is_infix_op_call, is_postfix_op_call, is_error _include("kinds.jl") _register_kinds() @@ -32,6 +32,7 @@ _include("runtime.jl") _include("syntax_macros.jl") _include("eval.jl") +_include("compat.jl") function __init__() _register_kinds() diff --git a/src/ast.jl b/src/ast.jl index 7188eba4..c16a9a51 100644 --- a/src/ast.jl +++ b/src/ast.jl @@ -498,7 +498,7 @@ end # the middle of a pass. const CompileHints = Base.ImmutableDict{Symbol,Any} -function setmeta(ex::SyntaxTree; kws...) +function setmeta!(ex::SyntaxTree; kws...) @assert length(kws) == 1 # todo relax later ? key = first(keys(kws)) value = first(values(kws)) @@ -506,9 +506,12 @@ function setmeta(ex::SyntaxTree; kws...) m = get(ex, :meta, nothing) isnothing(m) ? CompileHints(key, value) : CompileHints(m, key, value) end - setattr(ex; meta=meta) + setattr!(ex; meta=meta) + ex end +setmeta(ex::SyntaxTree; kws...) = setmeta!(copy_node(ex); kws...) + function getmeta(ex::SyntaxTree, name::Symbol, default) meta = get(ex, :meta, nothing) isnothing(meta) ? default : get(meta, name, default) diff --git a/src/closure_conversion.jl b/src/closure_conversion.jl index 211d6922..79bde082 100644 --- a/src/closure_conversion.jl +++ b/src/closure_conversion.jl @@ -147,6 +147,7 @@ function convert_global_assignment(ctx, ex, var, rhs0) end push!(stmts, @ast ctx ex [K"=" var rhs]) @ast ctx ex [K"block" + [K"globaldecl" var] stmts... rhs1 ] @@ -337,6 +338,13 @@ function _convert_closures(ctx::ClosureConversionCtx, ex) elseif binfo.is_always_defined || is_self_captured(ctx, var) # Captured but unboxed vars are always defined @ast ctx ex true::K"Bool" + elseif binfo.kind == :global + # Normal isdefined won't work for globals (#56985) + @ast ctx ex [K"call" + "isdefinedglobal"::K"core" + ctx.mod::K"Value" + binfo.name::K"Symbol" + false::K"Bool"] else ex end @@ -344,12 +352,13 @@ function _convert_closures(ctx::ClosureConversionCtx, ex) @assert kind(ex[1]) == K"BindingId" binfo = lookup_binding(ctx, ex[1]) if binfo.kind == :global - @ast ctx ex [K"call" - "set_binding_type!"::K"core" - binfo.mod::K"Value" - binfo.name::K"Symbol" - _convert_closures(ctx, ex[2]) - ] + @ast ctx ex [K"block" + # flisp has this, but our K"assert" handling is in a previous pass + # [K"assert" "toplevel_only"::K"Symbol" [K"inert" ex]] + [K"globaldecl" + ex[1] + _convert_closures(ctx, ex[2])] + "nothing"::K"core"] else makeleaf(ctx, ex, K"TOMBSTONE") end @@ -382,6 +391,7 @@ function _convert_closures(ctx::ClosureConversionCtx, ex) type_for_closure(ctx, ex, name_str, field_syms, field_is_box) if !ctx.is_toplevel_seq_point push!(ctx.toplevel_stmts, closure_type_def) + push!(ctx.toplevel_stmts, @ast ctx ex [K"latestworld_if_toplevel"]) closure_type_def = nothing end closure_info = ClosureInfo(closure_type_, field_syms, field_inds) @@ -406,6 +416,7 @@ function _convert_closures(ctx::ClosureConversionCtx, ex) end @ast ctx ex [K"block" closure_type_def + [K"latestworld_if_toplevel"] closure_type := if isempty(type_params) closure_type_ else diff --git a/src/compat.jl b/src/compat.jl new file mode 100644 index 00000000..d177e26d --- /dev/null +++ b/src/compat.jl @@ -0,0 +1,462 @@ +const JS = JuliaSyntax + +function _insert_tree_node(graph::SyntaxGraph, k::JS.Kind, + src::SourceAttrType, flags::UInt16=0x0000) + id = newnode!(graph) + sethead!(graph, id, k) + setattr!(graph, id, source=src) + setflags!(graph, id, flags) + return id +end + +""" +An Expr -> SyntaxTree transformation that should preserve semantics, but will +have low-quality provenance info (namely, each tree node will be associated with +the last seen LineNumberNode in the pre-order expr traversal). + +Last-resort option so that, for example, we can lower the output of old +Expr-producing macros. Always prefer re-parsing source text over using this. + +Supports parsed and/or macro-expanded exprs, but not lowered exprs +""" +function expr_to_syntaxtree(@nospecialize(e), + lnn::Union{LineNumberNode, Nothing}=nothing, + ctx=nothing) + graph = if isnothing(ctx) + ensure_attributes!(SyntaxGraph(), + kind=Kind, syntax_flags=UInt16, + source=SourceAttrType, var_id=Int, value=Any, + name_val=String, is_toplevel_thunk=Bool) + else + syntax_graph(ctx) + end + toplevel_src = if isnothing(lnn) + # Provenance sinkhole for all nodes until we hit a linenode + dummy_src = SourceRef( + SourceFile("No source for expression $e"), + 1, JS.GreenNode(K"None", 0)) + _insert_tree_node(graph, K"None", dummy_src) + else + lnn + end + st_id, _ = _insert_convert_expr(e, graph, toplevel_src) + out = SyntaxTree(graph, st_id) + return out +end + +function _expr_replace!(@nospecialize(e), replace_pred::Function, replacer!::Function, + recurse_pred=(@nospecialize e)->true) + if replace_pred(e) + replacer!(e) + end + if e isa Expr && recurse_pred(e) + for a in e.args + _expr_replace!(a, replace_pred, replacer!, recurse_pred) + end + end +end + +function _to_iterspec(exs::Vector) + if length(exs) === 1 && exs[1].head === :filter + @assert length(exs[1].args) >= 2 + return Expr(:filter, _to_iterspec(exs[1].args[2:end]), exs[1].args[1]) + end + outex = Expr(:iteration) + for e in exs + if e.head === :block + for iter in e.args + push!(outex.args, Expr(:in, iter.args...)) + end + elseif e.head === :(=) + push!(outex.args, Expr(:in, e.args...)) + else + @assert false "unknown iterspec in $e" + end + end + return outex +end + +""" +Return `e.args`, but with any parameters in SyntaxTree (flattened, source) order. +Parameters are expected to be as `e.args[pos]`. + +e.g. orderings of (a,b,c;d;e;f): + Expr: (tuple (parameters (parameters (parameters f) e) d) a b c) + SyntaxTree: (tuple a b c (parameters d) (parameters e) (parameters f)) +""" +function collect_expr_parameters(e::Expr, pos::Int) + params = expr_parameters(e, pos) + isnothing(params) && return copy(e.args) + args = Any[e.args[1:pos-1]..., e.args[pos+1:end]...] + return _flatten_params!(args, params) +end +function _flatten_params!(out::Vector{Any}, p::Expr) + p1 = expr_parameters(p, 1) + if !isnothing(p1) + push!(out, Expr(:parameters, p.args[2:end]...)) + _flatten_params!(out, p1) + else + push!(out, p::Any) + end + return out +end +function expr_parameters(p::Expr, pos::Int) + if length(p.args) >= pos && + p.args[pos] isa Expr && + p.args[pos].head === :parameters + return p.args[pos] + end + return nothing +end + +"Unwrap (usually block) if it has only one non-linenode child" +function maybe_strip_block(b::Expr) + e1 = findfirst(c -> !isa(c, LineNumberNode), b.args) + isnothing(e1) && return b + e2 = findfirst(c -> !isa(c, LineNumberNode), b.args[e1+1:end]) + !isnothing(e2) && return b + return b.args[e1] +end + +# Get kind by string if exists. TODO relies on internals +function find_kind(s::String) + out = get(JS._kind_str_to_int, s, nothing) + return isnothing(out) ? nothing : JS.Kind(out) +end + +function is_dotted_operator(s::AbstractString) + return length(s) >= 2 && + s[1] === '.' && + JS.is_operator(something(find_kind(s[2:end]), K"None")) +end + +# Expr doesn't record whether or not var"x" was used on x, so just assume one +# was used for any invalid identifier, but lose the information otherwise. +function _insert_var_str(child::NodeId, graph::SyntaxGraph, src::SourceAttrType) + var_id = _insert_tree_node(graph, K"var", src) + setchildren!(graph, var_id, [child]) + setflags!(graph, child, JS.RAW_STRING_FLAG) + setflags!(graph, var_id, JS.NON_TERMINAL_FLAG) + return (var_id, src) +end + +function is_call_expr(e) + return e isa Expr && (e.head === :call || + e.head in (:where, :(::)) && is_call_expr(e.args[1])) +end + +""" +Insert `e` converted to a syntaxtree into graph and recurse on children. Return +a pair (my_node_id, last_srcloc). Should not mutate `e`. + +`src` is the latest location found in the pre-order traversal, and is the line +number node to be associated with `e`. +""" +function _insert_convert_expr(@nospecialize(e), graph::SyntaxGraph, src::SourceAttrType) + if isnothing(e) + st_id = _insert_tree_node(graph, K"core", src) + setattr!(graph, st_id, name_val="nothing") + return (st_id, src) + elseif e isa Symbol + st_id = _insert_tree_node(graph, K"Identifier", src) + setattr!(graph, st_id; name_val=String(e)) + if !Base.isoperator(e) && !Base.is_valid_identifier(e) + return _insert_var_str(st_id, graph, src) + end + return (st_id, src) + elseif e isa LineNumberNode + return (nothing, e) + # elseif e isa QuoteNode + # st_id = _insert_tree_node(graph, K"inert", src) + # quote_child, _ = _insert_convert_expr(e.value, graph, src) + # setchildren!(graph, st_id, NodeId[quote_child]) + # return (st_id, src) + elseif e isa String + st_id = _insert_tree_node(graph, K"string", src) + id_inner = _insert_tree_node(graph, K"String", src) + setattr!(graph, id_inner, value=e) + setchildren!(graph, st_id, [id_inner]) + return (st_id, src) + elseif !(e isa Expr) + if !(e isa Union{Number, Bool, Char, GlobalRef, Nothing}) + # @info "unknown leaf type in expr, guessing value:" e typeof(e) + end + # TODO: st_k of Float. others? + st_k = e isa Integer ? K"Integer" : find_kind(string(typeof(e))) + st_id = _insert_tree_node(graph, isnothing(st_k) ? K"Value" : st_k, src) + setattr!(graph, st_id, value=e) + return (st_id, src) + end + nargs = length(e.args) + + # `e` is an expr. In many cases, it suffices to + # - guess that the kind name is the same as the expr head + # - add no syntax flags + # - map e.args to syntax tree children one-to-one + maybe_kind = find_kind(string(e.head)) + st_k = isnothing(maybe_kind) ? K"None" : maybe_kind + st_flags = 0x0000 + child_exprs::Vector{Any} = copy(e.args) + + # The following are special cases where the kind, flags, or children are + # different from what we guessed above. + if Base.isoperator(e.head) && st_k === K"None" + # e.head is an updating assignment operator (+=, .-=, etc). Non-= + # dotted ops are wrapped in a call, so we don't reach this. + s = string(e.head) + @assert s[end] === '=' && nargs === 2 + if s[1] === '.' + st_k = K".op=" + op = s[2:end-1] + else + st_k = K"op=" + op = s[1:end-1] + end + child_exprs = [e.args[1], Symbol(op), e.args[2]] + elseif e.head === :comparison + for i = 2:2:length(child_exprs) + op = child_exprs[i] + @assert op isa Symbol + op_s = string(op) + if is_dotted_operator(op_s) + child_exprs[i] = Expr(:., Symbol(op_s[2:end])) + end + end + elseif e.head === :macrocall + @assert nargs >= 2 + a1 = e.args[1] + child_exprs = collect_expr_parameters(e, 3) + # macrocall has a linenode "argument" here. should we set src? + deleteat!(child_exprs, 2) + if a1 isa Symbol + child_exprs[1] = Expr(:MacroName, a1) + elseif a1 isa Expr && a1.head === :(.) && a1.args[2] isa QuoteNode + child_exprs[1] = Expr(:(.), a1.args[1], Expr(:MacroName, a1.args[2].value)) + elseif a1 isa GlobalRef + # TODO syntax-introduced macrocalls + if a1.name === Symbol("@cmd") + # expr_children = [] + elseif a1.name === Symbol("@doc") + elseif a1.name === Symbol("@int128_str") + elseif a1.name === Symbol("@int128_str") + elseif a1.name === Symbol("@big_str") + end + elseif a1 isa Function + else + error("Unknown macrocall form $(sprint(dump, e))") + end + + # TODO node->expr handles do blocks here? + elseif e.head === Symbol("'") + @assert nargs === 1 + st_k = K"call" + st_flags |= JS.POSTFIX_OP_FLAG + child_exprs = [e.head, e.args[1]] + elseif e.head === :. && nargs === 2 + a2 = e.args[2] + if a2 isa Expr && a2.head === :tuple + st_k = K"dotcall" + tuple_exprs = collect_expr_parameters(a2, 1) + child_exprs = pushfirst!(tuple_exprs, e.args[1]) + elseif a2 isa QuoteNode && a2.value isa Symbol + e.args[2] = a2.value + elseif a2 isa Expr && a2.head === :MacroName + else + @error "Unknown 2-arg dot form?" e + end + elseif e.head === :for + @assert nargs === 2 + child_exprs = Expr[_to_iterspec(Any[e.args[1]]), e.args[2]] + elseif e.head === :where + @assert nargs >= 2 + if !(e.args[2] isa Expr && e.args[2].head === :braces) + child_exprs = [e.args[1], Expr(:braces, e.args[2:end]...)] + end + elseif e.head in (:tuple, :vect, :braces) + child_exprs = collect_expr_parameters(e, 1) + elseif e.head in (:curly, :ref) + child_exprs = collect_expr_parameters(e, 2) + elseif e.head === :try + child_exprs = Any[e.args[1]] + # Expr: + # (try (block ...) var (block ...) [block ...] [block ...]) + # # try catch_var catch finally else + # SyntaxTree: + # (try (block ...) + # [catch var (block ...)] + # [else (block ...)] + # [finally (block ...)]) + if e.args[2] != false || e.args[3] != false + push!(child_exprs, + Expr(:catch, + e.args[2] === false ? Expr(:catch_var_placeholder) : e.args[2], + e.args[3] === false ? nothing : e.args[3])) + end + if nargs >= 5 + push!(child_exprs, Expr(:else, e.args[5])) + end + if nargs >= 4 + push!(child_exprs, + Expr(:finally, e.args[4] === false ? nothing : e.args[4])) + end + elseif e.head === :flatten || e.head === :generator + st_k = K"generator" + child_exprs = Any[] + next = e + while next.head === :flatten + @assert next.args[1].head === :generator + push!(child_exprs, _to_iterspec(next.args[1].args[2:end])) + next = next.args[1].args[1] + end + @assert next.head === :generator + push!(child_exprs, _to_iterspec(next.args[2:end])) + pushfirst!(child_exprs, next.args[1]) + elseif e.head === :ncat || e.head === :nrow + st_flags |= JS.set_numeric_flags(e.args[1]) + child_exprs = child_exprs[2:end] + elseif e.head === :typed_ncat + st_flags |= JS.set_numeric_flags(e.args[2]) + deleteat!(child_exprs, 2) + elseif e.head === :(->) + @assert nargs === 2 + if !(e.args[1] isa Expr && e.args[1].head === :tuple) + child_exprs[1] = Expr(:tuple, e.args[1]) + end + child_exprs[2] = maybe_strip_block(e.args[2]) + elseif e.head === :call + child_exprs = collect_expr_parameters(e, 2) + a1 = child_exprs[1] + if a1 isa Symbol + a1s = string(a1) + if is_dotted_operator(a1s) + # non-assigning dotop like .+ or .== + st_k = K"dotcall" + child_exprs[1] = Symbol(a1s[2:end]) + end + end + elseif e.head === :(=) + if is_call_expr(e.args[1]) + st_k = K"function" + st_flags |= JS.SHORT_FORM_FUNCTION_FLAG + child_exprs[2] = maybe_strip_block(child_exprs[2]) + end + elseif e.head === :module + @assert nargs === 3 + if !e.args[1] + st_flags |= JS.BARE_MODULE_FLAG + end + child_exprs = [e.args[2], e.args[3]] + elseif e.head === :do + # Expr: + # (do (call f args...) (-> (tuple lam_args...) (block ...))) + # SyntaxTree: + # (call f args... (do (tuple lam_args...) (block ...))) + st_k = K"call" + child_exprs = [e.args[1].args..., Expr(:do_lambda, e.args[2].args...)] + elseif e.head === :let + if nargs >= 1 && !(e.args[1] isa Expr && e.args[1].head === :block) + child_exprs[1] = Expr(:block, e.args[1]) + end + elseif e.head === :struct + e.args[1] && (st_flags |= JS.MUTABLE_FLAG) + child_exprs = child_exprs[2:end] + # TODO handle docstrings after refactor + elseif (e.head === :using || e.head === :import) + _expr_replace!(e, + (e)->(e isa Expr && e.head === :.), + (e)->(e.head = :importpath)) + elseif e.head === :kw + st_k = K"=" + end + + # The following heads are not emitted from parsing, but old macros could + # produce these and they would historically be accepted by flisp lowering. + if e.head === Symbol("latestworld-if-toplevel") + st_k = K"latestworld_if_toplevel" + elseif e.head === Symbol("hygienic-scope") + st_k = K"hygienic_scope" + elseif e.head === :meta + # Messy and undocumented. Sometimes we want a K"meta". + @assert e.args[1] isa Symbol + if e.args[1] === :nospecialize + if nargs > 2 + st_k = K"block" + # Kick the can down the road (should only be simple atoms?) + child_exprs = map(c->Expr(:meta, :nospecialize, c), child_exprs[2:end]) + else + st_id, src = _insert_convert_expr(e.args[2], graph, src) + setmeta!(SyntaxTree(graph, st_id); nospecialize=true) + return st_id, src + end + else + @assert nargs === 1 + child_exprs[1] = Expr(:sym_not_identifier, e.args[1]) + end + elseif e.head === :symbolicgoto || e.head === :symboliclabel + @assert nargs === 1 + st_k = e.head === :symbolicgoto ? K"symbolic_label" : K"symbolic_goto" + st_id = _insert_tree_node(graph, st_k, src) + setattr!(graph, st_id, name_val=string(e.args[1])) + return (st_id, src) + elseif e.head === :inline || e.head === :noinline + @assert nargs === 1 && e.args[1] isa Bool + # TODO: JuliaLowering doesn't accept this (non-:meta) form yet + return (nothing, src) + elseif e.head === :core + @assert nargs === 1 + @assert e.args[1] isa Symbol + coreref_name = string(e.args[1]) + st_id = _insert_tree_node(graph, K"core", src) + setattr!(graph, st_id; name_val=coreref_name) + return st_id, src + elseif e.head === :islocal || e.head === :isglobal + st_k = K"extension" + child_exprs = [Expr(:sym_not_identifier, e.head), e.args[1]] + end + + # Temporary heads introduced by converting the parent expr + if e.head === :MacroName + @assert nargs === 1 + st_id = _insert_tree_node(graph, K"MacroName", src, st_flags) + mac_name = string(e.args[1]) + setattr!(graph, st_id, name_val=mac_name == "@__dot__" ? "@." : mac_name) + if !Base.is_valid_identifier(mac_name[2:end]) + return _insert_var_str(st_id, graph, src) + end + return (st_id, src) + elseif e.head === :catch_var_placeholder + st_id = _insert_tree_node(graph, K"Placeholder", src, st_flags) + setattr!(graph, st_id, name_val="") + return (st_id, src) + elseif e.head === :sym_not_identifier + estr = String(e.args[1]) + st_k = K"Symbol" + st_id = _insert_tree_node(graph, st_k, src) + setattr!(graph, st_id, name_val=estr) + return (st_id, src) + elseif e.head === :do_lambda + st_k = K"do" + end + + if st_k === K"None" + error("no kind for expr head `$(e.head)`\n$(sprint(dump, e))") + end + + st_flags |= JS.NON_TERMINAL_FLAG + st_id = _insert_tree_node(graph, st_k, src, st_flags) + st_child_ids, last_src = _insert_expr_children(child_exprs, graph, src) + setchildren!(graph, st_id, st_child_ids) + return st_id, last_src +end + +function _insert_expr_children(child_exprs::Vector{Any}, graph::SyntaxGraph, + src::SourceAttrType) + st_child_ids = NodeId[] + last_src = src + for c in child_exprs + (c_id, c_src) = _insert_convert_expr(c, graph, last_src) + isnothing(c_id) || push!(st_child_ids, c_id) + last_src = something(c_src, src) + end + return st_child_ids, last_src +end diff --git a/src/desugaring.jl b/src/desugaring.jl index b45603e5..0729032b 100644 --- a/src/desugaring.jl +++ b/src/desugaring.jl @@ -690,10 +690,10 @@ function expand_dotcall(ctx, ex) ] elseif k == K"comparison" expand_dotcall(ctx, expand_compare_chain(ctx, ex)) - elseif (k == K"&&" || k == K"||") && is_dotted(ex) + elseif k == K".&&" || k == K".||" @ast ctx ex [K"call" "broadcasted"::K"top" - (k == K"&&" ? "andand" : "oror")::K"top" + (k == K".&&" ? "andand" : "oror")::K"top" (expand_dotcall(ctx, arg) for arg in children(ex))... ] else @@ -702,8 +702,7 @@ function expand_dotcall(ctx, ex) end function expand_fuse_broadcast(ctx, ex) - if kind(ex) == K"=" - @assert is_dotted(ex) + if kind(ex) == K".=" || kind(ex) == K".op=" @chk numchildren(ex) == 2 lhs = ex[1] kl = kind(lhs) @@ -814,8 +813,7 @@ function expand_generator(ctx, ex) outervars_by_key = Dict{NameKey,typeof(ex)}() for iterspecs in ex[2:end-1] for iterspec in children(iterspecs) - lhs = iterspec[1] - foreach_lhs_var(lhs) do var + for var in lhs_bound_names(iterspec[1]) @assert kind(var) == K"Identifier" # Todo: K"BindingId"? outervars_by_key[NameKey(var)] = var end @@ -1165,16 +1163,20 @@ end # Expand assignments # Expand UnionAll definitions, eg `X{T} = Y{T,T}` -function expand_unionall_def(ctx, srcref, lhs, rhs) +function expand_unionall_def(ctx, srcref, lhs, rhs, is_const=true) if numchildren(lhs) <= 1 throw(LoweringError(lhs, "empty type parameter list in type alias")) end name = lhs[1] - @ast ctx srcref [K"block" - [K"const_if_global" name] - unionall_type := expand_forms_2(ctx, [K"where" rhs lhs[2:end]...]) - expand_forms_2(ctx, [K"=" name unionall_type]) - ] + expand_forms_2( + ctx, + @ast ctx srcref [K"block" + rr := [K"where" rhs lhs[2:end]...] + [is_const ? K"constdecl" : K"assign_or_constdecl_if_global" name rr] + [K"latestworld_if_toplevel"] + [K"removable" rr] + ] + ) end # Expand general assignment syntax, including @@ -1184,13 +1186,13 @@ end # * Assignments to array elements # * Destructuring # * Typed variable declarations -function expand_assignment(ctx, ex) +function expand_assignment(ctx, ex, is_const=false) @chk numchildren(ex) == 2 lhs = ex[1] rhs = ex[2] kl = kind(lhs) if kl == K"curly" - expand_unionall_def(ctx, ex, lhs, rhs) + expand_unionall_def(ctx, ex, lhs, rhs, is_const) elseif kind(rhs) == K"=" # Expand chains of assignments # a = b = c ==> b=c; a=c @@ -1207,7 +1209,9 @@ function expand_assignment(ctx, ex) tmp_rhs = ssavar(ctx, rhs, "rhs") rr = tmp_rhs end - for i in 1:length(stmts) + # In const a = b = c, only a is const + stmts[1] = @ast ctx ex [(is_const ? K"constdecl" : K"=") stmts[1] rr] + for i in 2:length(stmts) stmts[i] = @ast ctx ex [K"=" stmts[i] rr] end if !isnothing(tmp_rhs) @@ -1220,9 +1224,19 @@ function expand_assignment(ctx, ex) ] ) elseif is_identifier_like(lhs) - sink_assignment(ctx, ex, lhs, expand_forms_2(ctx, rhs)) + if is_const + @ast ctx ex [K"block" + rr := expand_forms_2(ctx, rhs) + [K"constdecl" lhs rr] + [K"latestworld"] + [K"removable" rr] + ] + else + sink_assignment(ctx, ex, lhs, expand_forms_2(ctx, rhs)) + end elseif kl == K"." # a.b = rhs ==> setproperty!(a, :b, rhs) + @chk !is_const (ex, "cannot declare `.` form const") @chk numchildren(lhs) == 2 a = lhs[1] b = lhs[2] @@ -1250,16 +1264,23 @@ function expand_assignment(ctx, ex) end elseif kl == K"ref" # a[i1, i2] = rhs + @chk !is_const (ex, "cannot declare ref form const") expand_forms_2(ctx, expand_setindex(ctx, ex)) elseif kl == K"::" && numchildren(lhs) == 2 x = lhs[1] T = lhs[2] - res = if is_identifier_like(x) + res = if is_const + expand_forms_2(ctx, @ast ctx ex [K"const" + [K"=" + lhs[1] + convert_for_type_decl(ctx, ex, rhs, T, true) + ]]) + elseif is_identifier_like(x) # Identifer in lhs[1] is a variable type declaration, eg # x::T = rhs @ast ctx ex [K"block" [K"decl" lhs[1] lhs[2]] - [K"=" lhs[1] rhs] + is_const ? [K"const" [K"=" lhs[1] rhs]] : [K"=" lhs[1] rhs] ] else # Otherwise just a type assertion, eg @@ -1271,6 +1292,7 @@ function expand_assignment(ctx, ex) # needs to be detected somewhere but won't be detected here. Maybe # it shows that remove_argument_side_effects() is not the ideal # solution here? + # TODO: handle underscore? @ast ctx ex [K"block" stmts... [K"::" l1 lhs[2]] @@ -1293,7 +1315,7 @@ end function expand_update_operator(ctx, ex) k = kind(ex) - dotted = is_dotted(ex) + dotted = k == K".op=" @chk numchildren(ex) == 3 lhs = ex[1] @@ -1335,7 +1357,7 @@ function expand_update_operator(ctx, ex) @ast ctx ex [K"block" stmts... - [K"="(syntax_flags=(dotted ? JuliaSyntax.DOTOP_FLAG : nothing)) + [(dotted ? K".=" : K"=") lhs [(dotted ? K"dotcall" : K"call") op @@ -1438,7 +1460,7 @@ function expand_let(ctx, ex) ] elseif kind(lhs) == K"tuple" lhs_locals = SyntaxList(ctx) - foreach_lhs_var(lhs) do var + for var in lhs_bound_names(lhs) push!(lhs_locals, @ast ctx var [K"local" var]) push!(lhs_locals, @ast ctx var [K"always_defined" var]) end @@ -1822,6 +1844,17 @@ function expand_call(ctx, ex) expand_forms_2(ctx, farg) expand_forms_2(ctx, _wrap_unsplatted_args(ctx, ex, args))... ] + elseif kind(farg) == K"Identifier" && farg.name_val == "include" + # world age special case + r = ssavar(ctx, ex) + @ast ctx ex [K"block" + [K"=" r [K"call" + expand_forms_2(ctx, farg) + expand_forms_2(ctx, args)... + ]] + [K"latestworld_if_toplevel"] + r + ] else @ast ctx ex [K"call" expand_forms_2(ctx, farg) @@ -1864,23 +1897,6 @@ end #------------------------------------------------------------------------------- # Expand for loops -# Extract the variable names assigned to from a "fancy assignment left hand -# side" such as nested tuple destructuring. -function foreach_lhs_var(f::Function, ex) - k = kind(ex) - if k == K"Identifier" || k == K"BindingId" - f(ex) - elseif k == K"::" && numchildren(ex) == 2 - foreach_lhs_var(f, ex[1]) - elseif k == K"tuple" || k == K"parameters" - for e in children(ex) - foreach_lhs_var(f, e) - end - end - # k == K"Placeholder" ignored, along with everything else - we assume - # validation is done elsewhere. -end - function expand_for(ctx, ex) iterspecs = ex[1] @@ -1896,7 +1912,7 @@ function expand_for(ctx, ex) @chk kind(iterspec) == K"in" lhs = iterspec[1] if kind(lhs) != K"outer" - foreach_lhs_var(lhs) do var + for var in lhs_bound_names(lhs) push!(copied_vars, @ast ctx var [K"=" var var]) end end @@ -1913,7 +1929,7 @@ function expand_for(ctx, ex) if outer lhs = lhs[1] end - foreach_lhs_var(lhs) do var + for var in lhs_bound_names(lhs) if outer push!(lhs_outer_defs, @ast ctx var var) else @@ -2068,7 +2084,7 @@ end # (x::T, (y::U, z)) # strip out stmts = (local x) (decl x T) (local x) (decl y U) (local z) # and return (x, (y, z)) -function strip_decls!(ctx, stmts, declkind, declkind2, declmeta, ex) +function strip_decls!(ctx, stmts, declkind, declmeta, ex) k = kind(ex) if k == K"Identifier" if !isnothing(declmeta) @@ -2076,9 +2092,6 @@ function strip_decls!(ctx, stmts, declkind, declkind2, declmeta, ex) else push!(stmts, makenode(ctx, ex, declkind, ex)) end - if !isnothing(declkind2) - push!(stmts, makenode(ctx, ex, declkind2, ex)) - end ex elseif k == K"Placeholder" ex @@ -2087,41 +2100,34 @@ function strip_decls!(ctx, stmts, declkind, declkind2, declmeta, ex) name = ex[1] @chk kind(name) == K"Identifier" push!(stmts, makenode(ctx, ex, K"decl", name, ex[2])) - strip_decls!(ctx, stmts, declkind, declkind2, declmeta, ex[1]) + strip_decls!(ctx, stmts, declkind, declmeta, ex[1]) elseif k == K"tuple" || k == K"parameters" cs = SyntaxList(ctx) for e in children(ex) - push!(cs, strip_decls!(ctx, stmts, declkind, declkind2, declmeta, e)) + push!(cs, strip_decls!(ctx, stmts, declkind, declmeta, e)) end makenode(ctx, ex, k, cs) + else + throw(LoweringError(ex, "invalid kind $k in $declkind declaration")) end end -# local x, (y=2), z ==> local x; local y; y = 2; local z -# const x = 1 ==> const x; x = 1 -# global x::T = 1 ==> (block (global x) (decl x T) (x = 1)) -function expand_decls(ctx, ex) +# Separate decls and assignments (which require re-expansion) +# local x, (y=2), z ==> local x; local z; y = 2 +function expand_decls(ctx, ex, is_const=false) declkind = kind(ex) + @assert declkind in KSet"local global" declmeta = get(ex, :meta, nothing) - if numchildren(ex) == 1 && kind(ex[1]) ∈ KSet"const global local" - declkind2 = kind(ex[1]) - bindings = children(ex[1]) - else - declkind2 = nothing - bindings = children(ex) - end + bindings = children(ex) stmts = SyntaxList(ctx) for binding in bindings kb = kind(binding) if is_prec_assignment(kb) @chk numchildren(binding) == 2 - lhs = strip_decls!(ctx, stmts, declkind, declkind2, declmeta, binding[1]) - push!(stmts, @ast ctx binding [kb lhs binding[2]]) - elseif is_sym_decl(binding) - if declkind == K"const" || declkind2 == K"const" - throw(LoweringError(ex, "expected assignment after `const`")) - end - strip_decls!(ctx, stmts, declkind, declkind2, declmeta, binding) + lhs = strip_decls!(ctx, stmts, declkind, declmeta, binding[1]) + push!(stmts, expand_assignment(ctx, @ast ctx binding [kb lhs binding[2]])) + elseif is_sym_decl(binding) && !is_const + strip_decls!(ctx, stmts, declkind, declmeta, binding) else throw(LoweringError(ex, "invalid syntax in variable declaration")) end @@ -2129,6 +2135,46 @@ function expand_decls(ctx, ex) makenode(ctx, ex, K"block", stmts) end +# Extract the variable names assigned to from a "fancy assignment left hand +# side" such as nested tuple destructuring, curlies, and calls. +function lhs_bound_names(ex, out=SyntaxList(ex)) + k = kind(ex) + if k == K"Placeholder" + # Ignored + elseif is_identifier_like(ex) + push!(out, ex) + elseif (k === K"::" && numchildren(ex) === 2) || k in KSet"call curly where" + lhs_bound_names(ex[1], out) + elseif k in KSet"tuple parameters" + map(c->lhs_bound_names(c, out), children(ex)) + end + return out +end + +function expand_const_decl(ctx, ex) + k = kind(ex[1]) + if k == K"global" + asgn = ex[1][1] + @chk (kind(asgn) == K"=") (ex, "expected assignment after `const`") + globals = map(lhs_bound_names(asgn[1])) do x + @ast ctx ex [K"global" x] + end + @ast ctx ex [K"block" + globals... + expand_assignment(ctx, asgn, true) + ] + elseif k == K"=" + if numchildren(ex[1]) >= 1 && kind(ex[1][1]) == K"tuple" + TODO(ex[1][1], "`const` tuple assignment desugaring") + end + expand_assignment(ctx, ex[1], true) + elseif k == K"local" + throw(LoweringError(ex, "unsupported `const local` declaration")) + else + throw(LoweringError(ex, "expected assignment after `const`")) + end +end + #------------------------------------------------------------------------------- # Expansion of function definitions @@ -2243,6 +2289,7 @@ function method_def_expr(ctx, srcref, callex_srcref, method_table, ret_var # might be `nothing` and hence removed ] ] + [K"latestworld"] [K"removable" method_metadata] ] end @@ -2371,10 +2418,12 @@ function expand_function_generator(ctx, srcref, callex_srcref, func_name, func_n # Code generator definition gen_func_method_defs = @ast ctx srcref [K"block" [K"function_decl" gen_name] + [K"latestworld_if_toplevel"] [K"scope_block"(scope_type=:hard) [K"method_defs" gen_name [K"block" + [K"latestworld_if_toplevel"] method_def_expr(ctx, srcref, callex_srcref, nothing, SyntaxList(ctx), gen_arg_names, gen_arg_types, gen_body, nothing) ] @@ -2708,6 +2757,7 @@ function keyword_function_defs(ctx, srcref, callex_srcref, name_str, typevar_nam kw_func_method_defs = @ast ctx srcref [K"block" [K"function_decl" body_func_name] + [K"latestworld"] [K"scope_block"(scope_type=:hard) [K"method_defs" body_func_name @@ -2777,6 +2827,7 @@ function expand_function_def(ctx, ex, docs, rewrite_call=identity, rewrite_body= end return @ast ctx ex [K"block" [K"function_decl" name] + [K"latestworld"] name ] end @@ -3013,6 +3064,7 @@ function expand_function_def(ctx, ex, docs, rewrite_call=identity, rewrite_body= end gen_func_method_defs kw_func_method_defs + [K"latestworld_if_toplevel"] [K"scope_block"(scope_type=:hard) [K"method_defs" isnothing(bare_func_name) ? "nothing"::K"core" : bare_func_name @@ -3313,20 +3365,24 @@ function expand_abstract_or_primitive_type(ctx, ex) ] [K"=" name newtype_var] [K"call" "_setsuper!"::K"core" newtype_var supertype] - [K"call" "_typebody!"::K"core" newtype_var] + [K"call" "_typebody!"::K"core" false::K"Bool" name] ] ] [K"assert" "toplevel_only"::K"Symbol" [K"inert" ex] ] [K"global" name] - [K"const" name] [K"if" [K"&&" - [K"isdefined" name] + [K"call" + "isdefinedglobal"::K"core" + ctx.mod::K"Value" + name=>K"Symbol" + false::K"Bool"] [K"call" "_equiv_typedef"::K"core" name newtype_var] ] nothing_(ctx, ex) - [K"=" name newtype_var] + [K"constdecl" name newtype_var] ] + [K"latestworld"] nothing_(ctx, ex) ] end @@ -3744,6 +3800,24 @@ function _constructor_min_initalized(ex::SyntaxTree) end end +# Let S be a struct we're defining in module M. Below is a hack to allow its +# field types to refer to S as M.S. See #56497. +function insert_struct_shim(ctx, fieldtypes, name) + function replace_type(ex) + if kind(ex) == K"." && + numchildren(ex) == 2 && + kind(ex[2]) == K"Symbol" && + ex[2].name_val == name.name_val + @ast ctx ex [K"call" "struct_name_shim"::K"core" ex[1] ex[2] ctx.mod::K"Value" name] + elseif numchildren(ex) > 0 + mapchildren(replace_type, ctx, ex) + else + ex + end + end + map(replace_type, fieldtypes) +end + function expand_struct_def(ctx, ex, docs) @chk numchildren(ex) == 2 type_sig = ex[1] @@ -3764,6 +3838,9 @@ function expand_struct_def(ctx, ex, docs) min_initialized = minimum((_constructor_min_initalized(e) for e in inner_defs), init=length(field_names)) newtype_var = ssavar(ctx, ex, "struct_type") + hasprev = ssavar(ctx, ex, "hasprev") + prev = ssavar(ctx, ex, "prev") + newdef = ssavar(ctx, ex, "newdef") layer = new_scope_layer(ctx, struct_name) global_struct_name = adopt_scope(struct_name, layer) if !isempty(typevar_names) @@ -3827,9 +3904,9 @@ function expand_struct_def(ctx, ex, docs) @ast ctx ex [K"block" [K"assert" "toplevel_only"::K"Symbol" [K"inert" ex] ] [K"scope_block"(scope_type=:hard) + # Needed for later constdecl to work, though plain global form may be removed soon. + [K"global" global_struct_name] [K"block" - [K"global" global_struct_name] - [K"const" global_struct_name] [K"local" struct_name] [K"always_defined" struct_name] typevar_stmts... @@ -3848,35 +3925,39 @@ function expand_struct_def(ctx, ex, docs) ] [K"=" struct_name newtype_var] [K"call"(supertype) "_setsuper!"::K"core" newtype_var supertype] - [K"if" - [K"isdefined" global_struct_name] - [K"if" - [K"call" "_equiv_typedef"::K"core" global_struct_name newtype_var] - [K"block" - # If this is compatible with an old definition, use - # the existing type object and throw away the new - # type - [K"=" struct_name global_struct_name] - if !isempty(typevar_names) - # And resassign the typevar_names - these may be - # referenced in the definition of the field - # types below - [K"=" - [K"tuple" typevar_names...] - prev_typevars - ] - end - ] - # Otherwise do an assignment to trigger an error - [K"=" global_struct_name struct_name] + [K"=" hasprev + [K"&&" [K"call" "isdefinedglobal"::K"core" + ctx.mod::K"Value" + struct_name=>K"Symbol" + false::K"Bool"] + [K"call" "_equiv_typedef"::K"core" global_struct_name newtype_var] + ]] + [K"=" prev [K"if" hasprev global_struct_name false::K"Bool"]] + [K"if" hasprev + [K"block" + # if this is compatible with an old definition, use the old parameters, but the + # new object. This will fail to capture recursive cases, but the call to typebody! + # below is permitted to choose either type definition to put into the binding table + if !isempty(typevar_names) + # And resassign the typevar_names - these may be + # referenced in the definition of the field + # types below + [K"=" [K"tuple" typevar_names...] prev_typevars] + end ] - [K"=" global_struct_name struct_name] - ] - [K"call"(type_body) - "_typebody!"::K"core" - struct_name - [K"call" "svec"::K"core" field_types...] ] + [K"=" newdef + [K"call"(type_body) + "_typebody!"::K"core" + prev + newtype_var + [K"call" "svec"::K"core" insert_struct_shim(ctx, field_types, struct_name)...] + ]] + [K"constdecl" + global_struct_name + newdef + ] + [K"latestworld"] # Default constructors if isempty(inner_defs) default_inner_constructors(ctx, ex, global_struct_name, @@ -4172,7 +4253,7 @@ function expand_forms_2(ctx::DesugaringContext, ex::SyntaxTree, docs=nothing) throw(LoweringError(ex, "unimplemented or unsupported atomic declaration")) elseif k == K"call" expand_call(ctx, ex) - elseif k == K"dotcall" || ((k == K"&&" || k == K"||") && is_dotted(ex)) + elseif k == K"dotcall" || k == K".&&" || k == K".||" || k == K".=" expand_forms_2(ctx, expand_fuse_broadcast(ctx, ex)) elseif k == K"." expand_forms_2(ctx, expand_dot(ctx, ex)) @@ -4208,14 +4289,10 @@ function expand_forms_2(ctx::DesugaringContext, ex::SyntaxTree, docs=nothing) adopt_scope(string(k)::K"Identifier", ex) children(ex)... ]) - elseif k == K"op=" + elseif k == K"op=" || k == K".op=" expand_forms_2(ctx, expand_update_operator(ctx, ex)) elseif k == K"=" - if is_dotted(ex) - expand_forms_2(ctx, expand_fuse_broadcast(ctx, ex)) - else - expand_assignment(ctx, ex) - end + expand_assignment(ctx, ex) elseif k == K"break" numchildren(ex) > 0 ? ex : @ast ctx ex [K"break" "loop_exit"::K"symbolic_label"] @@ -4271,12 +4348,14 @@ function expand_forms_2(ctx::DesugaringContext, ex::SyntaxTree, docs=nothing) ] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, ex)) - elseif k == K"local" || k == K"global" || k == K"const" - if numchildren(ex) == 1 && kind(ex[1]) == K"Identifier" - # Don't recurse when already simplified - `local x`, etc - ex + elseif k == K"const" + expand_const_decl(ctx, ex) + elseif k == K"local" || k == K"global" + if k == K"global" && kind(ex[1]) == K"const" + # Normalize `global const` to `const global` + expand_const_decl(ctx, @ast ctx ex [K"const" [K"global" ex[1][1]]]) else - expand_forms_2(ctx, expand_decls(ctx, ex)) + expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) diff --git a/src/eval.jl b/src/eval.jl index eb4f2806..93e43ef2 100644 --- a/src/eval.jl +++ b/src/eval.jl @@ -12,6 +12,18 @@ function macroexpand(mod::Module, ex) ex1 end +function codeinfo_has_image_globalref(@nospecialize(e)) + if e isa GlobalRef + return 0x00 !== @ccall jl_object_in_image(e.mod::Any)::UInt8 + elseif e isa Core.CodeInfo + return any(codeinfo_has_image_globalref, e.code) + elseif e isa Expr + return any(codeinfo_has_image_globalref, e.args) + else + return false + end +end + _CodeInfo_need_ver = v"1.12.0-DEV.512" if VERSION < _CodeInfo_need_ver function _CodeInfo(args...) @@ -20,19 +32,29 @@ if VERSION < _CodeInfo_need_ver else # debuginfo changed completely as of https://github.com/JuliaLang/julia/pull/52415 # nargs / isva was added as of https://github.com/JuliaLang/julia/pull/54341 + # field rettype added in https://github.com/JuliaLang/julia/pull/54655 + # field has_image_globalref added in https://github.com/JuliaLang/julia/pull/57433 # CodeInfo constructor. TODO: Should be in Core let fns = fieldnames(Core.CodeInfo) fts = fieldtypes(Core.CodeInfo) conversions = [:(convert($t, $n)) for (t,n) in zip(fts, fns)] - expected_fns = (:code, :debuginfo, :ssavaluetypes, :ssaflags, :slotnames, :slotflags, :slottypes, :parent, :method_for_inference_limit_heuristics, :edges, :min_world, :max_world, :nargs, :propagate_inbounds, :has_fcall, :nospecializeinfer, :isva, :inlining, :constprop, :purity, :inlining_cost) - expected_fts = (Vector{Any}, Core.DebugInfo, Any, Vector{UInt32}, Vector{Symbol}, Vector{UInt8}, Any, Any, Any, Any, UInt64, UInt64, UInt64, Bool, Bool, Bool, Bool, UInt8, UInt8, UInt16, UInt16) + expected_fns = (:code, :debuginfo, :ssavaluetypes, :ssaflags, :slotnames, :slotflags, :slottypes, :rettype, :parent, :edges, :min_world, :max_world, :method_for_inference_limit_heuristics, :nargs, :propagate_inbounds, :has_fcall, :has_image_globalref, :nospecializeinfer, :isva, :inlining, :constprop, :purity, :inlining_cost) + expected_fts = (Vector{Any}, Core.DebugInfo, Any, Vector{UInt32}, Vector{Symbol}, Vector{UInt8}, Any, Any, Any, Any, UInt64, UInt64, Any, UInt64, Bool, Bool, Bool, Bool, Bool, UInt8, UInt8, UInt16, UInt16) - code = if fns != expected_fns || fts != expected_fts + code = if fns != expected_fns + unexpected_fns = collect(setdiff(Set(fns), Set(expected_fns))) + missing_fns = collect(setdiff(Set(expected_fns), Set(fns))) :(function _CodeInfo(args...) - error("Unrecognized CodeInfo layout: Maybe version $VERSION is to new for this version of JuliaLowering?") - end) + error("Unrecognized CodeInfo fields: Maybe version $VERSION is too new for this version of JuliaLowering?" + * isempty(unexpected_fns) ? "" : "\nUnexpected fields found: $($unexpected_fns)" + * isempty(missing_fns) ? "" : "\nMissing fields: $($missing_fns)") + end) + elseif fts != expected_fts + :(function _CodeInfo(args...) + error("Unrecognized CodeInfo field types: Maybe version $VERSION is too new for this version of JuliaLowering?") + end) else :(function _CodeInfo($(fns...)) $(Expr(:new, :(Core.CodeInfo), conversions...)) @@ -142,6 +164,8 @@ function to_code_info(ex, mod, funcname, slots) debuginfo = finish_ir_debug_info!(current_codelocs_stack) + has_image_globalref = any(codeinfo_has_image_globalref, stmts) + # TODO: Set ssaflags based on call site annotations: # - @inbounds annotations # - call site @inline / @noinline @@ -172,6 +196,7 @@ function to_code_info(ex, mod, funcname, slots) max_world = typemax(Csize_t) isva = false inlining_cost = 0xffff + rettype = Any _CodeInfo( stmts, @@ -181,14 +206,16 @@ function to_code_info(ex, mod, funcname, slots) slotnames, slotflags, slottypes, + rettype, parent, - method_for_inference_limit_heuristics, edges, min_world, max_world, + method_for_inference_limit_heuristics, nargs, propagate_inbounds, has_fcall, + has_image_globalref, nospecializeinfer, isva, inlining, @@ -213,12 +240,7 @@ function to_lowered_expr(mod, ex, ssa_offset=0) elseif k == K"top" GlobalRef(Base, Symbol(ex.name_val)) elseif k == K"globalref" - if mod === ex.mod - # Implicitly refers to name in parent module. - Symbol(ex.name_val) - else - GlobalRef(ex.mod, Symbol(ex.name_val)) - end + GlobalRef(ex.mod, Symbol(ex.name_val)) elseif k == K"Identifier" # Implicitly refers to name in parent module # TODO: Should we even have plain identifiers at this point or should @@ -268,8 +290,6 @@ function to_lowered_expr(mod, ex, ssa_offset=0) Core.NewvarNode(to_lowered_expr(mod, ex[1], ssa_offset)) elseif k == K"new_opaque_closure" args = map(e->to_lowered_expr(mod, e, ssa_offset), children(ex)) - # TODO: put allow_partial back in once we update to the latest julia - splice!(args, 4) # allow_partial Expr(:new_opaque_closure, args...) elseif k == K"meta" args = Any[to_lowered_expr(mod, e, ssa_offset) for e in children(ex)] @@ -288,9 +308,11 @@ function to_lowered_expr(mod, ex, ssa_offset=0) k == K"splatnew" ? :splatnew : k == K"=" ? :(=) : k == K"global" ? :global : - k == K"const" ? :const : + k == K"constdecl" ? :const : k == K"leave" ? :leave : k == K"isdefined" ? :isdefined : + k == K"latestworld" ? :latestworld : + k == K"globaldecl" ? :globaldecl : k == K"pop_exception" ? :pop_exception : k == K"captured_local" ? :captured_local : k == K"gc_preserve_begin" ? :gc_preserve_begin : diff --git a/src/kinds.jl b/src/kinds.jl index 6a1a4ecc..0ccf145f 100644 --- a/src/kinds.jl +++ b/src/kinds.jl @@ -49,6 +49,9 @@ function _register_kinds() # Internal initializer for struct types, for inner constructors/functions "new" "splatnew" + # For expr-macro compatibility; gone after expansion + "escape" + "hygienic_scope" # Catch-all for additional syntax extensions without the need to # extend `Kind`. Known extensions include: # locals, islocal @@ -96,7 +99,7 @@ function _register_kinds() "_opaque_closure" # The enclosed statements must be executed at top level "toplevel_butfirst" - "const_if_global" + "assign_or_constdecl_if_global" "moved_local" "label" "trycatchelse" @@ -111,6 +114,8 @@ function _register_kinds() # A local variable captured into a global method. Contains the # `index` of the associated `Box` in the rewrite list. "captured_local" + # Causes the linearization pass to conditionally emit a world age increment + "latestworld_if_toplevel" "END_LOWERING_KINDS" # The following kinds are emitted by lowering and used in Julia's untyped IR @@ -121,8 +126,12 @@ function _register_kinds() "slot" # Static parameter to a `CodeInfo` code object ("type parameters" to methods) "static_parameter" - # Reference to a global variable within a module + # References/declares a global variable within a module "globalref" + "globaldecl" + # Two-argument constant declaration and assignment. + # Translated to :const in the IR for now (we use K"const" already in parsing). + "constdecl" # Unconditional goto "goto" # Conditional goto @@ -143,6 +152,8 @@ function _register_kinds() "new_opaque_closure" # Wrapper for the lambda of around opaque closure methods "opaque_closure_method" + # World age increment + "latestworld" "END_IR_KINDS" ]) end diff --git a/src/linear_ir.jl b/src/linear_ir.jl index 0bb91f97..d356d2f7 100644 --- a/src/linear_ir.jl +++ b/src/linear_ir.jl @@ -3,7 +3,7 @@ function is_valid_ir_argument(ctx, ex) k = kind(ex) - if is_simple_atom(ctx, ex) || k == K"inert" || k == K"top" || k == K"core" + if is_simple_atom(ctx, ex) || k in KSet"inert top core quote" true elseif k == K"BindingId" binfo = lookup_binding(ctx, ex) @@ -11,16 +11,7 @@ function is_valid_ir_argument(ctx, ex) # TODO: Can we allow bk == :local || bk == :argument || bk == :static_parameter ??? # Why does flisp seem to allow (slot) and (static_parameter), but these # aren't yet converted to by existing lowering?? - if bk == :global - # Globals are nothrow when they are defined - we assume a previously - # defined global can never be set to undefined. (TODO: This could be - # broken when precompiling a module `B` in the presence of a badly - # behaved module `A`, which inconsistently defines globals during - # `A.__init__()`??) - is_defined_nothrow_global(binfo.mod, Symbol(binfo.name)) - else - false - end + (bk == :slot || bk == :static_parameter) else false end @@ -69,7 +60,7 @@ end Context for creating linear IR. One of these is created per lambda expression to flatten the body down to -a sequence of statements (linear IR). +a sequence of statements (linear IR), which eventually becomes one CodeInfo. """ struct LinearIRContext{GraphType} <: AbstractLoweringContext graph::GraphType @@ -334,18 +325,35 @@ function emit_break(ctx, ex) emit_jump(ctx, ex, target) end -function emit_assignment(ctx, srcref, lhs, rhs) +# `op` may also be K"constdecl" +function emit_assignment_or_setglobal(ctx, srcref, lhs, rhs, op=K"=") + # (const (globalref _ _) _) does not use setglobal! + binfo = lookup_binding(ctx, lhs.var_id) + if binfo.kind == :global && op == K"=" + emit(ctx, @ast ctx srcref [ + K"call" + "setglobal!"::K"core" + binfo.mod::K"Value" + binfo.name::K"Symbol" + rhs + ]) + else + emit(ctx, srcref, op, lhs, rhs) + end +end + +function emit_assignment(ctx, srcref, lhs, rhs, op=K"=") if !isnothing(rhs) if is_valid_ir_rvalue(ctx, lhs, rhs) - emit(ctx, srcref, K"=", lhs, rhs) + emit_assignment_or_setglobal(ctx, srcref, lhs, rhs, op) else r = emit_assign_tmp(ctx, rhs) - emit(ctx, srcref, K"=", lhs, r) + emit_assignment_or_setglobal(ctx, srcref, lhs, r, op) end else # in unreachable code (such as after return); still emit the assignment # so that the structure of those uses is preserved - emit(ctx, @ast ctx srcref [K"=" lhs "nothing"::K"core"]) + emit_assignment_or_setglobal(ctx, srcref, lhs, @ast ctx srcref "nothing"::K"core", op) nothing end end @@ -640,7 +648,7 @@ function compile(ctx::LinearIRContext, ex, needs_value, in_tail_pos) emit(ctx, callex) nothing end - elseif k == K"=" + elseif k == K"=" || k == K"constdecl" lhs = ex[1] if kind(lhs) == K"Placeholder" compile(ctx, ex[2], needs_value, in_tail_pos) @@ -649,14 +657,14 @@ function compile(ctx::LinearIRContext, ex, needs_value, in_tail_pos) # TODO look up arg-map for renaming if lhs was reassigned if needs_value && !isnothing(rhs) r = emit_assign_tmp(ctx, rhs) - emit(ctx, ex, K"=", lhs, r) + emit_assignment_or_setglobal(ctx, ex, lhs, r, k) if in_tail_pos emit_return(ctx, ex, r) else r end else - emit_assignment(ctx, ex, lhs, rhs) + emit_assignment(ctx, ex, lhs, rhs, k) end end elseif k == K"block" || k == K"scope_block" @@ -811,12 +819,19 @@ function compile(ctx::LinearIRContext, ex, needs_value, in_tail_pos) end elseif k == K"gc_preserve_begin" makenode(ctx, ex, k, compile_args(ctx, children(ex))) - elseif k == K"gc_preserve_end" || k == K"global" || k == K"const" + elseif k == K"gc_preserve_end" if needs_value throw(LoweringError(ex, "misplaced kind $k in value position")) end emit(ctx, ex) nothing + elseif k == K"global" + if needs_value + throw(LoweringError(ex, "misplaced kind $k in value position")) + end + emit(ctx, ex) + ctx.is_toplevel_thunk && emit(ctx, makenode(ctx, ex, K"latestworld")) + nothing elseif k == K"meta" emit(ctx, ex) if needs_value @@ -862,6 +877,21 @@ function compile(ctx::LinearIRContext, ex, needs_value, in_tail_pos) # TODO: also exclude deleted vars emit(ctx, ex) end + elseif k == K"globaldecl" + if needs_value + throw(LoweringError(ex, "misplaced global declaration")) + end + if numchildren(ex) == 1 || is_identifier_like(ex[2]) + emit(ctx, ex) + else + rr = emit_assign_tmp(ctx, ex[2]) + emit(ctx, @ast ctx ex [K"globaldecl" ex[1] rr]) + end + ctx.is_toplevel_thunk && emit(ctx, makenode(ctx, ex, K"latestworld")) + elseif k == K"latestworld" + emit(ctx, ex) + elseif k == K"latestworld_if_toplevel" + ctx.is_toplevel_thunk && emit(ctx, makeleaf(ctx, ex, K"latestworld")) else throw(LoweringError(ex, "Invalid syntax; $(repr(k))")) end diff --git a/src/runtime.jl b/src/runtime.jl index a3d9c2ce..23252400 100644 --- a/src/runtime.jl +++ b/src/runtime.jl @@ -130,7 +130,7 @@ function eval_closure_type(mod, closure_type_name, field_names, field_is_box) length(field_names)) Core._setsuper!(type, Core.Function) Base.eval(mod, :(const $closure_type_name = $type)) - Core._typebody!(type, Core.svec(field_types...)) + Core._typebody!(false, type, Core.svec(field_types...)) type end @@ -209,9 +209,8 @@ function module_import(into_mod::Module, is_using::Bool, end function module_public(mod::Module, is_exported::Bool, identifiers...) - for ident in identifiers - @ccall jl_module_public(mod::Module, Symbol(ident)::Symbol, is_exported::Cint)::Cvoid - end + # symbol jl_module_public is no longer exported as of #57765 + eval(mod, Expr((is_exported ? :export : :public), map(Symbol, identifiers)...)) end #-------------------------------------------------- @@ -282,7 +281,7 @@ end # expression into a CodeInfo. # # `args` passed into stub by the Julia runtime are (parent_func, static_params..., arg_types...) -function (g::GeneratedFunctionStub)(world::UInt, source::LineNumberNode, @nospecialize args...) +function (g::GeneratedFunctionStub)(world::UInt, source::Method, @nospecialize args...) # Some of the lowering pipeline from lower() and the pass-specific setup is # re-implemented here because generated functions are very much (but not # entirely) like macro expansion. @@ -334,7 +333,7 @@ function (g::GeneratedFunctionStub)(world::UInt, source::LineNumberNode, @nospec ctx2, ex2 = expand_forms_2( ctx1, ex1) # Wrap expansion in a non-toplevel lambda and run scope resolution - ex2 = @ast ctx2 source [K"lambda"(is_toplevel_thunk=false) + ex2 = @ast ctx2 ex0 [K"lambda"(is_toplevel_thunk=false) [K"block" (string(n)::K"Identifier" for n in g.argnames)... ] @@ -371,18 +370,7 @@ end # # (This should do what fl_defined_julia_global does for flisp lowering) function is_defined_and_owned_global(mod, name) - b = _get_module_binding(mod, name) - !isnothing(b) && isdefined(b, :owner) && b.owner === b -end - -# Return true if `name` is defined in `mod`, the sense that accessing it is nothrow. -# Has no side effects, unlike isdefined() -# -# (This should do what fl_nothrow_julia_global does for flisp lowering) -function is_defined_nothrow_global(mod, name) - b = _get_module_binding(mod, name) - !isnothing(b) && isdefined(b, :owner) || return false - isdefined(b.owner, :value) + Base.binding_kind(mod, name) === Base.PARTITION_KIND_GLOBAL end # "Reserve" a binding: create the binding if it doesn't exist but do not assign diff --git a/src/scope_analysis.jl b/src/scope_analysis.jl index 343b5c6b..38e8e23a 100644 --- a/src/scope_analysis.jl +++ b/src/scope_analysis.jl @@ -44,7 +44,11 @@ function _find_scope_vars!(ctx, assignments, locals, destructured_args, globals, end elseif k == K"global" _insert_if_not_present!(globals, NameKey(ex[1]), ex) - elseif k == K"=" + elseif k == K"assign_or_constdecl_if_global" + # like v = val, except that if `v` turns out global(either implicitly or + # by explicit `global`), it gains an implicit `const` + _insert_if_not_present!(assignments, NameKey(ex[1]), ex) + elseif k == K"=" || k == K"constdecl" v = decl_var(ex[1]) if !(kind(v) in KSet"BindingId globalref Placeholder") _insert_if_not_present!(assignments, NameKey(v), v) @@ -561,12 +565,14 @@ function _resolve_scopes(ctx, ex::SyntaxTree) end end resolved - elseif k == K"const_if_global" + elseif k == K"assign_or_constdecl_if_global" id = _resolve_scopes(ctx, ex[1]) - if lookup_binding(ctx, id).kind == :global - @ast ctx ex [K"const" id] + bk = lookup_binding(ctx, id).kind + @assert numchildren(ex) === 2 + if bk == :global + @ast ctx ex _resolve_scopes(ctx, [K"constdecl" ex[1] ex[2]]) else - makeleaf(ctx, ex, K"TOMBSTONE") + @ast ctx ex _resolve_scopes(ctx, [K"=" ex[1] ex[2]]) end else mapchildren(e->_resolve_scopes(ctx, e), ctx, ex) @@ -677,7 +683,7 @@ function analyze_variables!(ctx, ex) if kind(ex[1]) != K"BindingId" || lookup_binding(ctx, ex[1]).kind !== :local analyze_variables!(ctx, ex[1]) end - elseif k == K"const" + elseif k == K"constdecl" id = ex[1] if lookup_binding(ctx, id).kind == :local throw(LoweringError(ex, "unsupported `const` declaration on local variable")) diff --git a/src/syntax_graph.jl b/src/syntax_graph.jl index bdbf98e0..e5948da1 100644 --- a/src/syntax_graph.jl +++ b/src/syntax_graph.jl @@ -137,17 +137,20 @@ function Base.getproperty(graph::SyntaxGraph, name::Symbol) end function sethead!(graph, id::NodeId, h::JuliaSyntax.SyntaxHead) - graph.kind[id] = kind(h) - f = flags(h) - if f != 0 - graph.syntax_flags[id] = f - end + 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) + if f != 0 + graph.syntax_flags[id] = f + end +end + function _convert_nodes(graph::SyntaxGraph, node::SyntaxNode) id = newnode!(graph) sethead!(graph, id, head(node)) @@ -243,7 +246,7 @@ function attrnames(ex::SyntaxTree) [name for (name, value) in pairs(attrs) if haskey(value, ex._id)] end -function setattr(ex::SyntaxTree; extra_attrs...) +function copy_node(ex::SyntaxTree) graph = syntax_graph(ex) id = newnode!(graph) if !is_leaf(ex) @@ -251,6 +254,11 @@ function setattr(ex::SyntaxTree; extra_attrs...) 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 @@ -307,6 +315,7 @@ JuliaSyntax.source_line(src::LineNumberNode) = src.line # The follow somewhat strange cases are for where LineNumberNode is standing in # for SourceFile because we've only got Expr-based provenance info JuliaSyntax.sourcefile(src::LineNumberNode) = src +JuliaSyntax.sourcetext(src::LineNumberNode) = SubString("") JuliaSyntax.source_location(src::LineNumberNode, byte_index::Integer) = (src.line, 0) JuliaSyntax.source_location(::Type{LineNumberNode}, src::LineNumberNode, byte_index::Integer) = src JuliaSyntax.filename(src::LineNumberNode) = string(src.file) @@ -431,6 +440,7 @@ function _value_string(ex) k == K"Symbol" ? ":$(ex.name_val)" : k == K"globalref" ? "$(ex.mod).$(ex.name_val)" : k == K"slot" ? "slot" : + k == K"latestworld" ? "(latestworld)" : k == K"static_parameter" ? "static_parameter" : k == K"symbolic_label" ? "label:$(ex.name_val)" : k == K"symbolic_goto" ? "goto:$(ex.name_val)" : @@ -536,13 +546,11 @@ end JuliaSyntax.sourcefile(ex::SyntaxTree) = sourcefile(sourceref(ex)) JuliaSyntax.byte_range(ex::SyntaxTree) = byte_range(sourceref(ex)) -function JuliaSyntax._expr_leaf_val(ex::SyntaxTree) +function JuliaSyntax._expr_leaf_val(ex::SyntaxTree, _...) name = get(ex, :name_val, nothing) - if !isnothing(name) - Symbol(name) - else - ex.value - end + !isnothing(name) && return Symbol(name) + name = get(ex, :value, nothing) + return name end Base.Expr(ex::SyntaxTree) = JuliaSyntax.to_expr(ex) @@ -603,7 +611,7 @@ macro SyntaxTree(ex_old) throw(ArgumentError("@SyntaxTree expects a `quote` block or `:`-quoted expression")) end # 2. Re-parse the current source file as SyntaxTree instead - fname = String(__source__.file) + fname = isnothing(__source__.file) ? error("No current file") : String(__source__.file) if occursin(r"REPL\[\d+\]", fname) # Assume we should look at last history entry in REPL try diff --git a/src/utils.jl b/src/utils.jl index 5d749f05..b6f9e834 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -47,12 +47,12 @@ function showprov(io::IO, exs::AbstractVector; print(io, "\n\n") end k = kind(ex) - if isnothing(note) # use provided `note` otherwise - note = i > 1 && k == K"macrocall" ? "in macro expansion" : - i > 1 && k == K"$" ? "interpolated here" : - "in source" + if isnothing(note) + fallback_note = i > 1 && k == K"macrocall" ? "in macro expansion" : + i > 1 && k == K"$" ? "interpolated here" : + "in source" end - highlight(io, sr; note=note, highlight_kwargs...) + highlight(io, sr; note=something(note, fallback_note), highlight_kwargs...) if include_location line, _ = source_location(sr) diff --git a/test/assignments_ir.jl b/test/assignments_ir.jl index 9a1393c2..31fc09f1 100644 --- a/test/assignments_ir.jl +++ b/test/assignments_ir.jl @@ -31,20 +31,22 @@ begin end #--------------------- 1 (method TestMod.b) -2 TestMod.b -3 (call core.Typeof %₂) -4 (call core.svec %₃) -5 (call core.svec) -6 SourceLocation::3:9 -7 (call core.svec %₄ %₅ %₆) -8 --- method core.nothing %₇ +2 (latestworld) +3 TestMod.b +4 (call core.Typeof %₃) +5 (call core.svec %₄) +6 (call core.svec) +7 SourceLocation::3:9 +8 (call core.svec %₅ %₆ %₇) +9 --- method core.nothing %₈ slots: [slot₁/#self#(!read) slot₂/c(!read)] 1 TestMod.d 2 (= slot₂/c %₁) 3 (return %₁) -9 TestMod.b -10 (= slot₁/a %₉) -11 (return %₉) +10 (latestworld) +11 TestMod.b +12 (= slot₁/a %₁₁) +13 (return %₁₁) ######################################## # a.b = ... => setproperty! assignment @@ -117,17 +119,17 @@ end # UnionAll expansion at global scope results in const decl X{T} = Y{T,T} #--------------------- -1 (const TestMod.X) -2 (call core.TypeVar :T) -3 (= slot₁/T %₂) -4 slot₁/T -5 TestMod.Y +1 (call core.TypeVar :T) +2 (= slot₁/T %₁) +3 slot₁/T +4 TestMod.Y +5 slot₁/T 6 slot₁/T -7 slot₁/T -8 (call core.apply_type %₅ %₆ %₇) -9 (call core.UnionAll %₄ %₈) -10 (= TestMod.X %₉) -11 (return %₉) +7 (call core.apply_type %₄ %₅ %₆) +8 (call core.UnionAll %₃ %₇) +9 (constdecl TestMod.X %₈) +10 (latestworld) +11 (return %₈) ######################################## # UnionAll expansion in local scope @@ -144,7 +146,8 @@ end 7 (call core.apply_type %₄ %₅ %₆) 8 (call core.UnionAll %₃ %₇) 9 (= slot₁/X %₈) -10 (return %₈) +10 (latestworld) +11 (return %₈) ######################################## # Error: Invalid lhs in `=` diff --git a/test/closures_ir.jl b/test/closures_ir.jl index 6d6d1339..ac5246ea 100644 --- a/test/closures_ir.jl +++ b/test/closures_ir.jl @@ -15,16 +15,18 @@ end 5 (call core.svec :x) 6 (call core.svec true) 7 (call JuliaLowering.eval_closure_type TestMod :#f##0 %₅ %₆) -8 TestMod.#f##0 -9 slot₂/x -10 (new %₈ %₉) -11 (= slot₁/f %₁₀) -12 TestMod.#f##0 -13 (call core.svec %₁₂ core.Any) -14 (call core.svec) -15 SourceLocation::3:14 -16 (call core.svec %₁₃ %₁₄ %₁₅) -17 --- method core.nothing %₁₆ +8 (latestworld) +9 TestMod.#f##0 +10 slot₂/x +11 (new %₉ %₁₀) +12 (= slot₁/f %₁₁) +13 (latestworld) +14 TestMod.#f##0 +15 (call core.svec %₁₄ core.Any) +16 (call core.svec) +17 SourceLocation::3:14 +18 (call core.svec %₁₅ %₁₆ %₁₇) +19 --- method core.nothing %₁₈ slots: [slot₁/#self#(!read) slot₂/y slot₃/x(!read)] 1 TestMod.+ 2 (call core.getfield slot₁/#self# :x) @@ -36,8 +38,9 @@ end 8 (call core.getfield %₂ :contents) 9 (call %₁ %₈ slot₂/y) 10 (return %₉) -18 slot₁/f -19 (return %₁₈) +20 (latestworld) +21 slot₁/f +22 (return %₂₁) ######################################## # Closure declaration with no methods @@ -50,11 +53,13 @@ end 1 (call core.svec) 2 (call core.svec) 3 (call JuliaLowering.eval_closure_type TestMod :#no_method_f##0 %₁ %₂) -4 TestMod.#no_method_f##0 -5 (new %₄) -6 (= slot₁/no_method_f %₅) -7 slot₁/no_method_f -8 (return %₇) +4 (latestworld) +5 TestMod.#no_method_f##0 +6 (new %₅) +7 (= slot₁/no_method_f %₆) +8 (latestworld) +9 slot₁/no_method_f +10 (return %₉) ######################################## # Closure which sets the value of a captured variable @@ -72,23 +77,26 @@ end 5 (call core.svec :x) 6 (call core.svec true) 7 (call JuliaLowering.eval_closure_type TestMod :#f##1 %₅ %₆) -8 TestMod.#f##1 -9 slot₂/x -10 (new %₈ %₉) -11 (= slot₁/f %₁₀) -12 TestMod.#f##1 -13 (call core.svec %₁₂ core.Any) -14 (call core.svec) -15 SourceLocation::3:14 -16 (call core.svec %₁₃ %₁₄ %₁₅) -17 --- method core.nothing %₁₆ +8 (latestworld) +9 TestMod.#f##1 +10 slot₂/x +11 (new %₉ %₁₀) +12 (= slot₁/f %₁₁) +13 (latestworld) +14 TestMod.#f##1 +15 (call core.svec %₁₄ core.Any) +16 (call core.svec) +17 SourceLocation::3:14 +18 (call core.svec %₁₅ %₁₆ %₁₇) +19 --- method core.nothing %₁₈ slots: [slot₁/#self#(!read) slot₂/y(!read)] 1 2 2 (call core.getfield slot₁/#self# :x) 3 (call core.setfield! %₂ :contents %₁) 4 (return %₁) -18 slot₁/f -19 (return %₁₈) +20 (latestworld) +21 slot₁/f +22 (return %₂₁) ######################################## # Function where arguments are captured into a closure and assigned @@ -101,27 +109,30 @@ function f(x) end #--------------------- 1 (method TestMod.f) -2 (call core.svec :x) -3 (call core.svec true) -4 (call JuliaLowering.eval_closure_type TestMod :#f#g##0 %₂ %₃) -5 TestMod.#f#g##0 -6 (call core.svec %₅) -7 (call core.svec) -8 SourceLocation::2:14 -9 (call core.svec %₆ %₇ %₈) -10 --- method core.nothing %₉ +2 (latestworld) +3 (call core.svec :x) +4 (call core.svec true) +5 (call JuliaLowering.eval_closure_type TestMod :#f#g##0 %₃ %₄) +6 (latestworld) +7 TestMod.#f#g##0 +8 (call core.svec %₇) +9 (call core.svec) +10 SourceLocation::2:14 +11 (call core.svec %₈ %₉ %₁₀) +12 --- method core.nothing %₁₁ slots: [slot₁/#self#(!read)] 1 10 2 (call core.getfield slot₁/#self# :x) 3 (call core.setfield! %₂ :contents %₁) 4 (return %₁) -11 TestMod.f -12 (call core.Typeof %₁₁) -13 (call core.svec %₁₂ core.Any) -14 (call core.svec) -15 SourceLocation::1:10 -16 (call core.svec %₁₃ %₁₄ %₁₅) -17 --- method core.nothing %₁₆ +13 (latestworld) +14 TestMod.f +15 (call core.Typeof %₁₄) +16 (call core.svec %₁₅ core.Any) +17 (call core.svec) +18 SourceLocation::1:10 +19 (call core.svec %₁₆ %₁₇ %₁₈) +20 --- method core.nothing %₁₉ slots: [slot₁/#self#(!read) slot₂/x slot₃/g(called) slot₄/x(!read)] 1 (= slot₂/x (call core.Box slot₂/x)) 2 TestMod.#f#g##0 @@ -137,8 +148,9 @@ end 12 slot₄/x 13 (call core.getfield %₇ :contents) 14 (return %₁₃) -18 TestMod.f -19 (return %₁₈) +21 (latestworld) +22 TestMod.f +23 (return %₂₂) ######################################## # Closure where a local `x` is captured but not boxed @@ -150,26 +162,29 @@ function f(x) end #--------------------- 1 (method TestMod.f) -2 (call core.svec :x) -3 (call core.svec false) -4 (call JuliaLowering.eval_closure_type TestMod :#f#g##1 %₂ %₃) -5 TestMod.#f#g##1 -6 (call core.svec %₅) -7 (call core.svec) -8 SourceLocation::2:14 -9 (call core.svec %₆ %₇ %₈) -10 --- method core.nothing %₉ +2 (latestworld) +3 (call core.svec :x) +4 (call core.svec false) +5 (call JuliaLowering.eval_closure_type TestMod :#f#g##1 %₃ %₄) +6 (latestworld) +7 TestMod.#f#g##1 +8 (call core.svec %₇) +9 (call core.svec) +10 SourceLocation::2:14 +11 (call core.svec %₈ %₉ %₁₀) +12 --- method core.nothing %₁₁ slots: [slot₁/#self#(!read) slot₂/y(!read)] 1 (call core.getfield slot₁/#self# :x) 2 (= slot₂/y %₁) 3 (return %₁) -11 TestMod.f -12 (call core.Typeof %₁₁) -13 (call core.svec %₁₂ core.Any) -14 (call core.svec) -15 SourceLocation::1:10 -16 (call core.svec %₁₃ %₁₄ %₁₅) -17 --- method core.nothing %₁₆ +13 (latestworld) +14 TestMod.f +15 (call core.Typeof %₁₄) +16 (call core.svec %₁₅ core.Any) +17 (call core.svec) +18 SourceLocation::1:10 +19 (call core.svec %₁₆ %₁₇ %₁₈) +20 --- method core.nothing %₁₉ slots: [slot₁/#self#(!read) slot₂/x slot₃/g slot₄/z(!read)] 1 TestMod.#f#g##1 2 (call core.typeof slot₂/x) @@ -179,8 +194,9 @@ end 6 slot₂/x 7 (= slot₄/z %₆) 8 (return %₆) -18 TestMod.f -19 (return %₁₈) +21 (latestworld) +22 TestMod.f +23 (return %₂₂) ######################################## # Closure where a static parameter of an outer function is captured @@ -191,42 +207,44 @@ function f(::T) where T end #--------------------- 1 (method TestMod.f) -2 (call core.svec :T) -3 (call core.svec false) -4 (call JuliaLowering.eval_closure_type TestMod :#f#g##2 %₂ %₃) -5 TestMod.#f#g##2 -6 (call core.svec %₅) -7 (call core.svec) -8 SourceLocation::2:14 -9 (call core.svec %₆ %₇ %₈) -10 --- method core.nothing %₉ +2 (latestworld) +3 (call core.svec :T) +4 (call core.svec false) +5 (call JuliaLowering.eval_closure_type TestMod :#f#g##2 %₃ %₄) +6 (latestworld) +7 TestMod.#f#g##2 +8 (call core.svec %₇) +9 (call core.svec) +10 SourceLocation::2:14 +11 (call core.svec %₈ %₉ %₁₀) +12 --- method core.nothing %₁₁ slots: [slot₁/#self#(!read)] 1 TestMod.use 2 (call core.getfield slot₁/#self# :T) 3 (call %₁ %₂) 4 (return %₃) -11 (= slot₁/T (call core.TypeVar :T)) -12 TestMod.f -13 (call core.Typeof %₁₂) -14 slot₁/T -15 (call core.svec %₁₃ %₁₄) -16 slot₁/T -17 (call core.svec %₁₆) -18 SourceLocation::1:10 -19 (call core.svec %₁₅ %₁₇ %₁₈) -20 --- method core.nothing %₁₉ +13 (latestworld) +14 (= slot₁/T (call core.TypeVar :T)) +15 TestMod.f +16 (call core.Typeof %₁₅) +17 slot₁/T +18 (call core.svec %₁₆ %₁₇) +19 slot₁/T +20 (call core.svec %₁₉) +21 SourceLocation::1:10 +22 (call core.svec %₁₈ %₂₀ %₂₁) +23 --- method core.nothing %₂₂ slots: [slot₁/#self#(!read) slot₂/_(!read) slot₃/g] 1 TestMod.#f#g##2 - 2 static_parameter₁ - 3 (call core.typeof %₂) - 4 (call core.apply_type %₁ %₃) - 5 static_parameter₁ - 6 (new %₄ %₅) - 7 (= slot₃/g %₆) - 8 slot₃/g - 9 (return %₈) -21 TestMod.f -22 (return %₂₁) + 2 (call core.typeof static_parameter₁) + 3 (call core.apply_type %₁ %₂) + 4 (new %₃ static_parameter₁) + 5 (= slot₃/g %₄) + 6 slot₃/g + 7 (return %₆) +24 (latestworld) +25 TestMod.f +26 (return %₂₅) ######################################## # Closure captures with `isdefined` @@ -243,15 +261,17 @@ function f(x) end #--------------------- 1 (method TestMod.f) -2 (call core.svec :x :y) -3 (call core.svec false true) -4 (call JuliaLowering.eval_closure_type TestMod :#f#g##3 %₂ %₃) -5 TestMod.#f#g##3 -6 (call core.svec %₅) -7 (call core.svec) -8 SourceLocation::2:14 -9 (call core.svec %₆ %₇ %₈) -10 --- method core.nothing %₉ +2 (latestworld) +3 (call core.svec :x :y) +4 (call core.svec false true) +5 (call JuliaLowering.eval_closure_type TestMod :#f#g##3 %₃ %₄) +6 (latestworld) +7 TestMod.#f#g##3 +8 (call core.svec %₇) +9 (call core.svec) +10 SourceLocation::2:14 +11 (call core.svec %₈ %₉ %₁₀) +12 --- method core.nothing %₁₁ slots: [slot₁/#self#(!read) slot₂/z] 1 (= slot₂/z 3) 2 (call core.getfield slot₁/#self# :y) @@ -259,13 +279,14 @@ end 4 (isdefined slot₂/z) 5 (call core.tuple true %₃ %₄) 6 (return %₅) -11 TestMod.f -12 (call core.Typeof %₁₁) -13 (call core.svec %₁₂ core.Any) -14 (call core.svec) -15 SourceLocation::1:10 -16 (call core.svec %₁₃ %₁₄ %₁₅) -17 --- method core.nothing %₁₆ +13 (latestworld) +14 TestMod.f +15 (call core.Typeof %₁₄) +16 (call core.svec %₁₅ core.Any) +17 (call core.svec) +18 SourceLocation::1:10 +19 (call core.svec %₁₆ %₁₇ %₁₈) +20 --- method core.nothing %₁₉ slots: [slot₁/#self#(!read) slot₂/x slot₃/g slot₄/y] 1 (= slot₄/y (call core.Box)) 2 TestMod.#f#g##3 @@ -281,8 +302,9 @@ end 12 (call core.isdefined %₁₁ :contents) 13 (call core.tuple %₁₂ true) 14 (return %₁₃) -18 TestMod.f -19 (return %₁₈) +21 (latestworld) +22 TestMod.f +23 (return %₂₂) ######################################## # Nested captures - here `g` captures `x` because it is needed to initialize @@ -322,13 +344,14 @@ end 3 slot₁/x 4 (call core.setfield! %₃ :contents %₂) 5 (method TestMod.f) -6 TestMod.f -7 (call core.Typeof %₆) -8 (call core.svec %₇) -9 (call core.svec) -10 SourceLocation::3:14 -11 (call core.svec %₈ %₉ %₁₀) -12 --- code_info +6 (latestworld) +7 TestMod.f +8 (call core.Typeof %₇) +9 (call core.svec %₈) +10 (call core.svec) +11 SourceLocation::3:14 +12 (call core.svec %₉ %₁₀ %₁₁) +13 --- code_info slots: [slot₁/#self#(!read) slot₂/x(!read)] 1 TestMod.+ 2 (captured_local 1) @@ -342,12 +365,13 @@ end 10 (captured_local 1) 11 (call core.setfield! %₁₀ :contents %₉) 12 (return %₉) -13 slot₁/x -14 (call core.svec %₁₃) -15 (call JuliaLowering.replace_captured_locals! %₁₂ %₁₄) -16 --- method core.nothing %₁₁ %₁₅ -17 TestMod.f -18 (return %₁₇) +14 slot₁/x +15 (call core.svec %₁₄) +16 (call JuliaLowering.replace_captured_locals! %₁₃ %₁₅) +17 --- method core.nothing %₁₂ %₁₆ +18 (latestworld) +19 TestMod.f +20 (return %₁₉) ######################################## # Anonymous function syntax with -> @@ -356,19 +380,22 @@ x -> x*x 1 (call core.svec) 2 (call core.svec) 3 (call JuliaLowering.eval_closure_type TestMod :#->##0 %₁ %₂) -4 TestMod.#->##0 -5 (new %₄) -6 TestMod.#->##0 -7 (call core.svec %₆ core.Any) -8 (call core.svec) -9 SourceLocation::1:1 -10 (call core.svec %₇ %₈ %₉) -11 --- method core.nothing %₁₀ +4 (latestworld) +5 TestMod.#->##0 +6 (new %₅) +7 (latestworld) +8 TestMod.#->##0 +9 (call core.svec %₈ core.Any) +10 (call core.svec) +11 SourceLocation::1:1 +12 (call core.svec %₉ %₁₀ %₁₁) +13 --- method core.nothing %₁₂ slots: [slot₁/#self#(!read) slot₂/x] 1 TestMod.* 2 (call %₁ slot₂/x slot₂/x) 3 (return %₂) -12 (return %₅) +14 (latestworld) +15 (return %₆) ######################################## # Anonymous function syntax with `function` @@ -379,19 +406,22 @@ end 1 (call core.svec) 2 (call core.svec) 3 (call JuliaLowering.eval_closure_type TestMod :##anon###0 %₁ %₂) -4 TestMod.##anon###0 -5 (new %₄) -6 TestMod.##anon###0 -7 (call core.svec %₆ core.Any) -8 (call core.svec) -9 SourceLocation::1:10 -10 (call core.svec %₇ %₈ %₉) -11 --- method core.nothing %₁₀ +4 (latestworld) +5 TestMod.##anon###0 +6 (new %₅) +7 (latestworld) +8 TestMod.##anon###0 +9 (call core.svec %₈ core.Any) +10 (call core.svec) +11 SourceLocation::1:10 +12 (call core.svec %₉ %₁₀ %₁₁) +13 --- method core.nothing %₁₂ slots: [slot₁/#self#(!read) slot₂/x] 1 TestMod.* 2 (call %₁ slot₂/x slot₂/x) 3 (return %₂) -12 (return %₅) +14 (latestworld) +15 (return %₆) ######################################## # `do` blocks @@ -407,21 +437,25 @@ end 6 (call core.svec) 7 (call core.svec) 8 (call JuliaLowering.eval_closure_type TestMod :#do##0 %₆ %₇) -9 TestMod.#do##0 -10 (call core.svec %₉ core.Any) -11 (call core.svec) -12 SourceLocation::1:13 -13 (call core.svec %₁₀ %₁₁ %₁₂) -14 --- method core.nothing %₁₃ +9 (latestworld) +10 TestMod.#do##0 +11 (call core.svec %₁₀ core.Any) +12 (call core.svec) +13 SourceLocation::1:13 +14 (call core.svec %₁₁ %₁₂ %₁₃) +15 --- method core.nothing %₁₄ slots: [slot₁/#self#(!read) slot₂/y] 1 TestMod.+ 2 (call %₁ slot₂/y 2) 3 (return %₂) -15 TestMod.#do##0 -16 (new %₁₅) -17 TestMod.x -18 (call core.kwcall %₅ %₁ %₁₆ %₁₇) -19 (return %₁₈) +16 (latestworld) +17 (latestworld) +18 TestMod.#do##0 +19 (new %₁₈) +20 (latestworld) +21 TestMod.x +22 (call core.kwcall %₅ %₁ %₁₉ %₂₁) +23 (return %₂₂) ######################################## # Error: Static parameter clashing with closure name @@ -510,17 +544,19 @@ end 3 (call core.svec :recursive_b) 4 (call core.svec true) 5 (call JuliaLowering.eval_closure_type TestMod :#recursive_a##0 %₃ %₄) -6 TestMod.#recursive_a##0 -7 slot₂/recursive_b -8 (new %₆ %₇) -9 slot₁/recursive_a -10 (call core.setfield! %₉ :contents %₈) -11 TestMod.#recursive_a##0 -12 (call core.svec %₁₁) -13 (call core.svec) -14 SourceLocation::2:14 -15 (call core.svec %₁₂ %₁₃ %₁₄) -16 --- method core.nothing %₁₅ +6 (latestworld) +7 TestMod.#recursive_a##0 +8 slot₂/recursive_b +9 (new %₇ %₈) +10 slot₁/recursive_a +11 (call core.setfield! %₁₀ :contents %₉) +12 (latestworld) +13 TestMod.#recursive_a##0 +14 (call core.svec %₁₃) +15 (call core.svec) +16 SourceLocation::2:14 +17 (call core.svec %₁₄ %₁₅ %₁₆) +18 --- method core.nothing %₁₇ slots: [slot₁/#self#(!read) slot₂/recursive_b(!read)] 1 (call core.getfield slot₁/#self# :recursive_b) 2 (call core.isdefined %₁ :contents) @@ -531,20 +567,23 @@ end 7 (call core.getfield %₁ :contents) 8 (call %₇) 9 (return %₈) -17 (call core.svec :recursive_a) -18 (call core.svec true) -19 (call JuliaLowering.eval_closure_type TestMod :#recursive_b##0 %₁₇ %₁₈) -20 TestMod.#recursive_b##0 -21 slot₁/recursive_a -22 (new %₂₀ %₂₁) -23 slot₂/recursive_b -24 (call core.setfield! %₂₃ :contents %₂₂) -25 TestMod.#recursive_b##0 -26 (call core.svec %₂₅) -27 (call core.svec) -28 SourceLocation::5:14 -29 (call core.svec %₂₆ %₂₇ %₂₈) -30 --- method core.nothing %₂₉ +19 (latestworld) +20 (call core.svec :recursive_a) +21 (call core.svec true) +22 (call JuliaLowering.eval_closure_type TestMod :#recursive_b##0 %₂₀ %₂₁) +23 (latestworld) +24 TestMod.#recursive_b##0 +25 slot₁/recursive_a +26 (new %₂₄ %₂₅) +27 slot₂/recursive_b +28 (call core.setfield! %₂₇ :contents %₂₆) +29 (latestworld) +30 TestMod.#recursive_b##0 +31 (call core.svec %₃₀) +32 (call core.svec) +33 SourceLocation::5:14 +34 (call core.svec %₃₁ %₃₂ %₃₃) +35 --- method core.nothing %₃₄ slots: [slot₁/#self#(!read) slot₂/recursive_a(!read)] 1 (call core.getfield slot₁/#self# :recursive_a) 2 (call core.isdefined %₁ :contents) @@ -555,14 +594,15 @@ end 7 (call core.getfield %₁ :contents) 8 (call %₇) 9 (return %₈) -31 slot₂/recursive_b -32 (call core.isdefined %₃₁ :contents) -33 (gotoifnot %₃₂ label₃₅) -34 (goto label₃₇) -35 (newvar slot₄/recursive_b) -36 slot₄/recursive_b -37 (call core.getfield %₃₁ :contents) -38 (return %₃₇) +36 (latestworld) +37 slot₂/recursive_b +38 (call core.isdefined %₃₇ :contents) +39 (gotoifnot %₃₈ label₄₁) +40 (goto label₄₃) +41 (newvar slot₄/recursive_b) +42 slot₄/recursive_b +43 (call core.getfield %₃₇ :contents) +44 (return %₄₃) ######################################## # Closure with keywords @@ -580,26 +620,29 @@ end 6 (call core.svec :#f_kw_closure#0) 7 (call core.svec true) 8 (call JuliaLowering.eval_closure_type TestMod :#f_kw_closure##0 %₆ %₇) -9 TestMod.#f_kw_closure##0 -10 slot₂/#f_kw_closure#0 -11 (new %₉ %₁₀) -12 (= slot₃/f_kw_closure %₁₁) -13 (call core.svec :y) -14 (call core.svec true) -15 (call JuliaLowering.eval_closure_type TestMod :##f_kw_closure#0##0 %₁₃ %₁₄) -16 TestMod.##f_kw_closure#0##0 -17 slot₁/y -18 (new %₁₆ %₁₇) -19 slot₂/#f_kw_closure#0 -20 (call core.setfield! %₁₉ :contents %₁₈) -21 TestMod.##f_kw_closure#0##0 -22 TestMod.X -23 TestMod.#f_kw_closure##0 -24 (call core.svec %₂₁ %₂₂ %₂₃) -25 (call core.svec) -26 SourceLocation::2:14 +9 (latestworld) +10 TestMod.#f_kw_closure##0 +11 slot₂/#f_kw_closure#0 +12 (new %₁₀ %₁₁) +13 (= slot₃/f_kw_closure %₁₂) +14 (call core.svec :y) +15 (call core.svec true) +16 (call JuliaLowering.eval_closure_type TestMod :##f_kw_closure#0##0 %₁₄ %₁₅) +17 (latestworld) +18 TestMod.##f_kw_closure#0##0 +19 slot₁/y +20 (new %₁₈ %₁₉) +21 slot₂/#f_kw_closure#0 +22 (call core.setfield! %₂₁ :contents %₂₀) +23 (latestworld) +24 TestMod.##f_kw_closure#0##0 +25 TestMod.X +26 TestMod.#f_kw_closure##0 27 (call core.svec %₂₄ %₂₅ %₂₆) -28 --- method core.nothing %₂₇ +28 (call core.svec) +29 SourceLocation::2:14 +30 (call core.svec %₂₇ %₂₈ %₂₉) +31 --- method core.nothing %₃₀ slots: [slot₁/#self#(!read) slot₂/x slot₃/#self#(!read) slot₄/y(!read)] 1 (meta :nkw 1) 2 TestMod.+ @@ -612,13 +655,14 @@ end 9 (call core.getfield %₃ :contents) 10 (call %₂ slot₂/x %₉) 11 (return %₁₀) -29 (call core.typeof core.kwcall) -30 TestMod.#f_kw_closure##0 -31 (call core.svec %₂₉ core.NamedTuple %₃₀) -32 (call core.svec) -33 SourceLocation::2:14 -34 (call core.svec %₃₁ %₃₂ %₃₃) -35 --- code_info +32 (latestworld) +33 (call core.typeof core.kwcall) +34 TestMod.#f_kw_closure##0 +35 (call core.svec %₃₃ core.NamedTuple %₃₄) +36 (call core.svec) +37 SourceLocation::2:14 +38 (call core.svec %₃₅ %₃₆ %₃₇) +39 --- code_info slots: [slot₁/#self#(!read) slot₂/kws slot₃/#self# slot₄/kwtmp slot₅/x(!read) slot₆/#f_kw_closure#0(!read)] 1 (newvar slot₅/x) 2 (call core.isdefined slot₂/kws :x) @@ -652,16 +696,18 @@ end 30 (call core.getfield %₂₄ :contents) 31 (call %₃₀ %₁₆ slot₃/#self#) 32 (return %₃₁) -36 slot₂/#f_kw_closure#0 -37 (call core.svec %₃₆) -38 (call JuliaLowering.replace_captured_locals! %₃₅ %₃₇) -39 --- method core.nothing %₃₄ %₃₈ -40 TestMod.#f_kw_closure##0 +40 slot₂/#f_kw_closure#0 41 (call core.svec %₄₀) -42 (call core.svec) -43 SourceLocation::2:14 -44 (call core.svec %₄₁ %₄₂ %₄₃) -45 --- method core.nothing %₄₄ +42 (call JuliaLowering.replace_captured_locals! %₃₉ %₄₁) +43 --- method core.nothing %₃₈ %₄₂ +44 (latestworld) +45 (latestworld) +46 TestMod.#f_kw_closure##0 +47 (call core.svec %₄₆) +48 (call core.svec) +49 SourceLocation::2:14 +50 (call core.svec %₄₇ %₄₈ %₄₉) +51 --- method core.nothing %₅₀ slots: [slot₁/#self# slot₂/#f_kw_closure#0(!read)] 1 (call core.getfield slot₁/#self# :#f_kw_closure#0) 2 (call core.isdefined %₁ :contents) @@ -673,8 +719,9 @@ end 8 TestMod.x_default 9 (call %₇ %₈ slot₁/#self#) 10 (return %₉) -46 slot₃/f_kw_closure -47 (return %₄₆) +52 (latestworld) +53 slot₃/f_kw_closure +54 (return %₅₃) ######################################## # Closure capturing a typed local must also capture the type expression diff --git a/test/compat.jl b/test/compat.jl new file mode 100644 index 00000000..c43985ab --- /dev/null +++ b/test/compat.jl @@ -0,0 +1,373 @@ +using Test +using JuliaLowering +const JS = JuliaSyntax +const JL = JuliaLowering + +# Parse string->expr->tree->expr. This is for bulk testing that the expr->tree +# conversion preserves semantics. +function parse_ete(args...) + outex, pos = JS.core_parser_hook(args...) + st = JL.expr_to_syntaxtree(outex) + local out + try + out = Expr(st) + catch e + show(args[1]) + @error "Failed to convert back to expr:" st + Base.showerror(stdout, e, Base.catch_backtrace()) + return outex, pos + end + return out, pos + # @warn "after:" st +end + +function fix_module(m::Module) + # Make `m` equivalent to `module anonymous end` + Core.eval(m, :(eval(x) = Core.eval($m, x))) + Core.eval(m, :(include(x) = Base.include($m, x))) + m +end + +test_mod_1 = fix_module(Module()) +test_mod_2 = fix_module(Module()) + +# parse and eval "normally" vs. with expr->tree->expr transformation, returning +# the result of both evaluations. +function test_eval_ete(s::AbstractString) + ps = JS.ParseStream(s) + JS.parse!(ps) + good_tree = JS.build_tree(JL.SyntaxTree, ps) + local good_expr + try + good_expr = Expr(good_tree) + try + good_out = Core.eval(test_mod_1, good_expr) + Core._setparser!(parse_ete) + test_out = Core.eval(test_mod_2, Meta.parseall(s)) + # @warn "reference tree:" + # show(stdout, MIME("text/plain"), good_tree) + @test good_out == test_out + catch e + show(stdout, MIME("text/plain"), good_expr) + Base.showerror(stdout, e, Base.catch_backtrace()) + @test "test threw; see output" == "" + finally + Core._setparser!(JS.core_parser_hook) + # Core.eval(test_mod_2, good_expr) # even them out? + end + + catch e_ + @error good_tree + Base.showerror(stdout, e_, Base.catch_backtrace()) + @test "failed to convert known-good syntax tree???" == "" + end +end + +# Remove any information that can't be recovered from an Expr +function normalize_st!(st) + k = JS.kind(st) + + if JS.is_infix_op_call(st) && (k === K"call" || k === K"dotcall") + # Infix calls are not preserved in Expr + args = JS.children(st) + + pre_st_args = JL.NodeId[args[2]._id, args[1]._id] + for c in args[3:end] + # there has got to be a better way + push!(pre_st_args, c._id) + end + pre_st_flags = (JS.flags(st) & ~JS.INFIX_FLAG) | JS.PREFIX_CALL_FLAG + pre_st = JL.makeleaf(st._graph, st, k) + JL.setchildren!(pre_st._graph, pre_st._id, pre_st_args) + JL.setflags!(pre_st._graph, pre_st._id, pre_st_flags) + return pre_st + elseif k in JS.KSet"tuple block macrocall" + # Parens are not preserved + JL.setflags!(st._graph, st._id, JS.flags(st) & ~JS.PARENS_FLAG) + elseif k === K"toplevel" + JL.setflags!(st._graph, st._id, JS.flags(st) & ~JS.TOPLEVEL_SEMICOLONS_FLAG) + end + + # All ops are prefix ops in an expr + JL.setflags!(st._graph, st._id, JS.flags(st) & ~JS.PREFIX_OP_FLAG) + + return st +end + +function st_roughly_equal(st_good, st_test) + st_good = normalize_st!(st_good) + out = kind(st_good) === kind(st_test) && + JS.flags(st_good) === JS.flags(st_test) && + JS.numchildren(st_good) === JS.numchildren(st_test) && + JS.is_leaf(st_good) === JS.is_leaf(st_test) && + get(st_good, :value, nothing) === get(st_test, :value, nothing) && + get(st_good, :name_val, nothing) === get(st_test, :name_val, nothing) && + all(map(st_roughly_equal, JS.children(st_good), JS.children(st_test))) + !out && @warn("!st_roughly_equal (normalized_reference, test):", + JS.sourcetext(st_good), st_good, st_test) + return out +end +# @test tree ~= tree->expr->tree +function tet_eq(s::String) + p1 = JS.parsestmt(SyntaxTree, s; ignore_errors=true) + p2 = JL.expr_to_syntaxtree(Expr(p1)) + @test st_roughly_equal(p1, p2) +end + +@testset "expr->syntaxtree" begin + @testset "semantics only" begin + test_eval_ete("let x = 2; x += 5; x -= 1; [1] .*= 1; end") + test_eval_ete("try; 1; catch e; e; else; 2; finally; 3; end") + test_eval_ete("for x in 1:2, y in 3:4; x + y; end") + + test_eval_ete("[x+y for x in 1:2, y in 3:4]") + test_eval_ete("Int[x+y for x in 1:2, y in 3:4 if true]") + + test_eval_ete("for x in 1; x+=1\n if true\n continue \n elseif false \n break\n end\n end") + test_eval_ete("@time 1") + test_eval_ete("Base.Meta.@lower 1") + test_eval_ete("function foo(x, y=1; z, what::Int=5); x + y + z + what; end; foo(1,2;z=3)") + + test_eval_ete("(()->1)()") + test_eval_ete("((x)->2)(3)") + test_eval_ete("((x,y)->4)(5,6)") + test_eval_ete("filter([1,2,3]) do x; x > 1; end") + test_eval_ete(""" + struct X + f1::Int # hi + "foo" + f2::Int + f3::Int + X(y) = new(y,y,y) + end + """) + test_eval_ete("global x,y") + test_eval_ete("global (x,y)") + test_eval_ete("999999999999999999999999999999999999999") + end + + @testset "syntaxtree equivalence (tests from JuliaSyntax expr.jl)" begin + tet_eq("begin a\nb\n\nc\nend") + tet_eq("(a;b;c)") + tet_eq("begin end") + tet_eq("(;;)") + tet_eq("a;b") + tet_eq("module A\n\nbody\nend") + tet_eq("function f()\na\n\nb\nend") + tet_eq("f() = 1") + tet_eq("macro f()\na\nend") + tet_eq("function f end") + tet_eq("macro f end") + tet_eq("function (f() where T) end") + tet_eq("function (f()::S) end") + tet_eq("a -> b") + tet_eq("(a,) -> b") + tet_eq("(a where T) -> b") + tet_eq("a -> (\nb;c)") + tet_eq("a -> begin\nb\nc\nend") + tet_eq("(a;b=1) -> c") + tet_eq("(a...;b...) -> c") + tet_eq("(;) -> c") + tet_eq("a::T -> b") + tet_eq("if a\nb\nelseif c\n d\nend") + tet_eq("let i=is, j=js\nbody\nend") + tet_eq("for x=xs\n\nend") + tet_eq("for x=xs\ny\nend") + tet_eq("while cond\n\nend") + tet_eq("while cond\ny\nend") + tet_eq("f() = xs") + tet_eq("f() =\n(a;b)") + tet_eq("f() =\nbegin\na\nb\nend") + tet_eq("let f(x) =\ng(x)=1\nend") + tet_eq("f() .= xs") + tet_eq("for i=is body end") + tet_eq("for i=is, j=js\nbody\nend") + tet_eq("function (xs...)\nbody end") + tet_eq("\"str\"") + tet_eq("\"\$(\"str\")\"") + tet_eq("```\n a\n b```") + tet_eq("\"\"\"\n a\n \$x\n b\n c\"\"\"") + tet_eq("`x") + tet_eq("`") + tet_eq("'a'") + tet_eq("'α'") + tet_eq("'\\xce\\xb1'") + tet_eq("f(x) do y\n body end") + tet_eq("@f(x) do y body end") + tet_eq("f(x; a=1) do y body end") + tet_eq("g(f(x) do y\n body end)") + tet_eq("f(a=1)") + tet_eq("f(; b=2)") + tet_eq("f(a=1; b=2)") + tet_eq("f(a; b; c)") + tet_eq("+(a=1,)") + tet_eq("(a=1)()") + tet_eq("(x=1) != 2") + tet_eq("+(a=1)") + tet_eq("(a=1)'") + tet_eq("(a=1)'ᵀ") + tet_eq("f.(a=1; b=2)") + tet_eq("(a=1,)") + tet_eq("(a=1,; b=2)") + tet_eq("(a=1,; b=2; c=3)") + tet_eq("x[i=j]") + tet_eq("(i=j)[x]") + tet_eq("x[a, b; i=j]") + tet_eq("(i=j){x}") + tet_eq("x{a, b; i=j}") + tet_eq("[a=1,; b=2]") + tet_eq("{a=1,; b=2}") + tet_eq("f(a .= 1)") + tet_eq("f(((a = 1)))") + tet_eq("(((a = 1)),)") + tet_eq("(;((a = 1)),)") + tet_eq("a.b") + tet_eq("a.\$b") + tet_eq("a.:b") + tet_eq("a.@b x") + tet_eq("f.(x,y)") + tet_eq("f.(x=1)") + tet_eq("f.(a=1; b=2)") + tet_eq("(a=1).()") + tet_eq("x .+ y") + tet_eq("(x=1) .+ y") + tet_eq("a .< b .< c") + tet_eq("a .< (.<) .< c") + tet_eq(".*(x)") + tet_eq(".+(x)") + tet_eq(".+x") + tet_eq("(.+)(x)") + tet_eq("(.+).(x)") + tet_eq(".+") + tet_eq(":.+") + tet_eq(":(.+)") + tet_eq("quote .+ end") + tet_eq(".+{x}") + tet_eq(":.=") + tet_eq(":(.=)") + tet_eq("f(.+)") + tet_eq("(a, .+)") + tet_eq("A.:.+") + tet_eq("./x") + tet_eq("x += y") + tet_eq("x .+= y") + tet_eq(":+=") + tet_eq(":(+=)") + tet_eq(":.+=") + tet_eq(":(.+=)") + tet_eq("x \u2212= y") + tet_eq("let x=1\n end") + tet_eq("let x=1 ; end") + tet_eq("let x ; end") + tet_eq("let x::1 ; end") + tet_eq("let x=1,y=2 end") + tet_eq("let x+=1 ; end") + tet_eq("let ; end") + tet_eq("let ; body end") + tet_eq("let\na\nb\nend") + tet_eq("A where T") + tet_eq("A where {T}") + tet_eq("A where {S, T}") + tet_eq("A where {X, Y; Z}") + tet_eq("@m\n") + tet_eq("\n@m") + tet_eq("@m(x; a)") + tet_eq("@m(a=1; b=2)") + tet_eq("@.") + tet_eq("using A: @.") + tet_eq("@var\"#\" a") + tet_eq("A.@var\"#\" a") + tet_eq("@S[a,b]") + tet_eq("@S[a b]") + tet_eq("@S[a; b]") + tet_eq("@S[a ;; b]") + tet_eq("var\"x\"") + tet_eq("var\"\"") + tet_eq("var\"\\\"\"") + tet_eq("var\"\\\\\\\"\"") + tet_eq("var\"\\\\x\"") + tet_eq("var\"x\"+y") + tet_eq("[x,y ; z]") + tet_eq("[a ;;; b ;;;; c]") + tet_eq("[a b ; c d]") + tet_eq("[a\nb]") + tet_eq("[a b]") + tet_eq("[a b ; c d]") + tet_eq("T[a ;;; b ;;;; c]") + tet_eq("T[a b ; c d]") + tet_eq("T[a\nb]") + tet_eq("T[a b]") + tet_eq("T[a b ; c d]") + tet_eq("(x for a in as for b in bs)") + tet_eq("(x for a in as, b in bs)") + tet_eq("(x for a in as, b in bs if z)") + tet_eq("(x for a in as, b in bs for c in cs, d in ds)") + tet_eq("(x for a in as for b in bs if z)") + tet_eq("(x for a in as if z for b in bs)") + tet_eq("[x for a = as for b = bs if cond1 for c = cs if cond2]" ) + tet_eq("[x for a = as if begin cond2 end]" ) + tet_eq("(x for a in as if z)") + tet_eq("try x catch e; y end") + tet_eq("try x finally y end") + tet_eq("try x catch e; y finally z end") + tet_eq("try x catch e; y else z end") + tet_eq("try x catch e; y else z finally w end") + tet_eq("try x finally y catch e z end") + tet_eq("try x end") + tet_eq("2x") + tet_eq("(2)(3)x") + tet_eq("\"x\" f") + tet_eq("\n\"x\" f") + tet_eq("foo\"str\"") + tet_eq("\n`str`") + tet_eq("foo`str`") + tet_eq("foo`str`flag") + tet_eq("foo```\n a\n b```") + tet_eq("@foo_cmd `str`") + tet_eq("return x") + tet_eq("return") + tet_eq("0x00000000000000001") + tet_eq("(0x00000000000000001)") + tet_eq("struct A end") + tet_eq("mutable struct A end") + tet_eq("struct A <: B \n a::X \n end") + tet_eq("struct A \n a \n b \n end") + tet_eq("struct A const a end") + tet_eq("struct A \n \"doc\" \n a end") + tet_eq("export a") + tet_eq("export @a") + tet_eq("export @var\"'\"") + tet_eq("export a, \n @b") + tet_eq("export +, ==") + tet_eq("export \n a") + tet_eq("global x") + tet_eq("local x") + tet_eq("global x,y") + tet_eq("global const x = 1") + tet_eq("local const x = 1") + tet_eq("const global x = 1") + tet_eq("const local x = 1") + tet_eq("const x,y = 1,2") + tet_eq("const x = 1") + tet_eq("global x ~ 1") + tet_eq("global x += 1") + tet_eq("global (x,y)") + tet_eq("local (x,y)") + tet_eq("(;)") + tet_eq("(; a=1)") + tet_eq("(; a=1; b=2)") + tet_eq("(a; b; c,d)") + tet_eq("module A end") + tet_eq("baremodule A end") + tet_eq("--") + tet_eq("(x") + tet_eq("x do") + tet_eq("x var\"y\"") + tet_eq("var\"y") + tet_eq("import A") + tet_eq("import A.(:b).:c: x.:z") + tet_eq("import A.:+") + tet_eq("import A.(:+)") + tet_eq("import A.:(+)") + end +end diff --git a/test/decls.jl b/test/decls.jl index 08484dfa..8866b303 100644 --- a/test/decls.jl +++ b/test/decls.jl @@ -9,7 +9,7 @@ begin end """) === 1 -# In value position, yeild the right hand side, not `x` +# In value position, yield the right hand side, not `x` @test JuliaLowering.include_string(test_mod, """ local x::Int = 1.0 """) === 1.0 @@ -33,6 +33,29 @@ let end """) === (1, 20) +# Global const mixes +@test JuliaLowering.include_string(test_mod, "global x_g = 1") === 1 +@test Base.isdefinedglobal(test_mod, :x_g) +@test !Base.isconst(test_mod, :x_g) +@test test_mod.x_g === 1 + +@test JuliaLowering.include_string(test_mod, "const x_c = 1") === 1 +@test Base.isdefinedglobal(test_mod, :x_c) +@test Base.isconst(test_mod, :x_c) +@test test_mod.x_c === 1 + +@test JuliaLowering.include_string(test_mod, "global const x_gc = 1") === 1 +@test Base.isdefinedglobal(test_mod, :x_gc) +@test Base.isconst(test_mod, :x_gc) +@test test_mod.x_gc === 1 + +@test JuliaLowering.include_string(test_mod, "const global x_cg = 1") === 1 +@test Base.isdefinedglobal(test_mod, :x_cg) +@test Base.isconst(test_mod, :x_cg) +@test test_mod.x_cg === 1 +# Possibly worth testing excessive global/const keywords once we decide whether +# that's a parse error or a lowering error + # Global decls with types @test JuliaLowering.include_string(test_mod, """ global a_typed_global::Int = 10.0 @@ -49,4 +72,23 @@ end @test Core.get_binding_type(test_mod, :a_typed_global_2) === Int @test test_mod.a_typed_global_2 === 10 +@test JuliaLowering.include_string(test_mod, "const x_c_T::Int = 9") === 9 +@test Base.isdefinedglobal(test_mod, :x_c_T) +@test Base.isconst(test_mod, :x_c_T) + +@testset "typed const redeclaration" begin + # redeclaration of the same value used to be allowed + @test_throws ErrorException JuliaLowering.include_string(test_mod, "x_c_T = 9") + @test_throws ErrorException JuliaLowering.include_string(test_mod, "x_c_T = 10") + # redeclaration with const should be OK + @test JuliaLowering.include_string(test_mod, "const x_c_T::Int = 0") === 0 +end + +# Tuple/destructuring assignments +@test JuliaLowering.include_string(test_mod, "(a0, a1, a2) = [1,2,3]") == [1,2,3] + + +# Unsupported for now +@test_throws LoweringError JuliaLowering.include_string(test_mod, "const a,b,c = 1,2,3") + end diff --git a/test/decls_ir.jl b/test/decls_ir.jl index a8b9fd98..444fbdaa 100644 --- a/test/decls_ir.jl +++ b/test/decls_ir.jl @@ -21,63 +21,108 @@ local x::T = 1 # const const xx = 10 #--------------------- -1 (const TestMod.xx) -2 (= TestMod.xx 10) -3 (return 10) +1 10 +2 (constdecl TestMod.xx %₁) +3 (latestworld) +4 (return %₁) ######################################## # Typed const const xx::T = 10 #--------------------- 1 TestMod.T -2 (call core.set_binding_type! TestMod :xx %₁) -3 (const TestMod.xx) -4 (call core.get_binding_type TestMod :xx) -5 (= slot₁/tmp 10) -6 slot₁/tmp -7 (call core.isa %₆ %₄) -8 (gotoifnot %₇ label₁₀) -9 (goto label₁₂) +2 (= slot₁/tmp 10) +3 slot₁/tmp +4 (call core.isa %₃ %₁) +5 (gotoifnot %₄ label₇) +6 (goto label₁₀) +7 slot₁/tmp +8 (call top.convert %₁ %₇) +9 (= slot₁/tmp (call core.typeassert %₈ %₁)) 10 slot₁/tmp -11 (= slot₁/tmp (call top.convert %₄ %₁₀)) -12 slot₁/tmp -13 (= TestMod.xx %₁₂) -14 (return 10) +11 (constdecl TestMod.xx %₁₀) +12 (latestworld) +13 (return %₁₀) + +######################################## +# Error: Const tuple +const xxx,xxxx,xxxxx = 10,20,30 +#--------------------- +LoweringError: +const xxx,xxxx,xxxxx = 10,20,30 +# └─────────────┘ ── Lowering TODO: `const` tuple assignment desugaring + +######################################## +# Const in chain: only first is const +const c0 = v0 = v1 = 123 +#--------------------- +1 123 +2 (constdecl TestMod.c0 %₁) +3 (globaldecl TestMod.v0) +4 (latestworld) +5 (call core.get_binding_type TestMod :v0) +6 (= slot₁/tmp %₁) +7 slot₁/tmp +8 (call core.isa %₇ %₅) +9 (gotoifnot %₈ label₁₁) +10 (goto label₁₃) +11 slot₁/tmp +12 (= slot₁/tmp (call top.convert %₅ %₁₁)) +13 slot₁/tmp +14 (call core.setglobal! TestMod :v0 %₁₃) +15 (globaldecl TestMod.v1) +16 (latestworld) +17 (call core.get_binding_type TestMod :v1) +18 (= slot₂/tmp %₁) +19 slot₂/tmp +20 (call core.isa %₁₉ %₁₇) +21 (gotoifnot %₂₀ label₂₃) +22 (goto label₂₅) +23 slot₂/tmp +24 (= slot₂/tmp (call top.convert %₁₇ %₂₃)) +25 slot₂/tmp +26 (call core.setglobal! TestMod :v1 %₂₅) +27 (return %₁) ######################################## # Global assignment xx = 10 #--------------------- -1 (call core.get_binding_type TestMod :xx) -2 (= slot₁/tmp 10) -3 slot₁/tmp -4 (call core.isa %₃ %₁) -5 (gotoifnot %₄ label₇) -6 (goto label₉) -7 slot₁/tmp -8 (= slot₁/tmp (call top.convert %₁ %₇)) +1 (globaldecl TestMod.xx) +2 (latestworld) +3 (call core.get_binding_type TestMod :xx) +4 (= slot₁/tmp 10) +5 slot₁/tmp +6 (call core.isa %₅ %₃) +7 (gotoifnot %₆ label₉) +8 (goto label₁₁) 9 slot₁/tmp -10 (= TestMod.xx %₉) -11 (return 10) +10 (= slot₁/tmp (call top.convert %₃ %₉)) +11 slot₁/tmp +12 (call core.setglobal! TestMod :xx %₁₁) +13 (return 10) ######################################## # Typed global assignment global xx::T = 10 #--------------------- -1 TestMod.T -2 (call core.set_binding_type! TestMod :xx %₁) +1 (globaldecl TestMod.xx TestMod.T) +2 (latestworld) 3 (global TestMod.xx) -4 (call core.get_binding_type TestMod :xx) -5 (= slot₁/tmp 10) -6 slot₁/tmp -7 (call core.isa %₆ %₄) -8 (gotoifnot %₇ label₁₀) -9 (goto label₁₂) -10 slot₁/tmp -11 (= slot₁/tmp (call top.convert %₄ %₁₀)) -12 slot₁/tmp -13 (= TestMod.xx %₁₂) -14 (return 10) +4 (latestworld) +5 (globaldecl TestMod.xx) +6 (latestworld) +7 (call core.get_binding_type TestMod :xx) +8 (= slot₁/tmp 10) +9 slot₁/tmp +10 (call core.isa %₉ %₇) +11 (gotoifnot %₁₀ label₁₃) +12 (goto label₁₅) +13 slot₁/tmp +14 (= slot₁/tmp (call top.convert %₇ %₁₃)) +15 slot₁/tmp +16 (call core.setglobal! TestMod :xx %₁₅) +17 (return 10) ######################################## # Error: x declared twice @@ -99,7 +144,7 @@ const local x = 1 #--------------------- LoweringError: const local x = 1 -# ╙ ── unsupported `const` declaration on local variable +└───────────────┘ ── unsupported `const local` declaration ######################################## # Error: Const not supported on locals @@ -110,7 +155,7 @@ end LoweringError: let const x = 1 -# ╙ ── unsupported `const` declaration on local variable +# └────┘ ── unsupported `const` declaration on local variable end ######################################## @@ -122,13 +167,14 @@ function f(x) end #--------------------- 1 (method TestMod.f) -2 TestMod.f -3 (call core.Typeof %₂) -4 (call core.svec %₃ core.Any) -5 (call core.svec) -6 SourceLocation::1:10 -7 (call core.svec %₄ %₅ %₆) -8 --- method core.nothing %₇ +2 (latestworld) +3 TestMod.f +4 (call core.Typeof %₃) +5 (call core.svec %₄ core.Any) +6 (call core.svec) +7 SourceLocation::1:10 +8 (call core.svec %₅ %₆ %₇) +9 --- method core.nothing %₈ slots: [slot₁/#self#(!read) slot₂/x slot₃/tmp(!read) slot₄/tmp(!read)] 1 1 2 TestMod.Int @@ -156,8 +202,9 @@ end 24 (= slot₂/x %₂₃) 25 slot₂/x 26 (return %₂₅) -9 TestMod.f -10 (return %₉) +10 (latestworld) +11 TestMod.f +12 (return %₁₁) ######################################## # Error: global type decls only allowed at top level diff --git a/test/functions_ir.jl b/test/functions_ir.jl index 9abb27e9..6152a9d0 100644 --- a/test/functions_ir.jl +++ b/test/functions_ir.jl @@ -4,8 +4,9 @@ function f end #--------------------- 1 (method TestMod.f) -2 TestMod.f -3 (return %₂) +2 (latestworld) +3 TestMod.f +4 (return %₃) ######################################## # Functions with placeholder arg @@ -14,19 +15,21 @@ function f(x, _, y) end #--------------------- 1 (method TestMod.f) -2 TestMod.f -3 (call core.Typeof %₂) -4 (call core.svec %₃ core.Any core.Any core.Any) -5 (call core.svec) -6 SourceLocation::1:10 -7 (call core.svec %₄ %₅ %₆) -8 --- method core.nothing %₇ +2 (latestworld) +3 TestMod.f +4 (call core.Typeof %₃) +5 (call core.svec %₄ core.Any core.Any core.Any) +6 (call core.svec) +7 SourceLocation::1:10 +8 (call core.svec %₅ %₆ %₇) +9 --- method core.nothing %₈ slots: [slot₁/#self#(!read) slot₂/x slot₃/_(!read) slot₄/y] 1 TestMod.+ 2 (call %₁ slot₂/x slot₄/y) 3 (return %₂) -9 TestMod.f -10 (return %₉) +10 (latestworld) +11 TestMod.f +12 (return %₁₁) ######################################## # Functions with argument types only, no name @@ -35,19 +38,21 @@ function f(::T, x) end #--------------------- 1 (method TestMod.f) -2 TestMod.f -3 (call core.Typeof %₂) -4 TestMod.T -5 (call core.svec %₃ %₄ core.Any) -6 (call core.svec) -7 SourceLocation::1:10 -8 (call core.svec %₅ %₆ %₇) -9 --- method core.nothing %₈ +2 (latestworld) +3 TestMod.f +4 (call core.Typeof %₃) +5 TestMod.T +6 (call core.svec %₄ %₅ core.Any) +7 (call core.svec) +8 SourceLocation::1:10 +9 (call core.svec %₆ %₇ %₈) +10 --- method core.nothing %₉ slots: [slot₁/#self#(!read) slot₂/_(!read) slot₃/x] 1 slot₃/x 2 (return %₁) -10 TestMod.f -11 (return %₁₀) +11 (latestworld) +12 TestMod.f +13 (return %₁₂) ######################################## # Functions argument types @@ -56,19 +61,21 @@ function f(x, y::T) end #--------------------- 1 (method TestMod.f) -2 TestMod.f -3 (call core.Typeof %₂) -4 TestMod.T -5 (call core.svec %₃ core.Any %₄) -6 (call core.svec) -7 SourceLocation::1:10 -8 (call core.svec %₅ %₆ %₇) -9 --- method core.nothing %₈ +2 (latestworld) +3 TestMod.f +4 (call core.Typeof %₃) +5 TestMod.T +6 (call core.svec %₄ core.Any %₅) +7 (call core.svec) +8 SourceLocation::1:10 +9 (call core.svec %₆ %₇ %₈) +10 --- method core.nothing %₉ slots: [slot₁/#self#(!read) slot₂/x(!read) slot₃/y(!read)] 1 TestMod.body 2 (return %₁) -10 TestMod.f -11 (return %₁₀) +11 (latestworld) +12 TestMod.f +13 (return %₁₂) ######################################## # Functions with slurp of Any @@ -77,19 +84,21 @@ function f(x, ys...) end #--------------------- 1 (method TestMod.f) -2 TestMod.f -3 (call core.Typeof %₂) -4 (call core.apply_type core.Vararg core.Any) -5 (call core.svec %₃ core.Any %₄) -6 (call core.svec) -7 SourceLocation::1:10 -8 (call core.svec %₅ %₆ %₇) -9 --- method core.nothing %₈ +2 (latestworld) +3 TestMod.f +4 (call core.Typeof %₃) +5 (call core.apply_type core.Vararg core.Any) +6 (call core.svec %₄ core.Any %₅) +7 (call core.svec) +8 SourceLocation::1:10 +9 (call core.svec %₆ %₇ %₈) +10 --- method core.nothing %₉ slots: [slot₁/#self#(!read) slot₂/x(!read) slot₃/ys(!read)] 1 TestMod.body 2 (return %₁) -10 TestMod.f -11 (return %₁₀) +11 (latestworld) +12 TestMod.f +13 (return %₁₂) ######################################## # Functions with slurp of T @@ -98,20 +107,22 @@ function f(x, ys::T...) end #--------------------- 1 (method TestMod.f) -2 TestMod.f -3 (call core.Typeof %₂) -4 TestMod.T -5 (call core.apply_type core.Vararg %₄) -6 (call core.svec %₃ core.Any %₅) -7 (call core.svec) -8 SourceLocation::1:10 -9 (call core.svec %₆ %₇ %₈) -10 --- method core.nothing %₉ +2 (latestworld) +3 TestMod.f +4 (call core.Typeof %₃) +5 TestMod.T +6 (call core.apply_type core.Vararg %₅) +7 (call core.svec %₄ core.Any %₆) +8 (call core.svec) +9 SourceLocation::1:10 +10 (call core.svec %₇ %₈ %₉) +11 --- method core.nothing %₁₀ slots: [slot₁/#self#(!read) slot₂/x(!read) slot₃/ys(!read)] 1 TestMod.body 2 (return %₁) -11 TestMod.f -12 (return %₁₁) +12 (latestworld) +13 TestMod.f +14 (return %₁₃) ######################################## # Error: Function with slurp not in last position arg @@ -132,30 +143,29 @@ function f(::T, ::U, ::V) where T where {U,V} end #--------------------- 1 (method TestMod.f) -2 (= slot₂/U (call core.TypeVar :U)) -3 (= slot₃/V (call core.TypeVar :V)) -4 (= slot₁/T (call core.TypeVar :T)) -5 TestMod.f -6 (call core.Typeof %₅) -7 slot₁/T -8 slot₂/U -9 slot₃/V -10 (call core.svec %₆ %₇ %₈ %₉) -11 slot₂/U -12 slot₃/V -13 slot₁/T -14 (call core.svec %₁₁ %₁₂ %₁₃) -15 SourceLocation::1:10 -16 (call core.svec %₁₀ %₁₄ %₁₅) -17 --- method core.nothing %₁₆ +2 (latestworld) +3 (= slot₂/U (call core.TypeVar :U)) +4 (= slot₃/V (call core.TypeVar :V)) +5 (= slot₁/T (call core.TypeVar :T)) +6 TestMod.f +7 (call core.Typeof %₆) +8 slot₁/T +9 slot₂/U +10 slot₃/V +11 (call core.svec %₇ %₈ %₉ %₁₀) +12 slot₂/U +13 slot₃/V +14 slot₁/T +15 (call core.svec %₁₂ %₁₃ %₁₄) +16 SourceLocation::1:10 +17 (call core.svec %₁₁ %₁₅ %₁₆) +18 --- method core.nothing %₁₇ slots: [slot₁/#self#(!read) slot₂/_(!read) slot₃/_(!read) slot₄/_(!read)] - 1 static_parameter₃ - 2 static_parameter₁ - 3 static_parameter₂ - 4 (call core.tuple %₁ %₂ %₃) - 5 (return %₄) -18 TestMod.f -19 (return %₁₈) + 1 (call core.tuple static_parameter₃ static_parameter₁ static_parameter₂) + 2 (return %₁) +19 (latestworld) +20 TestMod.f +21 (return %₂₀) ######################################## # Static parameter with bounds and used with apply_type in argument @@ -164,25 +174,26 @@ function f(::S{T}) where X <: T <: Y end #--------------------- 1 (method TestMod.f) -2 TestMod.X -3 TestMod.Y -4 (= slot₁/T (call core.TypeVar :T %₂ %₃)) -5 TestMod.f -6 (call core.Typeof %₅) -7 TestMod.S -8 slot₁/T -9 (call core.apply_type %₇ %₈) -10 (call core.svec %₆ %₉) -11 slot₁/T -12 (call core.svec %₁₁) -13 SourceLocation::1:10 -14 (call core.svec %₁₀ %₁₂ %₁₃) -15 --- method core.nothing %₁₄ +2 (latestworld) +3 TestMod.X +4 TestMod.Y +5 (= slot₁/T (call core.TypeVar :T %₃ %₄)) +6 TestMod.f +7 (call core.Typeof %₆) +8 TestMod.S +9 slot₁/T +10 (call core.apply_type %₈ %₉) +11 (call core.svec %₇ %₁₀) +12 slot₁/T +13 (call core.svec %₁₂) +14 SourceLocation::1:10 +15 (call core.svec %₁₁ %₁₃ %₁₄) +16 --- method core.nothing %₁₅ slots: [slot₁/#self#(!read) slot₂/_(!read)] - 1 static_parameter₁ - 2 (return %₁) -16 TestMod.f -17 (return %₁₆) + 1 (return static_parameter₁) +17 (latestworld) +18 TestMod.f +19 (return %₁₈) ######################################## # Static parameter which is used only in the bounds of another static parameter @@ -192,28 +203,28 @@ function f(x, y::S) where {T, S<:AbstractVector{T}} end #--------------------- 1 (method TestMod.f) -2 (= slot₂/T (call core.TypeVar :T)) -3 TestMod.AbstractVector -4 slot₂/T -5 (call core.apply_type %₃ %₄) -6 (= slot₁/S (call core.TypeVar :S %₅)) -7 TestMod.f -8 (call core.Typeof %₇) -9 slot₁/S -10 (call core.svec %₈ core.Any %₉) -11 slot₂/T -12 slot₁/S -13 (call core.svec %₁₁ %₁₂) -14 SourceLocation::1:10 -15 (call core.svec %₁₀ %₁₃ %₁₄) -16 --- method core.nothing %₁₅ +2 (latestworld) +3 (= slot₂/T (call core.TypeVar :T)) +4 TestMod.AbstractVector +5 slot₂/T +6 (call core.apply_type %₄ %₅) +7 (= slot₁/S (call core.TypeVar :S %₆)) +8 TestMod.f +9 (call core.Typeof %₈) +10 slot₁/S +11 (call core.svec %₉ core.Any %₁₀) +12 slot₂/T +13 slot₁/S +14 (call core.svec %₁₂ %₁₃) +15 SourceLocation::1:10 +16 (call core.svec %₁₁ %₁₄ %₁₅) +17 --- method core.nothing %₁₆ slots: [slot₁/#self#(!read) slot₂/x(!read) slot₃/y(!read)] - 1 static_parameter₁ - 2 static_parameter₂ - 3 (call core.tuple %₁ %₂) - 4 (return %₃) -17 TestMod.f -18 (return %₁₇) + 1 (call core.tuple static_parameter₁ static_parameter₂) + 2 (return %₁) +18 (latestworld) +19 TestMod.f +20 (return %₁₉) ######################################## # Error: Static parameter which is unused @@ -237,13 +248,14 @@ function f(x)::Int end #--------------------- 1 (method TestMod.f) -2 TestMod.f -3 (call core.Typeof %₂) -4 (call core.svec %₃ core.Any) -5 (call core.svec) -6 SourceLocation::1:10 -7 (call core.svec %₄ %₅ %₆) -8 --- method core.nothing %₇ +2 (latestworld) +3 TestMod.f +4 (call core.Typeof %₃) +5 (call core.svec %₄ core.Any) +6 (call core.svec) +7 SourceLocation::1:10 +8 (call core.svec %₅ %₆ %₇) +9 --- method core.nothing %₈ slots: [slot₁/#self#(!read) slot₂/x slot₃/tmp(!read)] 1 TestMod.Int 2 (gotoifnot slot₂/x label₃) @@ -257,8 +269,9 @@ end 10 (= slot₃/tmp (call core.typeassert %₉ %₁)) 11 slot₃/tmp 12 (return %₁₁) -9 TestMod.f -10 (return %₉) +10 (latestworld) +11 TestMod.f +12 (return %₁₁) ######################################## # Callable type @@ -266,16 +279,18 @@ function (::T)(x) x end #--------------------- -1 TestMod.T -2 (call core.svec %₁ core.Any) -3 (call core.svec) -4 SourceLocation::1:10 -5 (call core.svec %₂ %₃ %₄) -6 --- method core.nothing %₅ +1 (latestworld) +2 TestMod.T +3 (call core.svec %₂ core.Any) +4 (call core.svec) +5 SourceLocation::1:10 +6 (call core.svec %₃ %₄ %₅) +7 --- method core.nothing %₆ slots: [slot₁/#self#(!read) slot₂/x] 1 slot₂/x 2 (return %₁) -7 (return core.nothing) +8 (latestworld) +9 (return core.nothing) ######################################## # Callable type with instance @@ -283,16 +298,18 @@ function (y::T)(x) (y, x) end #--------------------- -1 TestMod.T -2 (call core.svec %₁ core.Any) -3 (call core.svec) -4 SourceLocation::1:10 -5 (call core.svec %₂ %₃ %₄) -6 --- method core.nothing %₅ +1 (latestworld) +2 TestMod.T +3 (call core.svec %₂ core.Any) +4 (call core.svec) +5 SourceLocation::1:10 +6 (call core.svec %₃ %₄ %₅) +7 --- method core.nothing %₆ slots: [slot₁/y slot₂/x] 1 (call core.tuple slot₁/y slot₂/x) 2 (return %₁) -7 (return core.nothing) +8 (latestworld) +9 (return core.nothing) ######################################## # `where` params used in callable object type @@ -300,37 +317,40 @@ function (x::X1{T})() where T T end #--------------------- -1 (= slot₁/T (call core.TypeVar :T)) -2 TestMod.X1 -3 slot₁/T -4 (call core.apply_type %₂ %₃) -5 (call core.svec %₄) -6 slot₁/T -7 (call core.svec %₆) -8 SourceLocation::1:10 -9 (call core.svec %₅ %₇ %₈) -10 --- method core.nothing %₉ +1 (latestworld) +2 (= slot₁/T (call core.TypeVar :T)) +3 TestMod.X1 +4 slot₁/T +5 (call core.apply_type %₃ %₄) +6 (call core.svec %₅) +7 slot₁/T +8 (call core.svec %₇) +9 SourceLocation::1:10 +10 (call core.svec %₆ %₈ %₉) +11 --- method core.nothing %₁₀ slots: [slot₁/x(!read)] - 1 static_parameter₁ - 2 (return %₁) -11 (return core.nothing) + 1 (return static_parameter₁) +12 (latestworld) +13 (return core.nothing) ######################################## # Function with module ref in name function A.f() end #--------------------- -1 TestMod.A -2 (call top.getproperty %₁ :f) -3 (call core.Typeof %₂) -4 (call core.svec %₃) -5 (call core.svec) -6 SourceLocation::1:10 -7 (call core.svec %₄ %₅ %₆) -8 --- method core.nothing %₇ +1 (latestworld) +2 TestMod.A +3 (call top.getproperty %₂ :f) +4 (call core.Typeof %₃) +5 (call core.svec %₄) +6 (call core.svec) +7 SourceLocation::1:10 +8 (call core.svec %₅ %₆ %₇) +9 --- method core.nothing %₈ slots: [slot₁/#self#(!read)] 1 (return core.nothing) -9 (return core.nothing) +10 (latestworld) +11 (return core.nothing) ######################################## # Error: Invalid dotop function name @@ -359,44 +379,48 @@ function f(x::T, y::S=1, z::U=2) end #--------------------- 1 (method TestMod.f) -2 TestMod.f -3 (call core.Typeof %₂) -4 TestMod.T -5 (call core.svec %₃ %₄) -6 (call core.svec) -7 SourceLocation::1:10 -8 (call core.svec %₅ %₆ %₇) -9 --- method core.nothing %₈ +2 (latestworld) +3 TestMod.f +4 (call core.Typeof %₃) +5 TestMod.T +6 (call core.svec %₄ %₅) +7 (call core.svec) +8 SourceLocation::1:10 +9 (call core.svec %₆ %₇ %₈) +10 --- method core.nothing %₉ slots: [slot₁/#self#(called) slot₂/x] 1 (call slot₁/#self# slot₂/x 1 2) 2 (return %₁) -10 TestMod.f -11 (call core.Typeof %₁₀) -12 TestMod.T -13 TestMod.S -14 (call core.svec %₁₁ %₁₂ %₁₃) -15 (call core.svec) -16 SourceLocation::1:10 -17 (call core.svec %₁₄ %₁₅ %₁₆) -18 --- method core.nothing %₁₇ +11 (latestworld) +12 TestMod.f +13 (call core.Typeof %₁₂) +14 TestMod.T +15 TestMod.S +16 (call core.svec %₁₃ %₁₄ %₁₅) +17 (call core.svec) +18 SourceLocation::1:10 +19 (call core.svec %₁₆ %₁₇ %₁₈) +20 --- method core.nothing %₁₉ slots: [slot₁/#self#(called) slot₂/x slot₃/y] 1 (call slot₁/#self# slot₂/x slot₃/y 2) 2 (return %₁) -19 TestMod.f -20 (call core.Typeof %₁₉) -21 TestMod.T -22 TestMod.S -23 TestMod.U -24 (call core.svec %₂₀ %₂₁ %₂₂ %₂₃) -25 (call core.svec) -26 SourceLocation::1:10 -27 (call core.svec %₂₄ %₂₅ %₂₆) -28 --- method core.nothing %₂₇ +21 (latestworld) +22 TestMod.f +23 (call core.Typeof %₂₂) +24 TestMod.T +25 TestMod.S +26 TestMod.U +27 (call core.svec %₂₃ %₂₄ %₂₅ %₂₆) +28 (call core.svec) +29 SourceLocation::1:10 +30 (call core.svec %₂₇ %₂₈ %₂₉) +31 --- method core.nothing %₃₀ slots: [slot₁/#self#(!read) slot₂/x slot₃/y slot₄/z(!read)] 1 (call core.tuple slot₂/x slot₃/y) 2 (return %₁) -29 TestMod.f -30 (return %₂₉) +32 (latestworld) +33 TestMod.f +34 (return %₃₃) ######################################## # Default positional args which depend on other args @@ -405,38 +429,42 @@ function f(x=1, y=x) end #--------------------- 1 (method TestMod.f) -2 TestMod.f -3 (call core.Typeof %₂) -4 (call core.svec %₃) -5 (call core.svec) -6 SourceLocation::1:10 -7 (call core.svec %₄ %₅ %₆) -8 --- method core.nothing %₇ +2 (latestworld) +3 TestMod.f +4 (call core.Typeof %₃) +5 (call core.svec %₄) +6 (call core.svec) +7 SourceLocation::1:10 +8 (call core.svec %₅ %₆ %₇) +9 --- method core.nothing %₈ slots: [slot₁/#self#(called)] 1 (call slot₁/#self# 1) 2 (return %₁) -9 TestMod.f -10 (call core.Typeof %₉) -11 (call core.svec %₁₀ core.Any) -12 (call core.svec) -13 SourceLocation::1:10 -14 (call core.svec %₁₁ %₁₂ %₁₃) -15 --- method core.nothing %₁₄ +10 (latestworld) +11 TestMod.f +12 (call core.Typeof %₁₁) +13 (call core.svec %₁₂ core.Any) +14 (call core.svec) +15 SourceLocation::1:10 +16 (call core.svec %₁₃ %₁₄ %₁₅) +17 --- method core.nothing %₁₆ slots: [slot₁/#self#(called) slot₂/x] 1 (call slot₁/#self# slot₂/x slot₂/x) 2 (return %₁) -16 TestMod.f -17 (call core.Typeof %₁₆) -18 (call core.svec %₁₇ core.Any core.Any) -19 (call core.svec) -20 SourceLocation::1:10 -21 (call core.svec %₁₈ %₁₉ %₂₀) -22 --- method core.nothing %₂₁ +18 (latestworld) +19 TestMod.f +20 (call core.Typeof %₁₉) +21 (call core.svec %₂₀ core.Any core.Any) +22 (call core.svec) +23 SourceLocation::1:10 +24 (call core.svec %₂₁ %₂₂ %₂₃) +25 --- method core.nothing %₂₄ slots: [slot₁/#self#(!read) slot₂/x slot₃/y] 1 (call core.tuple slot₂/x slot₃/y) 2 (return %₁) -23 TestMod.f -24 (return %₂₃) +26 (latestworld) +27 TestMod.f +28 (return %₂₇) ######################################## # Default positional args with missing arg names (implicit placeholders) @@ -445,41 +473,45 @@ function f(::Int, y=1, z=2) end #--------------------- 1 (method TestMod.f) -2 TestMod.f -3 (call core.Typeof %₂) -4 TestMod.Int -5 (call core.svec %₃ %₄) -6 (call core.svec) -7 SourceLocation::1:10 -8 (call core.svec %₅ %₆ %₇) -9 --- method core.nothing %₈ +2 (latestworld) +3 TestMod.f +4 (call core.Typeof %₃) +5 TestMod.Int +6 (call core.svec %₄ %₅) +7 (call core.svec) +8 SourceLocation::1:10 +9 (call core.svec %₆ %₇ %₈) +10 --- method core.nothing %₉ slots: [slot₁/#self#(called) slot₂/_] 1 (call slot₁/#self# slot₂/_ 1 2) 2 (return %₁) -10 TestMod.f -11 (call core.Typeof %₁₀) -12 TestMod.Int -13 (call core.svec %₁₁ %₁₂ core.Any) -14 (call core.svec) -15 SourceLocation::1:10 -16 (call core.svec %₁₃ %₁₄ %₁₅) -17 --- method core.nothing %₁₆ +11 (latestworld) +12 TestMod.f +13 (call core.Typeof %₁₂) +14 TestMod.Int +15 (call core.svec %₁₃ %₁₄ core.Any) +16 (call core.svec) +17 SourceLocation::1:10 +18 (call core.svec %₁₅ %₁₆ %₁₇) +19 --- method core.nothing %₁₈ slots: [slot₁/#self#(called) slot₂/_ slot₃/y] 1 (call slot₁/#self# slot₂/_ slot₃/y 2) 2 (return %₁) -18 TestMod.f -19 (call core.Typeof %₁₈) -20 TestMod.Int -21 (call core.svec %₁₉ %₂₀ core.Any core.Any) -22 (call core.svec) -23 SourceLocation::1:10 -24 (call core.svec %₂₁ %₂₂ %₂₃) -25 --- method core.nothing %₂₄ +20 (latestworld) +21 TestMod.f +22 (call core.Typeof %₂₁) +23 TestMod.Int +24 (call core.svec %₂₂ %₂₃ core.Any core.Any) +25 (call core.svec) +26 SourceLocation::1:10 +27 (call core.svec %₂₄ %₂₅ %₂₆) +28 --- method core.nothing %₂₇ slots: [slot₁/#self#(!read) slot₂/_(!read) slot₃/y slot₄/z] 1 (call core.tuple slot₃/y slot₄/z) 2 (return %₁) -26 TestMod.f -27 (return %₂₆) +29 (latestworld) +30 TestMod.f +31 (return %₃₀) ######################################## # Default positional args with placeholders @@ -488,30 +520,33 @@ function f(_::Int, x=1) end #--------------------- 1 (method TestMod.f) -2 TestMod.f -3 (call core.Typeof %₂) -4 TestMod.Int -5 (call core.svec %₃ %₄) -6 (call core.svec) -7 SourceLocation::1:10 -8 (call core.svec %₅ %₆ %₇) -9 --- method core.nothing %₈ +2 (latestworld) +3 TestMod.f +4 (call core.Typeof %₃) +5 TestMod.Int +6 (call core.svec %₄ %₅) +7 (call core.svec) +8 SourceLocation::1:10 +9 (call core.svec %₆ %₇ %₈) +10 --- method core.nothing %₉ slots: [slot₁/#self#(called) slot₂/_] 1 (call slot₁/#self# slot₂/_ 1) 2 (return %₁) -10 TestMod.f -11 (call core.Typeof %₁₀) -12 TestMod.Int -13 (call core.svec %₁₁ %₁₂ core.Any) -14 (call core.svec) -15 SourceLocation::1:10 -16 (call core.svec %₁₃ %₁₄ %₁₅) -17 --- method core.nothing %₁₆ +11 (latestworld) +12 TestMod.f +13 (call core.Typeof %₁₂) +14 TestMod.Int +15 (call core.svec %₁₃ %₁₄ core.Any) +16 (call core.svec) +17 SourceLocation::1:10 +18 (call core.svec %₁₅ %₁₆ %₁₇) +19 --- method core.nothing %₁₈ slots: [slot₁/#self#(!read) slot₂/_(!read) slot₃/x] 1 slot₃/x 2 (return %₁) -18 TestMod.f -19 (return %₁₈) +20 (latestworld) +21 TestMod.f +22 (return %₂₁) ######################################## # Positional args with defaults and `where` clauses @@ -520,55 +555,59 @@ function f(x::T, y::S=1, z::U=2) where {T,S<:T,U<:S} end #--------------------- 1 (method TestMod.f) -2 (= slot₂/T (call core.TypeVar :T)) -3 slot₂/T -4 (= slot₁/S (call core.TypeVar :S %₃)) -5 slot₁/S -6 (= slot₃/U (call core.TypeVar :U %₅)) -7 TestMod.f -8 (call core.Typeof %₇) -9 slot₂/T -10 (call core.svec %₈ %₉) -11 slot₂/T -12 (call core.svec %₁₁) -13 SourceLocation::1:10 -14 (call core.svec %₁₀ %₁₂ %₁₃) -15 --- method core.nothing %₁₄ +2 (latestworld) +3 (= slot₂/T (call core.TypeVar :T)) +4 slot₂/T +5 (= slot₁/S (call core.TypeVar :S %₄)) +6 slot₁/S +7 (= slot₃/U (call core.TypeVar :U %₆)) +8 TestMod.f +9 (call core.Typeof %₈) +10 slot₂/T +11 (call core.svec %₉ %₁₀) +12 slot₂/T +13 (call core.svec %₁₂) +14 SourceLocation::1:10 +15 (call core.svec %₁₁ %₁₃ %₁₄) +16 --- method core.nothing %₁₅ slots: [slot₁/#self#(called) slot₂/x] 1 (call slot₁/#self# slot₂/x 1 2) 2 (return %₁) -16 TestMod.f -17 (call core.Typeof %₁₆) -18 slot₂/T -19 slot₁/S -20 (call core.svec %₁₇ %₁₈ %₁₉) -21 slot₂/T -22 slot₁/S -23 (call core.svec %₂₁ %₂₂) -24 SourceLocation::1:10 -25 (call core.svec %₂₀ %₂₃ %₂₄) -26 --- method core.nothing %₂₅ +17 (latestworld) +18 TestMod.f +19 (call core.Typeof %₁₈) +20 slot₂/T +21 slot₁/S +22 (call core.svec %₁₉ %₂₀ %₂₁) +23 slot₂/T +24 slot₁/S +25 (call core.svec %₂₃ %₂₄) +26 SourceLocation::1:10 +27 (call core.svec %₂₂ %₂₅ %₂₆) +28 --- method core.nothing %₂₇ slots: [slot₁/#self#(called) slot₂/x slot₃/y] 1 (call slot₁/#self# slot₂/x slot₃/y 2) 2 (return %₁) -27 TestMod.f -28 (call core.Typeof %₂₇) -29 slot₂/T -30 slot₁/S -31 slot₃/U -32 (call core.svec %₂₈ %₂₉ %₃₀ %₃₁) -33 slot₂/T -34 slot₁/S -35 slot₃/U -36 (call core.svec %₃₃ %₃₄ %₃₅) -37 SourceLocation::1:10 -38 (call core.svec %₃₂ %₃₆ %₃₇) -39 --- method core.nothing %₃₈ +29 (latestworld) +30 TestMod.f +31 (call core.Typeof %₃₀) +32 slot₂/T +33 slot₁/S +34 slot₃/U +35 (call core.svec %₃₁ %₃₂ %₃₃ %₃₄) +36 slot₂/T +37 slot₁/S +38 slot₃/U +39 (call core.svec %₃₆ %₃₇ %₃₈) +40 SourceLocation::1:10 +41 (call core.svec %₃₅ %₃₉ %₄₀) +42 --- method core.nothing %₄₁ slots: [slot₁/#self#(!read) slot₂/x slot₃/y slot₄/z] 1 (call core.tuple slot₂/x slot₃/y slot₄/z) 2 (return %₁) -40 TestMod.f -41 (return %₄₀) +43 (latestworld) +44 TestMod.f +45 (return %₄₄) ######################################## # Positional args and type parameters with transitive dependencies @@ -579,56 +618,57 @@ function f(x, y::S=[1], z::U=2) where {T, S<:AbstractVector{T}, U} end #--------------------- 1 (method TestMod.f) -2 (= slot₂/T (call core.TypeVar :T)) -3 TestMod.AbstractVector -4 slot₂/T -5 (call core.apply_type %₃ %₄) -6 (= slot₁/S (call core.TypeVar :S %₅)) -7 (= slot₃/U (call core.TypeVar :U)) -8 TestMod.f -9 (call core.Typeof %₈) -10 (call core.svec %₉ core.Any) -11 (call core.svec) -12 SourceLocation::1:10 -13 (call core.svec %₁₀ %₁₁ %₁₂) -14 --- method core.nothing %₁₃ +2 (latestworld) +3 (= slot₂/T (call core.TypeVar :T)) +4 TestMod.AbstractVector +5 slot₂/T +6 (call core.apply_type %₄ %₅) +7 (= slot₁/S (call core.TypeVar :S %₆)) +8 (= slot₃/U (call core.TypeVar :U)) +9 TestMod.f +10 (call core.Typeof %₉) +11 (call core.svec %₁₀ core.Any) +12 (call core.svec) +13 SourceLocation::1:10 +14 (call core.svec %₁₁ %₁₂ %₁₃) +15 --- method core.nothing %₁₄ slots: [slot₁/#self#(called) slot₂/x] 1 (call top.vect 1) 2 (call slot₁/#self# slot₂/x %₁ 2) 3 (return %₂) -15 TestMod.f -16 (call core.Typeof %₁₅) -17 slot₁/S -18 (call core.svec %₁₆ core.Any %₁₇) -19 slot₂/T -20 slot₁/S -21 (call core.svec %₁₉ %₂₀) -22 SourceLocation::1:10 -23 (call core.svec %₁₈ %₂₁ %₂₂) -24 --- method core.nothing %₂₃ +16 (latestworld) +17 TestMod.f +18 (call core.Typeof %₁₇) +19 slot₁/S +20 (call core.svec %₁₈ core.Any %₁₉) +21 slot₂/T +22 slot₁/S +23 (call core.svec %₂₁ %₂₂) +24 SourceLocation::1:10 +25 (call core.svec %₂₀ %₂₃ %₂₄) +26 --- method core.nothing %₂₅ slots: [slot₁/#self#(called) slot₂/x slot₃/y] 1 (call slot₁/#self# slot₂/x slot₃/y 2) 2 (return %₁) -25 TestMod.f -26 (call core.Typeof %₂₅) -27 slot₁/S -28 slot₃/U -29 (call core.svec %₂₆ core.Any %₂₇ %₂₈) -30 slot₂/T -31 slot₁/S -32 slot₃/U -33 (call core.svec %₃₀ %₃₁ %₃₂) -34 SourceLocation::1:10 -35 (call core.svec %₂₉ %₃₃ %₃₄) -36 --- method core.nothing %₃₅ +27 (latestworld) +28 TestMod.f +29 (call core.Typeof %₂₈) +30 slot₁/S +31 slot₃/U +32 (call core.svec %₂₉ core.Any %₃₀ %₃₁) +33 slot₂/T +34 slot₁/S +35 slot₃/U +36 (call core.svec %₃₃ %₃₄ %₃₅) +37 SourceLocation::1:10 +38 (call core.svec %₃₂ %₃₆ %₃₇) +39 --- method core.nothing %₃₈ slots: [slot₁/#self#(!read) slot₂/x slot₃/y slot₄/z] - 1 static_parameter₁ - 2 static_parameter₂ - 3 static_parameter₃ - 4 (call core.tuple slot₂/x slot₃/y slot₄/z %₁ %₂ %₃) - 5 (return %₄) -37 TestMod.f -38 (return %₃₇) + 1 (call core.tuple slot₂/x slot₃/y slot₄/z static_parameter₁ static_parameter₂ static_parameter₃) + 2 (return %₁) +40 (latestworld) +41 TestMod.f +42 (return %₄₁) ######################################## # Default positional args are allowed before trailing slurp with no default @@ -637,29 +677,32 @@ function f(x=1, ys...) end #--------------------- 1 (method TestMod.f) -2 TestMod.f -3 (call core.Typeof %₂) -4 (call core.svec %₃) -5 (call core.svec) -6 SourceLocation::1:10 -7 (call core.svec %₄ %₅ %₆) -8 --- method core.nothing %₇ +2 (latestworld) +3 TestMod.f +4 (call core.Typeof %₃) +5 (call core.svec %₄) +6 (call core.svec) +7 SourceLocation::1:10 +8 (call core.svec %₅ %₆ %₇) +9 --- method core.nothing %₈ slots: [slot₁/#self#(called)] 1 (call slot₁/#self# 1) 2 (return %₁) -9 TestMod.f -10 (call core.Typeof %₉) -11 (call core.apply_type core.Vararg core.Any) -12 (call core.svec %₁₀ core.Any %₁₁) -13 (call core.svec) -14 SourceLocation::1:10 -15 (call core.svec %₁₂ %₁₃ %₁₄) -16 --- method core.nothing %₁₅ +10 (latestworld) +11 TestMod.f +12 (call core.Typeof %₁₁) +13 (call core.apply_type core.Vararg core.Any) +14 (call core.svec %₁₂ core.Any %₁₃) +15 (call core.svec) +16 SourceLocation::1:10 +17 (call core.svec %₁₄ %₁₅ %₁₆) +18 --- method core.nothing %₁₇ slots: [slot₁/#self#(!read) slot₂/x(!read) slot₃/ys] 1 slot₃/ys 2 (return %₁) -17 TestMod.f -18 (return %₁₇) +19 (latestworld) +20 TestMod.f +21 (return %₂₀) ######################################## # Error: Default positional args before non-default arg @@ -680,29 +723,32 @@ function f(xs...=1) end #--------------------- 1 (method TestMod.f) -2 TestMod.f -3 (call core.Typeof %₂) -4 (call core.svec %₃) -5 (call core.svec) -6 SourceLocation::1:10 -7 (call core.svec %₄ %₅ %₆) -8 --- method core.nothing %₇ +2 (latestworld) +3 TestMod.f +4 (call core.Typeof %₃) +5 (call core.svec %₄) +6 (call core.svec) +7 SourceLocation::1:10 +8 (call core.svec %₅ %₆ %₇) +9 --- method core.nothing %₈ slots: [slot₁/#self#(called)] 1 (call slot₁/#self# 1) 2 (return %₁) -9 TestMod.f -10 (call core.Typeof %₉) -11 (call core.apply_type core.Vararg core.Any) -12 (call core.svec %₁₀ %₁₁) -13 (call core.svec) -14 SourceLocation::1:10 -15 (call core.svec %₁₂ %₁₃ %₁₄) -16 --- method core.nothing %₁₅ +10 (latestworld) +11 TestMod.f +12 (call core.Typeof %₁₁) +13 (call core.apply_type core.Vararg core.Any) +14 (call core.svec %₁₂ %₁₃) +15 (call core.svec) +16 SourceLocation::1:10 +17 (call core.svec %₁₄ %₁₅ %₁₆) +18 --- method core.nothing %₁₇ slots: [slot₁/#self#(!read) slot₂/xs] 1 slot₂/xs 2 (return %₁) -17 TestMod.f -18 (return %₁₇) +19 (latestworld) +20 TestMod.f +21 (return %₂₀) ######################################## # Positional arg with slurp and splatted default value @@ -711,30 +757,33 @@ function f(xs...=(1,2)...) end #--------------------- 1 (method TestMod.f) -2 TestMod.f -3 (call core.Typeof %₂) -4 (call core.svec %₃) -5 (call core.svec) -6 SourceLocation::1:10 -7 (call core.svec %₄ %₅ %₆) -8 --- method core.nothing %₇ +2 (latestworld) +3 TestMod.f +4 (call core.Typeof %₃) +5 (call core.svec %₄) +6 (call core.svec) +7 SourceLocation::1:10 +8 (call core.svec %₅ %₆ %₇) +9 --- method core.nothing %₈ slots: [slot₁/#self#] 1 (call core.tuple 1 2) 2 (call core._apply_iterate top.iterate slot₁/#self# %₁) 3 (return %₂) -9 TestMod.f -10 (call core.Typeof %₉) -11 (call core.apply_type core.Vararg core.Any) -12 (call core.svec %₁₀ %₁₁) -13 (call core.svec) -14 SourceLocation::1:10 -15 (call core.svec %₁₂ %₁₃ %₁₄) -16 --- method core.nothing %₁₅ +10 (latestworld) +11 TestMod.f +12 (call core.Typeof %₁₁) +13 (call core.apply_type core.Vararg core.Any) +14 (call core.svec %₁₂ %₁₃) +15 (call core.svec) +16 SourceLocation::1:10 +17 (call core.svec %₁₄ %₁₅ %₁₆) +18 --- method core.nothing %₁₇ slots: [slot₁/#self#(!read) slot₂/xs] 1 slot₂/xs 2 (return %₁) -17 TestMod.f -18 (return %₁₇) +19 (latestworld) +20 TestMod.f +21 (return %₂₀) ######################################## # Trivial function argument destructuring @@ -742,13 +791,14 @@ function f(x, (y,z), w) end #--------------------- 1 (method TestMod.f) -2 TestMod.f -3 (call core.Typeof %₂) -4 (call core.svec %₃ core.Any core.Any core.Any) -5 (call core.svec) -6 SourceLocation::1:10 -7 (call core.svec %₄ %₅ %₆) -8 --- method core.nothing %₇ +2 (latestworld) +3 TestMod.f +4 (call core.Typeof %₃) +5 (call core.svec %₄ core.Any core.Any core.Any) +6 (call core.svec) +7 SourceLocation::1:10 +8 (call core.svec %₅ %₆ %₇) +9 --- method core.nothing %₈ slots: [slot₁/#self#(!read) slot₂/x(!read) slot₃/destructured_arg slot₄/w(!read) slot₅/iterstate slot₆/y(!read) slot₇/z(!read)] 1 (call top.indexed_iterate slot₃/destructured_arg 1) 2 (= slot₆/y (call core.getfield %₁ 1)) @@ -757,8 +807,9 @@ end 5 (call top.indexed_iterate slot₃/destructured_arg 2 %₄) 6 (= slot₇/z (call core.getfield %₅ 1)) 7 (return core.nothing) -9 TestMod.f -10 (return %₉) +10 (latestworld) +11 TestMod.f +12 (return %₁₁) ######################################## # Function argument destructuring combined with splats, types and and defaults @@ -766,32 +817,35 @@ function f((x,)::T...=rhs) end #--------------------- 1 (method TestMod.f) -2 TestMod.f -3 (call core.Typeof %₂) -4 (call core.svec %₃) -5 (call core.svec) -6 SourceLocation::1:10 -7 (call core.svec %₄ %₅ %₆) -8 --- method core.nothing %₇ +2 (latestworld) +3 TestMod.f +4 (call core.Typeof %₃) +5 (call core.svec %₄) +6 (call core.svec) +7 SourceLocation::1:10 +8 (call core.svec %₅ %₆ %₇) +9 --- method core.nothing %₈ slots: [slot₁/#self#(called)] 1 TestMod.rhs 2 (call slot₁/#self# %₁) 3 (return %₂) -9 TestMod.f -10 (call core.Typeof %₉) -11 TestMod.T -12 (call core.apply_type core.Vararg %₁₁) -13 (call core.svec %₁₀ %₁₂) -14 (call core.svec) -15 SourceLocation::1:10 -16 (call core.svec %₁₃ %₁₄ %₁₅) -17 --- method core.nothing %₁₆ +10 (latestworld) +11 TestMod.f +12 (call core.Typeof %₁₁) +13 TestMod.T +14 (call core.apply_type core.Vararg %₁₃) +15 (call core.svec %₁₂ %₁₄) +16 (call core.svec) +17 SourceLocation::1:10 +18 (call core.svec %₁₅ %₁₆ %₁₇) +19 --- method core.nothing %₁₈ slots: [slot₁/#self#(!read) slot₂/destructured_arg slot₃/x(!read)] 1 (call top.indexed_iterate slot₂/destructured_arg 1) 2 (= slot₃/x (call core.getfield %₁ 1)) 3 (return core.nothing) -18 TestMod.f -19 (return %₁₈) +20 (latestworld) +21 TestMod.f +22 (return %₂₁) ######################################## # Function argument destructuring combined with splats, types and and defaults @@ -799,24 +853,26 @@ function f(x=default_x)::T end #--------------------- 1 (method TestMod.f) -2 TestMod.f -3 (call core.Typeof %₂) -4 (call core.svec %₃) -5 (call core.svec) -6 SourceLocation::1:10 -7 (call core.svec %₄ %₅ %₆) -8 --- method core.nothing %₇ +2 (latestworld) +3 TestMod.f +4 (call core.Typeof %₃) +5 (call core.svec %₄) +6 (call core.svec) +7 SourceLocation::1:10 +8 (call core.svec %₅ %₆ %₇) +9 --- method core.nothing %₈ slots: [slot₁/#self#(called)] 1 TestMod.default_x 2 (call slot₁/#self# %₁) 3 (return %₂) -9 TestMod.f -10 (call core.Typeof %₉) -11 (call core.svec %₁₀ core.Any) -12 (call core.svec) -13 SourceLocation::1:10 -14 (call core.svec %₁₁ %₁₂ %₁₃) -15 --- method core.nothing %₁₄ +10 (latestworld) +11 TestMod.f +12 (call core.Typeof %₁₁) +13 (call core.svec %₁₂ core.Any) +14 (call core.svec) +15 SourceLocation::1:10 +16 (call core.svec %₁₃ %₁₄ %₁₅) +17 --- method core.nothing %₁₆ slots: [slot₁/#self#(!read) slot₂/x(!read) slot₃/tmp(!read)] 1 TestMod.T 2 (= slot₃/tmp core.nothing) @@ -829,8 +885,9 @@ end 9 (= slot₃/tmp (call core.typeassert %₈ %₁)) 10 slot₃/tmp 11 (return %₁₀) -16 TestMod.f -17 (return %₁₆) +18 (latestworld) +19 TestMod.f +20 (return %₁₉) ######################################## # Duplicate destructured placeholders ok @@ -838,21 +895,23 @@ function f((_,), (_,)) end #--------------------- 1 (method TestMod.f) -2 TestMod.f -3 (call core.Typeof %₂) -4 (call core.svec %₃ core.Any core.Any) -5 (call core.svec) -6 SourceLocation::1:10 -7 (call core.svec %₄ %₅ %₆) -8 --- method core.nothing %₇ +2 (latestworld) +3 TestMod.f +4 (call core.Typeof %₃) +5 (call core.svec %₄ core.Any core.Any) +6 (call core.svec) +7 SourceLocation::1:10 +8 (call core.svec %₅ %₆ %₇) +9 --- method core.nothing %₈ slots: [slot₁/#self#(!read) slot₂/destructured_arg slot₃/destructured_arg] 1 (call top.indexed_iterate slot₂/destructured_arg 1) 2 (call core.getfield %₁ 1) 3 (call top.indexed_iterate slot₃/destructured_arg 1) 4 (call core.getfield %₃ 1) 5 (return core.nothing) -9 TestMod.f -10 (return %₉) +10 (latestworld) +11 TestMod.f +12 (return %₁₁) ######################################## # Slot flags @@ -861,20 +920,22 @@ function f(@nospecialize(x), g, y) end #--------------------- 1 (method TestMod.f) -2 TestMod.f -3 (call core.Typeof %₂) -4 (call core.svec %₃ core.Any core.Any core.Any) -5 (call core.svec) -6 SourceLocation::1:10 -7 (call core.svec %₄ %₅ %₆) -8 --- method core.nothing %₇ +2 (latestworld) +3 TestMod.f +4 (call core.Typeof %₃) +5 (call core.svec %₄ core.Any core.Any core.Any) +6 (call core.svec) +7 SourceLocation::1:10 +8 (call core.svec %₅ %₆ %₇) +9 --- method core.nothing %₈ slots: [slot₁/#self#(!read) slot₂/x(nospecialize,!read) slot₃/g(called) slot₄/y] 1 TestMod.+ 2 (call slot₃/g) 3 (call %₁ %₂ slot₄/y) 4 (return %₃) -9 TestMod.f -10 (return %₉) +10 (latestworld) +11 TestMod.f +12 (return %₁₁) ######################################## # Function return without arguments @@ -884,19 +945,21 @@ function f() end #--------------------- 1 (method TestMod.f) -2 TestMod.f -3 (call core.Typeof %₂) -4 (call core.svec %₃) -5 (call core.svec) -6 SourceLocation::1:10 -7 (call core.svec %₄ %₅ %₆) -8 --- method core.nothing %₇ +2 (latestworld) +3 TestMod.f +4 (call core.Typeof %₃) +5 (call core.svec %₄) +6 (call core.svec) +7 SourceLocation::1:10 +8 (call core.svec %₅ %₆ %₇) +9 --- method core.nothing %₈ slots: [slot₁/#self#(!read)] 1 (return core.nothing) 2 TestMod.after_return 3 (return %₂) -9 TestMod.f -10 (return %₉) +10 (latestworld) +11 TestMod.f +12 (return %₁₁) ######################################## # Binding docs to functions @@ -907,19 +970,21 @@ function f() end #--------------------- 1 (method TestMod.f) -2 TestMod.f -3 (call core.Typeof %₂) -4 (call core.svec %₃) -5 (call core.svec) -6 SourceLocation::4:10 -7 (call core.svec %₄ %₅ %₆) -8 --- method core.nothing %₇ +2 (latestworld) +3 TestMod.f +4 (call core.Typeof %₃) +5 (call core.svec %₄) +6 (call core.svec) +7 SourceLocation::4:10 +8 (call core.svec %₅ %₆ %₇) +9 --- method core.nothing %₈ slots: [slot₁/#self#(!read)] 1 (return core.nothing) -9 TestMod.f -10 (call JuliaLowering.bind_docs! %₉ "some docs\n" %₇) +10 (latestworld) 11 TestMod.f -12 (return %₁₁) +12 (call JuliaLowering.bind_docs! %₁₁ "some docs\n" %₈) +13 TestMod.f +14 (return %₁₃) ######################################## # Binding docs to callable type @@ -929,17 +994,19 @@ some docs function (x::T)() end #--------------------- -1 TestMod.T -2 (call core.svec %₁) -3 (call core.svec) -4 SourceLocation::4:10 -5 (call core.svec %₂ %₃ %₄) -6 --- method core.nothing %₅ +1 (latestworld) +2 TestMod.T +3 (call core.svec %₂) +4 (call core.svec) +5 SourceLocation::4:10 +6 (call core.svec %₃ %₄ %₅) +7 --- method core.nothing %₆ slots: [slot₁/x(!read)] 1 (return core.nothing) -7 TestMod.T -8 (call JuliaLowering.bind_docs! %₇ "some docs\n" %₅) -9 (return core.nothing) +8 (latestworld) +9 TestMod.T +10 (call JuliaLowering.bind_docs! %₉ "some docs\n" %₆) +11 (return core.nothing) ######################################## # Keyword function with defaults. @@ -957,56 +1024,60 @@ end #--------------------- 1 (method TestMod.f_kw_simple) 2 (method TestMod.#f_kw_simple#0) -3 TestMod.#f_kw_simple#0 -4 (call core.Typeof %₃) -5 TestMod.Char -6 TestMod.Bool -7 TestMod.f_kw_simple -8 (call core.Typeof %₇) -9 TestMod.Int -10 TestMod.Float64 -11 (call core.svec %₄ %₅ %₆ %₈ %₉ %₁₀) -12 (call core.svec) -13 SourceLocation::1:10 -14 (call core.svec %₁₁ %₁₂ %₁₃) -15 --- method core.nothing %₁₄ +3 (latestworld) +4 TestMod.#f_kw_simple#0 +5 (call core.Typeof %₄) +6 TestMod.Char +7 TestMod.Bool +8 TestMod.f_kw_simple +9 (call core.Typeof %₈) +10 TestMod.Int +11 TestMod.Float64 +12 (call core.svec %₅ %₆ %₇ %₉ %₁₀ %₁₁) +13 (call core.svec) +14 SourceLocation::1:10 +15 (call core.svec %₁₂ %₁₃ %₁₄) +16 --- method core.nothing %₁₅ slots: [slot₁/#self#(!read) slot₂/x slot₃/y slot₄/#self#(!read) slot₅/a slot₆/b] 1 (meta :nkw 2) 2 (call core.tuple slot₅/a slot₆/b slot₂/x slot₃/y) 3 (return %₂) -16 (call core.typeof core.kwcall) -17 TestMod.f_kw_simple -18 (call core.Typeof %₁₇) -19 (call core.svec %₁₆ core.NamedTuple %₁₈) -20 (call core.svec) -21 SourceLocation::1:10 -22 (call core.svec %₁₉ %₂₀ %₂₁) -23 --- method core.nothing %₂₂ +17 (latestworld) +18 (call core.typeof core.kwcall) +19 TestMod.f_kw_simple +20 (call core.Typeof %₁₉) +21 (call core.svec %₁₈ core.NamedTuple %₂₀) +22 (call core.svec) +23 SourceLocation::1:10 +24 (call core.svec %₂₁ %₂₂ %₂₃) +25 --- method core.nothing %₂₄ slots: [slot₁/#self#(called) slot₂/kws slot₃/#self#] 1 (call slot₁/#self# slot₂/kws slot₃/#self# 1 1.0) 2 (return %₁) -24 (call core.typeof core.kwcall) -25 TestMod.f_kw_simple -26 (call core.Typeof %₂₅) -27 TestMod.Int -28 (call core.svec %₂₄ core.NamedTuple %₂₆ %₂₇) -29 (call core.svec) -30 SourceLocation::1:10 -31 (call core.svec %₂₈ %₂₉ %₃₀) -32 --- method core.nothing %₃₁ +26 (latestworld) +27 (call core.typeof core.kwcall) +28 TestMod.f_kw_simple +29 (call core.Typeof %₂₈) +30 TestMod.Int +31 (call core.svec %₂₇ core.NamedTuple %₂₉ %₃₀) +32 (call core.svec) +33 SourceLocation::1:10 +34 (call core.svec %₃₁ %₃₂ %₃₃) +35 --- method core.nothing %₃₄ slots: [slot₁/#self#(called) slot₂/kws slot₃/#self# slot₄/a] 1 (call slot₁/#self# slot₂/kws slot₃/#self# slot₄/a 1.0) 2 (return %₁) -33 (call core.typeof core.kwcall) -34 TestMod.f_kw_simple -35 (call core.Typeof %₃₄) -36 TestMod.Int -37 TestMod.Float64 -38 (call core.svec %₃₃ core.NamedTuple %₃₅ %₃₆ %₃₇) -39 (call core.svec) -40 SourceLocation::1:10 -41 (call core.svec %₃₈ %₃₉ %₄₀) -42 --- method core.nothing %₄₁ +36 (latestworld) +37 (call core.typeof core.kwcall) +38 TestMod.f_kw_simple +39 (call core.Typeof %₃₈) +40 TestMod.Int +41 TestMod.Float64 +42 (call core.svec %₃₇ core.NamedTuple %₃₉ %₄₀ %₄₁) +43 (call core.svec) +44 SourceLocation::1:10 +45 (call core.svec %₄₂ %₄₃ %₄₄) +46 --- method core.nothing %₄₅ slots: [slot₁/#self#(!read) slot₂/kws slot₃/#self# slot₄/a slot₅/b slot₆/kwtmp slot₇/x(!read) slot₈/y(!read)] 1 (newvar slot₇/x) 2 (newvar slot₈/y) @@ -1048,42 +1119,47 @@ end 38 TestMod.#f_kw_simple#0 39 (call %₃₈ %₁₆ %₃₀ slot₃/#self# slot₄/a slot₅/b) 40 (return %₃₉) -43 TestMod.f_kw_simple -44 (call core.Typeof %₄₃) -45 (call core.svec %₄₄) -46 (call core.svec) -47 SourceLocation::1:10 -48 (call core.svec %₄₅ %₄₆ %₄₇) -49 --- method core.nothing %₄₈ +47 (latestworld) +48 (latestworld) +49 TestMod.f_kw_simple +50 (call core.Typeof %₄₉) +51 (call core.svec %₅₀) +52 (call core.svec) +53 SourceLocation::1:10 +54 (call core.svec %₅₁ %₅₂ %₅₃) +55 --- method core.nothing %₅₄ slots: [slot₁/#self#(called)] 1 (call slot₁/#self# 1 1.0) 2 (return %₁) -50 TestMod.f_kw_simple -51 (call core.Typeof %₅₀) -52 TestMod.Int -53 (call core.svec %₅₁ %₅₂) -54 (call core.svec) -55 SourceLocation::1:10 -56 (call core.svec %₅₃ %₅₄ %₅₅) -57 --- method core.nothing %₅₆ +56 (latestworld) +57 TestMod.f_kw_simple +58 (call core.Typeof %₅₇) +59 TestMod.Int +60 (call core.svec %₅₈ %₅₉) +61 (call core.svec) +62 SourceLocation::1:10 +63 (call core.svec %₆₀ %₆₁ %₆₂) +64 --- method core.nothing %₆₃ slots: [slot₁/#self#(called) slot₂/a] 1 (call slot₁/#self# slot₂/a 1.0) 2 (return %₁) -58 TestMod.f_kw_simple -59 (call core.Typeof %₅₈) -60 TestMod.Int -61 TestMod.Float64 -62 (call core.svec %₅₉ %₆₀ %₆₁) -63 (call core.svec) -64 SourceLocation::1:10 -65 (call core.svec %₆₂ %₆₃ %₆₄) -66 --- method core.nothing %₆₅ +65 (latestworld) +66 TestMod.f_kw_simple +67 (call core.Typeof %₆₆) +68 TestMod.Int +69 TestMod.Float64 +70 (call core.svec %₆₇ %₆₈ %₆₉) +71 (call core.svec) +72 SourceLocation::1:10 +73 (call core.svec %₇₀ %₇₁ %₇₂) +74 --- method core.nothing %₇₃ slots: [slot₁/#self# slot₂/a slot₃/b] 1 TestMod.#f_kw_simple#0 2 (call %₁ 'a' true slot₁/#self# slot₂/a slot₃/b) 3 (return %₂) -67 TestMod.f_kw_simple -68 (return %₆₇) +75 (latestworld) +76 TestMod.f_kw_simple +77 (return %₇₆) ######################################## # Keyword slurping - simple forwarding of all kws @@ -1093,49 +1169,54 @@ end #--------------------- 1 (method TestMod.f_kw_slurp_simple) 2 (method TestMod.#f_kw_slurp_simple#0) -3 TestMod.#f_kw_slurp_simple#0 -4 (call core.Typeof %₃) -5 (call top.pairs core.NamedTuple) -6 TestMod.f_kw_slurp_simple -7 (call core.Typeof %₆) -8 (call core.svec %₄ %₅ %₇) -9 (call core.svec) -10 SourceLocation::1:10 -11 (call core.svec %₈ %₉ %₁₀) -12 --- method core.nothing %₁₁ +3 (latestworld) +4 TestMod.#f_kw_slurp_simple#0 +5 (call core.Typeof %₄) +6 (call top.pairs core.NamedTuple) +7 TestMod.f_kw_slurp_simple +8 (call core.Typeof %₇) +9 (call core.svec %₅ %₆ %₈) +10 (call core.svec) +11 SourceLocation::1:10 +12 (call core.svec %₉ %₁₀ %₁₁) +13 --- method core.nothing %₁₂ slots: [slot₁/#self#(!read) slot₂/all_kws slot₃/#self#(!read)] 1 (meta :nkw 1) 2 slot₂/all_kws 3 (return %₂) -13 (call core.typeof core.kwcall) -14 TestMod.f_kw_slurp_simple -15 (call core.Typeof %₁₄) -16 (call core.svec %₁₃ core.NamedTuple %₁₅) -17 (call core.svec) -18 SourceLocation::1:10 -19 (call core.svec %₁₆ %₁₇ %₁₈) -20 --- method core.nothing %₁₉ +14 (latestworld) +15 (call core.typeof core.kwcall) +16 TestMod.f_kw_slurp_simple +17 (call core.Typeof %₁₆) +18 (call core.svec %₁₅ core.NamedTuple %₁₇) +19 (call core.svec) +20 SourceLocation::1:10 +21 (call core.svec %₁₈ %₁₉ %₂₀) +22 --- method core.nothing %₂₁ slots: [slot₁/#self#(!read) slot₂/kws slot₃/#self# slot₄/all_kws(!read)] 1 (newvar slot₄/all_kws) 2 (call top.pairs slot₂/kws) 3 TestMod.#f_kw_slurp_simple#0 4 (call %₃ %₂ slot₃/#self#) 5 (return %₄) -21 TestMod.f_kw_slurp_simple -22 (call core.Typeof %₂₁) -23 (call core.svec %₂₂) -24 (call core.svec) -25 SourceLocation::1:10 -26 (call core.svec %₂₃ %₂₄ %₂₅) -27 --- method core.nothing %₂₆ +23 (latestworld) +24 (latestworld) +25 TestMod.f_kw_slurp_simple +26 (call core.Typeof %₂₅) +27 (call core.svec %₂₆) +28 (call core.svec) +29 SourceLocation::1:10 +30 (call core.svec %₂₇ %₂₈ %₂₉) +31 --- method core.nothing %₃₀ slots: [slot₁/#self#] 1 TestMod.#f_kw_slurp_simple#0 2 (call core.NamedTuple) 3 (call top.pairs %₂) 4 (call %₁ %₃ slot₁/#self#) 5 (return %₄) -28 TestMod.f_kw_slurp_simple -29 (return %₂₈) +32 (latestworld) +33 TestMod.f_kw_slurp_simple +34 (return %₃₃) ######################################## # Keyword slurping @@ -1145,28 +1226,30 @@ end #--------------------- 1 (method TestMod.f_kw_slurp) 2 (method TestMod.#f_kw_slurp#0) -3 TestMod.#f_kw_slurp#0 -4 (call core.Typeof %₃) -5 (call top.pairs core.NamedTuple) -6 TestMod.f_kw_slurp -7 (call core.Typeof %₆) -8 (call core.svec %₄ core.Any %₅ %₇) -9 (call core.svec) -10 SourceLocation::1:10 -11 (call core.svec %₈ %₉ %₁₀) -12 --- method core.nothing %₁₁ +3 (latestworld) +4 TestMod.#f_kw_slurp#0 +5 (call core.Typeof %₄) +6 (call top.pairs core.NamedTuple) +7 TestMod.f_kw_slurp +8 (call core.Typeof %₇) +9 (call core.svec %₅ core.Any %₆ %₈) +10 (call core.svec) +11 SourceLocation::1:10 +12 (call core.svec %₉ %₁₀ %₁₁) +13 --- method core.nothing %₁₂ slots: [slot₁/#self#(!read) slot₂/x(!read) slot₃/non_x_kws(!read) slot₄/#self#(!read)] 1 (meta :nkw 2) 2 TestMod.all_kws 3 (return %₂) -13 (call core.typeof core.kwcall) -14 TestMod.f_kw_slurp -15 (call core.Typeof %₁₄) -16 (call core.svec %₁₃ core.NamedTuple %₁₅) -17 (call core.svec) -18 SourceLocation::1:10 -19 (call core.svec %₁₆ %₁₇ %₁₈) -20 --- method core.nothing %₁₉ +14 (latestworld) +15 (call core.typeof core.kwcall) +16 TestMod.f_kw_slurp +17 (call core.Typeof %₁₆) +18 (call core.svec %₁₅ core.NamedTuple %₁₇) +19 (call core.svec) +20 SourceLocation::1:10 +21 (call core.svec %₁₈ %₁₉ %₂₀) +22 --- method core.nothing %₂₁ slots: [slot₁/#self#(!read) slot₂/kws slot₃/#self# slot₄/kwtmp slot₅/non_x_kws(!read) slot₆/x(!read)] 1 (newvar slot₅/non_x_kws) 2 (newvar slot₆/x) @@ -1185,13 +1268,15 @@ end 15 TestMod.#f_kw_slurp#0 16 (call %₁₅ %₁₀ %₁₄ slot₃/#self#) 17 (return %₁₆) -21 TestMod.f_kw_slurp -22 (call core.Typeof %₂₁) -23 (call core.svec %₂₂) -24 (call core.svec) -25 SourceLocation::1:10 -26 (call core.svec %₂₃ %₂₄ %₂₅) -27 --- method core.nothing %₂₆ +23 (latestworld) +24 (latestworld) +25 TestMod.f_kw_slurp +26 (call core.Typeof %₂₅) +27 (call core.svec %₂₆) +28 (call core.svec) +29 SourceLocation::1:10 +30 (call core.svec %₂₇ %₂₈ %₂₉) +31 --- method core.nothing %₃₀ slots: [slot₁/#self#] 1 TestMod.#f_kw_slurp#0 2 TestMod.x_default @@ -1199,8 +1284,9 @@ end 4 (call top.pairs %₃) 5 (call %₁ %₂ %₄ slot₁/#self#) 6 (return %₅) -28 TestMod.f_kw_slurp -29 (return %₂₈) +32 (latestworld) +33 TestMod.f_kw_slurp +34 (return %₃₃) ######################################## # Static parameters used in keywords, with and without the static parameter @@ -1214,40 +1300,40 @@ end #--------------------- 1 (method TestMod.f_kw_sparams) 2 (method TestMod.#f_kw_sparams#0) -3 (= slot₂/X (call core.TypeVar :X)) -4 (= slot₁/A (call core.TypeVar :A)) -5 TestMod.#f_kw_sparams#0 -6 (call core.Typeof %₅) -7 slot₁/A -8 slot₂/X -9 TestMod.f_kw_sparams -10 (call core.Typeof %₉) -11 slot₂/X -12 (call core.svec %₆ %₇ %₈ %₁₀ %₁₁) -13 slot₂/X -14 slot₁/A -15 (call core.svec %₁₃ %₁₄) -16 SourceLocation::1:10 -17 (call core.svec %₁₂ %₁₅ %₁₆) -18 --- method core.nothing %₁₇ +3 (latestworld) +4 (= slot₂/X (call core.TypeVar :X)) +5 (= slot₁/A (call core.TypeVar :A)) +6 TestMod.#f_kw_sparams#0 +7 (call core.Typeof %₆) +8 slot₁/A +9 slot₂/X +10 TestMod.f_kw_sparams +11 (call core.Typeof %₁₀) +12 slot₂/X +13 (call core.svec %₇ %₈ %₉ %₁₁ %₁₂) +14 slot₂/X +15 slot₁/A +16 (call core.svec %₁₄ %₁₅) +17 SourceLocation::1:10 +18 (call core.svec %₁₃ %₁₆ %₁₇) +19 --- method core.nothing %₁₈ slots: [slot₁/#self#(!read) slot₂/a(!read) slot₃/b(!read) slot₄/#self#(!read) slot₅/x(!read)] 1 (meta :nkw 2) - 2 static_parameter₁ - 3 static_parameter₂ - 4 (call core.tuple %₂ %₃) - 5 (return %₄) -19 (= slot₄/X (call core.TypeVar :X)) -20 (= slot₃/A (call core.TypeVar :A)) -21 (call core.typeof core.kwcall) -22 TestMod.f_kw_sparams -23 (call core.Typeof %₂₂) -24 slot₄/X -25 (call core.svec %₂₁ core.NamedTuple %₂₃ %₂₄) + 2 (call core.tuple static_parameter₁ static_parameter₂) + 3 (return %₂) +20 (latestworld) +21 (= slot₄/X (call core.TypeVar :X)) +22 (= slot₃/A (call core.TypeVar :A)) +23 (call core.typeof core.kwcall) +24 TestMod.f_kw_sparams +25 (call core.Typeof %₂₄) 26 slot₄/X -27 (call core.svec %₂₆) -28 SourceLocation::1:10 -29 (call core.svec %₂₅ %₂₇ %₂₈) -30 --- method core.nothing %₂₉ +27 (call core.svec %₂₃ core.NamedTuple %₂₅ %₂₆) +28 slot₄/X +29 (call core.svec %₂₈) +30 SourceLocation::1:10 +31 (call core.svec %₂₇ %₂₉ %₃₀) +32 --- method core.nothing %₃₁ slots: [slot₁/#self#(!read) slot₂/kws slot₃/#self# slot₄/x slot₅/kwtmp slot₆/a(!read) slot₇/b(!read)] 1 (newvar slot₆/a) 2 (newvar slot₇/b) @@ -1260,49 +1346,50 @@ end 9 (= slot₅/kwtmp %₈) 10 slot₅/kwtmp 11 (call core.isdefined slot₂/kws :b) - 12 (gotoifnot %₁₁ label₂₃) + 12 (gotoifnot %₁₁ label₂₁) 13 (call core.getfield slot₂/kws :b) - 14 static_parameter₁ - 15 (call core.isa %₁₃ %₁₄) - 16 (gotoifnot %₁₅ label₁₈) - 17 (goto label₂₁) - 18 static_parameter₁ - 19 (new core.TypeError :keyword argument :b %₁₈ %₁₃) - 20 (call core.throw %₁₉) - 21 (= slot₅/kwtmp %₁₃) - 22 (goto label₂₅) - 23 TestMod.b_def - 24 (= slot₅/kwtmp %₂₃) - 25 slot₅/kwtmp - 26 (call top.keys slot₂/kws) - 27 (call core.tuple :a :b) - 28 (call top.diff_names %₂₆ %₂₇) - 29 (call top.isempty %₂₈) - 30 (gotoifnot %₂₉ label₃₂) - 31 (goto label₃₃) - 32 (call top.kwerr slot₂/kws slot₃/#self# slot₄/x) - 33 TestMod.#f_kw_sparams#0 - 34 (call %₃₃ %₁₀ %₂₅ slot₃/#self# slot₄/x) - 35 (return %₃₄) -31 (= slot₆/X (call core.TypeVar :X)) -32 (= slot₅/A (call core.TypeVar :A)) -33 TestMod.f_kw_sparams -34 (call core.Typeof %₃₃) -35 slot₆/X -36 (call core.svec %₃₄ %₃₅) -37 slot₆/X -38 (call core.svec %₃₇) -39 SourceLocation::1:10 -40 (call core.svec %₃₆ %₃₈ %₃₉) -41 --- method core.nothing %₄₀ + 14 (call core.isa %₁₃ static_parameter₁) + 15 (gotoifnot %₁₄ label₁₇) + 16 (goto label₁₉) + 17 (new core.TypeError :keyword argument :b static_parameter₁ %₁₃) + 18 (call core.throw %₁₇) + 19 (= slot₅/kwtmp %₁₃) + 20 (goto label₂₃) + 21 TestMod.b_def + 22 (= slot₅/kwtmp %₂₁) + 23 slot₅/kwtmp + 24 (call top.keys slot₂/kws) + 25 (call core.tuple :a :b) + 26 (call top.diff_names %₂₄ %₂₅) + 27 (call top.isempty %₂₆) + 28 (gotoifnot %₂₇ label₃₀) + 29 (goto label₃₁) + 30 (call top.kwerr slot₂/kws slot₃/#self# slot₄/x) + 31 TestMod.#f_kw_sparams#0 + 32 (call %₃₁ %₁₀ %₂₃ slot₃/#self# slot₄/x) + 33 (return %₃₂) +33 (latestworld) +34 (latestworld) +35 (= slot₆/X (call core.TypeVar :X)) +36 (= slot₅/A (call core.TypeVar :A)) +37 TestMod.f_kw_sparams +38 (call core.Typeof %₃₇) +39 slot₆/X +40 (call core.svec %₃₈ %₃₉) +41 slot₆/X +42 (call core.svec %₄₁) +43 SourceLocation::1:10 +44 (call core.svec %₄₀ %₄₂ %₄₃) +45 --- method core.nothing %₄₄ slots: [slot₁/#self# slot₂/x] 1 TestMod.#f_kw_sparams#0 2 TestMod.a_def 3 TestMod.b_def 4 (call %₁ %₂ %₃ slot₁/#self# slot₂/x) 5 (return %₄) -42 TestMod.f_kw_sparams -43 (return %₄₂) +46 (latestworld) +47 TestMod.f_kw_sparams +48 (return %₄₇) ######################################## # Error: Static parameter which is unused in keyword body arg types @@ -1364,30 +1451,35 @@ end #--------------------- 1 (method TestMod.f_only_generated) 2 (method TestMod.#f_only_generated@generator#0) -3 TestMod.#f_only_generated@generator#0 -4 (call core.Typeof %₃) -5 (call core.svec %₄ JuliaLowering.MacroContext core.Any core.Any core.Any) -6 (call core.svec) -7 SourceLocation::1:21 -8 (call core.svec %₅ %₆ %₇) -9 --- method core.nothing %₈ +3 (latestworld) +4 (latestworld) +5 TestMod.#f_only_generated@generator#0 +6 (call core.Typeof %₅) +7 (call core.svec %₆ JuliaLowering.MacroContext core.Any core.Any core.Any) +8 (call core.svec) +9 SourceLocation::1:21 +10 (call core.svec %₇ %₈ %₉) +11 --- method core.nothing %₁₀ slots: [slot₁/#self#(!read) slot₂/__context__(!read) slot₃/#self#(!read) slot₄/x(nospecialize) slot₅/y(nospecialize)] 1 TestMod.generator_code 2 (call %₁ slot₄/x slot₅/y) 3 (return %₂) -10 TestMod.f_only_generated -11 (call core.Typeof %₁₀) -12 (call core.svec %₁₁ core.Any core.Any) -13 (call core.svec) -14 SourceLocation::1:21 -15 (call core.svec %₁₂ %₁₃ %₁₄) -16 --- method core.nothing %₁₅ +12 (latestworld) +13 (latestworld) +14 TestMod.f_only_generated +15 (call core.Typeof %₁₄) +16 (call core.svec %₁₅ core.Any core.Any) +17 (call core.svec) +18 SourceLocation::1:21 +19 (call core.svec %₁₆ %₁₇ %₁₈) +20 --- method core.nothing %₁₉ slots: [slot₁/#self#(!read) slot₂/x(!read) slot₃/y(!read)] - 1 (meta :generated (new JuliaLowering.GeneratedFunctionStub TestMod.#f_only_generated@generator#0 SourceRef(SourceFile("@generated function f_only_generated(x, y)\n generator_code(x,y)\nend", 0, nothing, 1, [1, 44, 68, 71]), 1, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"macrocall", 0x0000), 0x00000046, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"@", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"MacroName", 0x0000), 0x00000009, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"function", 0x0000), 0x0000003b, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"function", 0x0001), 0x00000008, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"call", 0x0000), 0x00000016, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000010, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"(", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K",", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K")", 0x0001), 0x00000001, nothing)]), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"block", 0x0000), 0x00000019, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"NewlineWs", 0x0001), 0x00000005, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"call", 0x0000), 0x00000013, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x0000000e, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"(", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K",", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K")", 0x0001), 0x00000001, nothing)]), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"NewlineWs", 0x0001), 0x00000001, nothing)]), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"end", 0x0001), 0x00000003, nothing)])])) (call core.svec :#self# :x :y) (call core.svec))) + 1 (meta :generated (new JuliaLowering.GeneratedFunctionStub TestMod.#f_only_generated@generator#0 SourceRef(SourceFile("@generated function f_only_generated(x, y)\n generator_code(x,y)\nend", 0, nothing, 1, [1, 44, 68]), 1, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"macrocall", 0x0080), 0x00000046, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"@", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"MacroName", 0x0000), 0x00000009, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"function", 0x0080), 0x0000003b, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"function", 0x0001), 0x00000008, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"call", 0x0080), 0x00000016, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000010, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"(", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K",", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K")", 0x0001), 0x00000001, nothing)]), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"block", 0x0080), 0x00000019, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"NewlineWs", 0x0001), 0x00000005, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"call", 0x0080), 0x00000013, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x0000000e, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"(", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K",", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K")", 0x0001), 0x00000001, nothing)]), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"NewlineWs", 0x0001), 0x00000001, nothing)]), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"end", 0x0001), 0x00000003, nothing)])])) (call core.svec :#self# :x :y) (call core.svec))) 2 (meta :generated_only) 3 (return core.nothing) -17 TestMod.f_only_generated -18 (return %₁₇) +21 (latestworld) +22 TestMod.f_only_generated +23 (return %₂₂) ######################################## # Partially generated function with `if @generated` @@ -1405,27 +1497,31 @@ end #--------------------- 1 (method TestMod.f_partially_generated) 2 (method TestMod.#f_partially_generated@generator#0) -3 TestMod.#f_partially_generated@generator#0 -4 (call core.Typeof %₃) -5 (call core.svec %₄ JuliaLowering.MacroContext core.Any core.Any core.Any) -6 (call core.svec) -7 SourceLocation::1:10 -8 (call core.svec %₅ %₆ %₇) -9 --- method core.nothing %₈ +3 (latestworld) +4 (latestworld) +5 TestMod.#f_partially_generated@generator#0 +6 (call core.Typeof %₅) +7 (call core.svec %₆ JuliaLowering.MacroContext core.Any core.Any core.Any) +8 (call core.svec) +9 SourceLocation::1:10 +10 (call core.svec %₇ %₈ %₉) +11 --- method core.nothing %₁₀ slots: [slot₁/#self#(!read) slot₂/__context__(!read) slot₃/#self#(!read) slot₄/x(nospecialize,!read) slot₅/y(nospecialize,!read)] 1 (call JuliaLowering.interpolate_ast (inert (block (= maybe_gen_stuff (call some_gen_stuff x y))))) 2 (call core.tuple %₁) 3 (call JuliaLowering.interpolate_ast (inert (block (block (= nongen_stuff (call bothgen x y)) ($ (block (call JuliaLowering.interpolate_ast (inert (block (= maybe_gen_stuff (call some_gen_stuff x y))))))) (tuple-p nongen_stuff maybe_gen_stuff)))) %₂) 4 (return %₃) -10 TestMod.f_partially_generated -11 (call core.Typeof %₁₀) -12 (call core.svec %₁₁ core.Any core.Any) -13 (call core.svec) -14 SourceLocation::1:10 -15 (call core.svec %₁₂ %₁₃ %₁₄) -16 --- method core.nothing %₁₅ +12 (latestworld) +13 (latestworld) +14 TestMod.f_partially_generated +15 (call core.Typeof %₁₄) +16 (call core.svec %₁₅ core.Any core.Any) +17 (call core.svec) +18 SourceLocation::1:10 +19 (call core.svec %₁₆ %₁₇ %₁₈) +20 --- method core.nothing %₁₉ slots: [slot₁/#self#(!read) slot₂/x slot₃/y slot₄/maybe_gen_stuff slot₅/nongen_stuff] - 1 (meta :generated (new JuliaLowering.GeneratedFunctionStub TestMod.#f_partially_generated@generator#0 SourceRef(SourceFile("function f_partially_generated(x, y)\n nongen_stuff = bothgen(x, y)\n if @generated\n quote\n maybe_gen_stuff = some_gen_stuff(x, y)\n end\n else\n maybe_gen_stuff = some_nongen_stuff(x, y)\n end\n (nongen_stuff, maybe_gen_stuff)\nend", 0, nothing, 1, [1, 38, 71, 89, 103, 154, 166, 175, 225, 233, 269, 272]), 1, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"function", 0x0000), 0x0000010f, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"function", 0x0001), 0x00000008, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"call", 0x0000), 0x0000001b, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000015, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"(", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K",", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K")", 0x0001), 0x00000001, nothing)]), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"block", 0x0000), 0x000000e8, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"NewlineWs", 0x0001), 0x00000005, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"=", 0x0000), 0x0000001c, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x0000000c, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"=", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"call", 0x0000), 0x0000000d, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000007, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"(", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K",", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K")", 0x0001), 0x00000001, nothing)])]), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"NewlineWs", 0x0001), 0x00000005, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"if", 0x0000), 0x0000009d, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"if", 0x0001), 0x00000002, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"macrocall", 0x0000), 0x0000000a, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"@", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"MacroName", 0x0000), 0x00000009, nothing)]), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"block", 0x0000), 0x00000052, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"NewlineWs", 0x0001), 0x00000009, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"quote", 0x0000), 0x00000044, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"block", 0x0000), 0x00000044, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"quote", 0x0001), 0x00000005, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"NewlineWs", 0x0001), 0x0000000d, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"=", 0x0000), 0x00000026, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x0000000f, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"=", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"call", 0x0000), 0x00000014, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x0000000e, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"(", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K",", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K")", 0x0001), 0x00000001, nothing)])]), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"NewlineWs", 0x0001), 0x00000009, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"end", 0x0001), 0x00000003, nothing)])]), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"NewlineWs", 0x0001), 0x00000005, nothing)]), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"else", 0x0001), 0x00000004, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"block", 0x0000), 0x00000037, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"NewlineWs", 0x0001), 0x00000009, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"=", 0x0000), 0x00000029, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x0000000f, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"=", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"call", 0x0000), 0x00000017, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000011, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"(", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K",", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K")", 0x0001), 0x00000001, nothing)])]), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"NewlineWs", 0x0001), 0x00000005, nothing)]), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"end", 0x0001), 0x00000003, nothing)]), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"NewlineWs", 0x0001), 0x00000005, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"tuple", 0x0020), 0x0000001f, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"(", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x0000000c, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K",", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x0000000f, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K")", 0x0001), 0x00000001, nothing)]), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"NewlineWs", 0x0001), 0x00000001, nothing)]), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"end", 0x0001), 0x00000003, nothing)])) (call core.svec :#self# :x :y) (call core.svec))) + 1 (meta :generated (new JuliaLowering.GeneratedFunctionStub TestMod.#f_partially_generated@generator#0 SourceRef(SourceFile("function f_partially_generated(x, y)\n nongen_stuff = bothgen(x, y)\n if @generated\n quote\n maybe_gen_stuff = some_gen_stuff(x, y)\n end\n else\n maybe_gen_stuff = some_nongen_stuff(x, y)\n end\n (nongen_stuff, maybe_gen_stuff)\nend", 0, nothing, 1, [1, 38, 71, 89, 103, 154, 166, 175, 225, 233, 269]), 1, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"function", 0x0080), 0x0000010f, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"function", 0x0001), 0x00000008, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"call", 0x0080), 0x0000001b, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000015, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"(", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K",", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K")", 0x0001), 0x00000001, nothing)]), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"block", 0x0080), 0x000000e8, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"NewlineWs", 0x0001), 0x00000005, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"=", 0x0080), 0x0000001c, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x0000000c, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"=", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"call", 0x0080), 0x0000000d, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000007, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"(", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K",", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K")", 0x0001), 0x00000001, nothing)])]), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"NewlineWs", 0x0001), 0x00000005, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"if", 0x0080), 0x0000009d, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"if", 0x0001), 0x00000002, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"macrocall", 0x0080), 0x0000000a, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"@", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"MacroName", 0x0000), 0x00000009, nothing)]), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"block", 0x0080), 0x00000052, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"NewlineWs", 0x0001), 0x00000009, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"quote", 0x0080), 0x00000044, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"block", 0x0080), 0x00000044, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"quote", 0x0001), 0x00000005, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"NewlineWs", 0x0001), 0x0000000d, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"=", 0x0080), 0x00000026, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x0000000f, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"=", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"call", 0x0080), 0x00000014, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x0000000e, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"(", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K",", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K")", 0x0001), 0x00000001, nothing)])]), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"NewlineWs", 0x0001), 0x00000009, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"end", 0x0001), 0x00000003, nothing)])]), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"NewlineWs", 0x0001), 0x00000005, nothing)]), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"else", 0x0001), 0x00000004, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"block", 0x0080), 0x00000037, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"NewlineWs", 0x0001), 0x00000009, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"=", 0x0080), 0x00000029, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x0000000f, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"=", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"call", 0x0080), 0x00000017, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000011, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"(", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K",", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K")", 0x0001), 0x00000001, nothing)])]), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"NewlineWs", 0x0001), 0x00000005, nothing)]), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"end", 0x0001), 0x00000003, nothing)]), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"NewlineWs", 0x0001), 0x00000005, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"tuple", 0x00a0), 0x0000001f, JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}[JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"(", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x0000000c, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K",", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Whitespace", 0x0001), 0x00000001, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"Identifier", 0x0000), 0x0000000f, nothing), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K")", 0x0001), 0x00000001, nothing)]), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"NewlineWs", 0x0001), 0x00000001, nothing)]), JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}(JuliaSyntax.SyntaxHead(K"end", 0x0001), 0x00000003, nothing)])) (call core.svec :#self# :x :y) (call core.svec))) 2 TestMod.bothgen 3 (= slot₅/nongen_stuff (call %₂ slot₂/x slot₃/y)) 4 TestMod.some_nongen_stuff @@ -1434,6 +1530,7 @@ end 7 slot₄/maybe_gen_stuff 8 (call core.tuple %₆ %₇) 9 (return %₈) -17 TestMod.f_partially_generated -18 (return %₁₇) +21 (latestworld) +22 TestMod.f_partially_generated +23 (return %₂₂) diff --git a/test/generators_ir.jl b/test/generators_ir.jl index 22b2a3ab..0fb9ddf2 100644 --- a/test/generators_ir.jl +++ b/test/generators_ir.jl @@ -5,21 +5,25 @@ 1 (call core.svec) 2 (call core.svec) 3 (call JuliaLowering.eval_closure_type TestMod :#->##0 %₁ %₂) -4 TestMod.#->##0 -5 (call core.svec %₄ core.Any) -6 (call core.svec) -7 SourceLocation::1:2 -8 (call core.svec %₅ %₆ %₇) -9 --- method core.nothing %₈ +4 (latestworld) +5 TestMod.#->##0 +6 (call core.svec %₅ core.Any) +7 (call core.svec) +8 SourceLocation::1:2 +9 (call core.svec %₆ %₇ %₈) +10 --- method core.nothing %₉ slots: [slot₁/#self#(!read) slot₂/x] 1 TestMod.+ 2 (call %₁ slot₂/x 1) 3 (return %₂) -10 TestMod.#->##0 -11 (new %₁₀) -12 TestMod.xs -13 (call top.Generator %₁₁ %₁₂) -14 (return %₁₃) +11 (latestworld) +12 (latestworld) +13 TestMod.#->##0 +14 (new %₁₃) +15 (latestworld) +16 TestMod.xs +17 (call top.Generator %₁₄ %₁₆) +18 (return %₁₇) ######################################## # Product iteration @@ -28,12 +32,13 @@ 1 (call core.svec) 2 (call core.svec) 3 (call JuliaLowering.eval_closure_type TestMod :#->##1 %₁ %₂) -4 TestMod.#->##1 -5 (call core.svec %₄ core.Any) -6 (call core.svec) -7 SourceLocation::1:2 -8 (call core.svec %₅ %₆ %₇) -9 --- method core.nothing %₈ +4 (latestworld) +5 TestMod.#->##1 +6 (call core.svec %₅ core.Any) +7 (call core.svec) +8 SourceLocation::1:2 +9 (call core.svec %₆ %₇ %₈) +10 --- method core.nothing %₉ slots: [slot₁/#self#(!read) slot₂/destructured_arg slot₃/iterstate slot₄/x slot₅/y] 1 (call top.indexed_iterate slot₂/destructured_arg 1) 2 (= slot₄/x (call core.getfield %₁ 1)) @@ -46,13 +51,16 @@ 9 slot₅/y 10 (call %₇ %₈ %₉) 11 (return %₁₀) -10 TestMod.#->##1 -11 (new %₁₀) -12 TestMod.xs -13 TestMod.ys -14 (call top.product %₁₂ %₁₃) -15 (call top.Generator %₁₁ %₁₄) -16 (return %₁₅) +11 (latestworld) +12 (latestworld) +13 TestMod.#->##1 +14 (new %₁₃) +15 (latestworld) +16 TestMod.xs +17 TestMod.ys +18 (call top.product %₁₆ %₁₇) +19 (call top.Generator %₁₄ %₁₈) +20 (return %₁₉) ######################################## # Use `identity` as the Generator function when possible eg in filters @@ -61,12 +69,13 @@ 1 (call core.svec) 2 (call core.svec) 3 (call JuliaLowering.eval_closure_type TestMod :#->##2 %₁ %₂) -4 TestMod.#->##2 -5 (call core.svec %₄ core.Any) -6 (call core.svec) -7 SourceLocation::1:29 -8 (call core.svec %₅ %₆ %₇) -9 --- method core.nothing %₈ +4 (latestworld) +5 TestMod.#->##2 +6 (call core.svec %₅ core.Any) +7 (call core.svec) +8 SourceLocation::1:29 +9 (call core.svec %₆ %₇ %₈) +10 --- method core.nothing %₉ slots: [slot₁/#self#(!read) slot₂/destructured_arg slot₃/iterstate slot₄/x slot₅/y(!read)] 1 (call top.indexed_iterate slot₂/destructured_arg 1) 2 (= slot₄/x (call core.getfield %₁ 1)) @@ -78,12 +87,15 @@ 8 slot₄/x 9 (call %₇ %₈) 10 (return %₉) -10 TestMod.#->##2 -11 (new %₁₀) -12 TestMod.iter -13 (call top.Filter %₁₁ %₁₂) -14 (call top.Generator top.identity %₁₃) -15 (return %₁₄) +11 (latestworld) +12 (latestworld) +13 TestMod.#->##2 +14 (new %₁₃) +15 (latestworld) +16 TestMod.iter +17 (call top.Filter %₁₄ %₁₆) +18 (call top.Generator top.identity %₁₇) +19 (return %₁₈) ######################################## # Use of placeholders in iteration vars @@ -92,19 +104,23 @@ 1 (call core.svec) 2 (call core.svec) 3 (call JuliaLowering.eval_closure_type TestMod :#->##3 %₁ %₂) -4 TestMod.#->##3 -5 (call core.svec %₄ core.Any) -6 (call core.svec) -7 SourceLocation::1:2 -8 (call core.svec %₅ %₆ %₇) -9 --- method core.nothing %₈ +4 (latestworld) +5 TestMod.#->##3 +6 (call core.svec %₅ core.Any) +7 (call core.svec) +8 SourceLocation::1:2 +9 (call core.svec %₆ %₇ %₈) +10 --- method core.nothing %₉ slots: [slot₁/#self#(!read) slot₂/_(!read)] 1 (return 1) -10 TestMod.#->##3 -11 (new %₁₀) -12 TestMod.xs -13 (call top.Generator %₁₁ %₁₂) -14 (return %₁₃) +11 (latestworld) +12 (latestworld) +13 TestMod.#->##3 +14 (new %₁₃) +15 (latestworld) +16 TestMod.xs +17 (call top.Generator %₁₄ %₁₆) +18 (return %₁₇) ######################################## # Error: Use of placeholders in body @@ -121,12 +137,13 @@ LoweringError: 1 (call core.svec) 2 (call core.svec) 3 (call JuliaLowering.eval_closure_type TestMod :#->##5 %₁ %₂) -4 TestMod.#->##5 -5 (call core.svec %₄ core.Any) -6 (call core.svec) -7 SourceLocation::1:2 -8 (call core.svec %₅ %₆ %₇) -9 --- method core.nothing %₈ +4 (latestworld) +5 TestMod.#->##5 +6 (call core.svec %₅ core.Any) +7 (call core.svec) +8 SourceLocation::1:2 +9 (call core.svec %₆ %₇ %₈) +10 --- method core.nothing %₉ slots: [slot₁/#self#(!read) slot₂/destructured_arg slot₃/iterstate slot₄/x(!read) slot₅/y(!read)] 1 (call top.indexed_iterate slot₂/destructured_arg 1) 2 (= slot₄/x (call core.getfield %₁ 1)) @@ -140,11 +157,14 @@ LoweringError: 10 (= slot₅/y (call core.getfield %₉ 1)) 11 TestMod.body 12 (return %₁₁) -10 TestMod.#->##5 -11 (new %₁₀) -12 TestMod.iter -13 (call top.Generator %₁₁ %₁₂) -14 (return %₁₃) +11 (latestworld) +12 (latestworld) +13 TestMod.#->##5 +14 (new %₁₃) +15 (latestworld) +16 TestMod.iter +17 (call top.Generator %₁₄ %₁₆) +18 (return %₁₇) ######################################## # return permitted in quoted syntax in generator @@ -153,20 +173,24 @@ LoweringError: 1 (call core.svec) 2 (call core.svec) 3 (call JuliaLowering.eval_closure_type TestMod :#->##6 %₁ %₂) -4 TestMod.#->##6 -5 (call core.svec %₄ core.Any) -6 (call core.svec) -7 SourceLocation::1:4 -8 (call core.svec %₅ %₆ %₇) -9 --- method core.nothing %₈ +4 (latestworld) +5 TestMod.#->##6 +6 (call core.svec %₅ core.Any) +7 (call core.svec) +8 SourceLocation::1:4 +9 (call core.svec %₆ %₇ %₈) +10 --- method core.nothing %₉ slots: [slot₁/#self#(!read) slot₂/_(!read)] 1 (call JuliaLowering.interpolate_ast (inert (return x))) 2 (return %₁) -10 TestMod.#->##6 -11 (new %₁₀) -12 TestMod.iter -13 (call top.Generator %₁₁ %₁₂) -14 (return %₁₃) +11 (latestworld) +12 (latestworld) +13 TestMod.#->##6 +14 (new %₁₃) +15 (latestworld) +16 TestMod.iter +17 (call top.Generator %₁₄ %₁₆) +18 (return %₁₇) ######################################## # Error: `return` not permitted in generator body @@ -183,26 +207,29 @@ LoweringError: 1 (call core.svec) 2 (call core.svec) 3 (call JuliaLowering.eval_closure_type TestMod :#->##7 %₁ %₂) -4 (call core.svec) +4 (latestworld) 5 (call core.svec) -6 (call JuliaLowering.eval_closure_type TestMod :#->#->##0 %₄ %₅) -7 TestMod.#->#->##0 -8 (call core.svec %₇ core.Any) -9 (call core.svec) -10 SourceLocation::1:2 -11 (call core.svec %₈ %₉ %₁₀) -12 --- method core.nothing %₁₁ +6 (call core.svec) +7 (call JuliaLowering.eval_closure_type TestMod :#->#->##0 %₅ %₆) +8 (latestworld) +9 TestMod.#->#->##0 +10 (call core.svec %₉ core.Any) +11 (call core.svec) +12 SourceLocation::1:2 +13 (call core.svec %₁₀ %₁₁ %₁₂) +14 --- method core.nothing %₁₃ slots: [slot₁/#self#(!read) slot₂/x slot₃/x] 1 slot₂/x 2 (= slot₃/x %₁) 3 slot₃/x 4 (return %₃) -13 TestMod.#->##7 -14 (call core.svec %₁₃ core.Any) -15 (call core.svec) -16 SourceLocation::1:2 -17 (call core.svec %₁₄ %₁₅ %₁₆) -18 --- method core.nothing %₁₇ +15 (latestworld) +16 TestMod.#->##7 +17 (call core.svec %₁₆ core.Any) +18 (call core.svec) +19 SourceLocation::1:2 +20 (call core.svec %₁₇ %₁₈ %₁₉) +21 --- method core.nothing %₂₀ slots: [slot₁/#self#(!read) slot₂/x(!read)] 1 TestMod.#->#->##0 2 (new %₁) @@ -210,13 +237,16 @@ LoweringError: 4 (call %₃ 1 2) 5 (call top.Generator %₂ %₄) 6 (return %₅) -19 TestMod.#->##7 -20 (new %₁₉) -21 TestMod.: -22 (call %₂₁ 1 3) -23 (call top.Generator %₂₀ %₂₂) -24 (call top.Flatten %₂₃) -25 (return %₂₄) +22 (latestworld) +23 (latestworld) +24 TestMod.#->##7 +25 (new %₂₄) +26 (latestworld) +27 TestMod.: +28 (call %₂₇ 1 3) +29 (call top.Generator %₂₅ %₂₈) +30 (call top.Flatten %₂₉) +31 (return %₃₀) ######################################## # Comprehension lowers to generator with collect diff --git a/test/macros_ir.jl b/test/macros_ir.jl index e1c6460c..792b7499 100644 --- a/test/macros_ir.jl +++ b/test/macros_ir.jl @@ -25,19 +25,21 @@ macro add_one(ex) end #--------------------- 1 (method TestMod.@add_one) -2 TestMod.@add_one -3 (call core.Typeof %₂) -4 (call core.svec %₃ JuliaLowering.MacroContext core.Any) -5 (call core.svec) -6 SourceLocation::1:7 -7 (call core.svec %₄ %₅ %₆) -8 --- method core.nothing %₇ +2 (latestworld) +3 TestMod.@add_one +4 (call core.Typeof %₃) +5 (call core.svec %₄ JuliaLowering.MacroContext core.Any) +6 (call core.svec) +7 SourceLocation::1:7 +8 (call core.svec %₅ %₆ %₇) +9 --- method core.nothing %₈ slots: [slot₁/#self#(!read) slot₂/__context__(!read) slot₃/ex] 1 (call core.tuple slot₃/ex) 2 (call JuliaLowering.interpolate_ast (inert (block (call-i ($ ex) + 1))) %₁) 3 (return %₂) -9 TestMod.@add_one -10 (return %₉) +10 (latestworld) +11 TestMod.@add_one +12 (return %₁₁) ######################################## # Macro using `__context__` @@ -46,19 +48,21 @@ macro foo(ex) end #--------------------- 1 (method TestMod.@foo) -2 TestMod.@foo -3 (call core.Typeof %₂) -4 (call core.svec %₃ JuliaLowering.MacroContext core.Any) -5 (call core.svec) -6 SourceLocation::1:7 -7 (call core.svec %₄ %₅ %₆) -8 --- method core.nothing %₇ +2 (latestworld) +3 TestMod.@foo +4 (call core.Typeof %₃) +5 (call core.svec %₄ JuliaLowering.MacroContext core.Any) +6 (call core.svec) +7 SourceLocation::1:7 +8 (call core.svec %₅ %₆ %₇) +9 --- method core.nothing %₈ slots: [slot₁/#self#(!read) slot₂/__context__ slot₃/ex(!read) slot₄/ctx(!read)] 1 slot₂/__context__ 2 (= slot₄/ctx %₁) 3 (return %₁) -9 TestMod.@foo -10 (return %₉) +10 (latestworld) +11 TestMod.@foo +12 (return %₁₁) ######################################## # Scope for symbols emitted by macros is the module where the method was diff --git a/test/misc.jl b/test/misc.jl index 90bc32cc..25b31256 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -46,4 +46,12 @@ cf_float = JuliaLowering.include_string(test_mod, """ """) @test @ccall($cf_float(2::Float64, 3::Float64)::Float64) == 32.0 +@testset "CodeInfo: has_image_globalref" begin + elower(s) = JuliaLowering.to_lowered_expr( + test_mod, JuliaLowering.lower( + test_mod, parsestmt(JuliaLowering.SyntaxTree, s))) + @test elower("function foo end").args[1].has_image_globalref === false + @test elower("Base.push!([], 1)").args[1].has_image_globalref === true +end + end diff --git a/test/misc_ir.jl b/test/misc_ir.jl index d073cf97..a2b9632c 100644 --- a/test/misc_ir.jl +++ b/test/misc_ir.jl @@ -390,3 +390,12 @@ LoweringError: x... └──┘ ── `...` expression outside call +######################################## +# `include` should increment world age +include("hi.jl") +#--------------------- +1 TestMod.include +2 (call %₁ "hi.jl") +3 (latestworld) +4 (return %₂) + diff --git a/test/modules.jl b/test/modules.jl index 66595ee6..97cb536f 100644 --- a/test/modules.jl +++ b/test/modules.jl @@ -13,7 +13,8 @@ end @test A.g() == "hi" @test A.include isa Function @test A.Base === Base -@test A.eval(:(x = -1)) == -1 && A.x == -1 +@test A.eval(:(x = -1)) == -1 +@test A.x == -1 B = JuliaLowering.include_string(test_mod, """ baremodule B diff --git a/test/scopes_ir.jl b/test/scopes_ir.jl index c0013a39..b40fbf92 100644 --- a/test/scopes_ir.jl +++ b/test/scopes_ir.jl @@ -73,19 +73,22 @@ end 1 (call core.svec) 2 (call core.svec) 3 (call JuliaLowering.eval_closure_type TestMod :#f##0 %₁ %₂) -4 TestMod.#f##0 -5 (new %₄) -6 (= slot₁/f %₅) -7 TestMod.#f##0 -8 (call core.svec %₇) -9 (call core.svec) -10 SourceLocation::1:5 -11 (call core.svec %₈ %₉ %₁₀) -12 --- method core.nothing %₁₁ +4 (latestworld) +5 TestMod.#f##0 +6 (new %₅) +7 (= slot₁/f %₆) +8 (latestworld) +9 TestMod.#f##0 +10 (call core.svec %₉) +11 (call core.svec) +12 SourceLocation::1:5 +13 (call core.svec %₁₀ %₁₁ %₁₂) +14 --- method core.nothing %₁₃ slots: [slot₁/#self#(!read)] 1 TestMod.body 2 (return %₁) -13 (return core.nothing) +15 (latestworld) +16 (return core.nothing) ######################################## # Error: Invalid `let` var with K"::" @@ -142,18 +145,20 @@ end 3 slot₁/y 4 (call core.setfield! %₃ :contents %₂) 5 (method TestMod.f) -6 TestMod.f -7 (call core.Typeof %₆) -8 (call core.svec %₇ core.Any) -9 (call core.svec) -10 SourceLocation::3:14 -11 (call core.svec %₈ %₉ %₁₀) -12 --- method core.nothing %₁₁ +6 (latestworld) +7 TestMod.f +8 (call core.Typeof %₇) +9 (call core.svec %₈ core.Any) +10 (call core.svec) +11 SourceLocation::3:14 +12 (call core.svec %₉ %₁₀ %₁₁) +13 --- method core.nothing %₁₂ slots: [slot₁/#self#(!read) slot₂/x(!read)] 1 (call core.tuple false true true) 2 (return %₁) -13 TestMod.f -14 (return %₁₃) +14 (latestworld) +15 TestMod.f +16 (return %₁₅) ######################################## # @islocal with global @@ -163,7 +168,8 @@ begin end #--------------------- 1 (global TestMod.x) -2 (return false) +2 (latestworld) +3 (return false) ######################################## # @locals with local and global @@ -175,13 +181,14 @@ end #--------------------- 1 (newvar slot₁/y) 2 (global TestMod.x) -3 (call core.apply_type top.Dict core.Symbol core.Any) -4 (call %₃) -5 (isdefined slot₁/y) -6 (gotoifnot %₅ label₉) -7 slot₁/y -8 (call top.setindex! %₄ %₇ :y) -9 (return %₄) +3 (latestworld) +4 (call core.apply_type top.Dict core.Symbol core.Any) +5 (call %₄) +6 (isdefined slot₁/y) +7 (gotoifnot %₆ label₁₀) +8 slot₁/y +9 (call top.setindex! %₅ %₈ :y) +10 (return %₅) ######################################## # @locals with function args (TODO: static parameters) @@ -190,21 +197,23 @@ function f(z) end #--------------------- 1 (method TestMod.f) -2 TestMod.f -3 (call core.Typeof %₂) -4 (call core.svec %₃ core.Any) -5 (call core.svec) -6 SourceLocation::1:10 -7 (call core.svec %₄ %₅ %₆) -8 --- method core.nothing %₇ +2 (latestworld) +3 TestMod.f +4 (call core.Typeof %₃) +5 (call core.svec %₄ core.Any) +6 (call core.svec) +7 SourceLocation::1:10 +8 (call core.svec %₅ %₆ %₇) +9 --- method core.nothing %₈ slots: [slot₁/#self#(!read) slot₂/z] 1 (call core.apply_type top.Dict core.Symbol core.Any) 2 (call %₁) 3 (gotoifnot true label₅) 4 (call top.setindex! %₂ slot₂/z :z) 5 (return %₂) -9 TestMod.f -10 (return %₉) +10 (latestworld) +11 TestMod.f +12 (return %₁₁) ######################################## # Error: Duplicate function argument names @@ -267,7 +276,7 @@ LoweringError: let local x global x -# └──────┘ ── Variable `x` declared both local and global +# ╙ ── Variable `x` declared both local and global end ######################################## @@ -279,7 +288,7 @@ end LoweringError: function f(x) local x -# └─────┘ ── local variable name `x` conflicts with an argument +# ╙ ── local variable name `x` conflicts with an argument end ######################################## @@ -291,7 +300,7 @@ end LoweringError: function f(x) global x -# └──────┘ ── global variable name `x` conflicts with an argument +# ╙ ── global variable name `x` conflicts with an argument end ######################################## @@ -304,7 +313,7 @@ end LoweringError: function f((x,)) global x -# └──────┘ ── Variable `x` declared both local and global +# ╙ ── Variable `x` declared both local and global end ######################################## @@ -316,7 +325,7 @@ end LoweringError: function f(::T) where T local T -# └─────┘ ── local variable name `T` conflicts with a static parameter +# ╙ ── local variable name `T` conflicts with a static parameter end ######################################## @@ -328,7 +337,7 @@ end LoweringError: function f(::T) where T global T -# └──────┘ ── global variable name `T` conflicts with a static parameter +# ╙ ── global variable name `T` conflicts with a static parameter end ######################################## @@ -343,7 +352,7 @@ LoweringError: function f(::T) where T let local T -# └─────┘ ── local variable name `T` conflicts with a static parameter +# ╙ ── local variable name `T` conflicts with a static parameter end end @@ -359,7 +368,7 @@ LoweringError: function f(::T) where T let global T -# └──────┘ ── global variable name `T` conflicts with a static parameter +# ╙ ── global variable name `T` conflicts with a static parameter end end @@ -418,6 +427,6 @@ end #--------------------- 1 1 2 (= slot₁/x %₁) -3 (isdefined TestMod.y) +3 (call core.isdefinedglobal TestMod :y false) 4 (return %₃) diff --git a/test/typedefs.jl b/test/typedefs.jl index d2f0594b..be509eeb 100644 --- a/test/typedefs.jl +++ b/test/typedefs.jl @@ -251,12 +251,13 @@ end """) @test fieldtypes(test_mod.M36104.T36104) == (Vector{test_mod.M36104.T36104},) @test_throws ErrorException("expected") JuliaLowering.include_string(test_mod, """struct X36104; x::error("expected"); end""") -@test isdefined(test_mod, :X36104) +@test !isdefined(test_mod, :X36104) JuliaLowering.include_string(test_mod, "struct X36104; x::Int; end") @test fieldtypes(test_mod.X36104) == (Int,) JuliaLowering.include_string(test_mod, "primitive type P36104 8 end") -@test_throws ErrorException("invalid redefinition of constant TestMod.P36104") #= - =# JuliaLowering.include_string(test_mod, "primitive type P36104 16 end") +JuliaLowering.include_string(test_mod, "const orig_P36104 = P36104") +JuliaLowering.include_string(test_mod, "primitive type P36104 16 end") +@test test_mod.P36104 !== test_mod.orig_P36104 # Struct with outer constructor where one typevar is constrained by the other # See https://github.com/JuliaLang/julia/issues/27269) diff --git a/test/typedefs_ir.jl b/test/typedefs_ir.jl index 14f0b1cc..b0b2312c 100644 --- a/test/typedefs_ir.jl +++ b/test/typedefs_ir.jl @@ -191,17 +191,19 @@ abstract type A end 2 (call core._abstracttype TestMod :A %₁) 3 (= slot₁/A %₂) 4 (call core._setsuper! %₂ core.Any) -5 (call core._typebody! %₂) -6 (global TestMod.A) -7 (const TestMod.A) -8 (isdefined TestMod.A) -9 (gotoifnot %₈ label₁₄) -10 TestMod.A -11 (call core._equiv_typedef %₁₀ %₂) -12 (gotoifnot %₁₁ label₁₄) -13 (goto label₁₅) -14 (= TestMod.A %₂) -15 (return core.nothing) +5 slot₁/A +6 (call core._typebody! false %₅) +7 (global TestMod.A) +8 (latestworld) +9 (call core.isdefinedglobal TestMod :A false) +10 (gotoifnot %₉ label₁₅) +11 TestMod.A +12 (call core._equiv_typedef %₁₁ %₂) +13 (gotoifnot %₁₂ label₁₅) +14 (goto label₁₆) +15 (constdecl TestMod.A %₂) +16 (latestworld) +17 (return core.nothing) ######################################## # Abstract type definition with supertype @@ -212,17 +214,19 @@ abstract type A <: B end 3 (= slot₁/A %₂) 4 TestMod.B 5 (call core._setsuper! %₂ %₄) -6 (call core._typebody! %₂) -7 (global TestMod.A) -8 (const TestMod.A) -9 (isdefined TestMod.A) -10 (gotoifnot %₉ label₁₅) -11 TestMod.A -12 (call core._equiv_typedef %₁₁ %₂) -13 (gotoifnot %₁₂ label₁₅) -14 (goto label₁₆) -15 (= TestMod.A %₂) -16 (return core.nothing) +6 slot₁/A +7 (call core._typebody! false %₆) +8 (global TestMod.A) +9 (latestworld) +10 (call core.isdefinedglobal TestMod :A false) +11 (gotoifnot %₁₀ label₁₆) +12 TestMod.A +13 (call core._equiv_typedef %₁₂ %₂) +14 (gotoifnot %₁₃ label₁₆) +15 (goto label₁₇) +16 (constdecl TestMod.A %₂) +17 (latestworld) +18 (return core.nothing) ######################################## # Abstract type definition with multiple typevars @@ -237,17 +241,19 @@ abstract type A{X, Y <: X} end 7 (call core._abstracttype TestMod :A %₆) 8 (= slot₁/A %₇) 9 (call core._setsuper! %₇ core.Any) -10 (call core._typebody! %₇) -11 (global TestMod.A) -12 (const TestMod.A) -13 (isdefined TestMod.A) -14 (gotoifnot %₁₃ label₁₉) -15 TestMod.A -16 (call core._equiv_typedef %₁₅ %₇) -17 (gotoifnot %₁₆ label₁₉) -18 (goto label₂₀) -19 (= TestMod.A %₇) -20 (return core.nothing) +10 slot₁/A +11 (call core._typebody! false %₁₀) +12 (global TestMod.A) +13 (latestworld) +14 (call core.isdefinedglobal TestMod :A false) +15 (gotoifnot %₁₄ label₂₀) +16 TestMod.A +17 (call core._equiv_typedef %₁₆ %₇) +18 (gotoifnot %₁₇ label₂₀) +19 (goto label₂₁) +20 (constdecl TestMod.A %₇) +21 (latestworld) +22 (return core.nothing) ######################################## # Error: Abstract type definition with bad signature @@ -293,17 +299,19 @@ primitive type P 8 end 2 (call core._primitivetype TestMod :P %₁ 8) 3 (= slot₁/P %₂) 4 (call core._setsuper! %₂ core.Any) -5 (call core._typebody! %₂) -6 (global TestMod.P) -7 (const TestMod.P) -8 (isdefined TestMod.P) -9 (gotoifnot %₈ label₁₄) -10 TestMod.P -11 (call core._equiv_typedef %₁₀ %₂) -12 (gotoifnot %₁₁ label₁₄) -13 (goto label₁₅) -14 (= TestMod.P %₂) -15 (return core.nothing) +5 slot₁/P +6 (call core._typebody! false %₅) +7 (global TestMod.P) +8 (latestworld) +9 (call core.isdefinedglobal TestMod :P false) +10 (gotoifnot %₉ label₁₅) +11 TestMod.P +12 (call core._equiv_typedef %₁₁ %₂) +13 (gotoifnot %₁₂ label₁₅) +14 (goto label₁₆) +15 (constdecl TestMod.P %₂) +16 (latestworld) +17 (return core.nothing) ######################################## # Complex primitive type definition @@ -318,17 +326,19 @@ primitive type P{X,Y} <: Z 32 end 7 (= slot₁/P %₆) 8 TestMod.Z 9 (call core._setsuper! %₆ %₈) -10 (call core._typebody! %₆) -11 (global TestMod.P) -12 (const TestMod.P) -13 (isdefined TestMod.P) -14 (gotoifnot %₁₃ label₁₉) -15 TestMod.P -16 (call core._equiv_typedef %₁₅ %₆) -17 (gotoifnot %₁₆ label₁₉) -18 (goto label₂₀) -19 (= TestMod.P %₆) -20 (return core.nothing) +10 slot₁/P +11 (call core._typebody! false %₁₀) +12 (global TestMod.P) +13 (latestworld) +14 (call core.isdefinedglobal TestMod :P false) +15 (gotoifnot %₁₄ label₂₀) +16 TestMod.P +17 (call core._equiv_typedef %₁₆ %₆) +18 (gotoifnot %₁₇ label₂₀) +19 (goto label₂₁) +20 (constdecl TestMod.P %₆) +21 (latestworld) +22 (return core.nothing) ######################################## # Primitive type definition with computed size (should this be allowed??) @@ -340,17 +350,19 @@ primitive type P P_nbits() end 4 (call core._primitivetype TestMod :P %₁ %₃) 5 (= slot₁/P %₄) 6 (call core._setsuper! %₄ core.Any) -7 (call core._typebody! %₄) -8 (global TestMod.P) -9 (const TestMod.P) -10 (isdefined TestMod.P) -11 (gotoifnot %₁₀ label₁₆) -12 TestMod.P -13 (call core._equiv_typedef %₁₂ %₄) -14 (gotoifnot %₁₃ label₁₆) -15 (goto label₁₇) -16 (= TestMod.P %₄) -17 (return core.nothing) +7 slot₁/P +8 (call core._typebody! false %₇) +9 (global TestMod.P) +10 (latestworld) +11 (call core.isdefinedglobal TestMod :P false) +12 (gotoifnot %₁₁ label₁₇) +13 TestMod.P +14 (call core._equiv_typedef %₁₃ %₄) +15 (gotoifnot %₁₄ label₁₇) +16 (goto label₁₈) +17 (constdecl TestMod.P %₄) +18 (latestworld) +19 (return core.nothing) ######################################## # Empty struct @@ -358,41 +370,45 @@ struct X end #--------------------- 1 (global TestMod.X) -2 (const TestMod.X) +2 (latestworld) 3 (call core.svec) 4 (call core.svec) 5 (call core.svec) 6 (call core._structtype TestMod :X %₃ %₄ %₅ false 0) 7 (= slot₁/X %₆) 8 (call core._setsuper! %₆ core.Any) -9 (isdefined TestMod.X) -10 (gotoifnot %₉ label₂₀) +9 (call core.isdefinedglobal TestMod :X false) +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 +12 (= slot₂/if_val (call core._equiv_typedef %₁₁ %₆)) +13 (goto label₁₅) +14 (= slot₂/if_val false) +15 slot₂/if_val +16 (gotoifnot %₁₅ label₂₀) +17 TestMod.X +18 (= slot₃/if_val %₁₇) +19 (goto label₂₁) +20 (= slot₃/if_val false) +21 slot₃/if_val +22 (gotoifnot %₁₅ label₂₃) 23 (call core.svec) -24 (call core._typebody! %₂₂ %₂₃) -25 TestMod.X -26 (call core.apply_type core.Type %₂₅) -27 (call core.svec %₂₆) -28 (call core.svec) -29 SourceLocation::1:1 -30 (call core.svec %₂₇ %₂₈ %₂₉) -31 --- method core.nothing %₃₀ +24 (call core._typebody! %₂₁ %₆ %₂₃) +25 (constdecl TestMod.X %₂₄) +26 (latestworld) +27 (latestworld) +28 TestMod.X +29 (call core.apply_type core.Type %₂₈) +30 (call core.svec %₂₉) +31 (call core.svec) +32 SourceLocation::1:1 +33 (call core.svec %₃₀ %₃₁ %₃₂) +34 --- method core.nothing %₃₃ slots: [slot₁/#self#(!read)] 1 TestMod.X 2 (new %₁) 3 (return %₂) -32 (return core.nothing) +35 (latestworld) +36 (return core.nothing) ######################################## # Basic struct @@ -403,41 +419,44 @@ struct X end #--------------------- 1 (global TestMod.X) -2 (const TestMod.X) +2 (latestworld) 3 (call core.svec) 4 (call core.svec :a :b :c) 5 (call core.svec) 6 (call core._structtype TestMod :X %₃ %₄ %₅ false 3) 7 (= slot₁/X %₆) 8 (call core._setsuper! %₆ core.Any) -9 (isdefined TestMod.X) -10 (gotoifnot %₉ label₂₀) +9 (call core.isdefinedglobal TestMod :X false) +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 +12 (= slot₂/if_val (call core._equiv_typedef %₁₁ %₆)) +13 (goto label₁₅) +14 (= slot₂/if_val false) +15 slot₂/if_val +16 (gotoifnot %₁₅ label₂₀) +17 TestMod.X +18 (= slot₃/if_val %₁₇) +19 (goto label₂₁) +20 (= slot₃/if_val false) +21 slot₃/if_val +22 (gotoifnot %₁₅ label₂₃) 23 TestMod.T 24 (call core.svec core.Any %₂₃ core.Any) -25 (call core._typebody! %₂₂ %₂₄) -26 TestMod.T -27 (call core.=== core.Any %₂₆) -28 (gotoifnot %₂₇ label₃₀) -29 (goto label₃₇) -30 TestMod.X -31 (call core.apply_type core.Type %₃₀) -32 (call core.svec %₃₁ core.Any core.Any core.Any) -33 (call core.svec) -34 SourceLocation::1:1 -35 (call core.svec %₃₂ %₃₃ %₃₄) -36 --- method core.nothing %₃₅ +25 (call core._typebody! %₂₁ %₆ %₂₄) +26 (constdecl TestMod.X %₂₅) +27 (latestworld) +28 TestMod.T +29 (call core.=== core.Any %₂₈) +30 (gotoifnot %₂₉ label₃₂) +31 (goto label₄₁) +32 (latestworld) +33 TestMod.X +34 (call core.apply_type core.Type %₃₃) +35 (call core.svec %₃₄ core.Any core.Any core.Any) +36 (call core.svec) +37 SourceLocation::1:1 +38 (call core.svec %₃₅ %₃₆ %₃₇) +39 --- method core.nothing %₃₈ slots: [slot₁/#ctor-self# slot₂/a slot₃/b slot₄/c slot₅/tmp] 1 (call core.fieldtype slot₁/#ctor-self# 2) 2 slot₃/b @@ -451,19 +470,22 @@ end 10 slot₅/tmp 11 (new slot₁/#ctor-self# slot₂/a %₁₀ slot₄/c) 12 (return %₁₁) -37 TestMod.X -38 (call core.apply_type core.Type %₃₇) -39 TestMod.T -40 (call core.svec %₃₈ core.Any %₃₉ core.Any) -41 (call core.svec) -42 SourceLocation::1:1 -43 (call core.svec %₄₀ %₄₁ %₄₂) -44 --- method core.nothing %₄₃ +40 (latestworld) +41 (latestworld) +42 TestMod.X +43 (call core.apply_type core.Type %₄₂) +44 TestMod.T +45 (call core.svec %₄₃ core.Any %₄₄ core.Any) +46 (call core.svec) +47 SourceLocation::1:1 +48 (call core.svec %₄₅ %₄₆ %₄₇) +49 --- method core.nothing %₄₈ slots: [slot₁/#self#(!read) slot₂/a slot₃/b slot₄/c] 1 TestMod.X 2 (new %₁ slot₂/a slot₃/b slot₄/c) 3 (return %₂) -45 (return core.nothing) +50 (latestworld) +51 (return core.nothing) ######################################## # Struct with supertype and type params @@ -471,7 +493,7 @@ struct X{U, S <: V <: T} <: Z end #--------------------- 1 (global TestMod.X) -2 (const TestMod.X) +2 (latestworld) 3 (= slot₂/U (call core.TypeVar :U)) 4 TestMod.S 5 TestMod.T @@ -485,50 +507,54 @@ end 13 (= slot₄/X %₁₂) 14 TestMod.Z 15 (call core._setsuper! %₁₂ %₁₄) -16 (isdefined TestMod.X) -17 (gotoifnot %₁₆ label₃₇) +16 (call core.isdefinedglobal TestMod :X false) +17 (gotoifnot %₁₆ label₂₁) 18 TestMod.X -19 (call core._equiv_typedef %₁₈ %₁₂) -20 (gotoifnot %₁₉ label₃₄) -21 TestMod.X -22 (= slot₄/X %₂₁) -23 TestMod.X -24 (call top.getproperty %₂₃ :body) -25 (call top.getproperty %₂₄ :body) -26 (call top.getproperty %₂₅ :parameters) -27 (call top.indexed_iterate %₂₆ 1) -28 (= slot₂/U (call core.getfield %₂₇ 1)) -29 (= slot₁/iterstate (call core.getfield %₂₇ 2)) -30 slot₁/iterstate -31 (call top.indexed_iterate %₂₆ 2 %₃₀) -32 (= slot₃/V (call core.getfield %₃₁ 1)) -33 (goto label₃₆) -34 slot₄/X -35 (= TestMod.X %₃₄) -36 (goto label₃₉) -37 slot₄/X -38 (= TestMod.X %₃₇) -39 slot₄/X +19 (= slot₅/if_val (call core._equiv_typedef %₁₈ %₁₂)) +20 (goto label₂₂) +21 (= slot₅/if_val false) +22 slot₅/if_val +23 (gotoifnot %₂₂ label₂₇) +24 TestMod.X +25 (= slot₆/if_val %₂₄) +26 (goto label₂₈) +27 (= slot₆/if_val false) +28 slot₆/if_val +29 (gotoifnot %₂₂ label₄₀) +30 TestMod.X +31 (call top.getproperty %₃₀ :body) +32 (call top.getproperty %₃₁ :body) +33 (call top.getproperty %₃₂ :parameters) +34 (call top.indexed_iterate %₃₃ 1) +35 (= slot₂/U (call core.getfield %₃₄ 1)) +36 (= slot₁/iterstate (call core.getfield %₃₄ 2)) +37 slot₁/iterstate +38 (call top.indexed_iterate %₃₃ 2 %₃₇) +39 (= slot₃/V (call core.getfield %₃₈ 1)) 40 (call core.svec) -41 (call core._typebody! %₃₉ %₄₀) -42 slot₂/U -43 slot₃/V -44 TestMod.X +41 (call core._typebody! %₂₈ %₁₂ %₄₀) +42 (constdecl TestMod.X %₄₁) +43 (latestworld) +44 (latestworld) 45 slot₂/U 46 slot₃/V -47 (call core.apply_type %₄₄ %₄₅ %₄₆) -48 (call core.apply_type core.Type %₄₇) -49 (call core.UnionAll %₄₃ %₄₈) -50 (call core.UnionAll %₄₂ %₄₉) -51 (call core.svec %₅₀) -52 (call core.svec) -53 SourceLocation::1:1 -54 (call core.svec %₅₁ %₅₂ %₅₃) -55 --- method core.nothing %₅₄ +47 TestMod.X +48 slot₂/U +49 slot₃/V +50 (call core.apply_type %₄₇ %₄₈ %₄₉) +51 (call core.apply_type core.Type %₅₀) +52 (call core.UnionAll %₄₆ %₅₁) +53 (call core.UnionAll %₄₅ %₅₂) +54 (call core.svec %₅₃) +55 (call core.svec) +56 SourceLocation::1:1 +57 (call core.svec %₅₄ %₅₅ %₅₆) +58 --- method core.nothing %₅₇ slots: [slot₁/#ctor-self#] 1 (new slot₁/#ctor-self#) 2 (return %₁) -56 (return core.nothing) +59 (latestworld) +60 (return core.nothing) ######################################## # Struct with const and atomic fields @@ -539,41 +565,45 @@ struct X end #--------------------- 1 (global TestMod.X) -2 (const TestMod.X) +2 (latestworld) 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₂₀) +9 (call core.isdefinedglobal TestMod :X false) +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 +12 (= slot₂/if_val (call core._equiv_typedef %₁₁ %₆)) +13 (goto label₁₅) +14 (= slot₂/if_val false) +15 slot₂/if_val +16 (gotoifnot %₁₅ label₂₀) +17 TestMod.X +18 (= slot₃/if_val %₁₇) +19 (goto label₂₁) +20 (= slot₃/if_val false) +21 slot₃/if_val +22 (gotoifnot %₁₅ label₂₃) 23 (call core.svec core.Any core.Any core.Any) -24 (call core._typebody! %₂₂ %₂₃) -25 TestMod.X -26 (call core.apply_type core.Type %₂₅) -27 (call core.svec %₂₆ core.Any core.Any core.Any) -28 (call core.svec) -29 SourceLocation::1:1 -30 (call core.svec %₂₇ %₂₈ %₂₉) -31 --- method core.nothing %₃₀ +24 (call core._typebody! %₂₁ %₆ %₂₃) +25 (constdecl TestMod.X %₂₄) +26 (latestworld) +27 (latestworld) +28 TestMod.X +29 (call core.apply_type core.Type %₂₈) +30 (call core.svec %₂₉ core.Any core.Any core.Any) +31 (call core.svec) +32 SourceLocation::1:1 +33 (call core.svec %₃₀ %₃₁ %₃₂) +34 --- method core.nothing %₃₃ slots: [slot₁/#self#(!read) slot₂/a slot₃/b slot₄/c] 1 TestMod.X 2 (new %₁ slot₂/a slot₃/b slot₄/c) 3 (return %₂) -32 (return core.nothing) +35 (latestworld) +36 (return core.nothing) ######################################## # Documented struct @@ -588,50 +618,54 @@ struct X end #--------------------- 1 (global TestMod.X) -2 (const TestMod.X) +2 (latestworld) 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₂₀) +9 (call core.isdefinedglobal TestMod :X false) +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 +12 (= slot₂/if_val (call core._equiv_typedef %₁₁ %₆)) +13 (goto label₁₅) +14 (= slot₂/if_val false) +15 slot₂/if_val +16 (gotoifnot %₁₅ label₂₀) +17 TestMod.X +18 (= slot₃/if_val %₁₇) +19 (goto label₂₁) +20 (= slot₃/if_val false) +21 slot₃/if_val +22 (gotoifnot %₁₅ label₂₃) 23 (call core.svec core.Any core.Any) -24 (call core._typebody! %₂₂ %₂₃) -25 TestMod.X -26 (call core.apply_type core.Type %₂₅) -27 (call core.svec %₂₆ core.Any core.Any) -28 (call core.svec) -29 SourceLocation::4:1 -30 (call core.svec %₂₇ %₂₈ %₂₉) -31 --- method core.nothing %₃₀ +24 (call core._typebody! %₂₁ %₆ %₂₃) +25 (constdecl TestMod.X %₂₄) +26 (latestworld) +27 (latestworld) +28 TestMod.X +29 (call core.apply_type core.Type %₂₈) +30 (call core.svec %₂₉ core.Any core.Any) +31 (call core.svec) +32 SourceLocation::4:1 +33 (call core.svec %₃₀ %₃₁ %₃₂) +34 --- method core.nothing %₃₃ slots: [slot₁/#self#(!read) slot₂/a slot₃/b] 1 TestMod.X 2 (new %₁ slot₂/a slot₃/b) 3 (return %₂) -32 JuliaLowering.bind_docs! -33 (call core.tuple :field_docs) -34 (call core.apply_type core.NamedTuple %₃₃) -35 (call core.svec 1 "field a docs" 2 "field b docs") -36 (call core.tuple %₃₅) -37 (call %₃₄ %₃₆) -38 TestMod.X -39 SourceLocation::4:1 -40 (call core.kwcall %₃₇ %₃₂ %₃₈ "X docs\n" %₃₉) -41 (return core.nothing) +35 (latestworld) +36 JuliaLowering.bind_docs! +37 (call core.tuple :field_docs) +38 (call core.apply_type core.NamedTuple %₃₇) +39 (call core.svec 1 "field a docs" 2 "field b docs") +40 (call core.tuple %₃₉) +41 (call %₃₈ %₄₀) +42 TestMod.X +43 SourceLocation::4:1 +44 (call core.kwcall %₄₁ %₃₆ %₄₂ "X docs\n" %₄₃) +45 (return core.nothing) ######################################## # Struct with outer constructor @@ -640,7 +674,7 @@ struct X{U} end #--------------------- 1 (global TestMod.X) -2 (const TestMod.X) +2 (latestworld) 3 (= slot₁/U (call core.TypeVar :U)) 4 slot₁/U 5 (call core.svec %₄) @@ -649,39 +683,42 @@ end 8 (call core._structtype TestMod :X %₅ %₆ %₇ false 1) 9 (= slot₂/X %₈) 10 (call core._setsuper! %₈ core.Any) -11 (isdefined TestMod.X) -12 (gotoifnot %₁₁ label₂₇) +11 (call core.isdefinedglobal TestMod :X false) +12 (gotoifnot %₁₁ label₁₆) 13 TestMod.X -14 (call core._equiv_typedef %₁₃ %₈) -15 (gotoifnot %₁₄ label₂₄) -16 TestMod.X -17 (= slot₂/X %₁₆) -18 TestMod.X -19 (call top.getproperty %₁₈ :body) -20 (call top.getproperty %₁₉ :parameters) -21 (call top.indexed_iterate %₂₀ 1) -22 (= slot₁/U (call core.getfield %₂₁ 1)) -23 (goto label₂₆) -24 slot₂/X -25 (= TestMod.X %₂₄) -26 (goto label₂₉) -27 slot₂/X -28 (= TestMod.X %₂₇) -29 slot₂/X +14 (= slot₃/if_val (call core._equiv_typedef %₁₃ %₈)) +15 (goto label₁₇) +16 (= slot₃/if_val false) +17 slot₃/if_val +18 (gotoifnot %₁₇ label₂₂) +19 TestMod.X +20 (= slot₄/if_val %₁₉) +21 (goto label₂₃) +22 (= slot₄/if_val false) +23 slot₄/if_val +24 (gotoifnot %₁₇ label₃₀) +25 TestMod.X +26 (call top.getproperty %₂₅ :body) +27 (call top.getproperty %₂₆ :parameters) +28 (call top.indexed_iterate %₂₇ 1) +29 (= slot₁/U (call core.getfield %₂₈ 1)) 30 slot₁/U 31 (call core.svec %₃₀) -32 (call core._typebody! %₂₉ %₃₁) -33 slot₁/U -34 TestMod.X -35 slot₁/U -36 (call core.apply_type %₃₄ %₃₅) -37 (call core.apply_type core.Type %₃₆) -38 (call core.UnionAll %₃₃ %₃₇) -39 (call core.svec %₃₈ core.Any) -40 (call core.svec) -41 SourceLocation::1:1 -42 (call core.svec %₃₉ %₄₀ %₄₁) -43 --- method core.nothing %₄₂ +32 (call core._typebody! %₂₃ %₈ %₃₁) +33 (constdecl TestMod.X %₃₂) +34 (latestworld) +35 (latestworld) +36 slot₁/U +37 TestMod.X +38 slot₁/U +39 (call core.apply_type %₃₇ %₃₈) +40 (call core.apply_type core.Type %₃₉) +41 (call core.UnionAll %₃₆ %₄₀) +42 (call core.svec %₄₁ core.Any) +43 (call core.svec) +44 SourceLocation::1:1 +45 (call core.svec %₄₂ %₄₃ %₄₄) +46 --- method core.nothing %₄₅ slots: [slot₁/#ctor-self# slot₂/x slot₃/tmp] 1 (call core.fieldtype slot₁/#ctor-self# 1) 2 slot₂/x @@ -695,22 +732,24 @@ end 10 slot₃/tmp 11 (new slot₁/#ctor-self# %₁₀) 12 (return %₁₁) -44 TestMod.X -45 (call core.apply_type core.Type %₄₄) -46 slot₁/U -47 (call core.svec %₄₅ %₄₆) -48 slot₁/U -49 (call core.svec %₄₈) -50 SourceLocation::1:1 -51 (call core.svec %₄₇ %₄₉ %₅₀) -52 --- method core.nothing %₅₁ +47 (latestworld) +48 (latestworld) +49 TestMod.X +50 (call core.apply_type core.Type %₄₉) +51 slot₁/U +52 (call core.svec %₅₀ %₅₁) +53 slot₁/U +54 (call core.svec %₅₃) +55 SourceLocation::1:1 +56 (call core.svec %₅₂ %₅₄ %₅₅) +57 --- method core.nothing %₅₆ slots: [slot₁/#self#(!read) slot₂/x] 1 TestMod.X - 2 static_parameter₁ - 3 (call core.apply_type %₁ %₂) - 4 (new %₃ slot₂/x) - 5 (return %₄) -53 (return core.nothing) + 2 (call core.apply_type %₁ static_parameter₁) + 3 (new %₂ slot₂/x) + 4 (return %₃) +58 (latestworld) +59 (return core.nothing) ######################################## # Struct with outer constructor where one typevar is constrained by the other @@ -720,7 +759,7 @@ struct X{T, S <: Vector{T}} end #--------------------- 1 (global TestMod.X) -2 (const TestMod.X) +2 (latestworld) 3 (= slot₃/T (call core.TypeVar :T)) 4 TestMod.Vector 5 slot₃/T @@ -734,49 +773,52 @@ end 13 (call core._structtype TestMod :X %₁₀ %₁₁ %₁₂ false 1) 14 (= slot₄/X %₁₃) 15 (call core._setsuper! %₁₃ core.Any) -16 (isdefined TestMod.X) -17 (gotoifnot %₁₆ label₃₇) +16 (call core.isdefinedglobal TestMod :X false) +17 (gotoifnot %₁₆ label₂₁) 18 TestMod.X -19 (call core._equiv_typedef %₁₈ %₁₃) -20 (gotoifnot %₁₉ label₃₄) -21 TestMod.X -22 (= slot₄/X %₂₁) -23 TestMod.X -24 (call top.getproperty %₂₃ :body) -25 (call top.getproperty %₂₄ :body) -26 (call top.getproperty %₂₅ :parameters) -27 (call top.indexed_iterate %₂₆ 1) -28 (= slot₃/T (call core.getfield %₂₇ 1)) -29 (= slot₁/iterstate (call core.getfield %₂₇ 2)) -30 slot₁/iterstate -31 (call top.indexed_iterate %₂₆ 2 %₃₀) -32 (= slot₂/S (call core.getfield %₃₁ 1)) -33 (goto label₃₆) -34 slot₄/X -35 (= TestMod.X %₃₄) -36 (goto label₃₉) -37 slot₄/X -38 (= TestMod.X %₃₇) -39 slot₄/X +19 (= slot₅/if_val (call core._equiv_typedef %₁₈ %₁₃)) +20 (goto label₂₂) +21 (= slot₅/if_val false) +22 slot₅/if_val +23 (gotoifnot %₂₂ label₂₇) +24 TestMod.X +25 (= slot₆/if_val %₂₄) +26 (goto label₂₈) +27 (= slot₆/if_val false) +28 slot₆/if_val +29 (gotoifnot %₂₂ label₄₀) +30 TestMod.X +31 (call top.getproperty %₃₀ :body) +32 (call top.getproperty %₃₁ :body) +33 (call top.getproperty %₃₂ :parameters) +34 (call top.indexed_iterate %₃₃ 1) +35 (= slot₃/T (call core.getfield %₃₄ 1)) +36 (= slot₁/iterstate (call core.getfield %₃₄ 2)) +37 slot₁/iterstate +38 (call top.indexed_iterate %₃₃ 2 %₃₇) +39 (= slot₂/S (call core.getfield %₃₈ 1)) 40 TestMod.Vector 41 slot₂/S 42 (call core.apply_type %₄₀ %₄₁) 43 (call core.svec %₄₂) -44 (call core._typebody! %₃₉ %₄₃) -45 slot₃/T -46 slot₂/S -47 TestMod.X +44 (call core._typebody! %₂₈ %₁₃ %₄₃) +45 (constdecl TestMod.X %₄₄) +46 (latestworld) +47 (latestworld) 48 slot₃/T 49 slot₂/S -50 (call core.apply_type %₄₇ %₄₈ %₄₉) -51 (call core.apply_type core.Type %₅₀) -52 (call core.UnionAll %₄₆ %₅₁) -53 (call core.UnionAll %₄₅ %₅₂) -54 (call core.svec %₅₃ core.Any) -55 (call core.svec) -56 SourceLocation::1:1 -57 (call core.svec %₅₄ %₅₅ %₅₆) -58 --- method core.nothing %₅₇ +50 TestMod.X +51 slot₃/T +52 slot₂/S +53 (call core.apply_type %₅₀ %₅₁ %₅₂) +54 (call core.apply_type core.Type %₅₃) +55 (call core.UnionAll %₄₉ %₅₄) +56 (call core.UnionAll %₄₈ %₅₅) +57 (call core.svec %₅₆ core.Any) +58 (call core.svec) +59 SourceLocation::1:1 +60 (call core.svec %₅₇ %₅₈ %₅₉) +61 --- method core.nothing %₆₀ slots: [slot₁/#ctor-self# slot₂/v slot₃/tmp] 1 (call core.fieldtype slot₁/#ctor-self# 1) 2 slot₂/v @@ -790,26 +832,27 @@ end 10 slot₃/tmp 11 (new slot₁/#ctor-self# %₁₀) 12 (return %₁₁) -59 TestMod.X -60 (call core.apply_type core.Type %₅₉) -61 TestMod.Vector -62 slot₂/S -63 (call core.apply_type %₆₁ %₆₂) -64 (call core.svec %₆₀ %₆₃) -65 slot₃/T -66 slot₂/S -67 (call core.svec %₆₅ %₆₆) -68 SourceLocation::1:1 -69 (call core.svec %₆₄ %₆₇ %₆₈) -70 --- method core.nothing %₆₉ +62 (latestworld) +63 (latestworld) +64 TestMod.X +65 (call core.apply_type core.Type %₆₄) +66 TestMod.Vector +67 slot₂/S +68 (call core.apply_type %₆₆ %₆₇) +69 (call core.svec %₆₅ %₆₈) +70 slot₃/T +71 slot₂/S +72 (call core.svec %₇₀ %₇₁) +73 SourceLocation::1:1 +74 (call core.svec %₆₉ %₇₂ %₇₃) +75 --- method core.nothing %₇₄ slots: [slot₁/#self#(!read) slot₂/v] 1 TestMod.X - 2 static_parameter₁ - 3 static_parameter₂ - 4 (call core.apply_type %₁ %₂ %₃) - 5 (new %₄ slot₂/v) - 6 (return %₅) -71 (return core.nothing) + 2 (call core.apply_type %₁ static_parameter₁ static_parameter₂) + 3 (new %₂ slot₂/v) + 4 (return %₃) +76 (latestworld) +77 (return core.nothing) ######################################## # User defined inner constructors and helper functions for structs without type params @@ -827,53 +870,59 @@ end #--------------------- 1 (= slot₂/f (call core.Box)) 2 (global TestMod.X) -3 (const TestMod.X) +3 (latestworld) 4 (call core.svec) 5 (call core.svec :x) 6 (call core.svec) 7 (call core._structtype TestMod :X %₄ %₅ %₆ false 1) 8 (= slot₁/X %₇) 9 (call core._setsuper! %₇ core.Any) -10 (isdefined TestMod.X) -11 (gotoifnot %₁₀ label₂₁) +10 (call core.isdefinedglobal TestMod :X false) +11 (gotoifnot %₁₀ label₁₅) 12 TestMod.X -13 (call core._equiv_typedef %₁₂ %₇) -14 (gotoifnot %₁₃ label₁₈) -15 TestMod.X -16 (= slot₁/X %₁₅) -17 (goto label₂₀) -18 slot₁/X -19 (= TestMod.X %₁₈) -20 (goto label₂₃) -21 slot₁/X -22 (= TestMod.X %₂₁) -23 slot₁/X +13 (= slot₄/if_val (call core._equiv_typedef %₁₂ %₇)) +14 (goto label₁₆) +15 (= slot₄/if_val false) +16 slot₄/if_val +17 (gotoifnot %₁₆ label₂₁) +18 TestMod.X +19 (= slot₅/if_val %₁₈) +20 (goto label₂₂) +21 (= slot₅/if_val false) +22 slot₅/if_val +23 (gotoifnot %₁₆ label₂₄) 24 (call core.svec core.Any) -25 (call core._typebody! %₂₃ %₂₄) -26 (call core.svec) -27 (call core.svec) -28 (call JuliaLowering.eval_closure_type TestMod :#f##0 %₂₆ %₂₇) -29 TestMod.#f##0 -30 (new %₂₉) -31 slot₂/f -32 (call core.setfield! %₃₁ :contents %₃₀) -33 TestMod.#f##0 -34 (call core.svec %₃₃) -35 (call core.svec) -36 SourceLocation::3:5 -37 (call core.svec %₃₄ %₃₅ %₃₆) -38 --- method core.nothing %₃₇ +25 (call core._typebody! %₂₂ %₇ %₂₄) +26 (constdecl TestMod.X %₂₅) +27 (latestworld) +28 (call core.svec) +29 (call core.svec) +30 (call JuliaLowering.eval_closure_type TestMod :#f##0 %₂₈ %₂₉) +31 (latestworld) +32 TestMod.#f##0 +33 (new %₃₂) +34 slot₂/f +35 (call core.setfield! %₃₄ :contents %₃₃) +36 (latestworld) +37 TestMod.#f##0 +38 (call core.svec %₃₇) +39 (call core.svec) +40 SourceLocation::3:5 +41 (call core.svec %₃₈ %₃₉ %₄₀) +42 --- method core.nothing %₄₁ slots: [slot₁/#self#(!read)] 1 TestMod.X 2 (new %₁ 1) 3 (return %₂) -39 TestMod.X -40 (call core.apply_type core.Type %₃₉) -41 (call core.svec %₄₀) -42 (call core.svec) -43 SourceLocation::4:5 -44 (call core.svec %₄₁ %₄₂ %₄₃) -45 --- code_info +43 (latestworld) +44 (latestworld) +45 TestMod.X +46 (call core.apply_type core.Type %₄₅) +47 (call core.svec %₄₆) +48 (call core.svec) +49 SourceLocation::4:5 +50 (call core.svec %₄₇ %₄₈ %₄₉) +51 --- code_info slots: [slot₁/#ctor-self#(!read) slot₂/f(!read)] 1 (captured_local 1) 2 (call core.isdefined %₁ :contents) @@ -884,28 +933,32 @@ end 7 (call core.getfield %₁ :contents) 8 (call %₇) 9 (return %₈) -46 slot₂/f -47 (call core.svec %₄₆) -48 (call JuliaLowering.replace_captured_locals! %₄₅ %₄₇) -49 --- method core.nothing %₄₄ %₄₈ -50 TestMod.X -51 (call core.apply_type core.Type %₅₀) -52 (call core.svec %₅₁ core.Any) -53 (call core.svec) -54 SourceLocation::5:5 -55 (call core.svec %₅₂ %₅₃ %₅₄) -56 --- method core.nothing %₅₅ +52 slot₂/f +53 (call core.svec %₅₂) +54 (call JuliaLowering.replace_captured_locals! %₅₁ %₅₃) +55 --- method core.nothing %₅₀ %₅₄ +56 (latestworld) +57 (latestworld) +58 TestMod.X +59 (call core.apply_type core.Type %₅₈) +60 (call core.svec %₅₉ core.Any) +61 (call core.svec) +62 SourceLocation::5:5 +63 (call core.svec %₆₀ %₆₁ %₆₂) +64 --- method core.nothing %₆₃ slots: [slot₁/#ctor-self# slot₂/x] 1 slot₁/#ctor-self# 2 (new %₁ slot₂/x) 3 (return %₂) -57 TestMod.X -58 (call core.apply_type core.Type %₅₇) -59 (call core.svec %₅₈ core.Any core.Any) -60 (call core.svec) -61 SourceLocation::6:5 -62 (call core.svec %₅₉ %₆₀ %₆₁) -63 --- method core.nothing %₆₂ +65 (latestworld) +66 (latestworld) +67 TestMod.X +68 (call core.apply_type core.Type %₆₇) +69 (call core.svec %₆₈ core.Any core.Any) +70 (call core.svec) +71 SourceLocation::6:5 +72 (call core.svec %₆₉ %₇₀ %₇₁) +73 --- method core.nothing %₇₂ slots: [slot₁/#ctor-self# slot₂/y slot₃/z slot₄/tmp(!read)] 1 TestMod.ReallyXIPromise 2 slot₁/#ctor-self# @@ -921,21 +974,24 @@ end 12 (= slot₄/tmp (call core.typeassert %₁₁ %₁)) 13 slot₄/tmp 14 (return %₁₃) -64 TestMod.X -65 (call core.apply_type core.Type %₆₄) -66 (call core.svec %₆₅ core.Any core.Any core.Any) -67 (call core.svec) -68 SourceLocation::10:5 -69 (call core.svec %₆₆ %₆₇ %₆₈) -70 --- method core.nothing %₆₉ +74 (latestworld) +75 (latestworld) +76 TestMod.X +77 (call core.apply_type core.Type %₇₆) +78 (call core.svec %₇₇ core.Any core.Any core.Any) +79 (call core.svec) +80 SourceLocation::10:5 +81 (call core.svec %₇₈ %₇₉ %₈₀) +82 --- method core.nothing %₈₁ slots: [slot₁/#ctor-self# slot₂/a slot₃/b(!read) slot₄/c(!read)] 1 slot₁/#ctor-self# 2 (new %₁ slot₂/a) 3 (return %₂) -71 TestMod.X -72 (call core.apply_type core.Type %₇₁) -73 (call JuliaLowering.bind_docs! %₇₂ "Docs for X constructor\n" %₆₉) -74 (return core.nothing) +83 (latestworld) +84 TestMod.X +85 (call core.apply_type core.Type %₈₄) +86 (call JuliaLowering.bind_docs! %₈₅ "Docs for X constructor\n" %₈₁) +87 (return core.nothing) ######################################## # User defined inner constructors and helper functions for structs with type params @@ -948,7 +1004,7 @@ end #--------------------- 1 (newvar slot₅/f) 2 (global TestMod.X) -3 (const TestMod.X) +3 (latestworld) 4 (= slot₂/S (call core.TypeVar :S)) 5 (= slot₃/T (call core.TypeVar :T)) 6 slot₂/S @@ -959,76 +1015,84 @@ end 11 (call core._structtype TestMod :X %₈ %₉ %₁₀ false 1) 12 (= slot₄/X %₁₁) 13 (call core._setsuper! %₁₁ core.Any) -14 (isdefined TestMod.X) -15 (gotoifnot %₁₄ label₃₅) +14 (call core.isdefinedglobal TestMod :X false) +15 (gotoifnot %₁₄ label₁₉) 16 TestMod.X -17 (call core._equiv_typedef %₁₆ %₁₁) -18 (gotoifnot %₁₇ label₃₂) -19 TestMod.X -20 (= slot₄/X %₁₉) -21 TestMod.X -22 (call top.getproperty %₂₁ :body) -23 (call top.getproperty %₂₂ :body) -24 (call top.getproperty %₂₃ :parameters) -25 (call top.indexed_iterate %₂₄ 1) -26 (= slot₂/S (call core.getfield %₂₅ 1)) -27 (= slot₁/iterstate (call core.getfield %₂₅ 2)) -28 slot₁/iterstate -29 (call top.indexed_iterate %₂₄ 2 %₂₈) -30 (= slot₃/T (call core.getfield %₂₉ 1)) -31 (goto label₃₄) -32 slot₄/X -33 (= TestMod.X %₃₂) -34 (goto label₃₇) -35 slot₄/X -36 (= TestMod.X %₃₅) -37 slot₄/X +17 (= slot₈/if_val (call core._equiv_typedef %₁₆ %₁₁)) +18 (goto label₂₀) +19 (= slot₈/if_val false) +20 slot₈/if_val +21 (gotoifnot %₂₀ label₂₅) +22 TestMod.X +23 (= slot₉/if_val %₂₂) +24 (goto label₂₆) +25 (= slot₉/if_val false) +26 slot₉/if_val +27 (gotoifnot %₂₀ label₃₈) +28 TestMod.X +29 (call top.getproperty %₂₈ :body) +30 (call top.getproperty %₂₉ :body) +31 (call top.getproperty %₃₀ :parameters) +32 (call top.indexed_iterate %₃₁ 1) +33 (= slot₂/S (call core.getfield %₃₂ 1)) +34 (= slot₁/iterstate (call core.getfield %₃₂ 2)) +35 slot₁/iterstate +36 (call top.indexed_iterate %₃₁ 2 %₃₅) +37 (= slot₃/T (call core.getfield %₃₆ 1)) 38 (call core.svec core.Any) -39 (call core._typebody! %₃₇ %₃₈) -40 TestMod.X -41 TestMod.A -42 TestMod.B -43 (call core.apply_type %₄₀ %₄₁ %₄₂) -44 (call core.apply_type core.Type %₄₃) -45 (call core.svec %₄₄) -46 (call core.svec) -47 SourceLocation::3:5 -48 (call core.svec %₄₅ %₄₆ %₄₇) -49 --- method core.nothing %₄₈ +39 (call core._typebody! %₂₆ %₁₁ %₃₈) +40 (constdecl TestMod.X %₃₉) +41 (latestworld) +42 (latestworld) +43 TestMod.X +44 TestMod.A +45 TestMod.B +46 (call core.apply_type %₄₃ %₄₄ %₄₅) +47 (call core.apply_type core.Type %₄₆) +48 (call core.svec %₄₇) +49 (call core.svec) +50 SourceLocation::3:5 +51 (call core.svec %₄₈ %₄₉ %₅₀) +52 --- method core.nothing %₅₁ slots: [slot₁/#ctor-self#] 1 slot₁/#ctor-self# 2 (new %₁ 1) 3 (return %₂) -50 (= slot₆/U (call core.TypeVar :U)) -51 (= slot₇/V (call core.TypeVar :V)) -52 TestMod.X -53 slot₆/U -54 slot₇/V -55 (call core.apply_type %₅₂ %₅₃ %₅₄) -56 (call core.apply_type core.Type %₅₅) -57 (call core.svec %₅₆) +53 (latestworld) +54 (latestworld) +55 (= slot₆/U (call core.TypeVar :U)) +56 (= slot₇/V (call core.TypeVar :V)) +57 TestMod.X 58 slot₆/U 59 slot₇/V -60 (call core.svec %₅₈ %₅₉) -61 SourceLocation::4:5 -62 (call core.svec %₅₇ %₆₀ %₆₁) -63 --- method core.nothing %₆₂ +60 (call core.apply_type %₅₇ %₅₈ %₅₉) +61 (call core.apply_type core.Type %₆₀) +62 (call core.svec %₆₁) +63 slot₆/U +64 slot₇/V +65 (call core.svec %₆₃ %₆₄) +66 SourceLocation::4:5 +67 (call core.svec %₆₂ %₆₅ %₆₆) +68 --- method core.nothing %₆₇ slots: [slot₁/#ctor-self#] 1 slot₁/#ctor-self# 2 (new %₁ 1) 3 (return %₂) -64 (call core.svec) -65 (call core.svec) -66 (call JuliaLowering.eval_closure_type TestMod :#f##1 %₆₄ %₆₅) -67 TestMod.#f##1 -68 (new %₆₇) -69 (= slot₅/f %₆₈) -70 TestMod.#f##1 -71 (call core.svec %₇₀) -72 (call core.svec) -73 SourceLocation::5:5 -74 (call core.svec %₇₁ %₇₂ %₇₃) -75 --- method core.nothing %₇₄ +69 (latestworld) +70 (call core.svec) +71 (call core.svec) +72 (call JuliaLowering.eval_closure_type TestMod :#f##1 %₇₀ %₇₁) +73 (latestworld) +74 TestMod.#f##1 +75 (new %₇₄) +76 (= slot₅/f %₇₅) +77 (latestworld) +78 TestMod.#f##1 +79 (call core.svec %₇₈) +80 (call core.svec) +81 SourceLocation::5:5 +82 (call core.svec %₇₉ %₈₀ %₈₁) +83 --- method core.nothing %₈₂ slots: [slot₁/#self#(!read)] 1 TestMod.X 2 TestMod.A @@ -1036,7 +1100,8 @@ end 4 (call core.apply_type %₁ %₂ %₃) 5 (new %₄ 1) 6 (return %₅) -76 (return core.nothing) +84 (latestworld) +85 (return core.nothing) ######################################## # new() calls with splats; `Any` fields @@ -1047,42 +1112,46 @@ struct X end #--------------------- 1 (global TestMod.X) -2 (const TestMod.X) +2 (latestworld) 3 (call core.svec) 4 (call core.svec :x :y) 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₂₀) +9 (call core.isdefinedglobal TestMod :X false) +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 +12 (= slot₂/if_val (call core._equiv_typedef %₁₁ %₆)) +13 (goto label₁₅) +14 (= slot₂/if_val false) +15 slot₂/if_val +16 (gotoifnot %₁₅ label₂₀) +17 TestMod.X +18 (= slot₃/if_val %₁₇) +19 (goto label₂₁) +20 (= slot₃/if_val false) +21 slot₃/if_val +22 (gotoifnot %₁₅ label₂₃) 23 (call core.svec core.Any core.Any) -24 (call core._typebody! %₂₂ %₂₃) -25 TestMod.X -26 (call core.apply_type core.Type %₂₅) -27 (call core.svec %₂₆ core.Any) -28 (call core.svec) -29 SourceLocation::4:5 -30 (call core.svec %₂₇ %₂₈ %₂₉) -31 --- method core.nothing %₃₀ +24 (call core._typebody! %₂₁ %₆ %₂₃) +25 (constdecl TestMod.X %₂₄) +26 (latestworld) +27 (latestworld) +28 TestMod.X +29 (call core.apply_type core.Type %₂₈) +30 (call core.svec %₂₉ core.Any) +31 (call core.svec) +32 SourceLocation::4:5 +33 (call core.svec %₃₀ %₃₁ %₃₂) +34 --- method core.nothing %₃₃ slots: [slot₁/#ctor-self# slot₂/xs] 1 slot₁/#ctor-self# 2 (call core._apply_iterate top.iterate core.tuple slot₂/xs) 3 (splatnew %₁ %₂) 4 (return %₃) -32 (return core.nothing) +35 (latestworld) +36 (return core.nothing) ######################################## # new() calls with splats; typed fields @@ -1093,7 +1162,7 @@ struct X{T} end #--------------------- 1 (global TestMod.X) -2 (const TestMod.X) +2 (latestworld) 3 (= slot₁/T (call core.TypeVar :T)) 4 slot₁/T 5 (call core.svec %₄) @@ -1102,40 +1171,43 @@ end 8 (call core._structtype TestMod :X %₅ %₆ %₇ false 2) 9 (= slot₂/X %₈) 10 (call core._setsuper! %₈ core.Any) -11 (isdefined TestMod.X) -12 (gotoifnot %₁₁ label₂₇) +11 (call core.isdefinedglobal TestMod :X false) +12 (gotoifnot %₁₁ label₁₆) 13 TestMod.X -14 (call core._equiv_typedef %₁₃ %₈) -15 (gotoifnot %₁₄ label₂₄) -16 TestMod.X -17 (= slot₂/X %₁₆) -18 TestMod.X -19 (call top.getproperty %₁₈ :body) -20 (call top.getproperty %₁₉ :parameters) -21 (call top.indexed_iterate %₂₀ 1) -22 (= slot₁/T (call core.getfield %₂₁ 1)) -23 (goto label₂₆) -24 slot₂/X -25 (= TestMod.X %₂₄) -26 (goto label₂₉) -27 slot₂/X -28 (= TestMod.X %₂₇) -29 slot₂/X +14 (= slot₄/if_val (call core._equiv_typedef %₁₃ %₈)) +15 (goto label₁₇) +16 (= slot₄/if_val false) +17 slot₄/if_val +18 (gotoifnot %₁₇ label₂₂) +19 TestMod.X +20 (= slot₅/if_val %₁₉) +21 (goto label₂₃) +22 (= slot₅/if_val false) +23 slot₅/if_val +24 (gotoifnot %₁₇ label₃₀) +25 TestMod.X +26 (call top.getproperty %₂₅ :body) +27 (call top.getproperty %₂₆ :parameters) +28 (call top.indexed_iterate %₂₇ 1) +29 (= slot₁/T (call core.getfield %₂₈ 1)) 30 slot₁/T 31 TestMod.A 32 (call core.svec %₃₀ %₃₁) -33 (call core._typebody! %₂₉ %₃₂) -34 (= slot₃/T (call core.TypeVar :T)) -35 TestMod.X -36 slot₃/T -37 (call core.apply_type %₃₅ %₃₆) -38 (call core.apply_type core.Type %₃₇) -39 (call core.svec %₃₈ core.Any) -40 slot₃/T -41 (call core.svec %₄₀) -42 SourceLocation::4:5 -43 (call core.svec %₃₉ %₄₁ %₄₂) -44 --- method core.nothing %₄₃ +33 (call core._typebody! %₂₃ %₈ %₃₂) +34 (constdecl TestMod.X %₃₃) +35 (latestworld) +36 (latestworld) +37 (= slot₃/T (call core.TypeVar :T)) +38 TestMod.X +39 slot₃/T +40 (call core.apply_type %₃₈ %₃₉) +41 (call core.apply_type core.Type %₄₀) +42 (call core.svec %₄₁ core.Any) +43 slot₃/T +44 (call core.svec %₄₃) +45 SourceLocation::4:5 +46 (call core.svec %₄₂ %₄₄ %₄₅) +47 --- method core.nothing %₄₆ slots: [slot₁/#ctor-self# slot₂/xs slot₃/tmp slot₄/tmp] 1 (call core._apply_iterate top.iterate core.tuple slot₂/xs) 2 (call core.nfields %₁) @@ -1168,7 +1240,8 @@ end 29 slot₄/tmp 30 (new %₁₁ %₂₀ %₂₉) 31 (return %₃₀) -45 (return core.nothing) +48 (latestworld) +49 (return core.nothing) ######################################## # Error: new doesn't accept keywords