Package evaluation to test CSTParser on Julia 1.14.0-DEV.1687 (b1350e5378*) started at 2026-02-05T12:31:20.053 ################################################################################ # Set-up # Installing PkgEval dependencies (TestEnv)... Activating project at `~/.julia/environments/v1.14` Set-up completed after 10.69s ################################################################################ # Installation # Installing CSTParser... Resolving package versions... Updating `~/.julia/environments/v1.14/Project.toml` [00ebfdb7] + CSTParser v3.4.3 Updating `~/.julia/environments/v1.14/Manifest.toml` [00ebfdb7] + CSTParser v3.4.3 [0796e94c] + Tokenize v0.5.29 Installation completed after 0.84s ################################################################################ # Precompilation # Precompiling PkgEval dependencies... Precompiling package dependencies... Precompiling packages... 6140.2 ms ✓ CSTParser 1 dependency successfully precompiled in 6 seconds. 33 already precompiled. Precompilation completed after 20.51s ################################################################################ # Testing # Testing CSTParser Status `/tmp/jl_Mn3VoW/Project.toml` [00ebfdb7] CSTParser v3.4.3 [f8b46487] TestItemRunner v1.1.4 [0796e94c] Tokenize v0.5.29 [8dfed614] Test v1.11.0 Status `/tmp/jl_Mn3VoW/Manifest.toml` [00ebfdb7] CSTParser v3.4.3 [f8b46487] TestItemRunner v1.1.4 [1c621080] TestItems v1.0.0 [0796e94c] Tokenize v0.5.29 [0dad84c5] ArgTools v1.1.2 [56f22d72] Artifacts v1.11.0 [2a0f44e3] Base64 v1.11.0 [ade2ca70] Dates v1.11.0 [f43a241f] Downloads v1.7.0 [7b1f6079] FileWatching v1.11.0 [b77e0a4c] InteractiveUtils v1.11.0 [ac6e5ff7] JuliaSyntaxHighlighting v1.13.0 [b27032c2] LibCURL v1.0.0 [76f85450] LibGit2 v1.11.0 [8f399da3] Libdl v1.11.0 [56ddb016] Logging v1.11.0 [d6f4376e] Markdown v1.11.0 [ca575930] NetworkOptions v1.3.0 [44cfe95a] Pkg v1.14.0 [de0858da] Printf v1.11.0 [9a3f8284] Random v1.11.0 [ea8e919c] SHA v1.0.0 [9e88b42a] Serialization v1.11.0 [f489334b] StyledStrings v1.13.0 [fa267f1f] TOML v1.0.3 [a4e569a6] Tar v1.10.0 [8dfed614] Test v1.11.0 [cf7118a7] UUIDs v1.11.0 [4ec0a83e] Unicode v1.11.0 [e66e0078] CompilerSupportLibraries_jll v1.3.0+1 [deac9b47] LibCURL_jll v8.18.0+0 [e37daf67] LibGit2_jll v1.9.2+0 [29816b5a] LibSSH2_jll v1.11.3+1 [14a3606d] MozillaCACerts_jll v2025.12.2 [458c3c95] OpenSSL_jll v3.5.5+0 [efcefdf7] PCRE2_jll v10.47.0+0 [83775a58] Zlib_jll v1.3.1+2 [3161d3a3] Zstd_jll v1.5.7+1 [8e850ede] nghttp2_jll v1.68.0+1 [3f19e933] p7zip_jll v17.7.0+0 Testing Running tests... Mismatch between flisp and CSTParser when parsing string for outer $ i = 1:3 end ParserState: ParseState at 23 last : INTEGER (1,19-1,19 INTEGER ) (ws) current : END (1,21-1,23 KEYWORD ) (empty) next : ENDMARKER (1,24-1,23 ENDMARKER ) (empty) CSTParser Expr: 1:23 for 1:16 1:2 OP: = 1:10 call 1:2 OP: $ 3:8 outer 9:10 i 11:14 block 11:14 call 11:11 OP: : 12:12 INTEGER: 1 13:14 INTEGER: 3 17:16 block Converted CSTParser Expr: for outer $ i = begin 1:3 end end Base EXPR: for outer $ i = 1:3 end for outer parsing: Test Failed at /home/pkgeval/.julia/packages/CSTParser/0hXvH/test/parser/test_keyword_blocks.jl:154 Expression: "for outer \$ i = 1:3 end" |> test_expr Evaluated: "for outer \$ i = 1:3 end" |> Main.var"##150".test_expr Stacktrace: [1] top-level scope @ ~/.julia/packages/CSTParser/0hXvH/test/parser/test_keyword_blocks.jl:150 [2] macro expansion @ /opt/julia/share/julia/stdlib/v1.14/Test/src/Test.jl:2244 [inlined] [3] macro expansion @ ~/.julia/packages/CSTParser/0hXvH/test/parser/test_keyword_blocks.jl:154 [inlined] [4] macro expansion @ /opt/julia/share/julia/stdlib/v1.14/Test/src/Test.jl:782 [inlined] :kw: Test Failed at /home/pkgeval/.julia/packages/CSTParser/0hXvH/test/shared.jl:37 Expression: to_codeobject(x) == jl_parse(s) Evaluated: f(::typeof(a) = begin 1 end) == f(::typeof(a) = 1) Stacktrace: [1] macro expansion @ /opt/julia/share/julia/stdlib/v1.14/Test/src/Test.jl:782 [inlined] [2] test_expr(s::String, head::Symbol, n::Int64, endswithtrivia::Bool) @ Main.var"##168" ~/.julia/packages/CSTParser/0hXvH/test/shared.jl:37 Mismatch between flisp and CSTParser when parsing string a.{1} ParserState: ParseState at 5 last : INTEGER (1,4-1,4 INTEGER ) (empty) current : RBRACE (1,5-1,5 RBRACE ) (empty) next : ENDMARKER (1,6-1,5 ENDMARKER ) (empty) CSTParser Expr: 1:5 1:1 OP: . 1:1 a 2:4 quote 2:4 braces 2:2 INTEGER: 1 Converted CSTParser Expr: a.:({1}) Base EXPR: a.:({1}) No longer broken things: Test Failed at /home/pkgeval/.julia/packages/CSTParser/0hXvH/test/parser/test_parser.jl:354 Expression: "a.{1}" |> test_expr Evaluated: "a.{1}" |> Main.var"##251".test_expr Stacktrace: [1] top-level scope @ ~/.julia/packages/CSTParser/0hXvH/test/parser/test_parser.jl:557 [2] macro expansion @ /opt/julia/share/julia/stdlib/v1.14/Test/src/Test.jl:782 [inlined] ┌ Error: parsing difference │ file = "/opt/julia/bin/../share/julia/JuliaLowering/src/compat.jl" └ @ Main.var"##302" ~/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:157 [K"meta" mapsyntax((s->begin if kind(s) === K"Identifier" setattr(s, :kind, K"Symbol") else s end end), syms)...;] [K"meta" mapsyntax((s->begin if kind(s) === K"Identifier" setattr(s, :kind, K"Symbol") else s end end), syms)...] K"meta" mapsyntax((s->begin if kind(s) === K"Identifier" setattr(s, :kind, K"Symbol") else s end end), syms)... K"meta" K"meta" @K_str mapsyntax((s->begin if kind(s) === K"Identifier" setattr(s, :kind, K"Symbol") else s end end), syms)... nothing K"meta" mapsyntax((s->begin if kind(s) === K"Identifier" setattr(s, :kind, K"Symbol") else s end end), syms)... K"meta" [K"meta" mapsyntax((s->begin if kind(s) === K"Identifier" setattr(s, :kind, K"Symbol") else s end end), syms)...;] [K"meta" mapsyntax((s->begin if kind(s) === K"Identifier" setattr(s, :kind, K"Symbol") else s end end), syms)...] @ast g st [K"meta" mapsyntax((s->begin if kind(s) === K"Identifier" setattr(s, :kind, K"Symbol") else s end end), syms)...;] @ast g st [K"meta" mapsyntax((s->begin if kind(s) === K"Identifier" setattr(s, :kind, K"Symbol") else s end end), syms)...] begin @ast g st [K"meta" mapsyntax((s->begin if kind(s) === K"Identifier" setattr(s, :kind, K"Symbol") else s end end), syms)...;] end begin @ast g st [K"meta" mapsyntax((s->begin if kind(s) === K"Identifier" setattr(s, :kind, K"Symbol") else s end end), syms)...] end [K"meta" syms...]->begin @ast g st [K"meta" mapsyntax((s->begin if kind(s) === K"Identifier" setattr(s, :kind, K"Symbol") else s end end), syms)...;] end [K"meta" syms...]->begin @ast g st [K"meta" mapsyntax((s->begin if kind(s) === K"Identifier" setattr(s, :kind, K"Symbol") else s end end), syms)...] end begin [K"Identifier"]->begin let s = st.name_val if s in ("ccall", "cglobal") setattr!(newleaf(g, st, K"core"), :name_val, st.name_val) elseif all((==)('_'), s) setattr!(mkleaf(st), :kind, K"Placeholder") else st end end end (_, when = is_leaf(st))->begin st end ([K"unknown_head" l r], when = begin s = st.name_val Base.isoperator(s) end)->begin let (op_s, out_k) = if s[1] === '.' (s[nextind(s, 1):prevind(s, var"end")], K".op=") else (s[1:prevind(s, var"end")], K"op=") end op_leaf = newleaf(g, st, K"Identifier") JS.copy_attrs!(op_leaf, st) setattr!(op_leaf, :name_val, op_s) @ast g st [out_k rec(l) op_leaf rec(r)] end end [K"comparison" cs0...]->begin let cs = copy(cs0) for (i, c) = enumerate(cs) cs[i] = if iseven(i) _dst_separate_dotop(cs[i]) else rec(cs[i]) end end mknode(st, cs) end end [K"'" x]->begin @ast g st [K"call" "'"::(K"Identifier")(scope_layer = st.scope_layer) rec(x)] end [K"." f [K"tuple" args...]]->begin _expand_literal_pow(@ast(g, st, [K"dotcall" rec(f) _dst_sink_parameters(args)...])) end [K"." l r]->begin let r2 = rec(r) @stm r2 begin [K"inert" r3]->begin @ast g st [K"." rec(l) r3] end r3->begin @ast g st [K"." rec(l) r3] end end end end [K"inert" [K"Identifier"]]->begin @ast g st st[1] => K"Symbol" end [K"inert" _]->begin st end [K"inert_syntaxtree" _]->begin st end [K"module" _...]->begin st end [K"toplevel" _...]->begin st end [K"for" [K"=" _ _] body]->begin @ast g st [K"for" [K"iteration" _dst_eq_to_in(st[1])] rec(body)] end [K"for" [K"block" iters...] body]->begin @ast g st [K"for"; [K"iteration" mapsyntax(_dst_eq_to_in, iters)...]; rec(body)] end ([K"where" t tds...], when = !(length(tds) === 1 && kind(tds[1]) === K"braces"))->begin @ast g st [K"where" rec(t) [K"braces" mapsyntax(rec, tds)...]] end (_, when = begin k = kind(st) k in KSet"tuple vect braces" end)->begin @ast g st [k _dst_sink_parameters(children(st))...] end (_, when = begin k = kind(st) k in KSet"curly ref" end)->begin @ast g st [k _dst_separate_dotop(st[1]); _dst_sink_parameters((children(st))[2:var"end"])...] end [K"call" f args...]->begin let (out_k, out_f) = @stm(_dst_separate_dotop(f), begin [K"." op]->begin (K"dotcall", op) end f_sep->begin (K"call", f_sep) end end) out = @ast(g, st, [out_k; out_f _dst_sink_parameters((children(st))[2:var"end"])...]) _expand_literal_pow(out) end end [K"try" tryb cvar catchb rest...]->begin let has_catch = !(_is_false(cvar) && _is_false(catchb)) cvar_out = if _is_false(cvar) newleaf(g, cvar, K"Placeholder") else rec(cvar) end has_finally = length(rest) >= 1 && !(_is_false(rest[1])) has_else = length(rest) === 2 @ast g st [K"try" rec(tryb); if has_catch [K"catch" cvar_out rec(catchb)] else nothing end; if has_else [K"else" rec(rest[2])] else nothing end; if has_finally [K"finally" rec(rest[1])] else nothing end] end end [K"flatten" _]->begin let out_iters = SyntaxList(st) next = st while kind(next) === K"flatten" push!(out_iters, _dst_iterspec(next, (next[1])[2:var"end"])) next = (next[1])[1] end @assert kind(next) === K"generator" push!(out_iters, _dst_iterspec(next, next[2:var"end"])) @ast g st [K"generator" rec(next[1]) out_iters...] end end [K"generator" body iters...]->begin @ast g st [K"generator" rec(body) _dst_iterspec(st, iters)] end [K"ncat" dim xs...]->begin let out = mknode(st, mapsyntax(rec, xs)) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end [K"nrow" dim xs...]->begin let out = mknode(st, mapsyntax(rec, xs)) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end [K"typed_ncat" t dim xs...]->begin let out_cs = pushfirst!(mapsyntax(rec, xs), rec(t)) out = mknode(st, out_cs) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end ([K"=" l r], when = is_eventually_call(l))->begin if has_if_generated(r) (gen, nongen) = (split_generated(r, true), split_generated(r, false)) @ast g st [K"generated_function" rec(l) gen nongen] else @ast g st [K"function" rec(l) rec(r)] end end [K"function" l r]->begin let if kind(l) === K"..." l = @ast(g, l, [K"tuple" l]) end if has_if_generated(r) (gen, nongen) = (split_generated(r, true), split_generated(r, false)) @ast g st [K"generated_function" rec(l) gen nongen] else @ast g st [K"function" rec(l) rec(r)] end end end [K"do" [K"call" f args...] [K"->" do_args do_body]]->begin let @ast g st [K"call"; rec(f); @ast(g, st[var"end"], [K"do" rec(do_args) rec(do_body)]); _dst_sink_parameters(args)...] end end ([K"let" binds body], when = kind(binds) !== K"block")->begin @ast g st [K"let" [K"block" rec(binds)] rec(body)] end [K"struct" mut sig body]->begin let flags = JS.flags(st) | if _is_false(mut) 0 else JS.MUTABLE_FLAG end @ast g st [(K"struct")(syntax_flags = flags); rec(sig); rec(body)] end end (_, when = kind(st) in KSet"using import")->begin let (paths, maybe_colon) = @stm(st[1], begin [K":" paths...]->begin (paths, st[1]) end _->begin (children(st), nothing) end end) out_cs = mapsyntax(_dst_importpath, paths) if !(isnothing(maybe_colon)) out_c1 = @ast(g, maybe_colon, [K":" out_cs...]) out_cs = SyntaxList(g, tree_ids(out_c1)) end mknode(st, out_cs) end end ([K"meta" [K"unknown_head" ps...]], when = (st[1]).name_val === "purity")->begin @ast g st [K"meta" "purity"::K"Symbol"; Base.EffectsOverride([x.value for x = ps]...)::K"Value"] end ([K"meta" s vs...], when = get(s, :name_val, "") in ("nospecialize", "specialize"))->begin let if length(vs) === 0 @ast g st [K"meta" s => K"Symbol"] elseif length(vs) === 1 out = est_to_dst(vs[1]) setmeta(out, Symbol(s), true) else out_cs = SyntaxList(g) for v = vs push!(out_cs, @ast(g, v, [K"meta" s => K"Symbol" v])) end @ast g st [K"block" out_cs...] end end end [K"meta" syms...]->begin @ast g st [K"meta" mapsyntax((s->begin if kind(s) === K"Identifier" setattr(s, :kind, K"Symbol") else s end end), syms)...;] end [K"inline" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"noinline" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"inbounds" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"core" x]->begin setattr!(mkleaf(st), :name_val, x.name_val) end [K"top" x]->begin setattr!(mkleaf(st), :name_val, x.name_val) end [K"copyast" [K"inert" ex]]->begin @ast g st [K"call"; interpolate_ast::K"Value"; Expr::K"Value"; [K"inert" ex]] end [K"symbolicgoto" lab]->begin setattr!(mkleaf(st), :name_val, lab.name_val) end [K"symboliclabel" lab]->begin setattr!(mkleaf(st), :name_val, lab.name_val) end [K"unknown_head" cs...]->begin let head = st.name_val if head === "latestworld-if-toplevel" newleaf(g, st, K"latestworld_if_toplevel") else @assert false string("unknown expr head (corresponding to no kind) between", "macro-expansion and desugaring: ", st) end end end [K"cfunction" typ fptr rt at sym]->begin @ast g st [K"cfunction"; rec(typ) rec(fptr); [(K"static_eval")(meta = name_hint("cfunction return type")) rec(rt)]; [(K"static_eval")(meta = name_hint("cfunction argument type")) rec(at)]; rec(sym)] end _->begin let out_cs::Vector{NodeId} = map((x->begin (rec(x))._id end), children(st)) if out_cs == children(st) st else mknode(st, out_cs) end end end end begin [K"Identifier"]->begin let s = st.name_val if s in ("ccall", "cglobal") setattr!(newleaf(g, st, K"core"), :name_val, st.name_val) elseif all((==)('_'), s) setattr!(mkleaf(st), :kind, K"Placeholder") else st end end end (_, when = is_leaf(st))->begin st end ([K"unknown_head" l r], when = begin s = st.name_val Base.isoperator(s) end)->begin let (op_s, out_k) = if s[1] === '.' (s[nextind(s, 1):prevind(s, var"end")], K".op=") else (s[1:prevind(s, var"end")], K"op=") end op_leaf = newleaf(g, st, K"Identifier") JS.copy_attrs!(op_leaf, st) setattr!(op_leaf, :name_val, op_s) @ast g st [out_k rec(l) op_leaf rec(r)] end end [K"comparison" cs0...]->begin let cs = copy(cs0) for (i, c) = enumerate(cs) cs[i] = if iseven(i) _dst_separate_dotop(cs[i]) else rec(cs[i]) end end mknode(st, cs) end end [K"'" x]->begin @ast g st [K"call" "'"::(K"Identifier")(scope_layer = st.scope_layer) rec(x)] end [K"." f [K"tuple" args...]]->begin _expand_literal_pow(@ast(g, st, [K"dotcall" rec(f) _dst_sink_parameters(args)...])) end [K"." l r]->begin let r2 = rec(r) @stm r2 begin [K"inert" r3]->begin @ast g st [K"." rec(l) r3] end r3->begin @ast g st [K"." rec(l) r3] end end end end [K"inert" [K"Identifier"]]->begin @ast g st st[1] => K"Symbol" end [K"inert" _]->begin st end [K"inert_syntaxtree" _]->begin st end [K"module" _...]->begin st end [K"toplevel" _...]->begin st end [K"for" [K"=" _ _] body]->begin @ast g st [K"for" [K"iteration" _dst_eq_to_in(st[1])] rec(body)] end [K"for" [K"block" iters...] body]->begin @ast g st [K"for"; [K"iteration" mapsyntax(_dst_eq_to_in, iters)...]; rec(body)] end ([K"where" t tds...], when = !(length(tds) === 1 && kind(tds[1]) === K"braces"))->begin @ast g st [K"where" rec(t) [K"braces" mapsyntax(rec, tds)...]] end (_, when = begin k = kind(st) k in KSet"tuple vect braces" end)->begin @ast g st [k _dst_sink_parameters(children(st))...] end (_, when = begin k = kind(st) k in KSet"curly ref" end)->begin @ast g st [k _dst_separate_dotop(st[1]); _dst_sink_parameters((children(st))[2:var"end"])...] end [K"call" f args...]->begin let (out_k, out_f) = @stm(_dst_separate_dotop(f), begin [K"." op]->begin (K"dotcall", op) end f_sep->begin (K"call", f_sep) end end) out = @ast(g, st, [out_k; out_f _dst_sink_parameters((children(st))[2:var"end"])...]) _expand_literal_pow(out) end end [K"try" tryb cvar catchb rest...]->begin let has_catch = !(_is_false(cvar) && _is_false(catchb)) cvar_out = if _is_false(cvar) newleaf(g, cvar, K"Placeholder") else rec(cvar) end has_finally = length(rest) >= 1 && !(_is_false(rest[1])) has_else = length(rest) === 2 @ast g st [K"try" rec(tryb); if has_catch [K"catch" cvar_out rec(catchb)] else nothing end; if has_else [K"else" rec(rest[2])] else nothing end; if has_finally [K"finally" rec(rest[1])] else nothing end] end end [K"flatten" _]->begin let out_iters = SyntaxList(st) next = st while kind(next) === K"flatten" push!(out_iters, _dst_iterspec(next, (next[1])[2:var"end"])) next = (next[1])[1] end @assert kind(next) === K"generator" push!(out_iters, _dst_iterspec(next, next[2:var"end"])) @ast g st [K"generator" rec(next[1]) out_iters...] end end [K"generator" body iters...]->begin @ast g st [K"generator" rec(body) _dst_iterspec(st, iters)] end [K"ncat" dim xs...]->begin let out = mknode(st, mapsyntax(rec, xs)) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end [K"nrow" dim xs...]->begin let out = mknode(st, mapsyntax(rec, xs)) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end [K"typed_ncat" t dim xs...]->begin let out_cs = pushfirst!(mapsyntax(rec, xs), rec(t)) out = mknode(st, out_cs) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end ([K"=" l r], when = is_eventually_call(l))->begin if has_if_generated(r) (gen, nongen) = (split_generated(r, true), split_generated(r, false)) @ast g st [K"generated_function" rec(l) gen nongen] else @ast g st [K"function" rec(l) rec(r)] end end [K"function" l r]->begin let if kind(l) === K"..." l = @ast(g, l, [K"tuple" l]) end if has_if_generated(r) (gen, nongen) = (split_generated(r, true), split_generated(r, false)) @ast g st [K"generated_function" rec(l) gen nongen] else @ast g st [K"function" rec(l) rec(r)] end end end [K"do" [K"call" f args...] [K"->" do_args do_body]]->begin let @ast g st [K"call"; rec(f); @ast(g, st[var"end"], [K"do" rec(do_args) rec(do_body)]); _dst_sink_parameters(args)...] end end ([K"let" binds body], when = kind(binds) !== K"block")->begin @ast g st [K"let" [K"block" rec(binds)] rec(body)] end [K"struct" mut sig body]->begin let flags = JS.flags(st) | if _is_false(mut) 0 else JS.MUTABLE_FLAG end @ast g st [(K"struct")(syntax_flags = flags); rec(sig); rec(body)] end end (_, when = kind(st) in KSet"using import")->begin let (paths, maybe_colon) = @stm(st[1], begin [K":" paths...]->begin (paths, st[1]) end _->begin (children(st), nothing) end end) out_cs = mapsyntax(_dst_importpath, paths) if !(isnothing(maybe_colon)) out_c1 = @ast(g, maybe_colon, [K":" out_cs...]) out_cs = SyntaxList(g, tree_ids(out_c1)) end mknode(st, out_cs) end end ([K"meta" [K"unknown_head" ps...]], when = (st[1]).name_val === "purity")->begin @ast g st [K"meta" "purity"::K"Symbol"; Base.EffectsOverride([x.value for x = ps]...)::K"Value"] end ([K"meta" s vs...], when = get(s, :name_val, "") in ("nospecialize", "specialize"))->begin let if length(vs) === 0 @ast g st [K"meta" s => K"Symbol"] elseif length(vs) === 1 out = est_to_dst(vs[1]) setmeta(out, Symbol(s), true) else out_cs = SyntaxList(g) for v = vs push!(out_cs, @ast(g, v, [K"meta" s => K"Symbol" v])) end @ast g st [K"block" out_cs...] end end end [K"meta" syms...]->begin @ast g st [K"meta" mapsyntax((s->begin if kind(s) === K"Identifier" setattr(s, :kind, K"Symbol") else s end end), syms)...] end [K"inline" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"noinline" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"inbounds" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"core" x]->begin setattr!(mkleaf(st), :name_val, x.name_val) end [K"top" x]->begin setattr!(mkleaf(st), :name_val, x.name_val) end [K"copyast" [K"inert" ex]]->begin @ast g st [K"call"; interpolate_ast::K"Value"; Expr::K"Value"; [K"inert" ex]] end [K"symbolicgoto" lab]->begin setattr!(mkleaf(st), :name_val, lab.name_val) end [K"symboliclabel" lab]->begin setattr!(mkleaf(st), :name_val, lab.name_val) end [K"unknown_head" cs...]->begin let head = st.name_val if head === "latestworld-if-toplevel" newleaf(g, st, K"latestworld_if_toplevel") else @assert false string("unknown expr head (corresponding to no kind) between", "macro-expansion and desugaring: ", st) end end end [K"cfunction" typ fptr rt at sym]->begin @ast g st [K"cfunction"; rec(typ) rec(fptr); [(K"static_eval")(meta = name_hint("cfunction return type")) rec(rt)]; [(K"static_eval")(meta = name_hint("cfunction argument type")) rec(at)]; rec(sym)] end _->begin let out_cs::Vector{NodeId} = map((x->begin (rec(x))._id end), children(st)) if out_cs == children(st) st else mknode(st, out_cs) end end end end @stm st begin [K"Identifier"]->begin let s = st.name_val if s in ("ccall", "cglobal") setattr!(newleaf(g, st, K"core"), :name_val, st.name_val) elseif all((==)('_'), s) setattr!(mkleaf(st), :kind, K"Placeholder") else st end end end (_, when = is_leaf(st))->begin st end ([K"unknown_head" l r], when = begin s = st.name_val Base.isoperator(s) end)->begin let (op_s, out_k) = if s[1] === '.' (s[nextind(s, 1):prevind(s, var"end")], K".op=") else (s[1:prevind(s, var"end")], K"op=") end op_leaf = newleaf(g, st, K"Identifier") JS.copy_attrs!(op_leaf, st) setattr!(op_leaf, :name_val, op_s) @ast g st [out_k rec(l) op_leaf rec(r)] end end [K"comparison" cs0...]->begin let cs = copy(cs0) for (i, c) = enumerate(cs) cs[i] = if iseven(i) _dst_separate_dotop(cs[i]) else rec(cs[i]) end end mknode(st, cs) end end [K"'" x]->begin @ast g st [K"call" "'"::(K"Identifier")(scope_layer = st.scope_layer) rec(x)] end [K"." f [K"tuple" args...]]->begin _expand_literal_pow(@ast(g, st, [K"dotcall" rec(f) _dst_sink_parameters(args)...])) end [K"." l r]->begin let r2 = rec(r) @stm r2 begin [K"inert" r3]->begin @ast g st [K"." rec(l) r3] end r3->begin @ast g st [K"." rec(l) r3] end end end end [K"inert" [K"Identifier"]]->begin @ast g st st[1] => K"Symbol" end [K"inert" _]->begin st end [K"inert_syntaxtree" _]->begin st end [K"module" _...]->begin st end [K"toplevel" _...]->begin st end [K"for" [K"=" _ _] body]->begin @ast g st [K"for" [K"iteration" _dst_eq_to_in(st[1])] rec(body)] end [K"for" [K"block" iters...] body]->begin @ast g st [K"for"; [K"iteration" mapsyntax(_dst_eq_to_in, iters)...]; rec(body)] end ([K"where" t tds...], when = !(length(tds) === 1 && kind(tds[1]) === K"braces"))->begin @ast g st [K"where" rec(t) [K"braces" mapsyntax(rec, tds)...]] end (_, when = begin k = kind(st) k in KSet"tuple vect braces" end)->begin @ast g st [k _dst_sink_parameters(children(st))...] end (_, when = begin k = kind(st) k in KSet"curly ref" end)->begin @ast g st [k _dst_separate_dotop(st[1]); _dst_sink_parameters((children(st))[2:var"end"])...] end [K"call" f args...]->begin let (out_k, out_f) = @stm(_dst_separate_dotop(f), begin [K"." op]->begin (K"dotcall", op) end f_sep->begin (K"call", f_sep) end end) out = @ast(g, st, [out_k; out_f _dst_sink_parameters((children(st))[2:var"end"])...]) _expand_literal_pow(out) end end [K"try" tryb cvar catchb rest...]->begin let has_catch = !(_is_false(cvar) && _is_false(catchb)) cvar_out = if _is_false(cvar) newleaf(g, cvar, K"Placeholder") else rec(cvar) end has_finally = length(rest) >= 1 && !(_is_false(rest[1])) has_else = length(rest) === 2 @ast g st [K"try" rec(tryb); if has_catch [K"catch" cvar_out rec(catchb)] else nothing end; if has_else [K"else" rec(rest[2])] else nothing end; if has_finally [K"finally" rec(rest[1])] else nothing end] end end [K"flatten" _]->begin let out_iters = SyntaxList(st) next = st while kind(next) === K"flatten" push!(out_iters, _dst_iterspec(next, (next[1])[2:var"end"])) next = (next[1])[1] end @assert kind(next) === K"generator" push!(out_iters, _dst_iterspec(next, next[2:var"end"])) @ast g st [K"generator" rec(next[1]) out_iters...] end end [K"generator" body iters...]->begin @ast g st [K"generator" rec(body) _dst_iterspec(st, iters)] end [K"ncat" dim xs...]->begin let out = mknode(st, mapsyntax(rec, xs)) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end [K"nrow" dim xs...]->begin let out = mknode(st, mapsyntax(rec, xs)) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end [K"typed_ncat" t dim xs...]->begin let out_cs = pushfirst!(mapsyntax(rec, xs), rec(t)) out = mknode(st, out_cs) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end ([K"=" l r], when = is_eventually_call(l))->begin if has_if_generated(r) (gen, nongen) = (split_generated(r, true), split_generated(r, false)) @ast g st [K"generated_function" rec(l) gen nongen] else @ast g st [K"function" rec(l) rec(r)] end end [K"function" l r]->begin let if kind(l) === K"..." l = @ast(g, l, [K"tuple" l]) end if has_if_generated(r) (gen, nongen) = (split_generated(r, true), split_generated(r, false)) @ast g st [K"generated_function" rec(l) gen nongen] else @ast g st [K"function" rec(l) rec(r)] end end end [K"do" [K"call" f args...] [K"->" do_args do_body]]->begin let @ast g st [K"call"; rec(f); @ast(g, st[var"end"], [K"do" rec(do_args) rec(do_body)]); _dst_sink_parameters(args)...] end end ([K"let" binds body], when = kind(binds) !== K"block")->begin @ast g st [K"let" [K"block" rec(binds)] rec(body)] end [K"struct" mut sig body]->begin let flags = JS.flags(st) | if _is_false(mut) 0 else JS.MUTABLE_FLAG end @ast g st [(K"struct")(syntax_flags = flags); rec(sig); rec(body)] end end (_, when = kind(st) in KSet"using import")->begin let (paths, maybe_colon) = @stm(st[1], begin [K":" paths...]->begin (paths, st[1]) end _->begin (children(st), nothing) end end) out_cs = mapsyntax(_dst_importpath, paths) if !(isnothing(maybe_colon)) out_c1 = @ast(g, maybe_colon, [K":" out_cs...]) out_cs = SyntaxList(g, tree_ids(out_c1)) end mknode(st, out_cs) end end ([K"meta" [K"unknown_head" ps...]], when = (st[1]).name_val === "purity")->begin @ast g st [K"meta" "purity"::K"Symbol"; Base.EffectsOverride([x.value for x = ps]...)::K"Value"] end ([K"meta" s vs...], when = get(s, :name_val, "") in ("nospecialize", "specialize"))->begin let if length(vs) === 0 @ast g st [K"meta" s => K"Symbol"] elseif length(vs) === 1 out = est_to_dst(vs[1]) setmeta(out, Symbol(s), true) else out_cs = SyntaxList(g) for v = vs push!(out_cs, @ast(g, v, [K"meta" s => K"Symbol" v])) end @ast g st [K"block" out_cs...] end end end [K"meta" syms...]->begin @ast g st [K"meta" mapsyntax((s->begin if kind(s) === K"Identifier" setattr(s, :kind, K"Symbol") else s end end), syms)...;] end [K"inline" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"noinline" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"inbounds" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"core" x]->begin setattr!(mkleaf(st), :name_val, x.name_val) end [K"top" x]->begin setattr!(mkleaf(st), :name_val, x.name_val) end [K"copyast" [K"inert" ex]]->begin @ast g st [K"call"; interpolate_ast::K"Value"; Expr::K"Value"; [K"inert" ex]] end [K"symbolicgoto" lab]->begin setattr!(mkleaf(st), :name_val, lab.name_val) end [K"symboliclabel" lab]->begin setattr!(mkleaf(st), :name_val, lab.name_val) end [K"unknown_head" cs...]->begin let head = st.name_val if head === "latestworld-if-toplevel" newleaf(g, st, K"latestworld_if_toplevel") else @assert false string("unknown expr head (corresponding to no kind) between", "macro-expansion and desugaring: ", st) end end end [K"cfunction" typ fptr rt at sym]->begin @ast g st [K"cfunction"; rec(typ) rec(fptr); [(K"static_eval")(meta = name_hint("cfunction return type")) rec(rt)]; [(K"static_eval")(meta = name_hint("cfunction argument type")) rec(at)]; rec(sym)] end _->begin let out_cs::Vector{NodeId} = map((x->begin (rec(x))._id end), children(st)) if out_cs == children(st) st else mknode(st, out_cs) end end end end @stm st begin [K"Identifier"]->begin let s = st.name_val if s in ("ccall", "cglobal") setattr!(newleaf(g, st, K"core"), :name_val, st.name_val) elseif all((==)('_'), s) setattr!(mkleaf(st), :kind, K"Placeholder") else st end end end (_, when = is_leaf(st))->begin st end ([K"unknown_head" l r], when = begin s = st.name_val Base.isoperator(s) end)->begin let (op_s, out_k) = if s[1] === '.' (s[nextind(s, 1):prevind(s, var"end")], K".op=") else (s[1:prevind(s, var"end")], K"op=") end op_leaf = newleaf(g, st, K"Identifier") JS.copy_attrs!(op_leaf, st) setattr!(op_leaf, :name_val, op_s) @ast g st [out_k rec(l) op_leaf rec(r)] end end [K"comparison" cs0...]->begin let cs = copy(cs0) for (i, c) = enumerate(cs) cs[i] = if iseven(i) _dst_separate_dotop(cs[i]) else rec(cs[i]) end end mknode(st, cs) end end [K"'" x]->begin @ast g st [K"call" "'"::(K"Identifier")(scope_layer = st.scope_layer) rec(x)] end [K"." f [K"tuple" args...]]->begin _expand_literal_pow(@ast(g, st, [K"dotcall" rec(f) _dst_sink_parameters(args)...])) end [K"." l r]->begin let r2 = rec(r) @stm r2 begin [K"inert" r3]->begin @ast g st [K"." rec(l) r3] end r3->begin @ast g st [K"." rec(l) r3] end end end end [K"inert" [K"Identifier"]]->begin @ast g st st[1] => K"Symbol" end [K"inert" _]->begin st end [K"inert_syntaxtree" _]->begin st end [K"module" _...]->begin st end [K"toplevel" _...]->begin st end [K"for" [K"=" _ _] body]->begin @ast g st [K"for" [K"iteration" _dst_eq_to_in(st[1])] rec(body)] end [K"for" [K"block" iters...] body]->begin @ast g st [K"for"; [K"iteration" mapsyntax(_dst_eq_to_in, iters)...]; rec(body)] end ([K"where" t tds...], when = !(length(tds) === 1 && kind(tds[1]) === K"braces"))->begin @ast g st [K"where" rec(t) [K"braces" mapsyntax(rec, tds)...]] end (_, when = begin k = kind(st) k in KSet"tuple vect braces" end)->begin @ast g st [k _dst_sink_parameters(children(st))...] end (_, when = begin k = kind(st) k in KSet"curly ref" end)->begin @ast g st [k _dst_separate_dotop(st[1]); _dst_sink_parameters((children(st))[2:var"end"])...] end [K"call" f args...]->begin let (out_k, out_f) = @stm(_dst_separate_dotop(f), begin [K"." op]->begin (K"dotcall", op) end f_sep->begin (K"call", f_sep) end end) out = @ast(g, st, [out_k; out_f _dst_sink_parameters((children(st))[2:var"end"])...]) _expand_literal_pow(out) end end [K"try" tryb cvar catchb rest...]->begin let has_catch = !(_is_false(cvar) && _is_false(catchb)) cvar_out = if _is_false(cvar) newleaf(g, cvar, K"Placeholder") else rec(cvar) end has_finally = length(rest) >= 1 && !(_is_false(rest[1])) has_else = length(rest) === 2 @ast g st [K"try" rec(tryb); if has_catch [K"catch" cvar_out rec(catchb)] else nothing end; if has_else [K"else" rec(rest[2])] else nothing end; if has_finally [K"finally" rec(rest[1])] else nothing end] end end [K"flatten" _]->begin let out_iters = SyntaxList(st) next = st while kind(next) === K"flatten" push!(out_iters, _dst_iterspec(next, (next[1])[2:var"end"])) next = (next[1])[1] end @assert kind(next) === K"generator" push!(out_iters, _dst_iterspec(next, next[2:var"end"])) @ast g st [K"generator" rec(next[1]) out_iters...] end end [K"generator" body iters...]->begin @ast g st [K"generator" rec(body) _dst_iterspec(st, iters)] end [K"ncat" dim xs...]->begin let out = mknode(st, mapsyntax(rec, xs)) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end [K"nrow" dim xs...]->begin let out = mknode(st, mapsyntax(rec, xs)) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end [K"typed_ncat" t dim xs...]->begin let out_cs = pushfirst!(mapsyntax(rec, xs), rec(t)) out = mknode(st, out_cs) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end ([K"=" l r], when = is_eventually_call(l))->begin if has_if_generated(r) (gen, nongen) = (split_generated(r, true), split_generated(r, false)) @ast g st [K"generated_function" rec(l) gen nongen] else @ast g st [K"function" rec(l) rec(r)] end end [K"function" l r]->begin let if kind(l) === K"..." l = @ast(g, l, [K"tuple" l]) end if has_if_generated(r) (gen, nongen) = (split_generated(r, true), split_generated(r, false)) @ast g st [K"generated_function" rec(l) gen nongen] else @ast g st [K"function" rec(l) rec(r)] end end end [K"do" [K"call" f args...] [K"->" do_args do_body]]->begin let @ast g st [K"call"; rec(f); @ast(g, st[var"end"], [K"do" rec(do_args) rec(do_body)]); _dst_sink_parameters(args)...] end end ([K"let" binds body], when = kind(binds) !== K"block")->begin @ast g st [K"let" [K"block" rec(binds)] rec(body)] end [K"struct" mut sig body]->begin let flags = JS.flags(st) | if _is_false(mut) 0 else JS.MUTABLE_FLAG end @ast g st [(K"struct")(syntax_flags = flags); rec(sig); rec(body)] end end (_, when = kind(st) in KSet"using import")->begin let (paths, maybe_colon) = @stm(st[1], begin [K":" paths...]->begin (paths, st[1]) end _->begin (children(st), nothing) end end) out_cs = mapsyntax(_dst_importpath, paths) if !(isnothing(maybe_colon)) out_c1 = @ast(g, maybe_colon, [K":" out_cs...]) out_cs = SyntaxList(g, tree_ids(out_c1)) end mknode(st, out_cs) end end ([K"meta" [K"unknown_head" ps...]], when = (st[1]).name_val === "purity")->begin @ast g st [K"meta" "purity"::K"Symbol"; Base.EffectsOverride([x.value for x = ps]...)::K"Value"] end ([K"meta" s vs...], when = get(s, :name_val, "") in ("nospecialize", "specialize"))->begin let if length(vs) === 0 @ast g st [K"meta" s => K"Symbol"] elseif length(vs) === 1 out = est_to_dst(vs[1]) setmeta(out, Symbol(s), true) else out_cs = SyntaxList(g) for v = vs push!(out_cs, @ast(g, v, [K"meta" s => K"Symbol" v])) end @ast g st [K"block" out_cs...] end end end [K"meta" syms...]->begin @ast g st [K"meta" mapsyntax((s->begin if kind(s) === K"Identifier" setattr(s, :kind, K"Symbol") else s end end), syms)...] end [K"inline" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"noinline" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"inbounds" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"core" x]->begin setattr!(mkleaf(st), :name_val, x.name_val) end [K"top" x]->begin setattr!(mkleaf(st), :name_val, x.name_val) end [K"copyast" [K"inert" ex]]->begin @ast g st [K"call"; interpolate_ast::K"Value"; Expr::K"Value"; [K"inert" ex]] end [K"symbolicgoto" lab]->begin setattr!(mkleaf(st), :name_val, lab.name_val) end [K"symboliclabel" lab]->begin setattr!(mkleaf(st), :name_val, lab.name_val) end [K"unknown_head" cs...]->begin let head = st.name_val if head === "latestworld-if-toplevel" newleaf(g, st, K"latestworld_if_toplevel") else @assert false string("unknown expr head (corresponding to no kind) between", "macro-expansion and desugaring: ", st) end end end [K"cfunction" typ fptr rt at sym]->begin @ast g st [K"cfunction"; rec(typ) rec(fptr); [(K"static_eval")(meta = name_hint("cfunction return type")) rec(rt)]; [(K"static_eval")(meta = name_hint("cfunction argument type")) rec(at)]; rec(sym)] end _->begin let out_cs::Vector{NodeId} = map((x->begin (rec(x))._id end), children(st)) if out_cs == children(st) st else mknode(st, out_cs) end end end end return @stm(st, begin [K"Identifier"]->begin let s = st.name_val if s in ("ccall", "cglobal") setattr!(newleaf(g, st, K"core"), :name_val, st.name_val) elseif all((==)('_'), s) setattr!(mkleaf(st), :kind, K"Placeholder") else st end end end (_, when = is_leaf(st))->begin st end ([K"unknown_head" l r], when = begin s = st.name_val Base.isoperator(s) end)->begin let (op_s, out_k) = if s[1] === '.' (s[nextind(s, 1):prevind(s, var"end")], K".op=") else (s[1:prevind(s, var"end")], K"op=") end op_leaf = newleaf(g, st, K"Identifier") JS.copy_attrs!(op_leaf, st) setattr!(op_leaf, :name_val, op_s) @ast g st [out_k rec(l) op_leaf rec(r)] end end [K"comparison" cs0...]->begin let cs = copy(cs0) for (i, c) = enumerate(cs) cs[i] = if iseven(i) _dst_separate_dotop(cs[i]) else rec(cs[i]) end end mknode(st, cs) end end [K"'" x]->begin @ast g st [K"call" "'"::(K"Identifier")(scope_layer = st.scope_layer) rec(x)] end [K"." f [K"tuple" args...]]->begin _expand_literal_pow(@ast(g, st, [K"dotcall" rec(f) _dst_sink_parameters(args)...])) end [K"." l r]->begin let r2 = rec(r) @stm r2 begin [K"inert" r3]->begin @ast g st [K"." rec(l) r3] end r3->begin @ast g st [K"." rec(l) r3] end end end end [K"inert" [K"Identifier"]]->begin @ast g st st[1] => K"Symbol" end [K"inert" _]->begin st end [K"inert_syntaxtree" _]->begin st end [K"module" _...]->begin st end [K"toplevel" _...]->begin st end [K"for" [K"=" _ _] body]->begin @ast g st [K"for" [K"iteration" _dst_eq_to_in(st[1])] rec(body)] end [K"for" [K"block" iters...] body]->begin @ast g st [K"for"; [K"iteration" mapsyntax(_dst_eq_to_in, iters)...]; rec(body)] end ([K"where" t tds...], when = !(length(tds) === 1 && kind(tds[1]) === K"braces"))->begin @ast g st [K"where" rec(t) [K"braces" mapsyntax(rec, tds)...]] end (_, when = begin k = kind(st) k in KSet"tuple vect braces" end)->begin @ast g st [k _dst_sink_parameters(children(st))...] end (_, when = begin k = kind(st) k in KSet"curly ref" end)->begin @ast g st [k _dst_separate_dotop(st[1]); _dst_sink_parameters((children(st))[2:var"end"])...] end [K"call" f args...]->begin let (out_k, out_f) = @stm(_dst_separate_dotop(f), begin [K"." op]->begin (K"dotcall", op) end f_sep->begin (K"call", f_sep) end end) out = @ast(g, st, [out_k; out_f _dst_sink_parameters((children(st))[2:var"end"])...]) _expand_literal_pow(out) end end [K"try" tryb cvar catchb rest...]->begin let has_catch = !(_is_false(cvar) && _is_false(catchb)) cvar_out = if _is_false(cvar) newleaf(g, cvar, K"Placeholder") else rec(cvar) end has_finally = length(rest) >= 1 && !(_is_false(rest[1])) has_else = length(rest) === 2 @ast g st [K"try" rec(tryb); if has_catch [K"catch" cvar_out rec(catchb)] else nothing end; if has_else [K"else" rec(rest[2])] else nothing end; if has_finally [K"finally" rec(rest[1])] else nothing end] end end [K"flatten" _]->begin let out_iters = SyntaxList(st) next = st while kind(next) === K"flatten" push!(out_iters, _dst_iterspec(next, (next[1])[2:var"end"])) next = (next[1])[1] end @assert kind(next) === K"generator" push!(out_iters, _dst_iterspec(next, next[2:var"end"])) @ast g st [K"generator" rec(next[1]) out_iters...] end end [K"generator" body iters...]->begin @ast g st [K"generator" rec(body) _dst_iterspec(st, iters)] end [K"ncat" dim xs...]->begin let out = mknode(st, mapsyntax(rec, xs)) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end [K"nrow" dim xs...]->begin let out = mknode(st, mapsyntax(rec, xs)) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end [K"typed_ncat" t dim xs...]->begin let out_cs = pushfirst!(mapsyntax(rec, xs), rec(t)) out = mknode(st, out_cs) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end ([K"=" l r], when = is_eventually_call(l))->begin if has_if_generated(r) (gen, nongen) = (split_generated(r, true), split_generated(r, false)) @ast g st [K"generated_function" rec(l) gen nongen] else @ast g st [K"function" rec(l) rec(r)] end end [K"function" l r]->begin let if kind(l) === K"..." l = @ast(g, l, [K"tuple" l]) end if has_if_generated(r) (gen, nongen) = (split_generated(r, true), split_generated(r, false)) @ast g st [K"generated_function" rec(l) gen nongen] else @ast g st [K"function" rec(l) rec(r)] end end end [K"do" [K"call" f args...] [K"->" do_args do_body]]->begin let @ast g st [K"call"; rec(f); @ast(g, st[var"end"], [K"do" rec(do_args) rec(do_body)]); _dst_sink_parameters(args)...] end end ([K"let" binds body], when = kind(binds) !== K"block")->begin @ast g st [K"let" [K"block" rec(binds)] rec(body)] end [K"struct" mut sig body]->begin let flags = JS.flags(st) | if _is_false(mut) 0 else JS.MUTABLE_FLAG end @ast g st [(K"struct")(syntax_flags = flags); rec(sig); rec(body)] end end (_, when = kind(st) in KSet"using import")->begin let (paths, maybe_colon) = @stm(st[1], begin [K":" paths...]->begin (paths, st[1]) end _->begin (children(st), nothing) end end) out_cs = mapsyntax(_dst_importpath, paths) if !(isnothing(maybe_colon)) out_c1 = @ast(g, maybe_colon, [K":" out_cs...]) out_cs = SyntaxList(g, tree_ids(out_c1)) end mknode(st, out_cs) end end ([K"meta" [K"unknown_head" ps...]], when = (st[1]).name_val === "purity")->begin @ast g st [K"meta" "purity"::K"Symbol"; Base.EffectsOverride([x.value for x = ps]...)::K"Value"] end ([K"meta" s vs...], when = get(s, :name_val, "") in ("nospecialize", "specialize"))->begin let if length(vs) === 0 @ast g st [K"meta" s => K"Symbol"] elseif length(vs) === 1 out = est_to_dst(vs[1]) setmeta(out, Symbol(s), true) else out_cs = SyntaxList(g) for v = vs push!(out_cs, @ast(g, v, [K"meta" s => K"Symbol" v])) end @ast g st [K"block" out_cs...] end end end [K"meta" syms...]->begin @ast g st [K"meta" mapsyntax((s->begin if kind(s) === K"Identifier" setattr(s, :kind, K"Symbol") else s end end), syms)...;] end [K"inline" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"noinline" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"inbounds" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"core" x]->begin setattr!(mkleaf(st), :name_val, x.name_val) end [K"top" x]->begin setattr!(mkleaf(st), :name_val, x.name_val) end [K"copyast" [K"inert" ex]]->begin @ast g st [K"call"; interpolate_ast::K"Value"; Expr::K"Value"; [K"inert" ex]] end [K"symbolicgoto" lab]->begin setattr!(mkleaf(st), :name_val, lab.name_val) end [K"symboliclabel" lab]->begin setattr!(mkleaf(st), :name_val, lab.name_val) end [K"unknown_head" cs...]->begin let head = st.name_val if head === "latestworld-if-toplevel" newleaf(g, st, K"latestworld_if_toplevel") else @assert false string("unknown expr head (corresponding to no kind) between", "macro-expansion and desugaring: ", st) end end end [K"cfunction" typ fptr rt at sym]->begin @ast g st [K"cfunction"; rec(typ) rec(fptr); [(K"static_eval")(meta = name_hint("cfunction return type")) rec(rt)]; [(K"static_eval")(meta = name_hint("cfunction argument type")) rec(at)]; rec(sym)] end _->begin let out_cs::Vector{NodeId} = map((x->begin (rec(x))._id end), children(st)) if out_cs == children(st) st else mknode(st, out_cs) end end end end) return @stm(st, begin [K"Identifier"]->begin let s = st.name_val if s in ("ccall", "cglobal") setattr!(newleaf(g, st, K"core"), :name_val, st.name_val) elseif all((==)('_'), s) setattr!(mkleaf(st), :kind, K"Placeholder") else st end end end (_, when = is_leaf(st))->begin st end ([K"unknown_head" l r], when = begin s = st.name_val Base.isoperator(s) end)->begin let (op_s, out_k) = if s[1] === '.' (s[nextind(s, 1):prevind(s, var"end")], K".op=") else (s[1:prevind(s, var"end")], K"op=") end op_leaf = newleaf(g, st, K"Identifier") JS.copy_attrs!(op_leaf, st) setattr!(op_leaf, :name_val, op_s) @ast g st [out_k rec(l) op_leaf rec(r)] end end [K"comparison" cs0...]->begin let cs = copy(cs0) for (i, c) = enumerate(cs) cs[i] = if iseven(i) _dst_separate_dotop(cs[i]) else rec(cs[i]) end end mknode(st, cs) end end [K"'" x]->begin @ast g st [K"call" "'"::(K"Identifier")(scope_layer = st.scope_layer) rec(x)] end [K"." f [K"tuple" args...]]->begin _expand_literal_pow(@ast(g, st, [K"dotcall" rec(f) _dst_sink_parameters(args)...])) end [K"." l r]->begin let r2 = rec(r) @stm r2 begin [K"inert" r3]->begin @ast g st [K"." rec(l) r3] end r3->begin @ast g st [K"." rec(l) r3] end end end end [K"inert" [K"Identifier"]]->begin @ast g st st[1] => K"Symbol" end [K"inert" _]->begin st end [K"inert_syntaxtree" _]->begin st end [K"module" _...]->begin st end [K"toplevel" _...]->begin st end [K"for" [K"=" _ _] body]->begin @ast g st [K"for" [K"iteration" _dst_eq_to_in(st[1])] rec(body)] end [K"for" [K"block" iters...] body]->begin @ast g st [K"for"; [K"iteration" mapsyntax(_dst_eq_to_in, iters)...]; rec(body)] end ([K"where" t tds...], when = !(length(tds) === 1 && kind(tds[1]) === K"braces"))->begin @ast g st [K"where" rec(t) [K"braces" mapsyntax(rec, tds)...]] end (_, when = begin k = kind(st) k in KSet"tuple vect braces" end)->begin @ast g st [k _dst_sink_parameters(children(st))...] end (_, when = begin k = kind(st) k in KSet"curly ref" end)->begin @ast g st [k _dst_separate_dotop(st[1]); _dst_sink_parameters((children(st))[2:var"end"])...] end [K"call" f args...]->begin let (out_k, out_f) = @stm(_dst_separate_dotop(f), begin [K"." op]->begin (K"dotcall", op) end f_sep->begin (K"call", f_sep) end end) out = @ast(g, st, [out_k; out_f _dst_sink_parameters((children(st))[2:var"end"])...]) _expand_literal_pow(out) end end [K"try" tryb cvar catchb rest...]->begin let has_catch = !(_is_false(cvar) && _is_false(catchb)) cvar_out = if _is_false(cvar) newleaf(g, cvar, K"Placeholder") else rec(cvar) end has_finally = length(rest) >= 1 && !(_is_false(rest[1])) has_else = length(rest) === 2 @ast g st [K"try" rec(tryb); if has_catch [K"catch" cvar_out rec(catchb)] else nothing end; if has_else [K"else" rec(rest[2])] else nothing end; if has_finally [K"finally" rec(rest[1])] else nothing end] end end [K"flatten" _]->begin let out_iters = SyntaxList(st) next = st while kind(next) === K"flatten" push!(out_iters, _dst_iterspec(next, (next[1])[2:var"end"])) next = (next[1])[1] end @assert kind(next) === K"generator" push!(out_iters, _dst_iterspec(next, next[2:var"end"])) @ast g st [K"generator" rec(next[1]) out_iters...] end end [K"generator" body iters...]->begin @ast g st [K"generator" rec(body) _dst_iterspec(st, iters)] end [K"ncat" dim xs...]->begin let out = mknode(st, mapsyntax(rec, xs)) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end [K"nrow" dim xs...]->begin let out = mknode(st, mapsyntax(rec, xs)) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end [K"typed_ncat" t dim xs...]->begin let out_cs = pushfirst!(mapsyntax(rec, xs), rec(t)) out = mknode(st, out_cs) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end ([K"=" l r], when = is_eventually_call(l))->begin if has_if_generated(r) (gen, nongen) = (split_generated(r, true), split_generated(r, false)) @ast g st [K"generated_function" rec(l) gen nongen] else @ast g st [K"function" rec(l) rec(r)] end end [K"function" l r]->begin let if kind(l) === K"..." l = @ast(g, l, [K"tuple" l]) end if has_if_generated(r) (gen, nongen) = (split_generated(r, true), split_generated(r, false)) @ast g st [K"generated_function" rec(l) gen nongen] else @ast g st [K"function" rec(l) rec(r)] end end end [K"do" [K"call" f args...] [K"->" do_args do_body]]->begin let @ast g st [K"call"; rec(f); @ast(g, st[var"end"], [K"do" rec(do_args) rec(do_body)]); _dst_sink_parameters(args)...] end end ([K"let" binds body], when = kind(binds) !== K"block")->begin @ast g st [K"let" [K"block" rec(binds)] rec(body)] end [K"struct" mut sig body]->begin let flags = JS.flags(st) | if _is_false(mut) 0 else JS.MUTABLE_FLAG end @ast g st [(K"struct")(syntax_flags = flags); rec(sig); rec(body)] end end (_, when = kind(st) in KSet"using import")->begin let (paths, maybe_colon) = @stm(st[1], begin [K":" paths...]->begin (paths, st[1]) end _->begin (children(st), nothing) end end) out_cs = mapsyntax(_dst_importpath, paths) if !(isnothing(maybe_colon)) out_c1 = @ast(g, maybe_colon, [K":" out_cs...]) out_cs = SyntaxList(g, tree_ids(out_c1)) end mknode(st, out_cs) end end ([K"meta" [K"unknown_head" ps...]], when = (st[1]).name_val === "purity")->begin @ast g st [K"meta" "purity"::K"Symbol"; Base.EffectsOverride([x.value for x = ps]...)::K"Value"] end ([K"meta" s vs...], when = get(s, :name_val, "") in ("nospecialize", "specialize"))->begin let if length(vs) === 0 @ast g st [K"meta" s => K"Symbol"] elseif length(vs) === 1 out = est_to_dst(vs[1]) setmeta(out, Symbol(s), true) else out_cs = SyntaxList(g) for v = vs push!(out_cs, @ast(g, v, [K"meta" s => K"Symbol" v])) end @ast g st [K"block" out_cs...] end end end [K"meta" syms...]->begin @ast g st [K"meta" mapsyntax((s->begin if kind(s) === K"Identifier" setattr(s, :kind, K"Symbol") else s end end), syms)...] end [K"inline" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"noinline" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"inbounds" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"core" x]->begin setattr!(mkleaf(st), :name_val, x.name_val) end [K"top" x]->begin setattr!(mkleaf(st), :name_val, x.name_val) end [K"copyast" [K"inert" ex]]->begin @ast g st [K"call"; interpolate_ast::K"Value"; Expr::K"Value"; [K"inert" ex]] end [K"symbolicgoto" lab]->begin setattr!(mkleaf(st), :name_val, lab.name_val) end [K"symboliclabel" lab]->begin setattr!(mkleaf(st), :name_val, lab.name_val) end [K"unknown_head" cs...]->begin let head = st.name_val if head === "latestworld-if-toplevel" newleaf(g, st, K"latestworld_if_toplevel") else @assert false string("unknown expr head (corresponding to no kind) between", "macro-expansion and desugaring: ", st) end end end [K"cfunction" typ fptr rt at sym]->begin @ast g st [K"cfunction"; rec(typ) rec(fptr); [(K"static_eval")(meta = name_hint("cfunction return type")) rec(rt)]; [(K"static_eval")(meta = name_hint("cfunction argument type")) rec(at)]; rec(sym)] end _->begin let out_cs::Vector{NodeId} = map((x->begin (rec(x))._id end), children(st)) if out_cs == children(st) st else mknode(st, out_cs) end end end end) begin g = st._graph rec = @__FUNCTION__() return @stm(st, begin [K"Identifier"]->begin let s = st.name_val if s in ("ccall", "cglobal") setattr!(newleaf(g, st, K"core"), :name_val, st.name_val) elseif all((==)('_'), s) setattr!(mkleaf(st), :kind, K"Placeholder") else st end end end (_, when = is_leaf(st))->begin st end ([K"unknown_head" l r], when = begin s = st.name_val Base.isoperator(s) end)->begin let (op_s, out_k) = if s[1] === '.' (s[nextind(s, 1):prevind(s, var"end")], K".op=") else (s[1:prevind(s, var"end")], K"op=") end op_leaf = newleaf(g, st, K"Identifier") JS.copy_attrs!(op_leaf, st) setattr!(op_leaf, :name_val, op_s) @ast g st [out_k rec(l) op_leaf rec(r)] end end [K"comparison" cs0...]->begin let cs = copy(cs0) for (i, c) = enumerate(cs) cs[i] = if iseven(i) _dst_separate_dotop(cs[i]) else rec(cs[i]) end end mknode(st, cs) end end [K"'" x]->begin @ast g st [K"call" "'"::(K"Identifier")(scope_layer = st.scope_layer) rec(x)] end [K"." f [K"tuple" args...]]->begin _expand_literal_pow(@ast(g, st, [K"dotcall" rec(f) _dst_sink_parameters(args)...])) end [K"." l r]->begin let r2 = rec(r) @stm r2 begin [K"inert" r3]->begin @ast g st [K"." rec(l) r3] end r3->begin @ast g st [K"." rec(l) r3] end end end end [K"inert" [K"Identifier"]]->begin @ast g st st[1] => K"Symbol" end [K"inert" _]->begin st end [K"inert_syntaxtree" _]->begin st end [K"module" _...]->begin st end [K"toplevel" _...]->begin st end [K"for" [K"=" _ _] body]->begin @ast g st [K"for" [K"iteration" _dst_eq_to_in(st[1])] rec(body)] end [K"for" [K"block" iters...] body]->begin @ast g st [K"for"; [K"iteration" mapsyntax(_dst_eq_to_in, iters)...]; rec(body)] end ([K"where" t tds...], when = !(length(tds) === 1 && kind(tds[1]) === K"braces"))->begin @ast g st [K"where" rec(t) [K"braces" mapsyntax(rec, tds)...]] end (_, when = begin k = kind(st) k in KSet"tuple vect braces" end)->begin @ast g st [k _dst_sink_parameters(children(st))...] end (_, when = begin k = kind(st) k in KSet"curly ref" end)->begin @ast g st [k _dst_separate_dotop(st[1]); _dst_sink_parameters((children(st))[2:var"end"])...] end [K"call" f args...]->begin let (out_k, out_f) = @stm(_dst_separate_dotop(f), begin [K"." op]->begin (K"dotcall", op) end f_sep->begin (K"call", f_sep) end end) out = @ast(g, st, [out_k; out_f _dst_sink_parameters((children(st))[2:var"end"])...]) _expand_literal_pow(out) end end [K"try" tryb cvar catchb rest...]->begin let has_catch = !(_is_false(cvar) && _is_false(catchb)) cvar_out = if _is_false(cvar) newleaf(g, cvar, K"Placeholder") else rec(cvar) end has_finally = length(rest) >= 1 && !(_is_false(rest[1])) has_else = length(rest) === 2 @ast g st [K"try" rec(tryb); if has_catch [K"catch" cvar_out rec(catchb)] else nothing end; if has_else [K"else" rec(rest[2])] else nothing end; if has_finally [K"finally" rec(rest[1])] else nothing end] end end [K"flatten" _]->begin let out_iters = SyntaxList(st) next = st while kind(next) === K"flatten" push!(out_iters, _dst_iterspec(next, (next[1])[2:var"end"])) next = (next[1])[1] end @assert kind(next) === K"generator" push!(out_iters, _dst_iterspec(next, next[2:var"end"])) @ast g st [K"generator" rec(next[1]) out_iters...] end end [K"generator" body iters...]->begin @ast g st [K"generator" rec(body) _dst_iterspec(st, iters)] end [K"ncat" dim xs...]->begin let out = mknode(st, mapsyntax(rec, xs)) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end [K"nrow" dim xs...]->begin let out = mknode(st, mapsyntax(rec, xs)) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end [K"typed_ncat" t dim xs...]->begin let out_cs = pushfirst!(mapsyntax(rec, xs), rec(t)) out = mknode(st, out_cs) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end ([K"=" l r], when = is_eventually_call(l))->begin if has_if_generated(r) (gen, nongen) = (split_generated(r, true), split_generated(r, false)) @ast g st [K"generated_function" rec(l) gen nongen] else @ast g st [K"function" rec(l) rec(r)] end end [K"function" l r]->begin let if kind(l) === K"..." l = @ast(g, l, [K"tuple" l]) end if has_if_generated(r) (gen, nongen) = (split_generated(r, true), split_generated(r, false)) @ast g st [K"generated_function" rec(l) gen nongen] else @ast g st [K"function" rec(l) rec(r)] end end end [K"do" [K"call" f args...] [K"->" do_args do_body]]->begin let @ast g st [K"call"; rec(f); @ast(g, st[var"end"], [K"do" rec(do_args) rec(do_body)]); _dst_sink_parameters(args)...] end end ([K"let" binds body], when = kind(binds) !== K"block")->begin @ast g st [K"let" [K"block" rec(binds)] rec(body)] end [K"struct" mut sig body]->begin let flags = JS.flags(st) | if _is_false(mut) 0 else JS.MUTABLE_FLAG end @ast g st [(K"struct")(syntax_flags = flags); rec(sig); rec(body)] end end (_, when = kind(st) in KSet"using import")->begin let (paths, maybe_colon) = @stm(st[1], begin [K":" paths...]->begin (paths, st[1]) end _->begin (children(st), nothing) end end) out_cs = mapsyntax(_dst_importpath, paths) if !(isnothing(maybe_colon)) out_c1 = @ast(g, maybe_colon, [K":" out_cs...]) out_cs = SyntaxList(g, tree_ids(out_c1)) end mknode(st, out_cs) end end ([K"meta" [K"unknown_head" ps...]], when = (st[1]).name_val === "purity")->begin @ast g st [K"meta" "purity"::K"Symbol"; Base.EffectsOverride([x.value for x = ps]...)::K"Value"] end ([K"meta" s vs...], when = get(s, :name_val, "") in ("nospecialize", "specialize"))->begin let if length(vs) === 0 @ast g st [K"meta" s => K"Symbol"] elseif length(vs) === 1 out = est_to_dst(vs[1]) setmeta(out, Symbol(s), true) else out_cs = SyntaxList(g) for v = vs push!(out_cs, @ast(g, v, [K"meta" s => K"Symbol" v])) end @ast g st [K"block" out_cs...] end end end [K"meta" syms...]->begin @ast g st [K"meta" mapsyntax((s->begin if kind(s) === K"Identifier" setattr(s, :kind, K"Symbol") else s end end), syms)...;] end [K"inline" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"noinline" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"inbounds" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"core" x]->begin setattr!(mkleaf(st), :name_val, x.name_val) end [K"top" x]->begin setattr!(mkleaf(st), :name_val, x.name_val) end [K"copyast" [K"inert" ex]]->begin @ast g st [K"call"; interpolate_ast::K"Value"; Expr::K"Value"; [K"inert" ex]] end [K"symbolicgoto" lab]->begin setattr!(mkleaf(st), :name_val, lab.name_val) end [K"symboliclabel" lab]->begin setattr!(mkleaf(st), :name_val, lab.name_val) end [K"unknown_head" cs...]->begin let head = st.name_val if head === "latestworld-if-toplevel" newleaf(g, st, K"latestworld_if_toplevel") else @assert false string("unknown expr head (corresponding to no kind) between", "macro-expansion and desugaring: ", st) end end end [K"cfunction" typ fptr rt at sym]->begin @ast g st [K"cfunction"; rec(typ) rec(fptr); [(K"static_eval")(meta = name_hint("cfunction return type")) rec(rt)]; [(K"static_eval")(meta = name_hint("cfunction argument type")) rec(at)]; rec(sym)] end _->begin let out_cs::Vector{NodeId} = map((x->begin (rec(x))._id end), children(st)) if out_cs == children(st) st else mknode(st, out_cs) end end end end) end begin g = st._graph rec = @__FUNCTION__() return @stm(st, begin [K"Identifier"]->begin let s = st.name_val if s in ("ccall", "cglobal") setattr!(newleaf(g, st, K"core"), :name_val, st.name_val) elseif all((==)('_'), s) setattr!(mkleaf(st), :kind, K"Placeholder") else st end end end (_, when = is_leaf(st))->begin st end ([K"unknown_head" l r], when = begin s = st.name_val Base.isoperator(s) end)->begin let (op_s, out_k) = if s[1] === '.' (s[nextind(s, 1):prevind(s, var"end")], K".op=") else (s[1:prevind(s, var"end")], K"op=") end op_leaf = newleaf(g, st, K"Identifier") JS.copy_attrs!(op_leaf, st) setattr!(op_leaf, :name_val, op_s) @ast g st [out_k rec(l) op_leaf rec(r)] end end [K"comparison" cs0...]->begin let cs = copy(cs0) for (i, c) = enumerate(cs) cs[i] = if iseven(i) _dst_separate_dotop(cs[i]) else rec(cs[i]) end end mknode(st, cs) end end [K"'" x]->begin @ast g st [K"call" "'"::(K"Identifier")(scope_layer = st.scope_layer) rec(x)] end [K"." f [K"tuple" args...]]->begin _expand_literal_pow(@ast(g, st, [K"dotcall" rec(f) _dst_sink_parameters(args)...])) end [K"." l r]->begin let r2 = rec(r) @stm r2 begin [K"inert" r3]->begin @ast g st [K"." rec(l) r3] end r3->begin @ast g st [K"." rec(l) r3] end end end end [K"inert" [K"Identifier"]]->begin @ast g st st[1] => K"Symbol" end [K"inert" _]->begin st end [K"inert_syntaxtree" _]->begin st end [K"module" _...]->begin st end [K"toplevel" _...]->begin st end [K"for" [K"=" _ _] body]->begin @ast g st [K"for" [K"iteration" _dst_eq_to_in(st[1])] rec(body)] end [K"for" [K"block" iters...] body]->begin @ast g st [K"for"; [K"iteration" mapsyntax(_dst_eq_to_in, iters)...]; rec(body)] end ([K"where" t tds...], when = !(length(tds) === 1 && kind(tds[1]) === K"braces"))->begin @ast g st [K"where" rec(t) [K"braces" mapsyntax(rec, tds)...]] end (_, when = begin k = kind(st) k in KSet"tuple vect braces" end)->begin @ast g st [k _dst_sink_parameters(children(st))...] end (_, when = begin k = kind(st) k in KSet"curly ref" end)->begin @ast g st [k _dst_separate_dotop(st[1]); _dst_sink_parameters((children(st))[2:var"end"])...] end [K"call" f args...]->begin let (out_k, out_f) = @stm(_dst_separate_dotop(f), begin [K"." op]->begin (K"dotcall", op) end f_sep->begin (K"call", f_sep) end end) out = @ast(g, st, [out_k; out_f _dst_sink_parameters((children(st))[2:var"end"])...]) _expand_literal_pow(out) end end [K"try" tryb cvar catchb rest...]->begin let has_catch = !(_is_false(cvar) && _is_false(catchb)) cvar_out = if _is_false(cvar) newleaf(g, cvar, K"Placeholder") else rec(cvar) end has_finally = length(rest) >= 1 && !(_is_false(rest[1])) has_else = length(rest) === 2 @ast g st [K"try" rec(tryb); if has_catch [K"catch" cvar_out rec(catchb)] else nothing end; if has_else [K"else" rec(rest[2])] else nothing end; if has_finally [K"finally" rec(rest[1])] else nothing end] end end [K"flatten" _]->begin let out_iters = SyntaxList(st) next = st while kind(next) === K"flatten" push!(out_iters, _dst_iterspec(next, (next[1])[2:var"end"])) next = (next[1])[1] end @assert kind(next) === K"generator" push!(out_iters, _dst_iterspec(next, next[2:var"end"])) @ast g st [K"generator" rec(next[1]) out_iters...] end end [K"generator" body iters...]->begin @ast g st [K"generator" rec(body) _dst_iterspec(st, iters)] end [K"ncat" dim xs...]->begin let out = mknode(st, mapsyntax(rec, xs)) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end [K"nrow" dim xs...]->begin let out = mknode(st, mapsyntax(rec, xs)) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end [K"typed_ncat" t dim xs...]->begin let out_cs = pushfirst!(mapsyntax(rec, xs), rec(t)) out = mknode(st, out_cs) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end ([K"=" l r], when = is_eventually_call(l))->begin if has_if_generated(r) (gen, nongen) = (split_generated(r, true), split_generated(r, false)) @ast g st [K"generated_function" rec(l) gen nongen] else @ast g st [K"function" rec(l) rec(r)] end end [K"function" l r]->begin let if kind(l) === K"..." l = @ast(g, l, [K"tuple" l]) end if has_if_generated(r) (gen, nongen) = (split_generated(r, true), split_generated(r, false)) @ast g st [K"generated_function" rec(l) gen nongen] else @ast g st [K"function" rec(l) rec(r)] end end end [K"do" [K"call" f args...] [K"->" do_args do_body]]->begin let @ast g st [K"call"; rec(f); @ast(g, st[var"end"], [K"do" rec(do_args) rec(do_body)]); _dst_sink_parameters(args)...] end end ([K"let" binds body], when = kind(binds) !== K"block")->begin @ast g st [K"let" [K"block" rec(binds)] rec(body)] end [K"struct" mut sig body]->begin let flags = JS.flags(st) | if _is_false(mut) 0 else JS.MUTABLE_FLAG end @ast g st [(K"struct")(syntax_flags = flags); rec(sig); rec(body)] end end (_, when = kind(st) in KSet"using import")->begin let (paths, maybe_colon) = @stm(st[1], begin [K":" paths...]->begin (paths, st[1]) end _->begin (children(st), nothing) end end) out_cs = mapsyntax(_dst_importpath, paths) if !(isnothing(maybe_colon)) out_c1 = @ast(g, maybe_colon, [K":" out_cs...]) out_cs = SyntaxList(g, tree_ids(out_c1)) end mknode(st, out_cs) end end ([K"meta" [K"unknown_head" ps...]], when = (st[1]).name_val === "purity")->begin @ast g st [K"meta" "purity"::K"Symbol"; Base.EffectsOverride([x.value for x = ps]...)::K"Value"] end ([K"meta" s vs...], when = get(s, :name_val, "") in ("nospecialize", "specialize"))->begin let if length(vs) === 0 @ast g st [K"meta" s => K"Symbol"] elseif length(vs) === 1 out = est_to_dst(vs[1]) setmeta(out, Symbol(s), true) else out_cs = SyntaxList(g) for v = vs push!(out_cs, @ast(g, v, [K"meta" s => K"Symbol" v])) end @ast g st [K"block" out_cs...] end end end [K"meta" syms...]->begin @ast g st [K"meta" mapsyntax((s->begin if kind(s) === K"Identifier" setattr(s, :kind, K"Symbol") else s end end), syms)...] end [K"inline" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"noinline" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"inbounds" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"core" x]->begin setattr!(mkleaf(st), :name_val, x.name_val) end [K"top" x]->begin setattr!(mkleaf(st), :name_val, x.name_val) end [K"copyast" [K"inert" ex]]->begin @ast g st [K"call"; interpolate_ast::K"Value"; Expr::K"Value"; [K"inert" ex]] end [K"symbolicgoto" lab]->begin setattr!(mkleaf(st), :name_val, lab.name_val) end [K"symboliclabel" lab]->begin setattr!(mkleaf(st), :name_val, lab.name_val) end [K"unknown_head" cs...]->begin let head = st.name_val if head === "latestworld-if-toplevel" newleaf(g, st, K"latestworld_if_toplevel") else @assert false string("unknown expr head (corresponding to no kind) between", "macro-expansion and desugaring: ", st) end end end [K"cfunction" typ fptr rt at sym]->begin @ast g st [K"cfunction"; rec(typ) rec(fptr); [(K"static_eval")(meta = name_hint("cfunction return type")) rec(rt)]; [(K"static_eval")(meta = name_hint("cfunction argument type")) rec(at)]; rec(sym)] end _->begin let out_cs::Vector{NodeId} = map((x->begin (rec(x))._id end), children(st)) if out_cs == children(st) st else mknode(st, out_cs) end end end end) end function est_to_dst(st::SyntaxTree; all_expanded = true) g = st._graph rec = @__FUNCTION__() return @stm(st, begin [K"Identifier"]->begin let s = st.name_val if s in ("ccall", "cglobal") setattr!(newleaf(g, st, K"core"), :name_val, st.name_val) elseif all((==)('_'), s) setattr!(mkleaf(st), :kind, K"Placeholder") else st end end end (_, when = is_leaf(st))->begin st end ([K"unknown_head" l r], when = begin s = st.name_val Base.isoperator(s) end)->begin let (op_s, out_k) = if s[1] === '.' (s[nextind(s, 1):prevind(s, var"end")], K".op=") else (s[1:prevind(s, var"end")], K"op=") end op_leaf = newleaf(g, st, K"Identifier") JS.copy_attrs!(op_leaf, st) setattr!(op_leaf, :name_val, op_s) @ast g st [out_k rec(l) op_leaf rec(r)] end end [K"comparison" cs0...]->begin let cs = copy(cs0) for (i, c) = enumerate(cs) cs[i] = if iseven(i) _dst_separate_dotop(cs[i]) else rec(cs[i]) end end mknode(st, cs) end end [K"'" x]->begin @ast g st [K"call" "'"::(K"Identifier")(scope_layer = st.scope_layer) rec(x)] end [K"." f [K"tuple" args...]]->begin _expand_literal_pow(@ast(g, st, [K"dotcall" rec(f) _dst_sink_parameters(args)...])) end [K"." l r]->begin let r2 = rec(r) @stm r2 begin [K"inert" r3]->begin @ast g st [K"." rec(l) r3] end r3->begin @ast g st [K"." rec(l) r3] end end end end [K"inert" [K"Identifier"]]->begin @ast g st st[1] => K"Symbol" end [K"inert" _]->begin st end [K"inert_syntaxtree" _]->begin st end [K"module" _...]->begin st end [K"toplevel" _...]->begin st end [K"for" [K"=" _ _] body]->begin @ast g st [K"for" [K"iteration" _dst_eq_to_in(st[1])] rec(body)] end [K"for" [K"block" iters...] body]->begin @ast g st [K"for"; [K"iteration" mapsyntax(_dst_eq_to_in, iters)...]; rec(body)] end ([K"where" t tds...], when = !(length(tds) === 1 && kind(tds[1]) === K"braces"))->begin @ast g st [K"where" rec(t) [K"braces" mapsyntax(rec, tds)...]] end (_, when = begin k = kind(st) k in KSet"tuple vect braces" end)->begin @ast g st [k _dst_sink_parameters(children(st))...] end (_, when = begin k = kind(st) k in KSet"curly ref" end)->begin @ast g st [k _dst_separate_dotop(st[1]); _dst_sink_parameters((children(st))[2:var"end"])...] end [K"call" f args...]->begin let (out_k, out_f) = @stm(_dst_separate_dotop(f), begin [K"." op]->begin (K"dotcall", op) end f_sep->begin (K"call", f_sep) end end) out = @ast(g, st, [out_k; out_f _dst_sink_parameters((children(st))[2:var"end"])...]) _expand_literal_pow(out) end end [K"try" tryb cvar catchb rest...]->begin let has_catch = !(_is_false(cvar) && _is_false(catchb)) cvar_out = if _is_false(cvar) newleaf(g, cvar, K"Placeholder") else rec(cvar) end has_finally = length(rest) >= 1 && !(_is_false(rest[1])) has_else = length(rest) === 2 @ast g st [K"try" rec(tryb); if has_catch [K"catch" cvar_out rec(catchb)] else nothing end; if has_else [K"else" rec(rest[2])] else nothing end; if has_finally [K"finally" rec(rest[1])] else nothing end] end end [K"flatten" _]->begin let out_iters = SyntaxList(st) next = st while kind(next) === K"flatten" push!(out_iters, _dst_iterspec(next, (next[1])[2:var"end"])) next = (next[1])[1] end @assert kind(next) === K"generator" push!(out_iters, _dst_iterspec(next, next[2:var"end"])) @ast g st [K"generator" rec(next[1]) out_iters...] end end [K"generator" body iters...]->begin @ast g st [K"generator" rec(body) _dst_iterspec(st, iters)] end [K"ncat" dim xs...]->begin let out = mknode(st, mapsyntax(rec, xs)) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end [K"nrow" dim xs...]->begin let out = mknode(st, mapsyntax(rec, xs)) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end [K"typed_ncat" t dim xs...]->begin let out_cs = pushfirst!(mapsyntax(rec, xs), rec(t)) out = mknode(st, out_cs) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end ([K"=" l r], when = is_eventually_call(l))->begin if has_if_generated(r) (gen, nongen) = (split_generated(r, true), split_generated(r, false)) @ast g st [K"generated_function" rec(l) gen nongen] else @ast g st [K"function" rec(l) rec(r)] end end [K"function" l r]->begin let if kind(l) === K"..." l = @ast(g, l, [K"tuple" l]) end if has_if_generated(r) (gen, nongen) = (split_generated(r, true), split_generated(r, false)) @ast g st [K"generated_function" rec(l) gen nongen] else @ast g st [K"function" rec(l) rec(r)] end end end [K"do" [K"call" f args...] [K"->" do_args do_body]]->begin let @ast g st [K"call"; rec(f); @ast(g, st[var"end"], [K"do" rec(do_args) rec(do_body)]); _dst_sink_parameters(args)...] end end ([K"let" binds body], when = kind(binds) !== K"block")->begin @ast g st [K"let" [K"block" rec(binds)] rec(body)] end [K"struct" mut sig body]->begin let flags = JS.flags(st) | if _is_false(mut) 0 else JS.MUTABLE_FLAG end @ast g st [(K"struct")(syntax_flags = flags); rec(sig); rec(body)] end end (_, when = kind(st) in KSet"using import")->begin let (paths, maybe_colon) = @stm(st[1], begin [K":" paths...]->begin (paths, st[1]) end _->begin (children(st), nothing) end end) out_cs = mapsyntax(_dst_importpath, paths) if !(isnothing(maybe_colon)) out_c1 = @ast(g, maybe_colon, [K":" out_cs...]) out_cs = SyntaxList(g, tree_ids(out_c1)) end mknode(st, out_cs) end end ([K"meta" [K"unknown_head" ps...]], when = (st[1]).name_val === "purity")->begin @ast g st [K"meta" "purity"::K"Symbol"; Base.EffectsOverride([x.value for x = ps]...)::K"Value"] end ([K"meta" s vs...], when = get(s, :name_val, "") in ("nospecialize", "specialize"))->begin let if length(vs) === 0 @ast g st [K"meta" s => K"Symbol"] elseif length(vs) === 1 out = est_to_dst(vs[1]) setmeta(out, Symbol(s), true) else out_cs = SyntaxList(g) for v = vs push!(out_cs, @ast(g, v, [K"meta" s => K"Symbol" v])) end @ast g st [K"block" out_cs...] end end end [K"meta" syms...]->begin @ast g st [K"meta" mapsyntax((s->begin if kind(s) === K"Identifier" setattr(s, :kind, K"Symbol") else s end end), syms)...;] end [K"inline" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"noinline" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"inbounds" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"core" x]->begin setattr!(mkleaf(st), :name_val, x.name_val) end [K"top" x]->begin setattr!(mkleaf(st), :name_val, x.name_val) end [K"copyast" [K"inert" ex]]->begin @ast g st [K"call"; interpolate_ast::K"Value"; Expr::K"Value"; [K"inert" ex]] end [K"symbolicgoto" lab]->begin setattr!(mkleaf(st), :name_val, lab.name_val) end [K"symboliclabel" lab]->begin setattr!(mkleaf(st), :name_val, lab.name_val) end [K"unknown_head" cs...]->begin let head = st.name_val if head === "latestworld-if-toplevel" newleaf(g, st, K"latestworld_if_toplevel") else @assert false string("unknown expr head (corresponding to no kind) between", "macro-expansion and desugaring: ", st) end end end [K"cfunction" typ fptr rt at sym]->begin @ast g st [K"cfunction"; rec(typ) rec(fptr); [(K"static_eval")(meta = name_hint("cfunction return type")) rec(rt)]; [(K"static_eval")(meta = name_hint("cfunction argument type")) rec(at)]; rec(sym)] end _->begin let out_cs::Vector{NodeId} = map((x->begin (rec(x))._id end), children(st)) if out_cs == children(st) st else mknode(st, out_cs) end end end end) end function est_to_dst(st::SyntaxTree; all_expanded = true) g = st._graph rec = @__FUNCTION__() return @stm(st, begin [K"Identifier"]->begin let s = st.name_val if s in ("ccall", "cglobal") setattr!(newleaf(g, st, K"core"), :name_val, st.name_val) elseif all((==)('_'), s) setattr!(mkleaf(st), :kind, K"Placeholder") else st end end end (_, when = is_leaf(st))->begin st end ([K"unknown_head" l r], when = begin s = st.name_val Base.isoperator(s) end)->begin let (op_s, out_k) = if s[1] === '.' (s[nextind(s, 1):prevind(s, var"end")], K".op=") else (s[1:prevind(s, var"end")], K"op=") end op_leaf = newleaf(g, st, K"Identifier") JS.copy_attrs!(op_leaf, st) setattr!(op_leaf, :name_val, op_s) @ast g st [out_k rec(l) op_leaf rec(r)] end end [K"comparison" cs0...]->begin let cs = copy(cs0) for (i, c) = enumerate(cs) cs[i] = if iseven(i) _dst_separate_dotop(cs[i]) else rec(cs[i]) end end mknode(st, cs) end end [K"'" x]->begin @ast g st [K"call" "'"::(K"Identifier")(scope_layer = st.scope_layer) rec(x)] end [K"." f [K"tuple" args...]]->begin _expand_literal_pow(@ast(g, st, [K"dotcall" rec(f) _dst_sink_parameters(args)...])) end [K"." l r]->begin let r2 = rec(r) @stm r2 begin [K"inert" r3]->begin @ast g st [K"." rec(l) r3] end r3->begin @ast g st [K"." rec(l) r3] end end end end [K"inert" [K"Identifier"]]->begin @ast g st st[1] => K"Symbol" end [K"inert" _]->begin st end [K"inert_syntaxtree" _]->begin st end [K"module" _...]->begin st end [K"toplevel" _...]->begin st end [K"for" [K"=" _ _] body]->begin @ast g st [K"for" [K"iteration" _dst_eq_to_in(st[1])] rec(body)] end [K"for" [K"block" iters...] body]->begin @ast g st [K"for"; [K"iteration" mapsyntax(_dst_eq_to_in, iters)...]; rec(body)] end ([K"where" t tds...], when = !(length(tds) === 1 && kind(tds[1]) === K"braces"))->begin @ast g st [K"where" rec(t) [K"braces" mapsyntax(rec, tds)...]] end (_, when = begin k = kind(st) k in KSet"tuple vect braces" end)->begin @ast g st [k _dst_sink_parameters(children(st))...] end (_, when = begin k = kind(st) k in KSet"curly ref" end)->begin @ast g st [k _dst_separate_dotop(st[1]); _dst_sink_parameters((children(st))[2:var"end"])...] end [K"call" f args...]->begin let (out_k, out_f) = @stm(_dst_separate_dotop(f), begin [K"." op]->begin (K"dotcall", op) end f_sep->begin (K"call", f_sep) end end) out = @ast(g, st, [out_k; out_f _dst_sink_parameters((children(st))[2:var"end"])...]) _expand_literal_pow(out) end end [K"try" tryb cvar catchb rest...]->begin let has_catch = !(_is_false(cvar) && _is_false(catchb)) cvar_out = if _is_false(cvar) newleaf(g, cvar, K"Placeholder") else rec(cvar) end has_finally = length(rest) >= 1 && !(_is_false(rest[1])) has_else = length(rest) === 2 @ast g st [K"try" rec(tryb); if has_catch [K"catch" cvar_out rec(catchb)] else nothing end; if has_else [K"else" rec(rest[2])] else nothing end; if has_finally [K"finally" rec(rest[1])] else nothing end] end end [K"flatten" _]->begin let out_iters = SyntaxList(st) next = st while kind(next) === K"flatten" push!(out_iters, _dst_iterspec(next, (next[1])[2:var"end"])) next = (next[1])[1] end @assert kind(next) === K"generator" push!(out_iters, _dst_iterspec(next, next[2:var"end"])) @ast g st [K"generator" rec(next[1]) out_iters...] end end [K"generator" body iters...]->begin @ast g st [K"generator" rec(body) _dst_iterspec(st, iters)] end [K"ncat" dim xs...]->begin let out = mknode(st, mapsyntax(rec, xs)) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end [K"nrow" dim xs...]->begin let out = mknode(st, mapsyntax(rec, xs)) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end [K"typed_ncat" t dim xs...]->begin let out_cs = pushfirst!(mapsyntax(rec, xs), rec(t)) out = mknode(st, out_cs) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end ([K"=" l r], when = is_eventually_call(l))->begin if has_if_generated(r) (gen, nongen) = (split_generated(r, true), split_generated(r, false)) @ast g st [K"generated_function" rec(l) gen nongen] else @ast g st [K"function" rec(l) rec(r)] end end [K"function" l r]->begin let if kind(l) === K"..." l = @ast(g, l, [K"tuple" l]) end if has_if_generated(r) (gen, nongen) = (split_generated(r, true), split_generated(r, false)) @ast g st [K"generated_function" rec(l) gen nongen] else @ast g st [K"function" rec(l) rec(r)] end end end [K"do" [K"call" f args...] [K"->" do_args do_body]]->begin let @ast g st [K"call"; rec(f); @ast(g, st[var"end"], [K"do" rec(do_args) rec(do_body)]); _dst_sink_parameters(args)...] end end ([K"let" binds body], when = kind(binds) !== K"block")->begin @ast g st [K"let" [K"block" rec(binds)] rec(body)] end [K"struct" mut sig body]->begin let flags = JS.flags(st) | if _is_false(mut) 0 else JS.MUTABLE_FLAG end @ast g st [(K"struct")(syntax_flags = flags); rec(sig); rec(body)] end end (_, when = kind(st) in KSet"using import")->begin let (paths, maybe_colon) = @stm(st[1], begin [K":" paths...]->begin (paths, st[1]) end _->begin (children(st), nothing) end end) out_cs = mapsyntax(_dst_importpath, paths) if !(isnothing(maybe_colon)) out_c1 = @ast(g, maybe_colon, [K":" out_cs...]) out_cs = SyntaxList(g, tree_ids(out_c1)) end mknode(st, out_cs) end end ([K"meta" [K"unknown_head" ps...]], when = (st[1]).name_val === "purity")->begin @ast g st [K"meta" "purity"::K"Symbol"; Base.EffectsOverride([x.value for x = ps]...)::K"Value"] end ([K"meta" s vs...], when = get(s, :name_val, "") in ("nospecialize", "specialize"))->begin let if length(vs) === 0 @ast g st [K"meta" s => K"Symbol"] elseif length(vs) === 1 out = est_to_dst(vs[1]) setmeta(out, Symbol(s), true) else out_cs = SyntaxList(g) for v = vs push!(out_cs, @ast(g, v, [K"meta" s => K"Symbol" v])) end @ast g st [K"block" out_cs...] end end end [K"meta" syms...]->begin @ast g st [K"meta" mapsyntax((s->begin if kind(s) === K"Identifier" setattr(s, :kind, K"Symbol") else s end end), syms)...] end [K"inline" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"noinline" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"inbounds" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"core" x]->begin setattr!(mkleaf(st), :name_val, x.name_val) end [K"top" x]->begin setattr!(mkleaf(st), :name_val, x.name_val) end [K"copyast" [K"inert" ex]]->begin @ast g st [K"call"; interpolate_ast::K"Value"; Expr::K"Value"; [K"inert" ex]] end [K"symbolicgoto" lab]->begin setattr!(mkleaf(st), :name_val, lab.name_val) end [K"symboliclabel" lab]->begin setattr!(mkleaf(st), :name_val, lab.name_val) end [K"unknown_head" cs...]->begin let head = st.name_val if head === "latestworld-if-toplevel" newleaf(g, st, K"latestworld_if_toplevel") else @assert false string("unknown expr head (corresponding to no kind) between", "macro-expansion and desugaring: ", st) end end end [K"cfunction" typ fptr rt at sym]->begin @ast g st [K"cfunction"; rec(typ) rec(fptr); [(K"static_eval")(meta = name_hint("cfunction return type")) rec(rt)]; [(K"static_eval")(meta = name_hint("cfunction argument type")) rec(at)]; rec(sym)] end _->begin let out_cs::Vector{NodeId} = map((x->begin (rec(x))._id end), children(st)) if out_cs == children(st) st else mknode(st, out_cs) end end end end) end Core.@doc "Convert the Expr-like tree (EST) coming from macro expansion to the tree\ndesugaring expects (DST), where some forms have SyntaxNode structure and others\nhave Expr structure.\n\nWe may drop cases from this conversion, for example, if...\n\n- syntax evolution changes a form in Expr and EST to use DST structure, so the\n input we receive here is \"already done\"\n\n- desugaring changes to accept the EST form instead of the DST one, so we can\n leave our input unchanged\n\nWe can assume `st` has passed `valid_st1`. Errors arising from invalid AST\n(including finding `macrocall/escape/quote` forms) should be handled there.\n" function est_to_dst(st::SyntaxTree; all_expanded = true) g = st._graph rec = @__FUNCTION__() return @stm(st, begin [K"Identifier"]->begin let s = st.name_val if s in ("ccall", "cglobal") setattr!(newleaf(g, st, K"core"), :name_val, st.name_val) elseif all((==)('_'), s) setattr!(mkleaf(st), :kind, K"Placeholder") else st end end end (_, when = is_leaf(st))->begin st end ([K"unknown_head" l r], when = begin s = st.name_val Base.isoperator(s) end)->begin let (op_s, out_k) = if s[1] === '.' (s[nextind(s, 1):prevind(s, var"end")], K".op=") else (s[1:prevind(s, var"end")], K"op=") end op_leaf = newleaf(g, st, K"Identifier") JS.copy_attrs!(op_leaf, st) setattr!(op_leaf, :name_val, op_s) @ast g st [out_k rec(l) op_leaf rec(r)] end end [K"comparison" cs0...]->begin let cs = copy(cs0) for (i, c) = enumerate(cs) cs[i] = if iseven(i) _dst_separate_dotop(cs[i]) else rec(cs[i]) end end mknode(st, cs) end end [K"'" x]->begin @ast g st [K"call" "'"::(K"Identifier")(scope_layer = st.scope_layer) rec(x)] end [K"." f [K"tuple" args...]]->begin _expand_literal_pow(@ast(g, st, [K"dotcall" rec(f) _dst_sink_parameters(args)...])) end [K"." l r]->begin let r2 = rec(r) @stm r2 begin [K"inert" r3]->begin @ast g st [K"." rec(l) r3] end r3->begin @ast g st [K"." rec(l) r3] end end end end [K"inert" [K"Identifier"]]->begin @ast g st st[1] => K"Symbol" end [K"inert" _]->begin st end [K"inert_syntaxtree" _]->begin st end [K"module" _...]->begin st end [K"toplevel" _...]->begin st end [K"for" [K"=" _ _] body]->begin @ast g st [K"for" [K"iteration" _dst_eq_to_in(st[1])] rec(body)] end [K"for" [K"block" iters...] body]->begin @ast g st [K"for"; [K"iteration" mapsyntax(_dst_eq_to_in, iters)...]; rec(body)] end ([K"where" t tds...], when = !(length(tds) === 1 && kind(tds[1]) === K"braces"))->begin @ast g st [K"where" rec(t) [K"braces" mapsyntax(rec, tds)...]] end (_, when = begin k = kind(st) k in KSet"tuple vect braces" end)->begin @ast g st [k _dst_sink_parameters(children(st))...] end (_, when = begin k = kind(st) k in KSet"curly ref" end)->begin @ast g st [k _dst_separate_dotop(st[1]); _dst_sink_parameters((children(st))[2:var"end"])...] end [K"call" f args...]->begin let (out_k, out_f) = @stm(_dst_separate_dotop(f), begin [K"." op]->begin (K"dotcall", op) end f_sep->begin (K"call", f_sep) end end) out = @ast(g, st, [out_k; out_f _dst_sink_parameters((children(st))[2:var"end"])...]) _expand_literal_pow(out) end end [K"try" tryb cvar catchb rest...]->begin let has_catch = !(_is_false(cvar) && _is_false(catchb)) cvar_out = if _is_false(cvar) newleaf(g, cvar, K"Placeholder") else rec(cvar) end has_finally = length(rest) >= 1 && !(_is_false(rest[1])) has_else = length(rest) === 2 @ast g st [K"try" rec(tryb); if has_catch [K"catch" cvar_out rec(catchb)] else nothing end; if has_else [K"else" rec(rest[2])] else nothing end; if has_finally [K"finally" rec(rest[1])] else nothing end] end end [K"flatten" _]->begin let out_iters = SyntaxList(st) next = st while kind(next) === K"flatten" push!(out_iters, _dst_iterspec(next, (next[1])[2:var"end"])) next = (next[1])[1] end @assert kind(next) === K"generator" push!(out_iters, _dst_iterspec(next, next[2:var"end"])) @ast g st [K"generator" rec(next[1]) out_iters...] end end [K"generator" body iters...]->begin @ast g st [K"generator" rec(body) _dst_iterspec(st, iters)] end [K"ncat" dim xs...]->begin let out = mknode(st, mapsyntax(rec, xs)) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end [K"nrow" dim xs...]->begin let out = mknode(st, mapsyntax(rec, xs)) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end [K"typed_ncat" t dim xs...]->begin let out_cs = pushfirst!(mapsyntax(rec, xs), rec(t)) out = mknode(st, out_cs) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end ([K"=" l r], when = is_eventually_call(l))->begin if has_if_generated(r) (gen, nongen) = (split_generated(r, true), split_generated(r, false)) @ast g st [K"generated_function" rec(l) gen nongen] else @ast g st [K"function" rec(l) rec(r)] end end [K"function" l r]->begin let if kind(l) === K"..." l = @ast(g, l, [K"tuple" l]) end if has_if_generated(r) (gen, nongen) = (split_generated(r, true), split_generated(r, false)) @ast g st [K"generated_function" rec(l) gen nongen] else @ast g st [K"function" rec(l) rec(r)] end end end [K"do" [K"call" f args...] [K"->" do_args do_body]]->begin let @ast g st [K"call"; rec(f); @ast(g, st[var"end"], [K"do" rec(do_args) rec(do_body)]); _dst_sink_parameters(args)...] end end ([K"let" binds body], when = kind(binds) !== K"block")->begin @ast g st [K"let" [K"block" rec(binds)] rec(body)] end [K"struct" mut sig body]->begin let flags = JS.flags(st) | if _is_false(mut) 0 else JS.MUTABLE_FLAG end @ast g st [(K"struct")(syntax_flags = flags); rec(sig); rec(body)] end end (_, when = kind(st) in KSet"using import")->begin let (paths, maybe_colon) = @stm(st[1], begin [K":" paths...]->begin (paths, st[1]) end _->begin (children(st), nothing) end end) out_cs = mapsyntax(_dst_importpath, paths) if !(isnothing(maybe_colon)) out_c1 = @ast(g, maybe_colon, [K":" out_cs...]) out_cs = SyntaxList(g, tree_ids(out_c1)) end mknode(st, out_cs) end end ([K"meta" [K"unknown_head" ps...]], when = (st[1]).name_val === "purity")->begin @ast g st [K"meta" "purity"::K"Symbol"; Base.EffectsOverride([x.value for x = ps]...)::K"Value"] end ([K"meta" s vs...], when = get(s, :name_val, "") in ("nospecialize", "specialize"))->begin let if length(vs) === 0 @ast g st [K"meta" s => K"Symbol"] elseif length(vs) === 1 out = est_to_dst(vs[1]) setmeta(out, Symbol(s), true) else out_cs = SyntaxList(g) for v = vs push!(out_cs, @ast(g, v, [K"meta" s => K"Symbol" v])) end @ast g st [K"block" out_cs...] end end end [K"meta" syms...]->begin @ast g st [K"meta" mapsyntax((s->begin if kind(s) === K"Identifier" setattr(s, :kind, K"Symbol") else s end end), syms)...;] end [K"inline" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"noinline" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"inbounds" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"core" x]->begin setattr!(mkleaf(st), :name_val, x.name_val) end [K"top" x]->begin setattr!(mkleaf(st), :name_val, x.name_val) end [K"copyast" [K"inert" ex]]->begin @ast g st [K"call"; interpolate_ast::K"Value"; Expr::K"Value"; [K"inert" ex]] end [K"symbolicgoto" lab]->begin setattr!(mkleaf(st), :name_val, lab.name_val) end [K"symboliclabel" lab]->begin setattr!(mkleaf(st), :name_val, lab.name_val) end [K"unknown_head" cs...]->begin let head = st.name_val if head === "latestworld-if-toplevel" newleaf(g, st, K"latestworld_if_toplevel") else @assert false string("unknown expr head (corresponding to no kind) between", "macro-expansion and desugaring: ", st) end end end [K"cfunction" typ fptr rt at sym]->begin @ast g st [K"cfunction"; rec(typ) rec(fptr); [(K"static_eval")(meta = name_hint("cfunction return type")) rec(rt)]; [(K"static_eval")(meta = name_hint("cfunction argument type")) rec(at)]; rec(sym)] end _->begin let out_cs::Vector{NodeId} = map((x->begin (rec(x))._id end), children(st)) if out_cs == children(st) st else mknode(st, out_cs) end end end end) end Core.@doc "Convert the Expr-like tree (EST) coming from macro expansion to the tree\ndesugaring expects (DST), where some forms have SyntaxNode structure and others\nhave Expr structure.\n\nWe may drop cases from this conversion, for example, if...\n\n- syntax evolution changes a form in Expr and EST to use DST structure, so the\n input we receive here is \"already done\"\n\n- desugaring changes to accept the EST form instead of the DST one, so we can\n leave our input unchanged\n\nWe can assume `st` has passed `valid_st1`. Errors arising from invalid AST\n(including finding `macrocall/escape/quote` forms) should be handled there.\n" function est_to_dst(st::SyntaxTree; all_expanded = true) g = st._graph rec = @__FUNCTION__() return @stm(st, begin [K"Identifier"]->begin let s = st.name_val if s in ("ccall", "cglobal") setattr!(newleaf(g, st, K"core"), :name_val, st.name_val) elseif all((==)('_'), s) setattr!(mkleaf(st), :kind, K"Placeholder") else st end end end (_, when = is_leaf(st))->begin st end ([K"unknown_head" l r], when = begin s = st.name_val Base.isoperator(s) end)->begin let (op_s, out_k) = if s[1] === '.' (s[nextind(s, 1):prevind(s, var"end")], K".op=") else (s[1:prevind(s, var"end")], K"op=") end op_leaf = newleaf(g, st, K"Identifier") JS.copy_attrs!(op_leaf, st) setattr!(op_leaf, :name_val, op_s) @ast g st [out_k rec(l) op_leaf rec(r)] end end [K"comparison" cs0...]->begin let cs = copy(cs0) for (i, c) = enumerate(cs) cs[i] = if iseven(i) _dst_separate_dotop(cs[i]) else rec(cs[i]) end end mknode(st, cs) end end [K"'" x]->begin @ast g st [K"call" "'"::(K"Identifier")(scope_layer = st.scope_layer) rec(x)] end [K"." f [K"tuple" args...]]->begin _expand_literal_pow(@ast(g, st, [K"dotcall" rec(f) _dst_sink_parameters(args)...])) end [K"." l r]->begin let r2 = rec(r) @stm r2 begin [K"inert" r3]->begin @ast g st [K"." rec(l) r3] end r3->begin @ast g st [K"." rec(l) r3] end end end end [K"inert" [K"Identifier"]]->begin @ast g st st[1] => K"Symbol" end [K"inert" _]->begin st end [K"inert_syntaxtree" _]->begin st end [K"module" _...]->begin st end [K"toplevel" _...]->begin st end [K"for" [K"=" _ _] body]->begin @ast g st [K"for" [K"iteration" _dst_eq_to_in(st[1])] rec(body)] end [K"for" [K"block" iters...] body]->begin @ast g st [K"for"; [K"iteration" mapsyntax(_dst_eq_to_in, iters)...]; rec(body)] end ([K"where" t tds...], when = !(length(tds) === 1 && kind(tds[1]) === K"braces"))->begin @ast g st [K"where" rec(t) [K"braces" mapsyntax(rec, tds)...]] end (_, when = begin k = kind(st) k in KSet"tuple vect braces" end)->begin @ast g st [k _dst_sink_parameters(children(st))...] end (_, when = begin k = kind(st) k in KSet"curly ref" end)->begin @ast g st [k _dst_separate_dotop(st[1]); _dst_sink_parameters((children(st))[2:var"end"])...] end [K"call" f args...]->begin let (out_k, out_f) = @stm(_dst_separate_dotop(f), begin [K"." op]->begin (K"dotcall", op) end f_sep->begin (K"call", f_sep) end end) out = @ast(g, st, [out_k; out_f _dst_sink_parameters((children(st))[2:var"end"])...]) _expand_literal_pow(out) end end [K"try" tryb cvar catchb rest...]->begin let has_catch = !(_is_false(cvar) && _is_false(catchb)) cvar_out = if _is_false(cvar) newleaf(g, cvar, K"Placeholder") else rec(cvar) end has_finally = length(rest) >= 1 && !(_is_false(rest[1])) has_else = length(rest) === 2 @ast g st [K"try" rec(tryb); if has_catch [K"catch" cvar_out rec(catchb)] else nothing end; if has_else [K"else" rec(rest[2])] else nothing end; if has_finally [K"finally" rec(rest[1])] else nothing end] end end [K"flatten" _]->begin let out_iters = SyntaxList(st) next = st while kind(next) === K"flatten" push!(out_iters, _dst_iterspec(next, (next[1])[2:var"end"])) next = (next[1])[1] end @assert kind(next) === K"generator" push!(out_iters, _dst_iterspec(next, next[2:var"end"])) @ast g st [K"generator" rec(next[1]) out_iters...] end end [K"generator" body iters...]->begin @ast g st [K"generator" rec(body) _dst_iterspec(st, iters)] end [K"ncat" dim xs...]->begin let out = mknode(st, mapsyntax(rec, xs)) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end [K"nrow" dim xs...]->begin let out = mknode(st, mapsyntax(rec, xs)) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end [K"typed_ncat" t dim xs...]->begin let out_cs = pushfirst!(mapsyntax(rec, xs), rec(t)) out = mknode(st, out_cs) setattr!(out, :syntax_flags, JS.flags(st) | JS.set_numeric_flags(dim.value)) end end ([K"=" l r], when = is_eventually_call(l))->begin if has_if_generated(r) (gen, nongen) = (split_generated(r, true), split_generated(r, false)) @ast g st [K"generated_function" rec(l) gen nongen] else @ast g st [K"function" rec(l) rec(r)] end end [K"function" l r]->begin let if kind(l) === K"..." l = @ast(g, l, [K"tuple" l]) end if has_if_generated(r) (gen, nongen) = (split_generated(r, true), split_generated(r, false)) @ast g st [K"generated_function" rec(l) gen nongen] else @ast g st [K"function" rec(l) rec(r)] end end end [K"do" [K"call" f args...] [K"->" do_args do_body]]->begin let @ast g st [K"call"; rec(f); @ast(g, st[var"end"], [K"do" rec(do_args) rec(do_body)]); _dst_sink_parameters(args)...] end end ([K"let" binds body], when = kind(binds) !== K"block")->begin @ast g st [K"let" [K"block" rec(binds)] rec(body)] end [K"struct" mut sig body]->begin let flags = JS.flags(st) | if _is_false(mut) 0 else JS.MUTABLE_FLAG end @ast g st [(K"struct")(syntax_flags = flags); rec(sig); rec(body)] end end (_, when = kind(st) in KSet"using import")->begin let (paths, maybe_colon) = @stm(st[1], begin [K":" paths...]->begin (paths, st[1]) end _->begin (children(st), nothing) end end) out_cs = mapsyntax(_dst_importpath, paths) if !(isnothing(maybe_colon)) out_c1 = @ast(g, maybe_colon, [K":" out_cs...]) out_cs = SyntaxList(g, tree_ids(out_c1)) end mknode(st, out_cs) end end ([K"meta" [K"unknown_head" ps...]], when = (st[1]).name_val === "purity")->begin @ast g st [K"meta" "purity"::K"Symbol"; Base.EffectsOverride([x.value for x = ps]...)::K"Value"] end ([K"meta" s vs...], when = get(s, :name_val, "") in ("nospecialize", "specialize"))->begin let if length(vs) === 0 @ast g st [K"meta" s => K"Symbol"] elseif length(vs) === 1 out = est_to_dst(vs[1]) setmeta(out, Symbol(s), true) else out_cs = SyntaxList(g) for v = vs push!(out_cs, @ast(g, v, [K"meta" s => K"Symbol" v])) end @ast g st [K"block" out_cs...] end end end [K"meta" syms...]->begin @ast g st [K"meta" mapsyntax((s->begin if kind(s) === K"Identifier" setattr(s, :kind, K"Symbol") else s end end), syms)...] end [K"inline" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"noinline" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"inbounds" _]->begin newleaf(g, st, K"TOMBSTONE") end [K"core" x]->begin setattr!(mkleaf(st), :name_val, x.name_val) end [K"top" x]->begin setattr!(mkleaf(st), :name_val, x.name_val) end [K"copyast" [K"inert" ex]]->begin @ast g st [K"call"; interpolate_ast::K"Value"; Expr::K"Value"; [K"inert" ex]] end [K"symbolicgoto" lab]->begin setattr!(mkleaf(st), :name_val, lab.name_val) end [K"symboliclabel" lab]->begin setattr!(mkleaf(st), :name_val, lab.name_val) end [K"unknown_head" cs...]->begin let head = st.name_val if head === "latestworld-if-toplevel" newleaf(g, st, K"latestworld_if_toplevel") else @assert false string("unknown expr head (corresponding to no kind) between", "macro-expansion and desugaring: ", st) end end end [K"cfunction" typ fptr rt at sym]->begin @ast g st [K"cfunction"; rec(typ) rec(fptr); [(K"static_eval")(meta = name_hint("cfunction return type")) rec(rt)]; [(K"static_eval")(meta = name_hint("cfunction argument type")) rec(at)]; rec(sym)] end _->begin let out_cs::Vector{NodeId} = map((x->begin (rec(x))._id end), children(st)) if out_cs == children(st) st else mknode(st, out_cs) end end end end) end Parsing files in Base: Test Failed at /home/pkgeval/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:166 Expression: false Stacktrace: [1] macro expansion @ /opt/julia/share/julia/stdlib/v1.14/Test/src/Test.jl:782 [inlined] [2] top-level scope @ ~/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:166 ┌ Error: parsing difference │ file = "/opt/julia/bin/../share/julia/JuliaLowering/src/desugaring.jl" └ @ Main.var"##302" ~/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:157 "svec" ::K"core" "svec"::K"core" ::K"core" K"core" K"core" @K_str ::K"core" K"core" "svec" ::K"core" "svec"::K"core" "svec" ::K"core" "svec"::K"core" ::K"core" K"core" K"core" @K_str ::K"core" K"core" "svec" ::K"core" "svec"::K"core" [K"call"; "svec" ::K"core"; arg_types...] [K"call"; "svec"::K"core"; arg_types...] "svec" ::K"core" "svec"::K"core" ::K"core" K"core" K"core" @K_str ::K"core" K"core" "svec" ::K"core" "svec"::K"core" [K"call"; "svec" ::K"core"; typevar_names...] [K"call"; "svec"::K"core"; typevar_names...] [(K"call")(callex_srcref); "svec" ::K"core"; [K"call"; "svec" ::K"core"; arg_types...]; [K"call"; "svec" ::K"core"; typevar_names...]; ::(K"SourceLocation")(callex_srcref)] [(K"call")(callex_srcref); "svec"::K"core"; [K"call"; "svec"::K"core"; arg_types...]; [K"call"; "svec"::K"core"; typevar_names...]; ::(K"SourceLocation")(callex_srcref)] method_metadata := [(K"call")(callex_srcref); "svec" ::K"core"; [K"call"; "svec" ::K"core"; arg_types...]; [K"call"; "svec" ::K"core"; typevar_names...]; ::(K"SourceLocation")(callex_srcref)] method_metadata := [(K"call")(callex_srcref); "svec"::K"core"; [K"call"; "svec"::K"core"; arg_types...]; [K"call"; "svec"::K"core"; typevar_names...]; ::(K"SourceLocation")(callex_srcref)] [K"block"; method_metadata := [(K"call")(callex_srcref); "svec" ::K"core"; [K"call"; "svec" ::K"core"; arg_types...]; [K"call"; "svec" ::K"core"; typevar_names...]; ::(K"SourceLocation")(callex_srcref)]; [K"method"; if isnothing(method_table) "nothing"::K"core" else method_table end; method_metadata; [(K"lambda")(body, is_toplevel_thunk = false, toplevel_pure = false); [K"block" arg_names...]; [K"block" typevar_names...]; body; ret_var]]; [K"removable" method_metadata]] [K"block"; method_metadata := [(K"call")(callex_srcref); "svec"::K"core"; [K"call"; "svec"::K"core"; arg_types...]; [K"call"; "svec"::K"core"; typevar_names...]; ::(K"SourceLocation")(callex_srcref)]; [K"method"; if isnothing(method_table) "nothing"::K"core" else method_table end; method_metadata; [(K"lambda")(body, is_toplevel_thunk = false, toplevel_pure = false); [K"block" arg_names...]; [K"block" typevar_names...]; body; ret_var]]; [K"removable" method_metadata]] @ast ctx srcref [K"block"; method_metadata := [(K"call")(callex_srcref); "svec" ::K"core"; [K"call"; "svec" ::K"core"; arg_types...]; [K"call"; "svec" ::K"core"; typevar_names...]; ::(K"SourceLocation")(callex_srcref)]; [K"method"; if isnothing(method_table) "nothing"::K"core" else method_table end; method_metadata; [(K"lambda")(body, is_toplevel_thunk = false, toplevel_pure = false); [K"block" arg_names...]; [K"block" typevar_names...]; body; ret_var]]; [K"removable" method_metadata]] @ast ctx srcref [K"block"; method_metadata := [(K"call")(callex_srcref); "svec"::K"core"; [K"call"; "svec"::K"core"; arg_types...]; [K"call"; "svec"::K"core"; typevar_names...]; ::(K"SourceLocation")(callex_srcref)]; [K"method"; if isnothing(method_table) "nothing"::K"core" else method_table end; method_metadata; [(K"lambda")(body, is_toplevel_thunk = false, toplevel_pure = false); [K"block" arg_names...]; [K"block" typevar_names...]; body; ret_var]]; [K"removable" method_metadata]] begin @ast ctx srcref [K"block"; method_metadata := [(K"call")(callex_srcref); "svec" ::K"core"; [K"call"; "svec" ::K"core"; arg_types...]; [K"call"; "svec" ::K"core"; typevar_names...]; ::(K"SourceLocation")(callex_srcref)]; [K"method"; if isnothing(method_table) "nothing"::K"core" else method_table end; method_metadata; [(K"lambda")(body, is_toplevel_thunk = false, toplevel_pure = false); [K"block" arg_names...]; [K"block" typevar_names...]; body; ret_var]]; [K"removable" method_metadata]] end begin @ast ctx srcref [K"block"; method_metadata := [(K"call")(callex_srcref); "svec"::K"core"; [K"call"; "svec"::K"core"; arg_types...]; [K"call"; "svec"::K"core"; typevar_names...]; ::(K"SourceLocation")(callex_srcref)]; [K"method"; if isnothing(method_table) "nothing"::K"core" else method_table end; method_metadata; [(K"lambda")(body, is_toplevel_thunk = false, toplevel_pure = false); [K"block" arg_names...]; [K"block" typevar_names...]; body; ret_var]]; [K"removable" method_metadata]] end function method_def_expr(ctx, srcref, callex_srcref, method_table, typevar_names, arg_names, arg_types, body, ret_var = nothing) @ast ctx srcref [K"block"; method_metadata := [(K"call")(callex_srcref); "svec" ::K"core"; [K"call"; "svec" ::K"core"; arg_types...]; [K"call"; "svec" ::K"core"; typevar_names...]; ::(K"SourceLocation")(callex_srcref)]; [K"method"; if isnothing(method_table) "nothing"::K"core" else method_table end; method_metadata; [(K"lambda")(body, is_toplevel_thunk = false, toplevel_pure = false); [K"block" arg_names...]; [K"block" typevar_names...]; body; ret_var]]; [K"removable" method_metadata]] end function method_def_expr(ctx, srcref, callex_srcref, method_table, typevar_names, arg_names, arg_types, body, ret_var = nothing) @ast ctx srcref [K"block"; method_metadata := [(K"call")(callex_srcref); "svec"::K"core"; [K"call"; "svec"::K"core"; arg_types...]; [K"call"; "svec"::K"core"; typevar_names...]; ::(K"SourceLocation")(callex_srcref)]; [K"method"; if isnothing(method_table) "nothing"::K"core" else method_table end; method_metadata; [(K"lambda")(body, is_toplevel_thunk = false, toplevel_pure = false); [K"block" arg_names...]; [K"block" typevar_names...]; body; ret_var]]; [K"removable" method_metadata]] end eval_using ::K"Value" eval_using::K"Value" ::K"Value" K"Value" K"Value" @K_str ::K"Value" K"Value" eval_using ::K"Value" eval_using::K"Value" ctx.mod ::K"Value" ctx.mod::K"Value" ::K"Value" K"Value" K"Value" @K_str ::K"Value" K"Value" ctx.mod ::K"Value" ctx.mod::K"Value" [K"call"; eval_using ::K"Value"; ctx.mod ::K"Value"; spec] [K"call"; eval_using::K"Value"; ctx.mod::K"Value"; spec] @ast ctx spec [K"call"; eval_using ::K"Value"; ctx.mod ::K"Value"; spec] @ast ctx spec [K"call"; eval_using::K"Value"; ctx.mod::K"Value"; spec] push!(stmts, @ast(ctx, spec, [K"call"; eval_using ::K"Value"; ctx.mod ::K"Value"; spec])) push!(stmts, @ast(ctx, spec, [K"call"; eval_using::K"Value"; ctx.mod::K"Value"; spec])) begin push!(stmts, @ast(ctx, spec, [K"call"; eval_using ::K"Value"; ctx.mod ::K"Value"; spec])) end begin push!(stmts, @ast(ctx, spec, [K"call"; eval_using::K"Value"; ctx.mod::K"Value"; spec])) end eval_import ::K"Value" eval_import::K"Value" ::K"Value" K"Value" K"Value" @K_str ::K"Value" K"Value" eval_import ::K"Value" eval_import::K"Value" !is_using ::K"Bool" (!is_using)::K"Bool" ::K"Bool" K"Bool" K"Bool" @K_str ::K"Bool" K"Bool" !is_using ::K"Bool" (!is_using)::K"Bool" ctx.mod ::K"Value" ctx.mod::K"Value" ::K"Value" K"Value" K"Value" @K_str ::K"Value" K"Value" ctx.mod ::K"Value" ctx.mod::K"Value" "nothing" ::K"top" "nothing"::K"top" ::K"top" K"top" K"top" @K_str ::K"top" K"top" "nothing" ::K"top" "nothing"::K"top" [K"call"; eval_import ::K"Value"; !is_using ::K"Bool"; ctx.mod ::K"Value"; "nothing" ::K"top"; spec] [K"call"; eval_import::K"Value"; (!is_using)::K"Bool"; ctx.mod::K"Value"; "nothing"::K"top"; spec] @ast ctx spec [K"call"; eval_import ::K"Value"; !is_using ::K"Bool"; ctx.mod ::K"Value"; "nothing" ::K"top"; spec] @ast ctx spec [K"call"; eval_import::K"Value"; (!is_using)::K"Bool"; ctx.mod::K"Value"; "nothing"::K"top"; spec] push!(stmts, @ast(ctx, spec, [K"call"; eval_import ::K"Value"; !is_using ::K"Bool"; ctx.mod ::K"Value"; "nothing" ::K"top"; spec])) push!(stmts, @ast(ctx, spec, [K"call"; eval_import::K"Value"; (!is_using)::K"Bool"; ctx.mod::K"Value"; "nothing"::K"top"; spec])) begin push!(stmts, @ast(ctx, spec, [K"call"; eval_import ::K"Value"; !is_using ::K"Bool"; ctx.mod ::K"Value"; "nothing" ::K"top"; spec])) end begin push!(stmts, @ast(ctx, spec, [K"call"; eval_import::K"Value"; (!is_using)::K"Bool"; ctx.mod::K"Value"; "nothing"::K"top"; spec])) end if is_using push!(stmts, @ast(ctx, spec, [K"call"; eval_using ::K"Value"; ctx.mod ::K"Value"; spec])) else push!(stmts, @ast(ctx, spec, [K"call"; eval_import ::K"Value"; !is_using ::K"Bool"; ctx.mod ::K"Value"; "nothing" ::K"top"; spec])) end if is_using push!(stmts, @ast(ctx, spec, [K"call"; eval_using::K"Value"; ctx.mod::K"Value"; spec])) else push!(stmts, @ast(ctx, spec, [K"call"; eval_import::K"Value"; (!is_using)::K"Bool"; ctx.mod::K"Value"; "nothing"::K"top"; spec])) end begin if is_using push!(stmts, @ast(ctx, spec, [K"call"; eval_using ::K"Value"; ctx.mod ::K"Value"; spec])) else push!(stmts, @ast(ctx, spec, [K"call"; eval_import ::K"Value"; !is_using ::K"Bool"; ctx.mod ::K"Value"; "nothing" ::K"top"; spec])) end push!(stmts, @ast(ctx, spec, ::K"latestworld")) end begin if is_using push!(stmts, @ast(ctx, spec, [K"call"; eval_using::K"Value"; ctx.mod::K"Value"; spec])) else push!(stmts, @ast(ctx, spec, [K"call"; eval_import::K"Value"; (!is_using)::K"Bool"; ctx.mod::K"Value"; "nothing"::K"top"; spec])) end push!(stmts, @ast(ctx, spec, ::K"latestworld")) end for spec = path_specs if is_using push!(stmts, @ast(ctx, spec, [K"call"; eval_using ::K"Value"; ctx.mod ::K"Value"; spec])) else push!(stmts, @ast(ctx, spec, [K"call"; eval_import ::K"Value"; !is_using ::K"Bool"; ctx.mod ::K"Value"; "nothing" ::K"top"; spec])) end push!(stmts, @ast(ctx, spec, ::K"latestworld")) end for spec = path_specs if is_using push!(stmts, @ast(ctx, spec, [K"call"; eval_using::K"Value"; ctx.mod::K"Value"; spec])) else push!(stmts, @ast(ctx, spec, [K"call"; eval_import::K"Value"; (!is_using)::K"Bool"; ctx.mod::K"Value"; "nothing"::K"top"; spec])) end push!(stmts, @ast(ctx, spec, ::K"latestworld")) end begin for spec = path_specs if is_using push!(stmts, @ast(ctx, spec, [K"call"; eval_using ::K"Value"; ctx.mod ::K"Value"; spec])) else push!(stmts, @ast(ctx, spec, [K"call"; eval_import ::K"Value"; !is_using ::K"Bool"; ctx.mod ::K"Value"; "nothing" ::K"top"; spec])) end push!(stmts, @ast(ctx, spec, ::K"latestworld")) end end begin for spec = path_specs if is_using push!(stmts, @ast(ctx, spec, [K"call"; eval_using::K"Value"; ctx.mod::K"Value"; spec])) else push!(stmts, @ast(ctx, spec, [K"call"; eval_import::K"Value"; (!is_using)::K"Bool"; ctx.mod::K"Value"; "nothing"::K"top"; spec])) end push!(stmts, @ast(ctx, spec, ::K"latestworld")) end end eval_import ::K"Value" eval_import::K"Value" ::K"Value" K"Value" K"Value" @K_str ::K"Value" K"Value" eval_import ::K"Value" eval_import::K"Value" !is_using ::K"Bool" (!is_using)::K"Bool" ::K"Bool" K"Bool" K"Bool" @K_str ::K"Bool" K"Bool" !is_using ::K"Bool" (!is_using)::K"Bool" ctx.mod ::K"Value" ctx.mod::K"Value" ::K"Value" K"Value" K"Value" @K_str ::K"Value" K"Value" ctx.mod ::K"Value" ctx.mod::K"Value" [K"call"; eval_import ::K"Value"; !is_using ::K"Bool"; ctx.mod ::K"Value"; from_path; path_specs...] [K"call"; eval_import::K"Value"; (!is_using)::K"Bool"; ctx.mod::K"Value"; from_path; path_specs...] @ast ctx ex [K"call"; eval_import ::K"Value"; !is_using ::K"Bool"; ctx.mod ::K"Value"; from_path; path_specs...] @ast ctx ex [K"call"; eval_import::K"Value"; (!is_using)::K"Bool"; ctx.mod::K"Value"; from_path; path_specs...] push!(stmts, @ast(ctx, ex, [K"call"; eval_import ::K"Value"; !is_using ::K"Bool"; ctx.mod ::K"Value"; from_path; path_specs...])) push!(stmts, @ast(ctx, ex, [K"call"; eval_import::K"Value"; (!is_using)::K"Bool"; ctx.mod::K"Value"; from_path; path_specs...])) begin push!(stmts, @ast(ctx, ex, [K"call"; eval_import ::K"Value"; !is_using ::K"Bool"; ctx.mod ::K"Value"; from_path; path_specs...])) push!(stmts, @ast(ctx, ex, ::K"latestworld")) end begin push!(stmts, @ast(ctx, ex, [K"call"; eval_import::K"Value"; (!is_using)::K"Bool"; ctx.mod::K"Value"; from_path; path_specs...])) push!(stmts, @ast(ctx, ex, ::K"latestworld")) end if isnothing(from_path) for spec = path_specs if is_using push!(stmts, @ast(ctx, spec, [K"call"; eval_using ::K"Value"; ctx.mod ::K"Value"; spec])) else push!(stmts, @ast(ctx, spec, [K"call"; eval_import ::K"Value"; !is_using ::K"Bool"; ctx.mod ::K"Value"; "nothing" ::K"top"; spec])) end push!(stmts, @ast(ctx, spec, ::K"latestworld")) end else push!(stmts, @ast(ctx, ex, [K"call"; eval_import ::K"Value"; !is_using ::K"Bool"; ctx.mod ::K"Value"; from_path; path_specs...])) push!(stmts, @ast(ctx, ex, ::K"latestworld")) end if isnothing(from_path) for spec = path_specs if is_using push!(stmts, @ast(ctx, spec, [K"call"; eval_using::K"Value"; ctx.mod::K"Value"; spec])) else push!(stmts, @ast(ctx, spec, [K"call"; eval_import::K"Value"; (!is_using)::K"Bool"; ctx.mod::K"Value"; "nothing"::K"top"; spec])) end push!(stmts, @ast(ctx, spec, ::K"latestworld")) end else push!(stmts, @ast(ctx, ex, [K"call"; eval_import::K"Value"; (!is_using)::K"Bool"; ctx.mod::K"Value"; from_path; path_specs...])) push!(stmts, @ast(ctx, ex, ::K"latestworld")) end begin if kind(ex[1]) == K":" @chk numchildren(ex[1]) >= 2 from = (ex[1])[1] from_path = @ast(ctx, from, QuoteNode(expand_importpath(from))::K"Value") paths = (ex[1])[2:var"end"] else @chk numchildren(ex) >= 1 from_path = nothing paths = children(ex) end path_specs = SyntaxList(ctx) for spec = paths as_name = nothing if kind(spec) == K"as" @chk numchildren(spec) == 2 @chk kind(spec[2]) == K"Identifier" as_name = Symbol((spec[2]).name_val) path = QuoteNode(Expr(:as, expand_importpath(spec[1]), as_name)) else path = QuoteNode(expand_importpath(spec)) end push!(path_specs, @ast(ctx, spec, path::K"Value")) end is_using = kind(ex) == K"using" stmts = SyntaxList(ctx) if isnothing(from_path) for spec = path_specs if is_using push!(stmts, @ast(ctx, spec, [K"call"; eval_using ::K"Value"; ctx.mod ::K"Value"; spec])) else push!(stmts, @ast(ctx, spec, [K"call"; eval_import ::K"Value"; !is_using ::K"Bool"; ctx.mod ::K"Value"; "nothing" ::K"top"; spec])) end push!(stmts, @ast(ctx, spec, ::K"latestworld")) end else push!(stmts, @ast(ctx, ex, [K"call"; eval_import ::K"Value"; !is_using ::K"Bool"; ctx.mod ::K"Value"; from_path; path_specs...])) push!(stmts, @ast(ctx, ex, ::K"latestworld")) end @ast ctx ex [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; stmts...; [K"removable" "nothing"::K"core"]] end begin if kind(ex[1]) == K":" @chk numchildren(ex[1]) >= 2 from = (ex[1])[1] from_path = @ast(ctx, from, QuoteNode(expand_importpath(from))::K"Value") paths = (ex[1])[2:var"end"] else @chk numchildren(ex) >= 1 from_path = nothing paths = children(ex) end path_specs = SyntaxList(ctx) for spec = paths as_name = nothing if kind(spec) == K"as" @chk numchildren(spec) == 2 @chk kind(spec[2]) == K"Identifier" as_name = Symbol((spec[2]).name_val) path = QuoteNode(Expr(:as, expand_importpath(spec[1]), as_name)) else path = QuoteNode(expand_importpath(spec)) end push!(path_specs, @ast(ctx, spec, path::K"Value")) end is_using = kind(ex) == K"using" stmts = SyntaxList(ctx) if isnothing(from_path) for spec = path_specs if is_using push!(stmts, @ast(ctx, spec, [K"call"; eval_using::K"Value"; ctx.mod::K"Value"; spec])) else push!(stmts, @ast(ctx, spec, [K"call"; eval_import::K"Value"; (!is_using)::K"Bool"; ctx.mod::K"Value"; "nothing"::K"top"; spec])) end push!(stmts, @ast(ctx, spec, ::K"latestworld")) end else push!(stmts, @ast(ctx, ex, [K"call"; eval_import::K"Value"; (!is_using)::K"Bool"; ctx.mod::K"Value"; from_path; path_specs...])) push!(stmts, @ast(ctx, ex, ::K"latestworld")) end @ast ctx ex [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; stmts...; [K"removable" "nothing"::K"core"]] end function expand_import_or_using(ctx, ex) if kind(ex[1]) == K":" @chk numchildren(ex[1]) >= 2 from = (ex[1])[1] from_path = @ast(ctx, from, QuoteNode(expand_importpath(from))::K"Value") paths = (ex[1])[2:var"end"] else @chk numchildren(ex) >= 1 from_path = nothing paths = children(ex) end path_specs = SyntaxList(ctx) for spec = paths as_name = nothing if kind(spec) == K"as" @chk numchildren(spec) == 2 @chk kind(spec[2]) == K"Identifier" as_name = Symbol((spec[2]).name_val) path = QuoteNode(Expr(:as, expand_importpath(spec[1]), as_name)) else path = QuoteNode(expand_importpath(spec)) end push!(path_specs, @ast(ctx, spec, path::K"Value")) end is_using = kind(ex) == K"using" stmts = SyntaxList(ctx) if isnothing(from_path) for spec = path_specs if is_using push!(stmts, @ast(ctx, spec, [K"call"; eval_using ::K"Value"; ctx.mod ::K"Value"; spec])) else push!(stmts, @ast(ctx, spec, [K"call"; eval_import ::K"Value"; !is_using ::K"Bool"; ctx.mod ::K"Value"; "nothing" ::K"top"; spec])) end push!(stmts, @ast(ctx, spec, ::K"latestworld")) end else push!(stmts, @ast(ctx, ex, [K"call"; eval_import ::K"Value"; !is_using ::K"Bool"; ctx.mod ::K"Value"; from_path; path_specs...])) push!(stmts, @ast(ctx, ex, ::K"latestworld")) end @ast ctx ex [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; stmts...; [K"removable" "nothing"::K"core"]] end function expand_import_or_using(ctx, ex) if kind(ex[1]) == K":" @chk numchildren(ex[1]) >= 2 from = (ex[1])[1] from_path = @ast(ctx, from, QuoteNode(expand_importpath(from))::K"Value") paths = (ex[1])[2:var"end"] else @chk numchildren(ex) >= 1 from_path = nothing paths = children(ex) end path_specs = SyntaxList(ctx) for spec = paths as_name = nothing if kind(spec) == K"as" @chk numchildren(spec) == 2 @chk kind(spec[2]) == K"Identifier" as_name = Symbol((spec[2]).name_val) path = QuoteNode(Expr(:as, expand_importpath(spec[1]), as_name)) else path = QuoteNode(expand_importpath(spec)) end push!(path_specs, @ast(ctx, spec, path::K"Value")) end is_using = kind(ex) == K"using" stmts = SyntaxList(ctx) if isnothing(from_path) for spec = path_specs if is_using push!(stmts, @ast(ctx, spec, [K"call"; eval_using::K"Value"; ctx.mod::K"Value"; spec])) else push!(stmts, @ast(ctx, spec, [K"call"; eval_import::K"Value"; (!is_using)::K"Bool"; ctx.mod::K"Value"; "nothing"::K"top"; spec])) end push!(stmts, @ast(ctx, spec, ::K"latestworld")) end else push!(stmts, @ast(ctx, ex, [K"call"; eval_import::K"Value"; (!is_using)::K"Bool"; ctx.mod::K"Value"; from_path; path_specs...])) push!(stmts, @ast(ctx, ex, ::K"latestworld")) end @ast ctx ex [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; stmts...; [K"removable" "nothing"::K"core"]] end eval ::K"Value" eval::K"Value" ::K"Value" K"Value" K"Value" @K_str ::K"Value" K"Value" eval ::K"Value" eval::K"Value" ctx.mod ::K"Value" ctx.mod::K"Value" ::K"Value" K"Value" K"Value" @K_str ::K"Value" K"Value" ctx.mod ::K"Value" ctx.mod::K"Value" [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]] [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]] [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]] [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]] @ast ctx ex [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]] @ast ctx ex [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]] ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) begin ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) end begin ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) end elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"local" || k == K"global" if k == K"global" && kind(ex[1]) == K"const" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"local" || k == K"global" if k == K"global" && kind(ex[1]) == K"const" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"continue" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_cont"::K"symboliclabel"] else @chk nc == 1 (ex, "Too many arguments to continue") label = ex[1] label_kind = kind(label) if !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"Symbol" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid continue label: expected identifier")) end @ast ctx ex [K"break" string(label.name_val, "#cont")::K"symboliclabel"] end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"continue" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_cont"::K"symboliclabel"] else @chk nc == 1 (ex, "Too many arguments to continue") label = ex[1] label_kind = kind(label) if !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"Symbol" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid continue label: expected identifier")) end @ast ctx ex [K"break" string(label.name_val, "#cont")::K"symboliclabel"] end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"break" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_exit"::K"symboliclabel"] else @chk nc <= 2 (ex, "Too many arguments to break") label = ex[1] label_kind = kind(label) if label_kind == K"Symbol" label = @ast(ctx, label, label.name_val::K"symboliclabel") elseif !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"symboliclabel" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid break label: expected identifier")) end if nc == 2 @ast ctx ex [K"break" label expand_forms_2(ctx, ex[2])] else @ast ctx ex [K"break" label] end end elseif k == K"continue" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_cont"::K"symboliclabel"] else @chk nc == 1 (ex, "Too many arguments to continue") label = ex[1] label_kind = kind(label) if !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"Symbol" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid continue label: expected identifier")) end @ast ctx ex [K"break" string(label.name_val, "#cont")::K"symboliclabel"] end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"break" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_exit"::K"symboliclabel"] else @chk nc <= 2 (ex, "Too many arguments to break") label = ex[1] label_kind = kind(label) if label_kind == K"Symbol" label = @ast(ctx, label, label.name_val::K"symboliclabel") elseif !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"symboliclabel" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid break label: expected identifier")) end if nc == 2 @ast ctx ex [K"break" label expand_forms_2(ctx, ex[2])] else @ast ctx ex [K"break" label] end end elseif k == K"continue" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_cont"::K"symboliclabel"] else @chk nc == 1 (ex, "Too many arguments to continue") label = ex[1] label_kind = kind(label) if !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"Symbol" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid continue label: expected identifier")) end @ast ctx ex [K"break" string(label.name_val, "#cont")::K"symboliclabel"] end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"=" expand_assignment(ctx, ex) elseif k == K"break" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_exit"::K"symboliclabel"] else @chk nc <= 2 (ex, "Too many arguments to break") label = ex[1] label_kind = kind(label) if label_kind == K"Symbol" label = @ast(ctx, label, label.name_val::K"symboliclabel") elseif !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"symboliclabel" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid break label: expected identifier")) end if nc == 2 @ast ctx ex [K"break" label expand_forms_2(ctx, ex[2])] else @ast ctx ex [K"break" label] end end elseif k == K"continue" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_cont"::K"symboliclabel"] else @chk nc == 1 (ex, "Too many arguments to continue") label = ex[1] label_kind = kind(label) if !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"Symbol" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid continue label: expected identifier")) end @ast ctx ex [K"break" string(label.name_val, "#cont")::K"symboliclabel"] end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"=" expand_assignment(ctx, ex) elseif k == K"break" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_exit"::K"symboliclabel"] else @chk nc <= 2 (ex, "Too many arguments to break") label = ex[1] label_kind = kind(label) if label_kind == K"Symbol" label = @ast(ctx, label, label.name_val::K"symboliclabel") elseif !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"symboliclabel" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid break label: expected identifier")) end if nc == 2 @ast ctx ex [K"break" label expand_forms_2(ctx, ex[2])] else @ast ctx ex [K"break" label] end end elseif k == K"continue" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_cont"::K"symboliclabel"] else @chk nc == 1 (ex, "Too many arguments to continue") label = ex[1] label_kind = kind(label) if !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"Symbol" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid continue label: expected identifier")) end @ast ctx ex [K"break" string(label.name_val, "#cont")::K"symboliclabel"] end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"op=" || k == K".op=" expand_forms_2(ctx, expand_update_operator(ctx, ex)) elseif k == K"=" expand_assignment(ctx, ex) elseif k == K"break" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_exit"::K"symboliclabel"] else @chk nc <= 2 (ex, "Too many arguments to break") label = ex[1] label_kind = kind(label) if label_kind == K"Symbol" label = @ast(ctx, label, label.name_val::K"symboliclabel") elseif !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"symboliclabel" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid break label: expected identifier")) end if nc == 2 @ast ctx ex [K"break" label expand_forms_2(ctx, ex[2])] else @ast ctx ex [K"break" label] end end elseif k == K"continue" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_cont"::K"symboliclabel"] else @chk nc == 1 (ex, "Too many arguments to continue") label = ex[1] label_kind = kind(label) if !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"Symbol" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid continue label: expected identifier")) end @ast ctx ex [K"break" string(label.name_val, "#cont")::K"symboliclabel"] end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"op=" || k == K".op=" expand_forms_2(ctx, expand_update_operator(ctx, ex)) elseif k == K"=" expand_assignment(ctx, ex) elseif k == K"break" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_exit"::K"symboliclabel"] else @chk nc <= 2 (ex, "Too many arguments to break") label = ex[1] label_kind = kind(label) if label_kind == K"Symbol" label = @ast(ctx, label, label.name_val::K"symboliclabel") elseif !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"symboliclabel" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid break label: expected identifier")) end if nc == 2 @ast ctx ex [K"break" label expand_forms_2(ctx, ex[2])] else @ast ctx ex [K"break" label] end end elseif k == K"continue" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_cont"::K"symboliclabel"] else @chk nc == 1 (ex, "Too many arguments to continue") label = ex[1] label_kind = kind(label) if !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"Symbol" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid continue label: expected identifier")) end @ast ctx ex [K"break" string(label.name_val, "#cont")::K"symboliclabel"] end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"<:" || (k == K">:" || k == K"-->") expand_forms_2(ctx, @ast(ctx, ex, [K"call"; adopt_scope(string(k)::K"Identifier", ex); children(ex)...])) elseif k == K"op=" || k == K".op=" expand_forms_2(ctx, expand_update_operator(ctx, ex)) elseif k == K"=" expand_assignment(ctx, ex) elseif k == K"break" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_exit"::K"symboliclabel"] else @chk nc <= 2 (ex, "Too many arguments to break") label = ex[1] label_kind = kind(label) if label_kind == K"Symbol" label = @ast(ctx, label, label.name_val::K"symboliclabel") elseif !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"symboliclabel" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid break label: expected identifier")) end if nc == 2 @ast ctx ex [K"break" label expand_forms_2(ctx, ex[2])] else @ast ctx ex [K"break" label] end end elseif k == K"continue" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_cont"::K"symboliclabel"] else @chk nc == 1 (ex, "Too many arguments to continue") label = ex[1] label_kind = kind(label) if !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"Symbol" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid continue label: expected identifier")) end @ast ctx ex [K"break" string(label.name_val, "#cont")::K"symboliclabel"] end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"<:" || (k == K">:" || k == K"-->") expand_forms_2(ctx, @ast(ctx, ex, [K"call"; adopt_scope(string(k)::K"Identifier", ex); children(ex)...])) elseif k == K"op=" || k == K".op=" expand_forms_2(ctx, expand_update_operator(ctx, ex)) elseif k == K"=" expand_assignment(ctx, ex) elseif k == K"break" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_exit"::K"symboliclabel"] else @chk nc <= 2 (ex, "Too many arguments to break") label = ex[1] label_kind = kind(label) if label_kind == K"Symbol" label = @ast(ctx, label, label.name_val::K"symboliclabel") elseif !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"symboliclabel" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid break label: expected identifier")) end if nc == 2 @ast ctx ex [K"break" label expand_forms_2(ctx, ex[2])] else @ast ctx ex [K"break" label] end end elseif k == K"continue" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_cont"::K"symboliclabel"] else @chk nc == 1 (ex, "Too many arguments to continue") label = ex[1] label_kind = kind(label) if !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"Symbol" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid continue label: expected identifier")) end @ast ctx ex [K"break" string(label.name_val, "#cont")::K"symboliclabel"] end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"::" @chk numchildren(ex) == 2 "`::` must be written `value::type` outside function argument lists" @ast ctx ex [K"call"; "typeassert"::K"core"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] elseif k == K"<:" || (k == K">:" || k == K"-->") expand_forms_2(ctx, @ast(ctx, ex, [K"call"; adopt_scope(string(k)::K"Identifier", ex); children(ex)...])) elseif k == K"op=" || k == K".op=" expand_forms_2(ctx, expand_update_operator(ctx, ex)) elseif k == K"=" expand_assignment(ctx, ex) elseif k == K"break" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_exit"::K"symboliclabel"] else @chk nc <= 2 (ex, "Too many arguments to break") label = ex[1] label_kind = kind(label) if label_kind == K"Symbol" label = @ast(ctx, label, label.name_val::K"symboliclabel") elseif !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"symboliclabel" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid break label: expected identifier")) end if nc == 2 @ast ctx ex [K"break" label expand_forms_2(ctx, ex[2])] else @ast ctx ex [K"break" label] end end elseif k == K"continue" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_cont"::K"symboliclabel"] else @chk nc == 1 (ex, "Too many arguments to continue") label = ex[1] label_kind = kind(label) if !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"Symbol" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid continue label: expected identifier")) end @ast ctx ex [K"break" string(label.name_val, "#cont")::K"symboliclabel"] end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"::" @chk numchildren(ex) == 2 "`::` must be written `value::type` outside function argument lists" @ast ctx ex [K"call"; "typeassert"::K"core"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] elseif k == K"<:" || (k == K">:" || k == K"-->") expand_forms_2(ctx, @ast(ctx, ex, [K"call"; adopt_scope(string(k)::K"Identifier", ex); children(ex)...])) elseif k == K"op=" || k == K".op=" expand_forms_2(ctx, expand_update_operator(ctx, ex)) elseif k == K"=" expand_assignment(ctx, ex) elseif k == K"break" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_exit"::K"symboliclabel"] else @chk nc <= 2 (ex, "Too many arguments to break") label = ex[1] label_kind = kind(label) if label_kind == K"Symbol" label = @ast(ctx, label, label.name_val::K"symboliclabel") elseif !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"symboliclabel" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid break label: expected identifier")) end if nc == 2 @ast ctx ex [K"break" label expand_forms_2(ctx, ex[2])] else @ast ctx ex [K"break" label] end end elseif k == K"continue" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_cont"::K"symboliclabel"] else @chk nc == 1 (ex, "Too many arguments to continue") label = ex[1] label_kind = kind(label) if !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"Symbol" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid continue label: expected identifier")) end @ast ctx ex [K"break" string(label.name_val, "#cont")::K"symboliclabel"] end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"&&" || k == K"||" @chk numchildren(ex) > 1 cs = expand_cond_children(ctx, ex) cond = if length(cs) == 2 cs[1] else newnode(ctx, ex, k, cs[1:var"end" - 1]) end if k == K"&&" @ast ctx ex [K"if" cond cs[var"end"] false::K"Bool"] else @ast ctx ex [K"if" cond true::K"Bool" cs[var"end"]] end elseif k == K"::" @chk numchildren(ex) == 2 "`::` must be written `value::type` outside function argument lists" @ast ctx ex [K"call"; "typeassert"::K"core"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] elseif k == K"<:" || (k == K">:" || k == K"-->") expand_forms_2(ctx, @ast(ctx, ex, [K"call"; adopt_scope(string(k)::K"Identifier", ex); children(ex)...])) elseif k == K"op=" || k == K".op=" expand_forms_2(ctx, expand_update_operator(ctx, ex)) elseif k == K"=" expand_assignment(ctx, ex) elseif k == K"break" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_exit"::K"symboliclabel"] else @chk nc <= 2 (ex, "Too many arguments to break") label = ex[1] label_kind = kind(label) if label_kind == K"Symbol" label = @ast(ctx, label, label.name_val::K"symboliclabel") elseif !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"symboliclabel" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid break label: expected identifier")) end if nc == 2 @ast ctx ex [K"break" label expand_forms_2(ctx, ex[2])] else @ast ctx ex [K"break" label] end end elseif k == K"continue" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_cont"::K"symboliclabel"] else @chk nc == 1 (ex, "Too many arguments to continue") label = ex[1] label_kind = kind(label) if !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"Symbol" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid continue label: expected identifier")) end @ast ctx ex [K"break" string(label.name_val, "#cont")::K"symboliclabel"] end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"&&" || k == K"||" @chk numchildren(ex) > 1 cs = expand_cond_children(ctx, ex) cond = if length(cs) == 2 cs[1] else newnode(ctx, ex, k, cs[1:var"end" - 1]) end if k == K"&&" @ast ctx ex [K"if" cond cs[var"end"] false::K"Bool"] else @ast ctx ex [K"if" cond true::K"Bool" cs[var"end"]] end elseif k == K"::" @chk numchildren(ex) == 2 "`::` must be written `value::type` outside function argument lists" @ast ctx ex [K"call"; "typeassert"::K"core"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] elseif k == K"<:" || (k == K">:" || k == K"-->") expand_forms_2(ctx, @ast(ctx, ex, [K"call"; adopt_scope(string(k)::K"Identifier", ex); children(ex)...])) elseif k == K"op=" || k == K".op=" expand_forms_2(ctx, expand_update_operator(ctx, ex)) elseif k == K"=" expand_assignment(ctx, ex) elseif k == K"break" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_exit"::K"symboliclabel"] else @chk nc <= 2 (ex, "Too many arguments to break") label = ex[1] label_kind = kind(label) if label_kind == K"Symbol" label = @ast(ctx, label, label.name_val::K"symboliclabel") elseif !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"symboliclabel" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid break label: expected identifier")) end if nc == 2 @ast ctx ex [K"break" label expand_forms_2(ctx, ex[2])] else @ast ctx ex [K"break" label] end end elseif k == K"continue" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_cont"::K"symboliclabel"] else @chk nc == 1 (ex, "Too many arguments to continue") label = ex[1] label_kind = kind(label) if !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"Symbol" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid continue label: expected identifier")) end @ast ctx ex [K"break" string(label.name_val, "#cont")::K"symboliclabel"] end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"?" @chk numchildren(ex) == 3 expand_forms_2(ctx, @ast(ctx, ex, [K"if" children(ex)...])) elseif k == K"&&" || k == K"||" @chk numchildren(ex) > 1 cs = expand_cond_children(ctx, ex) cond = if length(cs) == 2 cs[1] else newnode(ctx, ex, k, cs[1:var"end" - 1]) end if k == K"&&" @ast ctx ex [K"if" cond cs[var"end"] false::K"Bool"] else @ast ctx ex [K"if" cond true::K"Bool" cs[var"end"]] end elseif k == K"::" @chk numchildren(ex) == 2 "`::` must be written `value::type` outside function argument lists" @ast ctx ex [K"call"; "typeassert"::K"core"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] elseif k == K"<:" || (k == K">:" || k == K"-->") expand_forms_2(ctx, @ast(ctx, ex, [K"call"; adopt_scope(string(k)::K"Identifier", ex); children(ex)...])) elseif k == K"op=" || k == K".op=" expand_forms_2(ctx, expand_update_operator(ctx, ex)) elseif k == K"=" expand_assignment(ctx, ex) elseif k == K"break" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_exit"::K"symboliclabel"] else @chk nc <= 2 (ex, "Too many arguments to break") label = ex[1] label_kind = kind(label) if label_kind == K"Symbol" label = @ast(ctx, label, label.name_val::K"symboliclabel") elseif !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"symboliclabel" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid break label: expected identifier")) end if nc == 2 @ast ctx ex [K"break" label expand_forms_2(ctx, ex[2])] else @ast ctx ex [K"break" label] end end elseif k == K"continue" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_cont"::K"symboliclabel"] else @chk nc == 1 (ex, "Too many arguments to continue") label = ex[1] label_kind = kind(label) if !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"Symbol" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid continue label: expected identifier")) end @ast ctx ex [K"break" string(label.name_val, "#cont")::K"symboliclabel"] end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"?" @chk numchildren(ex) == 3 expand_forms_2(ctx, @ast(ctx, ex, [K"if" children(ex)...])) elseif k == K"&&" || k == K"||" @chk numchildren(ex) > 1 cs = expand_cond_children(ctx, ex) cond = if length(cs) == 2 cs[1] else newnode(ctx, ex, k, cs[1:var"end" - 1]) end if k == K"&&" @ast ctx ex [K"if" cond cs[var"end"] false::K"Bool"] else @ast ctx ex [K"if" cond true::K"Bool" cs[var"end"]] end elseif k == K"::" @chk numchildren(ex) == 2 "`::` must be written `value::type` outside function argument lists" @ast ctx ex [K"call"; "typeassert"::K"core"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] elseif k == K"<:" || (k == K">:" || k == K"-->") expand_forms_2(ctx, @ast(ctx, ex, [K"call"; adopt_scope(string(k)::K"Identifier", ex); children(ex)...])) elseif k == K"op=" || k == K".op=" expand_forms_2(ctx, expand_update_operator(ctx, ex)) elseif k == K"=" expand_assignment(ctx, ex) elseif k == K"break" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_exit"::K"symboliclabel"] else @chk nc <= 2 (ex, "Too many arguments to break") label = ex[1] label_kind = kind(label) if label_kind == K"Symbol" label = @ast(ctx, label, label.name_val::K"symboliclabel") elseif !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"symboliclabel" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid break label: expected identifier")) end if nc == 2 @ast ctx ex [K"break" label expand_forms_2(ctx, ex[2])] else @ast ctx ex [K"break" label] end end elseif k == K"continue" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_cont"::K"symboliclabel"] else @chk nc == 1 (ex, "Too many arguments to continue") label = ex[1] label_kind = kind(label) if !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"Symbol" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid continue label: expected identifier")) end @ast ctx ex [K"break" string(label.name_val, "#cont")::K"symboliclabel"] end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"." expand_forms_2(ctx, expand_dot(ctx, ex)) elseif k == K"?" @chk numchildren(ex) == 3 expand_forms_2(ctx, @ast(ctx, ex, [K"if" children(ex)...])) elseif k == K"&&" || k == K"||" @chk numchildren(ex) > 1 cs = expand_cond_children(ctx, ex) cond = if length(cs) == 2 cs[1] else newnode(ctx, ex, k, cs[1:var"end" - 1]) end if k == K"&&" @ast ctx ex [K"if" cond cs[var"end"] false::K"Bool"] else @ast ctx ex [K"if" cond true::K"Bool" cs[var"end"]] end elseif k == K"::" @chk numchildren(ex) == 2 "`::` must be written `value::type` outside function argument lists" @ast ctx ex [K"call"; "typeassert"::K"core"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] elseif k == K"<:" || (k == K">:" || k == K"-->") expand_forms_2(ctx, @ast(ctx, ex, [K"call"; adopt_scope(string(k)::K"Identifier", ex); children(ex)...])) elseif k == K"op=" || k == K".op=" expand_forms_2(ctx, expand_update_operator(ctx, ex)) elseif k == K"=" expand_assignment(ctx, ex) elseif k == K"break" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_exit"::K"symboliclabel"] else @chk nc <= 2 (ex, "Too many arguments to break") label = ex[1] label_kind = kind(label) if label_kind == K"Symbol" label = @ast(ctx, label, label.name_val::K"symboliclabel") elseif !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"symboliclabel" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid break label: expected identifier")) end if nc == 2 @ast ctx ex [K"break" label expand_forms_2(ctx, ex[2])] else @ast ctx ex [K"break" label] end end elseif k == K"continue" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_cont"::K"symboliclabel"] else @chk nc == 1 (ex, "Too many arguments to continue") label = ex[1] label_kind = kind(label) if !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"Symbol" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid continue label: expected identifier")) end @ast ctx ex [K"break" string(label.name_val, "#cont")::K"symboliclabel"] end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"." expand_forms_2(ctx, expand_dot(ctx, ex)) elseif k == K"?" @chk numchildren(ex) == 3 expand_forms_2(ctx, @ast(ctx, ex, [K"if" children(ex)...])) elseif k == K"&&" || k == K"||" @chk numchildren(ex) > 1 cs = expand_cond_children(ctx, ex) cond = if length(cs) == 2 cs[1] else newnode(ctx, ex, k, cs[1:var"end" - 1]) end if k == K"&&" @ast ctx ex [K"if" cond cs[var"end"] false::K"Bool"] else @ast ctx ex [K"if" cond true::K"Bool" cs[var"end"]] end elseif k == K"::" @chk numchildren(ex) == 2 "`::` must be written `value::type` outside function argument lists" @ast ctx ex [K"call"; "typeassert"::K"core"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] elseif k == K"<:" || (k == K">:" || k == K"-->") expand_forms_2(ctx, @ast(ctx, ex, [K"call"; adopt_scope(string(k)::K"Identifier", ex); children(ex)...])) elseif k == K"op=" || k == K".op=" expand_forms_2(ctx, expand_update_operator(ctx, ex)) elseif k == K"=" expand_assignment(ctx, ex) elseif k == K"break" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_exit"::K"symboliclabel"] else @chk nc <= 2 (ex, "Too many arguments to break") label = ex[1] label_kind = kind(label) if label_kind == K"Symbol" label = @ast(ctx, label, label.name_val::K"symboliclabel") elseif !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"symboliclabel" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid break label: expected identifier")) end if nc == 2 @ast ctx ex [K"break" label expand_forms_2(ctx, ex[2])] else @ast ctx ex [K"break" label] end end elseif k == K"continue" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_cont"::K"symboliclabel"] else @chk nc == 1 (ex, "Too many arguments to continue") label = ex[1] label_kind = kind(label) if !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"Symbol" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid continue label: expected identifier")) end @ast ctx ex [K"break" string(label.name_val, "#cont")::K"symboliclabel"] end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end 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)) elseif k == K"?" @chk numchildren(ex) == 3 expand_forms_2(ctx, @ast(ctx, ex, [K"if" children(ex)...])) elseif k == K"&&" || k == K"||" @chk numchildren(ex) > 1 cs = expand_cond_children(ctx, ex) cond = if length(cs) == 2 cs[1] else newnode(ctx, ex, k, cs[1:var"end" - 1]) end if k == K"&&" @ast ctx ex [K"if" cond cs[var"end"] false::K"Bool"] else @ast ctx ex [K"if" cond true::K"Bool" cs[var"end"]] end elseif k == K"::" @chk numchildren(ex) == 2 "`::` must be written `value::type` outside function argument lists" @ast ctx ex [K"call"; "typeassert"::K"core"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] elseif k == K"<:" || (k == K">:" || k == K"-->") expand_forms_2(ctx, @ast(ctx, ex, [K"call"; adopt_scope(string(k)::K"Identifier", ex); children(ex)...])) elseif k == K"op=" || k == K".op=" expand_forms_2(ctx, expand_update_operator(ctx, ex)) elseif k == K"=" expand_assignment(ctx, ex) elseif k == K"break" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_exit"::K"symboliclabel"] else @chk nc <= 2 (ex, "Too many arguments to break") label = ex[1] label_kind = kind(label) if label_kind == K"Symbol" label = @ast(ctx, label, label.name_val::K"symboliclabel") elseif !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"symboliclabel" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid break label: expected identifier")) end if nc == 2 @ast ctx ex [K"break" label expand_forms_2(ctx, ex[2])] else @ast ctx ex [K"break" label] end end elseif k == K"continue" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_cont"::K"symboliclabel"] else @chk nc == 1 (ex, "Too many arguments to continue") label = ex[1] label_kind = kind(label) if !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"Symbol" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid continue label: expected identifier")) end @ast ctx ex [K"break" string(label.name_val, "#cont")::K"symboliclabel"] end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end 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)) elseif k == K"?" @chk numchildren(ex) == 3 expand_forms_2(ctx, @ast(ctx, ex, [K"if" children(ex)...])) elseif k == K"&&" || k == K"||" @chk numchildren(ex) > 1 cs = expand_cond_children(ctx, ex) cond = if length(cs) == 2 cs[1] else newnode(ctx, ex, k, cs[1:var"end" - 1]) end if k == K"&&" @ast ctx ex [K"if" cond cs[var"end"] false::K"Bool"] else @ast ctx ex [K"if" cond true::K"Bool" cs[var"end"]] end elseif k == K"::" @chk numchildren(ex) == 2 "`::` must be written `value::type` outside function argument lists" @ast ctx ex [K"call"; "typeassert"::K"core"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] elseif k == K"<:" || (k == K">:" || k == K"-->") expand_forms_2(ctx, @ast(ctx, ex, [K"call"; adopt_scope(string(k)::K"Identifier", ex); children(ex)...])) elseif k == K"op=" || k == K".op=" expand_forms_2(ctx, expand_update_operator(ctx, ex)) elseif k == K"=" expand_assignment(ctx, ex) elseif k == K"break" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_exit"::K"symboliclabel"] else @chk nc <= 2 (ex, "Too many arguments to break") label = ex[1] label_kind = kind(label) if label_kind == K"Symbol" label = @ast(ctx, label, label.name_val::K"symboliclabel") elseif !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"symboliclabel" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid break label: expected identifier")) end if nc == 2 @ast ctx ex [K"break" label expand_forms_2(ctx, ex[2])] else @ast ctx ex [K"break" label] end end elseif k == K"continue" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_cont"::K"symboliclabel"] else @chk nc == 1 (ex, "Too many arguments to continue") label = ex[1] label_kind = kind(label) if !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"Symbol" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid continue label: expected identifier")) end @ast ctx ex [K"break" string(label.name_val, "#cont")::K"symboliclabel"] end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"call" expand_call(ctx, 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)) elseif k == K"?" @chk numchildren(ex) == 3 expand_forms_2(ctx, @ast(ctx, ex, [K"if" children(ex)...])) elseif k == K"&&" || k == K"||" @chk numchildren(ex) > 1 cs = expand_cond_children(ctx, ex) cond = if length(cs) == 2 cs[1] else newnode(ctx, ex, k, cs[1:var"end" - 1]) end if k == K"&&" @ast ctx ex [K"if" cond cs[var"end"] false::K"Bool"] else @ast ctx ex [K"if" cond true::K"Bool" cs[var"end"]] end elseif k == K"::" @chk numchildren(ex) == 2 "`::` must be written `value::type` outside function argument lists" @ast ctx ex [K"call"; "typeassert"::K"core"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] elseif k == K"<:" || (k == K">:" || k == K"-->") expand_forms_2(ctx, @ast(ctx, ex, [K"call"; adopt_scope(string(k)::K"Identifier", ex); children(ex)...])) elseif k == K"op=" || k == K".op=" expand_forms_2(ctx, expand_update_operator(ctx, ex)) elseif k == K"=" expand_assignment(ctx, ex) elseif k == K"break" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_exit"::K"symboliclabel"] else @chk nc <= 2 (ex, "Too many arguments to break") label = ex[1] label_kind = kind(label) if label_kind == K"Symbol" label = @ast(ctx, label, label.name_val::K"symboliclabel") elseif !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"symboliclabel" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid break label: expected identifier")) end if nc == 2 @ast ctx ex [K"break" label expand_forms_2(ctx, ex[2])] else @ast ctx ex [K"break" label] end end elseif k == K"continue" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_cont"::K"symboliclabel"] else @chk nc == 1 (ex, "Too many arguments to continue") label = ex[1] label_kind = kind(label) if !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"Symbol" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid continue label: expected identifier")) end @ast ctx ex [K"break" string(label.name_val, "#cont")::K"symboliclabel"] end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end elseif k == K"call" expand_call(ctx, 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)) elseif k == K"?" @chk numchildren(ex) == 3 expand_forms_2(ctx, @ast(ctx, ex, [K"if" children(ex)...])) elseif k == K"&&" || k == K"||" @chk numchildren(ex) > 1 cs = expand_cond_children(ctx, ex) cond = if length(cs) == 2 cs[1] else newnode(ctx, ex, k, cs[1:var"end" - 1]) end if k == K"&&" @ast ctx ex [K"if" cond cs[var"end"] false::K"Bool"] else @ast ctx ex [K"if" cond true::K"Bool" cs[var"end"]] end elseif k == K"::" @chk numchildren(ex) == 2 "`::` must be written `value::type` outside function argument lists" @ast ctx ex [K"call"; "typeassert"::K"core"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] elseif k == K"<:" || (k == K">:" || k == K"-->") expand_forms_2(ctx, @ast(ctx, ex, [K"call"; adopt_scope(string(k)::K"Identifier", ex); children(ex)...])) elseif k == K"op=" || k == K".op=" expand_forms_2(ctx, expand_update_operator(ctx, ex)) elseif k == K"=" expand_assignment(ctx, ex) elseif k == K"break" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_exit"::K"symboliclabel"] else @chk nc <= 2 (ex, "Too many arguments to break") label = ex[1] label_kind = kind(label) if label_kind == K"Symbol" label = @ast(ctx, label, label.name_val::K"symboliclabel") elseif !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"symboliclabel" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid break label: expected identifier")) end if nc == 2 @ast ctx ex [K"break" label expand_forms_2(ctx, ex[2])] else @ast ctx ex [K"break" label] end end elseif k == K"continue" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_cont"::K"symboliclabel"] else @chk nc == 1 (ex, "Too many arguments to continue") label = ex[1] label_kind = kind(label) if !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"Symbol" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid continue label: expected identifier")) end @ast ctx ex [K"break" string(label.name_val, "#cont")::K"symboliclabel"] end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end if k == K"atomic" throw(LoweringError(ex, "unimplemented or unsupported atomic declaration")) elseif k == K"call" expand_call(ctx, 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)) elseif k == K"?" @chk numchildren(ex) == 3 expand_forms_2(ctx, @ast(ctx, ex, [K"if" children(ex)...])) elseif k == K"&&" || k == K"||" @chk numchildren(ex) > 1 cs = expand_cond_children(ctx, ex) cond = if length(cs) == 2 cs[1] else newnode(ctx, ex, k, cs[1:var"end" - 1]) end if k == K"&&" @ast ctx ex [K"if" cond cs[var"end"] false::K"Bool"] else @ast ctx ex [K"if" cond true::K"Bool" cs[var"end"]] end elseif k == K"::" @chk numchildren(ex) == 2 "`::` must be written `value::type` outside function argument lists" @ast ctx ex [K"call"; "typeassert"::K"core"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] elseif k == K"<:" || (k == K">:" || k == K"-->") expand_forms_2(ctx, @ast(ctx, ex, [K"call"; adopt_scope(string(k)::K"Identifier", ex); children(ex)...])) elseif k == K"op=" || k == K".op=" expand_forms_2(ctx, expand_update_operator(ctx, ex)) elseif k == K"=" expand_assignment(ctx, ex) elseif k == K"break" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_exit"::K"symboliclabel"] else @chk nc <= 2 (ex, "Too many arguments to break") label = ex[1] label_kind = kind(label) if label_kind == K"Symbol" label = @ast(ctx, label, label.name_val::K"symboliclabel") elseif !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"symboliclabel" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid break label: expected identifier")) end if nc == 2 @ast ctx ex [K"break" label expand_forms_2(ctx, ex[2])] else @ast ctx ex [K"break" label] end end elseif k == K"continue" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_cont"::K"symboliclabel"] else @chk nc == 1 (ex, "Too many arguments to continue") label = ex[1] label_kind = kind(label) if !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"Symbol" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid continue label: expected identifier")) end @ast ctx ex [K"break" string(label.name_val, "#cont")::K"symboliclabel"] end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end if k == K"atomic" throw(LoweringError(ex, "unimplemented or unsupported atomic declaration")) elseif k == K"call" expand_call(ctx, 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)) elseif k == K"?" @chk numchildren(ex) == 3 expand_forms_2(ctx, @ast(ctx, ex, [K"if" children(ex)...])) elseif k == K"&&" || k == K"||" @chk numchildren(ex) > 1 cs = expand_cond_children(ctx, ex) cond = if length(cs) == 2 cs[1] else newnode(ctx, ex, k, cs[1:var"end" - 1]) end if k == K"&&" @ast ctx ex [K"if" cond cs[var"end"] false::K"Bool"] else @ast ctx ex [K"if" cond true::K"Bool" cs[var"end"]] end elseif k == K"::" @chk numchildren(ex) == 2 "`::` must be written `value::type` outside function argument lists" @ast ctx ex [K"call"; "typeassert"::K"core"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] elseif k == K"<:" || (k == K">:" || k == K"-->") expand_forms_2(ctx, @ast(ctx, ex, [K"call"; adopt_scope(string(k)::K"Identifier", ex); children(ex)...])) elseif k == K"op=" || k == K".op=" expand_forms_2(ctx, expand_update_operator(ctx, ex)) elseif k == K"=" expand_assignment(ctx, ex) elseif k == K"break" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_exit"::K"symboliclabel"] else @chk nc <= 2 (ex, "Too many arguments to break") label = ex[1] label_kind = kind(label) if label_kind == K"Symbol" label = @ast(ctx, label, label.name_val::K"symboliclabel") elseif !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"symboliclabel" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid break label: expected identifier")) end if nc == 2 @ast ctx ex [K"break" label expand_forms_2(ctx, ex[2])] else @ast ctx ex [K"break" label] end end elseif k == K"continue" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_cont"::K"symboliclabel"] else @chk nc == 1 (ex, "Too many arguments to continue") label = ex[1] label_kind = kind(label) if !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"Symbol" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid continue label: expected identifier")) end @ast ctx ex [K"break" string(label.name_val, "#cont")::K"symboliclabel"] end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end begin k = kind(ex) if k == K"atomic" throw(LoweringError(ex, "unimplemented or unsupported atomic declaration")) elseif k == K"call" expand_call(ctx, 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)) elseif k == K"?" @chk numchildren(ex) == 3 expand_forms_2(ctx, @ast(ctx, ex, [K"if" children(ex)...])) elseif k == K"&&" || k == K"||" @chk numchildren(ex) > 1 cs = expand_cond_children(ctx, ex) cond = if length(cs) == 2 cs[1] else newnode(ctx, ex, k, cs[1:var"end" - 1]) end if k == K"&&" @ast ctx ex [K"if" cond cs[var"end"] false::K"Bool"] else @ast ctx ex [K"if" cond true::K"Bool" cs[var"end"]] end elseif k == K"::" @chk numchildren(ex) == 2 "`::` must be written `value::type` outside function argument lists" @ast ctx ex [K"call"; "typeassert"::K"core"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] elseif k == K"<:" || (k == K">:" || k == K"-->") expand_forms_2(ctx, @ast(ctx, ex, [K"call"; adopt_scope(string(k)::K"Identifier", ex); children(ex)...])) elseif k == K"op=" || k == K".op=" expand_forms_2(ctx, expand_update_operator(ctx, ex)) elseif k == K"=" expand_assignment(ctx, ex) elseif k == K"break" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_exit"::K"symboliclabel"] else @chk nc <= 2 (ex, "Too many arguments to break") label = ex[1] label_kind = kind(label) if label_kind == K"Symbol" label = @ast(ctx, label, label.name_val::K"symboliclabel") elseif !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"symboliclabel" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid break label: expected identifier")) end if nc == 2 @ast ctx ex [K"break" label expand_forms_2(ctx, ex[2])] else @ast ctx ex [K"break" label] end end elseif k == K"continue" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_cont"::K"symboliclabel"] else @chk nc == 1 (ex, "Too many arguments to continue") label = ex[1] label_kind = kind(label) if !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"Symbol" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid continue label: expected identifier")) end @ast ctx ex [K"break" string(label.name_val, "#cont")::K"symboliclabel"] end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end end begin k = kind(ex) if k == K"atomic" throw(LoweringError(ex, "unimplemented or unsupported atomic declaration")) elseif k == K"call" expand_call(ctx, 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)) elseif k == K"?" @chk numchildren(ex) == 3 expand_forms_2(ctx, @ast(ctx, ex, [K"if" children(ex)...])) elseif k == K"&&" || k == K"||" @chk numchildren(ex) > 1 cs = expand_cond_children(ctx, ex) cond = if length(cs) == 2 cs[1] else newnode(ctx, ex, k, cs[1:var"end" - 1]) end if k == K"&&" @ast ctx ex [K"if" cond cs[var"end"] false::K"Bool"] else @ast ctx ex [K"if" cond true::K"Bool" cs[var"end"]] end elseif k == K"::" @chk numchildren(ex) == 2 "`::` must be written `value::type` outside function argument lists" @ast ctx ex [K"call"; "typeassert"::K"core"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] elseif k == K"<:" || (k == K">:" || k == K"-->") expand_forms_2(ctx, @ast(ctx, ex, [K"call"; adopt_scope(string(k)::K"Identifier", ex); children(ex)...])) elseif k == K"op=" || k == K".op=" expand_forms_2(ctx, expand_update_operator(ctx, ex)) elseif k == K"=" expand_assignment(ctx, ex) elseif k == K"break" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_exit"::K"symboliclabel"] else @chk nc <= 2 (ex, "Too many arguments to break") label = ex[1] label_kind = kind(label) if label_kind == K"Symbol" label = @ast(ctx, label, label.name_val::K"symboliclabel") elseif !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"symboliclabel" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid break label: expected identifier")) end if nc == 2 @ast ctx ex [K"break" label expand_forms_2(ctx, ex[2])] else @ast ctx ex [K"break" label] end end elseif k == K"continue" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_cont"::K"symboliclabel"] else @chk nc == 1 (ex, "Too many arguments to continue") label = ex[1] label_kind = kind(label) if !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"Symbol" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid continue label: expected identifier")) end @ast ctx ex [K"break" string(label.name_val, "#cont")::K"symboliclabel"] end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end end function expand_forms_2(ctx::DesugaringContext, ex::SyntaxTree, docs = nothing) k = kind(ex) if k == K"atomic" throw(LoweringError(ex, "unimplemented or unsupported atomic declaration")) elseif k == K"call" expand_call(ctx, 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)) elseif k == K"?" @chk numchildren(ex) == 3 expand_forms_2(ctx, @ast(ctx, ex, [K"if" children(ex)...])) elseif k == K"&&" || k == K"||" @chk numchildren(ex) > 1 cs = expand_cond_children(ctx, ex) cond = if length(cs) == 2 cs[1] else newnode(ctx, ex, k, cs[1:var"end" - 1]) end if k == K"&&" @ast ctx ex [K"if" cond cs[var"end"] false::K"Bool"] else @ast ctx ex [K"if" cond true::K"Bool" cs[var"end"]] end elseif k == K"::" @chk numchildren(ex) == 2 "`::` must be written `value::type` outside function argument lists" @ast ctx ex [K"call"; "typeassert"::K"core"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] elseif k == K"<:" || (k == K">:" || k == K"-->") expand_forms_2(ctx, @ast(ctx, ex, [K"call"; adopt_scope(string(k)::K"Identifier", ex); children(ex)...])) elseif k == K"op=" || k == K".op=" expand_forms_2(ctx, expand_update_operator(ctx, ex)) elseif k == K"=" expand_assignment(ctx, ex) elseif k == K"break" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_exit"::K"symboliclabel"] else @chk nc <= 2 (ex, "Too many arguments to break") label = ex[1] label_kind = kind(label) if label_kind == K"Symbol" label = @ast(ctx, label, label.name_val::K"symboliclabel") elseif !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"symboliclabel" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid break label: expected identifier")) end if nc == 2 @ast ctx ex [K"break" label expand_forms_2(ctx, ex[2])] else @ast ctx ex [K"break" label] end end elseif k == K"continue" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_cont"::K"symboliclabel"] else @chk nc == 1 (ex, "Too many arguments to continue") label = ex[1] label_kind = kind(label) if !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"Symbol" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid continue label: expected identifier")) end @ast ctx ex [K"break" string(label.name_val, "#cont")::K"symboliclabel"] end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end end function expand_forms_2(ctx::DesugaringContext, ex::SyntaxTree, docs = nothing) k = kind(ex) if k == K"atomic" throw(LoweringError(ex, "unimplemented or unsupported atomic declaration")) elseif k == K"call" expand_call(ctx, 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)) elseif k == K"?" @chk numchildren(ex) == 3 expand_forms_2(ctx, @ast(ctx, ex, [K"if" children(ex)...])) elseif k == K"&&" || k == K"||" @chk numchildren(ex) > 1 cs = expand_cond_children(ctx, ex) cond = if length(cs) == 2 cs[1] else newnode(ctx, ex, k, cs[1:var"end" - 1]) end if k == K"&&" @ast ctx ex [K"if" cond cs[var"end"] false::K"Bool"] else @ast ctx ex [K"if" cond true::K"Bool" cs[var"end"]] end elseif k == K"::" @chk numchildren(ex) == 2 "`::` must be written `value::type` outside function argument lists" @ast ctx ex [K"call"; "typeassert"::K"core"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] elseif k == K"<:" || (k == K">:" || k == K"-->") expand_forms_2(ctx, @ast(ctx, ex, [K"call"; adopt_scope(string(k)::K"Identifier", ex); children(ex)...])) elseif k == K"op=" || k == K".op=" expand_forms_2(ctx, expand_update_operator(ctx, ex)) elseif k == K"=" expand_assignment(ctx, ex) elseif k == K"break" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_exit"::K"symboliclabel"] else @chk nc <= 2 (ex, "Too many arguments to break") label = ex[1] label_kind = kind(label) if label_kind == K"Symbol" label = @ast(ctx, label, label.name_val::K"symboliclabel") elseif !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"symboliclabel" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid break label: expected identifier")) end if nc == 2 @ast ctx ex [K"break" label expand_forms_2(ctx, ex[2])] else @ast ctx ex [K"break" label] end end elseif k == K"continue" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_cont"::K"symboliclabel"] else @chk nc == 1 (ex, "Too many arguments to continue") label = ex[1] label_kind = kind(label) if !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"Symbol" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid continue label: expected identifier")) end @ast ctx ex [K"break" string(label.name_val, "#cont")::K"symboliclabel"] end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end end Core.@doc "Lowering pass 2 - desugaring\n\nThis pass simplifies expressions by expanding complicated syntax sugar into a\nsmall set of core syntactic forms. For example, field access syntax `a.b` is\nexpanded to a function call `getproperty(a, :b)`.\n" function expand_forms_2(ctx::DesugaringContext, ex::SyntaxTree, docs = nothing) k = kind(ex) if k == K"atomic" throw(LoweringError(ex, "unimplemented or unsupported atomic declaration")) elseif k == K"call" expand_call(ctx, 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)) elseif k == K"?" @chk numchildren(ex) == 3 expand_forms_2(ctx, @ast(ctx, ex, [K"if" children(ex)...])) elseif k == K"&&" || k == K"||" @chk numchildren(ex) > 1 cs = expand_cond_children(ctx, ex) cond = if length(cs) == 2 cs[1] else newnode(ctx, ex, k, cs[1:var"end" - 1]) end if k == K"&&" @ast ctx ex [K"if" cond cs[var"end"] false::K"Bool"] else @ast ctx ex [K"if" cond true::K"Bool" cs[var"end"]] end elseif k == K"::" @chk numchildren(ex) == 2 "`::` must be written `value::type` outside function argument lists" @ast ctx ex [K"call"; "typeassert"::K"core"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] elseif k == K"<:" || (k == K">:" || k == K"-->") expand_forms_2(ctx, @ast(ctx, ex, [K"call"; adopt_scope(string(k)::K"Identifier", ex); children(ex)...])) elseif k == K"op=" || k == K".op=" expand_forms_2(ctx, expand_update_operator(ctx, ex)) elseif k == K"=" expand_assignment(ctx, ex) elseif k == K"break" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_exit"::K"symboliclabel"] else @chk nc <= 2 (ex, "Too many arguments to break") label = ex[1] label_kind = kind(label) if label_kind == K"Symbol" label = @ast(ctx, label, label.name_val::K"symboliclabel") elseif !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"symboliclabel" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid break label: expected identifier")) end if nc == 2 @ast ctx ex [K"break" label expand_forms_2(ctx, ex[2])] else @ast ctx ex [K"break" label] end end elseif k == K"continue" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_cont"::K"symboliclabel"] else @chk nc == 1 (ex, "Too many arguments to continue") label = ex[1] label_kind = kind(label) if !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"Symbol" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid continue label: expected identifier")) end @ast ctx ex [K"break" string(label.name_val, "#cont")::K"symboliclabel"] end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval ::K"Value"; ctx.mod ::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end end Core.@doc "Lowering pass 2 - desugaring\n\nThis pass simplifies expressions by expanding complicated syntax sugar into a\nsmall set of core syntactic forms. For example, field access syntax `a.b` is\nexpanded to a function call `getproperty(a, :b)`.\n" function expand_forms_2(ctx::DesugaringContext, ex::SyntaxTree, docs = nothing) k = kind(ex) if k == K"atomic" throw(LoweringError(ex, "unimplemented or unsupported atomic declaration")) elseif k == K"call" expand_call(ctx, 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)) elseif k == K"?" @chk numchildren(ex) == 3 expand_forms_2(ctx, @ast(ctx, ex, [K"if" children(ex)...])) elseif k == K"&&" || k == K"||" @chk numchildren(ex) > 1 cs = expand_cond_children(ctx, ex) cond = if length(cs) == 2 cs[1] else newnode(ctx, ex, k, cs[1:var"end" - 1]) end if k == K"&&" @ast ctx ex [K"if" cond cs[var"end"] false::K"Bool"] else @ast ctx ex [K"if" cond true::K"Bool" cs[var"end"]] end elseif k == K"::" @chk numchildren(ex) == 2 "`::` must be written `value::type` outside function argument lists" @ast ctx ex [K"call"; "typeassert"::K"core"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] elseif k == K"<:" || (k == K">:" || k == K"-->") expand_forms_2(ctx, @ast(ctx, ex, [K"call"; adopt_scope(string(k)::K"Identifier", ex); children(ex)...])) elseif k == K"op=" || k == K".op=" expand_forms_2(ctx, expand_update_operator(ctx, ex)) elseif k == K"=" expand_assignment(ctx, ex) elseif k == K"break" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_exit"::K"symboliclabel"] else @chk nc <= 2 (ex, "Too many arguments to break") label = ex[1] label_kind = kind(label) if label_kind == K"Symbol" label = @ast(ctx, label, label.name_val::K"symboliclabel") elseif !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"symboliclabel" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid break label: expected identifier")) end if nc == 2 @ast ctx ex [K"break" label expand_forms_2(ctx, ex[2])] else @ast ctx ex [K"break" label] end end elseif k == K"continue" nc = numchildren(ex) if nc == 0 @ast ctx ex [K"break" "loop_cont"::K"symboliclabel"] else @chk nc == 1 (ex, "Too many arguments to continue") label = ex[1] label_kind = kind(label) if !(label_kind == K"Identifier" || (label_kind == K"Placeholder" || (label_kind == K"Symbol" || is_contextual_keyword(label_kind)))) throw(LoweringError(label, "Invalid continue label: expected identifier")) end @ast ctx ex [K"break" string(label.name_val, "#cont")::K"symboliclabel"] end elseif k == K"comparison" expand_forms_2(ctx, expand_compare_chain(ctx, ex)) elseif k == K"doc" @chk numchildren(ex) == 2 expand_doc(ctx, ex[2], ex) elseif k == K"for" expand_forms_2(ctx, expand_for(ctx, ex)) elseif k == K"comprehension" @chk numchildren(ex) == 1 @chk kind(ex[1]) == K"generator" @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1])] elseif k == K"typed_comprehension" @chk numchildren(ex) == 2 @chk kind(ex[2]) == K"generator" if numchildren(ex[2]) == 2 && kind((ex[2])[2]) == K"iteration" expand_forms_2(ctx, expand_comprehension_to_loops(ctx, ex)) else @ast ctx ex [K"call"; "collect"::K"top"; expand_forms_2(ctx, ex[1]); expand_forms_2(ctx, ex[2])] end elseif k == K"generator" expand_forms_2(ctx, expand_generator(ctx, ex)) elseif k == K"->" || k == K"do" expand_forms_2(ctx, expand_arrow(ctx, ex)) elseif k == K"function" || k == K"generated_function" expand_forms_2(ctx, expand_function_def(ctx, ex, docs)) elseif k == K"macro" @ast ctx ex [K"block"; [K"assert"; "global_toplevel_only"::K"Symbol"; [K"inert_syntaxtree" ex]]; expand_forms_2(ctx, expand_macro_def(ctx, ex))] elseif k == K"if" || k == K"elseif" @chk numchildren(ex) >= 2 @ast ctx ex [k; expand_condition(ctx, ex[1]); expand_forms_2(ctx, ex[2:var"end"])...] elseif k == K"let" expand_forms_2(ctx, expand_let(ctx, 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" expand_const_decl(ctx, @ast(ctx, ex, [K"const" [K"global" (ex[1])[1]]])) else expand_decls(ctx, ex) end elseif k == K"where" expand_forms_2(ctx, expand_wheres(ctx, ex)) elseif k == K"braces" || k == K"bracescat" throw(LoweringError(ex, "{ } syntax is reserved for future use")) elseif k == K"string" if numchildren(ex) == 1 && kind(ex[1]) == K"String" ex[1] else @ast ctx ex [K"call"; "string"::K"top"; expand_forms_2(ctx, children(ex))...] end elseif k == K"try" expand_forms_2(ctx, expand_try(ctx, ex)) elseif k == K"tuple" if has_parameters(ex) if numchildren(ex) > 1 throw(LoweringError(ex[var"end"], "unexpected semicolon in tuple - use `,` to separate tuple elements")) end expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex[1]), true)) elseif any_assignment(children(ex)) expand_forms_2(ctx, expand_named_tuple(ctx, ex, children(ex), true)) else expand_forms_2(ctx, @ast(ctx, ex, [K"call"; "tuple"::K"core"; children(ex)...])) end elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote block")) elseif k == K"module" throw(LoweringError(ex, "`module` is only allowed at top level")) elseif k == K"import" || k == K"using" expand_import_or_using(ctx, ex) elseif k == K"export" || k == K"public" expand_public(ctx, ex) elseif k == K"abstract" || k == K"primitive" expand_forms_2(ctx, expand_abstract_or_primitive_type(ctx, ex)) elseif k == K"struct" expand_forms_2(ctx, expand_struct_def(ctx, ex, docs)) elseif k == K"ref" sctx = with_stmts(ctx) (arr, idxs) = expand_ref_components(sctx, ex) expand_forms_2(ctx, @ast(ctx, ex, [K"block"; sctx.stmts...; [K"call"; "getindex"::K"top"; arr; idxs...]])) elseif k == K"curly" expand_forms_2(ctx, expand_curly(ctx, ex)) elseif k == K"toplevel" ex2 = @ast(ctx, ex, [K"block"; [K"assert" "toplevel_only"::K"Symbol" [K"inert_syntaxtree" ex]]; [K"call"; eval::K"Value"; ctx.mod::K"Value"; [K"inert_syntaxtree" ex]; [K"parameters"; [K"kw"; "expr_compat_mode"::K"Identifier"; ctx.expr_compat_mode::K"Bool"]]]]) expand_forms_2(ctx, ex2) elseif k == K"vect" check_no_parameters(ex, "unexpected semicolon in array expression") expand_array(ctx, ex, "vect") elseif k == K"hcat" expand_array(ctx, ex, "hcat") elseif k == K"typed_hcat" expand_array(ctx, ex, "typed_hcat") elseif k == K"opaque_closure" expand_forms_2(ctx, expand_opaque_closure(ctx, ex)) elseif k == K"vcat" || k == K"typed_vcat" expand_forms_2(ctx, expand_vcat(ctx, ex)) elseif k == K"ncat" || k == K"typed_ncat" expand_forms_2(ctx, expand_ncat(ctx, ex)) elseif k == K"while" @chk numchildren(ex) == 2 @ast ctx ex [K"break_block" "loop_exit"::K"symboliclabel"; [K"_while"; expand_condition(ctx, ex[1]); [K"break_block" "loop_cont"::K"symboliclabel"; [(K"scope_block")(scope_type = :neutral); expand_forms_2(ctx, ex[2])]]]] elseif k == K"inert" || k == K"inert_syntaxtree" ex elseif k == K"symbolicblock" @chk numchildren(ex) == 2 @ast ctx ex [K"symbolicblock" ex[1] expand_forms_2(ctx, ex[2])] elseif k == K"gc_preserve" s = ssavar(ctx, ex) r = ssavar(ctx, ex) @ast ctx ex [K"block"; s := [K"gc_preserve_begin" (children(ex))[2:var"end"]...]; r := expand_forms_2(ctx, (children(ex))[1]); [K"gc_preserve_end" s]; r] elseif k == K"&" throw(LoweringError(ex, "invalid syntax")) elseif k == K"$" throw(LoweringError(ex, "`\$` expression outside string or quote")) elseif k == K"..." throw(LoweringError(ex, "`...` expression outside call")) elseif is_leaf(ex) ex elseif k == K"return" if numchildren(ex) == 0 @ast ctx ex [K"return" "nothing"::K"core"] elseif numchildren(ex) == 1 mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) else throw(LoweringError(ex, "More than one argument to return")) end else mapchildren((e->begin expand_forms_2(ctx, e) end), ctx, ex) end end Parsing files in Base: Test Failed at /home/pkgeval/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:166 Expression: false Stacktrace: [1] macro expansion @ /opt/julia/share/julia/stdlib/v1.14/Test/src/Test.jl:782 [inlined] [2] top-level scope @ ~/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:166 ┌ Error: parsing difference │ file = "/opt/julia/bin/../share/julia/JuliaSyntax/test/literal_parsing.jl" └ @ Main.var"##302" ~/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:157 n == 340282366920938463463374607431768211456 n == 340282366920938463463374607431768211456 n isa BigInt && n == 340282366920938463463374607431768211456 n isa BigInt && n == 340282366920938463463374607431768211456 begin n = hexint("0x100000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end begin n = hexint("0x100000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end @test begin n = hexint("0x100000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end @test begin n = hexint("0x100000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end begin @test hexint("0xff") === UInt8(0xff) @test hexint("0x100") === UInt16(0x0100) @test hexint("0xffff") === UInt16(0xffff) @test hexint("0x10000") === UInt32(0x00010000) @test hexint("0xffffffff") === UInt32(0xffffffff) @test hexint("0x100000000") === UInt64(0x0000000100000000) @test hexint("0xffffffffffffffff") === UInt64(0xffffffffffffffff) @test hexint("0x10000000000000000") === UInt128(0x10000000000000000) @test hexint("0xffffffffffffffffffffffffffffffff") === UInt128(0xffffffffffffffffffffffffffffffff) @test begin n = hexint("0x100000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end end begin @test hexint("0xff") === UInt8(0xff) @test hexint("0x100") === UInt16(0x0100) @test hexint("0xffff") === UInt16(0xffff) @test hexint("0x10000") === UInt32(0x00010000) @test hexint("0xffffffff") === UInt32(0xffffffff) @test hexint("0x100000000") === UInt64(0x0000000100000000) @test hexint("0xffffffffffffffff") === UInt64(0xffffffffffffffff) @test hexint("0x10000000000000000") === UInt128(0x10000000000000000) @test hexint("0xffffffffffffffffffffffffffffffff") === UInt128(0xffffffffffffffffffffffffffffffff) @test begin n = hexint("0x100000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end end @testset "HexInt numeric limits for different types" begin @test hexint("0xff") === UInt8(0xff) @test hexint("0x100") === UInt16(0x0100) @test hexint("0xffff") === UInt16(0xffff) @test hexint("0x10000") === UInt32(0x00010000) @test hexint("0xffffffff") === UInt32(0xffffffff) @test hexint("0x100000000") === UInt64(0x0000000100000000) @test hexint("0xffffffffffffffff") === UInt64(0xffffffffffffffff) @test hexint("0x10000000000000000") === UInt128(0x10000000000000000) @test hexint("0xffffffffffffffffffffffffffffffff") === UInt128(0xffffffffffffffffffffffffffffffff) @test begin n = hexint("0x100000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end end @testset "HexInt numeric limits for different types" begin @test hexint("0xff") === UInt8(0xff) @test hexint("0x100") === UInt16(0x0100) @test hexint("0xffff") === UInt16(0xffff) @test hexint("0x10000") === UInt32(0x00010000) @test hexint("0xffffffff") === UInt32(0xffffffff) @test hexint("0x100000000") === UInt64(0x0000000100000000) @test hexint("0xffffffffffffffff") === UInt64(0xffffffffffffffff) @test hexint("0x10000000000000000") === UInt128(0x10000000000000000) @test hexint("0xffffffffffffffffffffffffffffffff") === UInt128(0xffffffffffffffffffffffffffffffff) @test begin n = hexint("0x100000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end end n == 340282366920938463463374607431768211456 n == 340282366920938463463374607431768211456 n isa BigInt && n == 340282366920938463463374607431768211456 n isa BigInt && n == 340282366920938463463374607431768211456 begin n = binint("0b100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end begin n = binint("0b100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end @test begin n = binint("0b100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end @test begin n = binint("0b100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end begin @test binint("0b11111111") === UInt8(0xff) @test binint("0b100000000") === UInt16(0x0100) @test binint("0b1111111111111111") === UInt16(0xffff) @test binint("0b10000000000000000") === UInt32(0x00010000) @test binint("0b11111111111111111111111111111111") === UInt32(0xffffffff) @test binint("0b100000000000000000000000000000000") === UInt64(0x0000000100000000) @test binint("0b1111111111111111111111111111111111111111111111111111111111111111") === UInt64(0xffffffffffffffff) @test binint("0b10000000000000000000000000000000000000000000000000000000000000000") === UInt128(0x10000000000000000) @test binint("0b11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111") === UInt128(0xffffffffffffffffffffffffffffffff) @test begin n = binint("0b100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end end begin @test binint("0b11111111") === UInt8(0xff) @test binint("0b100000000") === UInt16(0x0100) @test binint("0b1111111111111111") === UInt16(0xffff) @test binint("0b10000000000000000") === UInt32(0x00010000) @test binint("0b11111111111111111111111111111111") === UInt32(0xffffffff) @test binint("0b100000000000000000000000000000000") === UInt64(0x0000000100000000) @test binint("0b1111111111111111111111111111111111111111111111111111111111111111") === UInt64(0xffffffffffffffff) @test binint("0b10000000000000000000000000000000000000000000000000000000000000000") === UInt128(0x10000000000000000) @test binint("0b11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111") === UInt128(0xffffffffffffffffffffffffffffffff) @test begin n = binint("0b100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end end @testset "BinInt numeric limits for different types" begin @test binint("0b11111111") === UInt8(0xff) @test binint("0b100000000") === UInt16(0x0100) @test binint("0b1111111111111111") === UInt16(0xffff) @test binint("0b10000000000000000") === UInt32(0x00010000) @test binint("0b11111111111111111111111111111111") === UInt32(0xffffffff) @test binint("0b100000000000000000000000000000000") === UInt64(0x0000000100000000) @test binint("0b1111111111111111111111111111111111111111111111111111111111111111") === UInt64(0xffffffffffffffff) @test binint("0b10000000000000000000000000000000000000000000000000000000000000000") === UInt128(0x10000000000000000) @test binint("0b11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111") === UInt128(0xffffffffffffffffffffffffffffffff) @test begin n = binint("0b100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end end @testset "BinInt numeric limits for different types" begin @test binint("0b11111111") === UInt8(0xff) @test binint("0b100000000") === UInt16(0x0100) @test binint("0b1111111111111111") === UInt16(0xffff) @test binint("0b10000000000000000") === UInt32(0x00010000) @test binint("0b11111111111111111111111111111111") === UInt32(0xffffffff) @test binint("0b100000000000000000000000000000000") === UInt64(0x0000000100000000) @test binint("0b1111111111111111111111111111111111111111111111111111111111111111") === UInt64(0xffffffffffffffff) @test binint("0b10000000000000000000000000000000000000000000000000000000000000000") === UInt128(0x10000000000000000) @test binint("0b11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111") === UInt128(0xffffffffffffffffffffffffffffffff) @test begin n = binint("0b100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end end n == 340282366920938463463374607431768211456 n == 340282366920938463463374607431768211456 n isa BigInt && n == 340282366920938463463374607431768211456 n isa BigInt && n == 340282366920938463463374607431768211456 begin n = octint("0o4000000000000000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end begin n = octint("0o4000000000000000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end @test begin n = octint("0o4000000000000000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end @test begin n = octint("0o4000000000000000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end begin @test octint("0o377") === UInt8(0xff) @test octint("0o400") === UInt16(0x0100) @test octint("0o177777") === UInt16(0xffff) @test octint("0o200000") === UInt32(0x00010000) @test octint("0o37777777777") === UInt32(0xffffffff) @test octint("0o40000000000") === UInt64(0x0000000100000000) @test octint("0o1777777777777777777777") === UInt64(0xffffffffffffffff) @test octint("0o2000000000000000000000") === UInt128(0x10000000000000000) @test octint("0o3777777777777777777777777777777777777777777") === UInt128(0xffffffffffffffffffffffffffffffff) @test begin n = octint("0o4000000000000000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end end begin @test octint("0o377") === UInt8(0xff) @test octint("0o400") === UInt16(0x0100) @test octint("0o177777") === UInt16(0xffff) @test octint("0o200000") === UInt32(0x00010000) @test octint("0o37777777777") === UInt32(0xffffffff) @test octint("0o40000000000") === UInt64(0x0000000100000000) @test octint("0o1777777777777777777777") === UInt64(0xffffffffffffffff) @test octint("0o2000000000000000000000") === UInt128(0x10000000000000000) @test octint("0o3777777777777777777777777777777777777777777") === UInt128(0xffffffffffffffffffffffffffffffff) @test begin n = octint("0o4000000000000000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end end @testset "OctInt numeric limits for different types" begin @test octint("0o377") === UInt8(0xff) @test octint("0o400") === UInt16(0x0100) @test octint("0o177777") === UInt16(0xffff) @test octint("0o200000") === UInt32(0x00010000) @test octint("0o37777777777") === UInt32(0xffffffff) @test octint("0o40000000000") === UInt64(0x0000000100000000) @test octint("0o1777777777777777777777") === UInt64(0xffffffffffffffff) @test octint("0o2000000000000000000000") === UInt128(0x10000000000000000) @test octint("0o3777777777777777777777777777777777777777777") === UInt128(0xffffffffffffffffffffffffffffffff) @test begin n = octint("0o4000000000000000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end end @testset "OctInt numeric limits for different types" begin @test octint("0o377") === UInt8(0xff) @test octint("0o400") === UInt16(0x0100) @test octint("0o177777") === UInt16(0xffff) @test octint("0o200000") === UInt32(0x00010000) @test octint("0o37777777777") === UInt32(0xffffffff) @test octint("0o40000000000") === UInt64(0x0000000100000000) @test octint("0o1777777777777777777777") === UInt64(0xffffffffffffffff) @test octint("0o2000000000000000000000") === UInt128(0x10000000000000000) @test octint("0o3777777777777777777777777777777777777777777") === UInt128(0xffffffffffffffffffffffffffffffff) @test begin n = octint("0o4000000000000000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end end begin @testset "Signed Integers" begin @test parse_int_literal("-1") isa Int @test parse_int_literal("1") isa Int @test parse_int_literal("2147483647") isa Int @test parse_int_literal("9223372036854775807") isa Int64 @test parse_int_literal("9223372036854775808") isa Int128 @test parse_int_literal("170141183460469231731687303715884105727") isa Int128 @test parse_int_literal("170141183460469231731687303715884105728") isa BigInt end @testset "HexInt numeric limits for different types" begin @test hexint("0xff") === UInt8(0xff) @test hexint("0x100") === UInt16(0x0100) @test hexint("0xffff") === UInt16(0xffff) @test hexint("0x10000") === UInt32(0x00010000) @test hexint("0xffffffff") === UInt32(0xffffffff) @test hexint("0x100000000") === UInt64(0x0000000100000000) @test hexint("0xffffffffffffffff") === UInt64(0xffffffffffffffff) @test hexint("0x10000000000000000") === UInt128(0x10000000000000000) @test hexint("0xffffffffffffffffffffffffffffffff") === UInt128(0xffffffffffffffffffffffffffffffff) @test begin n = hexint("0x100000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end end @testset "HexInt string length limits for different types" begin @test hexint("0x00") === UInt8(0) @test hexint("0x000") === UInt16(0) @test hexint("0x0000") === UInt16(0) @test hexint("0x00000") === UInt32(0) @test hexint("0x00000000") === UInt32(0) @test hexint("0x000000000") === UInt64(0) @test hexint("0x0000000000000000") === UInt64(0) @test hexint("0x00000000000000000") === UInt128(0) @test hexint("0x00000000000000000000000000000000") === UInt128(0) @test begin n = hexint("0x000000000000000000000000000000000") n isa BigInt && n == 0 end end @testset "BinInt numeric limits for different types" begin @test binint("0b11111111") === UInt8(0xff) @test binint("0b100000000") === UInt16(0x0100) @test binint("0b1111111111111111") === UInt16(0xffff) @test binint("0b10000000000000000") === UInt32(0x00010000) @test binint("0b11111111111111111111111111111111") === UInt32(0xffffffff) @test binint("0b100000000000000000000000000000000") === UInt64(0x0000000100000000) @test binint("0b1111111111111111111111111111111111111111111111111111111111111111") === UInt64(0xffffffffffffffff) @test binint("0b10000000000000000000000000000000000000000000000000000000000000000") === UInt128(0x10000000000000000) @test binint("0b11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111") === UInt128(0xffffffffffffffffffffffffffffffff) @test begin n = binint("0b100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end end @testset "BinInt string length limits for different types" begin @test binint("0b00000000") === UInt8(0) @test binint("0b000000000") === UInt16(0) @test binint("0b0000000000000000") === UInt16(0) @test binint("0b00000000000000000") === UInt32(0) @test binint("0b00000000000000000000000000000000") === UInt32(0) @test binint("0b000000000000000000000000000000000") === UInt64(0) @test binint("0b0000000000000000000000000000000000000000000000000000000000000000") === UInt64(0) @test binint("0b00000000000000000000000000000000000000000000000000000000000000000") === UInt128(0) @test binint("0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") === UInt128(0) @test begin n = binint("0b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") n isa BigInt && n == 0 end end @testset "OctInt numeric limits for different types" begin @test octint("0o377") === UInt8(0xff) @test octint("0o400") === UInt16(0x0100) @test octint("0o177777") === UInt16(0xffff) @test octint("0o200000") === UInt32(0x00010000) @test octint("0o37777777777") === UInt32(0xffffffff) @test octint("0o40000000000") === UInt64(0x0000000100000000) @test octint("0o1777777777777777777777") === UInt64(0xffffffffffffffff) @test octint("0o2000000000000000000000") === UInt128(0x10000000000000000) @test octint("0o3777777777777777777777777777777777777777777") === UInt128(0xffffffffffffffffffffffffffffffff) @test begin n = octint("0o4000000000000000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end end @testset "OctInt string length limits for different types" begin @test octint("0o000") === UInt8(0) @test octint("0o0000") === UInt16(0) @test octint("0o000000") === UInt16(0) @test octint("0o0000000") === UInt32(0) @test octint("0o00000000000") === UInt32(0) @test octint("0o000000000000") === UInt64(0) @test octint("0o0000000000000000000000") === UInt64(0) @test octint("0o00000000000000000000000") === UInt128(0) @test octint("0o0000000000000000000000000000000000000000000") === UInt128(0) @test begin n = octint("0o00000000000000000000000000000000000000000000") n isa BigInt && n == 0 end end @testset "Underscore separators" begin @test parse_int_literal("10_000") === 10000 @test parse_uint_literal("0xff_ff", K"HexInt") === 0xffff @test parse_uint_literal("0b1111_1111", K"BinInt") === 0xff @test parse_uint_literal("0o177_777", K"OctInt") === 0xffff end @testset "\\minus ('\\u2212' / '−') allowed in numbers" begin @test parse_int_literal("−10") === -10 end end begin @testset "Signed Integers" begin @test parse_int_literal("-1") isa Int @test parse_int_literal("1") isa Int @test parse_int_literal("2147483647") isa Int @test parse_int_literal("9223372036854775807") isa Int64 @test parse_int_literal("9223372036854775808") isa Int128 @test parse_int_literal("170141183460469231731687303715884105727") isa Int128 @test parse_int_literal("170141183460469231731687303715884105728") isa BigInt end @testset "HexInt numeric limits for different types" begin @test hexint("0xff") === UInt8(0xff) @test hexint("0x100") === UInt16(0x0100) @test hexint("0xffff") === UInt16(0xffff) @test hexint("0x10000") === UInt32(0x00010000) @test hexint("0xffffffff") === UInt32(0xffffffff) @test hexint("0x100000000") === UInt64(0x0000000100000000) @test hexint("0xffffffffffffffff") === UInt64(0xffffffffffffffff) @test hexint("0x10000000000000000") === UInt128(0x10000000000000000) @test hexint("0xffffffffffffffffffffffffffffffff") === UInt128(0xffffffffffffffffffffffffffffffff) @test begin n = hexint("0x100000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end end @testset "HexInt string length limits for different types" begin @test hexint("0x00") === UInt8(0) @test hexint("0x000") === UInt16(0) @test hexint("0x0000") === UInt16(0) @test hexint("0x00000") === UInt32(0) @test hexint("0x00000000") === UInt32(0) @test hexint("0x000000000") === UInt64(0) @test hexint("0x0000000000000000") === UInt64(0) @test hexint("0x00000000000000000") === UInt128(0) @test hexint("0x00000000000000000000000000000000") === UInt128(0) @test begin n = hexint("0x000000000000000000000000000000000") n isa BigInt && n == 0 end end @testset "BinInt numeric limits for different types" begin @test binint("0b11111111") === UInt8(0xff) @test binint("0b100000000") === UInt16(0x0100) @test binint("0b1111111111111111") === UInt16(0xffff) @test binint("0b10000000000000000") === UInt32(0x00010000) @test binint("0b11111111111111111111111111111111") === UInt32(0xffffffff) @test binint("0b100000000000000000000000000000000") === UInt64(0x0000000100000000) @test binint("0b1111111111111111111111111111111111111111111111111111111111111111") === UInt64(0xffffffffffffffff) @test binint("0b10000000000000000000000000000000000000000000000000000000000000000") === UInt128(0x10000000000000000) @test binint("0b11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111") === UInt128(0xffffffffffffffffffffffffffffffff) @test begin n = binint("0b100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end end @testset "BinInt string length limits for different types" begin @test binint("0b00000000") === UInt8(0) @test binint("0b000000000") === UInt16(0) @test binint("0b0000000000000000") === UInt16(0) @test binint("0b00000000000000000") === UInt32(0) @test binint("0b00000000000000000000000000000000") === UInt32(0) @test binint("0b000000000000000000000000000000000") === UInt64(0) @test binint("0b0000000000000000000000000000000000000000000000000000000000000000") === UInt64(0) @test binint("0b00000000000000000000000000000000000000000000000000000000000000000") === UInt128(0) @test binint("0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") === UInt128(0) @test begin n = binint("0b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") n isa BigInt && n == 0 end end @testset "OctInt numeric limits for different types" begin @test octint("0o377") === UInt8(0xff) @test octint("0o400") === UInt16(0x0100) @test octint("0o177777") === UInt16(0xffff) @test octint("0o200000") === UInt32(0x00010000) @test octint("0o37777777777") === UInt32(0xffffffff) @test octint("0o40000000000") === UInt64(0x0000000100000000) @test octint("0o1777777777777777777777") === UInt64(0xffffffffffffffff) @test octint("0o2000000000000000000000") === UInt128(0x10000000000000000) @test octint("0o3777777777777777777777777777777777777777777") === UInt128(0xffffffffffffffffffffffffffffffff) @test begin n = octint("0o4000000000000000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end end @testset "OctInt string length limits for different types" begin @test octint("0o000") === UInt8(0) @test octint("0o0000") === UInt16(0) @test octint("0o000000") === UInt16(0) @test octint("0o0000000") === UInt32(0) @test octint("0o00000000000") === UInt32(0) @test octint("0o000000000000") === UInt64(0) @test octint("0o0000000000000000000000") === UInt64(0) @test octint("0o00000000000000000000000") === UInt128(0) @test octint("0o0000000000000000000000000000000000000000000") === UInt128(0) @test begin n = octint("0o00000000000000000000000000000000000000000000") n isa BigInt && n == 0 end end @testset "Underscore separators" begin @test parse_int_literal("10_000") === 10000 @test parse_uint_literal("0xff_ff", K"HexInt") === 0xffff @test parse_uint_literal("0b1111_1111", K"BinInt") === 0xff @test parse_uint_literal("0o177_777", K"OctInt") === 0xffff end @testset "\\minus ('\\u2212' / '−') allowed in numbers" begin @test parse_int_literal("−10") === -10 end end @testset "Integer parsing" begin @testset "Signed Integers" begin @test parse_int_literal("-1") isa Int @test parse_int_literal("1") isa Int @test parse_int_literal("2147483647") isa Int @test parse_int_literal("9223372036854775807") isa Int64 @test parse_int_literal("9223372036854775808") isa Int128 @test parse_int_literal("170141183460469231731687303715884105727") isa Int128 @test parse_int_literal("170141183460469231731687303715884105728") isa BigInt end @testset "HexInt numeric limits for different types" begin @test hexint("0xff") === UInt8(0xff) @test hexint("0x100") === UInt16(0x0100) @test hexint("0xffff") === UInt16(0xffff) @test hexint("0x10000") === UInt32(0x00010000) @test hexint("0xffffffff") === UInt32(0xffffffff) @test hexint("0x100000000") === UInt64(0x0000000100000000) @test hexint("0xffffffffffffffff") === UInt64(0xffffffffffffffff) @test hexint("0x10000000000000000") === UInt128(0x10000000000000000) @test hexint("0xffffffffffffffffffffffffffffffff") === UInt128(0xffffffffffffffffffffffffffffffff) @test begin n = hexint("0x100000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end end @testset "HexInt string length limits for different types" begin @test hexint("0x00") === UInt8(0) @test hexint("0x000") === UInt16(0) @test hexint("0x0000") === UInt16(0) @test hexint("0x00000") === UInt32(0) @test hexint("0x00000000") === UInt32(0) @test hexint("0x000000000") === UInt64(0) @test hexint("0x0000000000000000") === UInt64(0) @test hexint("0x00000000000000000") === UInt128(0) @test hexint("0x00000000000000000000000000000000") === UInt128(0) @test begin n = hexint("0x000000000000000000000000000000000") n isa BigInt && n == 0 end end @testset "BinInt numeric limits for different types" begin @test binint("0b11111111") === UInt8(0xff) @test binint("0b100000000") === UInt16(0x0100) @test binint("0b1111111111111111") === UInt16(0xffff) @test binint("0b10000000000000000") === UInt32(0x00010000) @test binint("0b11111111111111111111111111111111") === UInt32(0xffffffff) @test binint("0b100000000000000000000000000000000") === UInt64(0x0000000100000000) @test binint("0b1111111111111111111111111111111111111111111111111111111111111111") === UInt64(0xffffffffffffffff) @test binint("0b10000000000000000000000000000000000000000000000000000000000000000") === UInt128(0x10000000000000000) @test binint("0b11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111") === UInt128(0xffffffffffffffffffffffffffffffff) @test begin n = binint("0b100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end end @testset "BinInt string length limits for different types" begin @test binint("0b00000000") === UInt8(0) @test binint("0b000000000") === UInt16(0) @test binint("0b0000000000000000") === UInt16(0) @test binint("0b00000000000000000") === UInt32(0) @test binint("0b00000000000000000000000000000000") === UInt32(0) @test binint("0b000000000000000000000000000000000") === UInt64(0) @test binint("0b0000000000000000000000000000000000000000000000000000000000000000") === UInt64(0) @test binint("0b00000000000000000000000000000000000000000000000000000000000000000") === UInt128(0) @test binint("0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") === UInt128(0) @test begin n = binint("0b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") n isa BigInt && n == 0 end end @testset "OctInt numeric limits for different types" begin @test octint("0o377") === UInt8(0xff) @test octint("0o400") === UInt16(0x0100) @test octint("0o177777") === UInt16(0xffff) @test octint("0o200000") === UInt32(0x00010000) @test octint("0o37777777777") === UInt32(0xffffffff) @test octint("0o40000000000") === UInt64(0x0000000100000000) @test octint("0o1777777777777777777777") === UInt64(0xffffffffffffffff) @test octint("0o2000000000000000000000") === UInt128(0x10000000000000000) @test octint("0o3777777777777777777777777777777777777777777") === UInt128(0xffffffffffffffffffffffffffffffff) @test begin n = octint("0o4000000000000000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end end @testset "OctInt string length limits for different types" begin @test octint("0o000") === UInt8(0) @test octint("0o0000") === UInt16(0) @test octint("0o000000") === UInt16(0) @test octint("0o0000000") === UInt32(0) @test octint("0o00000000000") === UInt32(0) @test octint("0o000000000000") === UInt64(0) @test octint("0o0000000000000000000000") === UInt64(0) @test octint("0o00000000000000000000000") === UInt128(0) @test octint("0o0000000000000000000000000000000000000000000") === UInt128(0) @test begin n = octint("0o00000000000000000000000000000000000000000000") n isa BigInt && n == 0 end end @testset "Underscore separators" begin @test parse_int_literal("10_000") === 10000 @test parse_uint_literal("0xff_ff", K"HexInt") === 0xffff @test parse_uint_literal("0b1111_1111", K"BinInt") === 0xff @test parse_uint_literal("0o177_777", K"OctInt") === 0xffff end @testset "\\minus ('\\u2212' / '−') allowed in numbers" begin @test parse_int_literal("−10") === -10 end end @testset "Integer parsing" begin @testset "Signed Integers" begin @test parse_int_literal("-1") isa Int @test parse_int_literal("1") isa Int @test parse_int_literal("2147483647") isa Int @test parse_int_literal("9223372036854775807") isa Int64 @test parse_int_literal("9223372036854775808") isa Int128 @test parse_int_literal("170141183460469231731687303715884105727") isa Int128 @test parse_int_literal("170141183460469231731687303715884105728") isa BigInt end @testset "HexInt numeric limits for different types" begin @test hexint("0xff") === UInt8(0xff) @test hexint("0x100") === UInt16(0x0100) @test hexint("0xffff") === UInt16(0xffff) @test hexint("0x10000") === UInt32(0x00010000) @test hexint("0xffffffff") === UInt32(0xffffffff) @test hexint("0x100000000") === UInt64(0x0000000100000000) @test hexint("0xffffffffffffffff") === UInt64(0xffffffffffffffff) @test hexint("0x10000000000000000") === UInt128(0x10000000000000000) @test hexint("0xffffffffffffffffffffffffffffffff") === UInt128(0xffffffffffffffffffffffffffffffff) @test begin n = hexint("0x100000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end end @testset "HexInt string length limits for different types" begin @test hexint("0x00") === UInt8(0) @test hexint("0x000") === UInt16(0) @test hexint("0x0000") === UInt16(0) @test hexint("0x00000") === UInt32(0) @test hexint("0x00000000") === UInt32(0) @test hexint("0x000000000") === UInt64(0) @test hexint("0x0000000000000000") === UInt64(0) @test hexint("0x00000000000000000") === UInt128(0) @test hexint("0x00000000000000000000000000000000") === UInt128(0) @test begin n = hexint("0x000000000000000000000000000000000") n isa BigInt && n == 0 end end @testset "BinInt numeric limits for different types" begin @test binint("0b11111111") === UInt8(0xff) @test binint("0b100000000") === UInt16(0x0100) @test binint("0b1111111111111111") === UInt16(0xffff) @test binint("0b10000000000000000") === UInt32(0x00010000) @test binint("0b11111111111111111111111111111111") === UInt32(0xffffffff) @test binint("0b100000000000000000000000000000000") === UInt64(0x0000000100000000) @test binint("0b1111111111111111111111111111111111111111111111111111111111111111") === UInt64(0xffffffffffffffff) @test binint("0b10000000000000000000000000000000000000000000000000000000000000000") === UInt128(0x10000000000000000) @test binint("0b11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111") === UInt128(0xffffffffffffffffffffffffffffffff) @test begin n = binint("0b100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end end @testset "BinInt string length limits for different types" begin @test binint("0b00000000") === UInt8(0) @test binint("0b000000000") === UInt16(0) @test binint("0b0000000000000000") === UInt16(0) @test binint("0b00000000000000000") === UInt32(0) @test binint("0b00000000000000000000000000000000") === UInt32(0) @test binint("0b000000000000000000000000000000000") === UInt64(0) @test binint("0b0000000000000000000000000000000000000000000000000000000000000000") === UInt64(0) @test binint("0b00000000000000000000000000000000000000000000000000000000000000000") === UInt128(0) @test binint("0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") === UInt128(0) @test begin n = binint("0b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") n isa BigInt && n == 0 end end @testset "OctInt numeric limits for different types" begin @test octint("0o377") === UInt8(0xff) @test octint("0o400") === UInt16(0x0100) @test octint("0o177777") === UInt16(0xffff) @test octint("0o200000") === UInt32(0x00010000) @test octint("0o37777777777") === UInt32(0xffffffff) @test octint("0o40000000000") === UInt64(0x0000000100000000) @test octint("0o1777777777777777777777") === UInt64(0xffffffffffffffff) @test octint("0o2000000000000000000000") === UInt128(0x10000000000000000) @test octint("0o3777777777777777777777777777777777777777777") === UInt128(0xffffffffffffffffffffffffffffffff) @test begin n = octint("0o4000000000000000000000000000000000000000000") n isa BigInt && n == 340282366920938463463374607431768211456 end end @testset "OctInt string length limits for different types" begin @test octint("0o000") === UInt8(0) @test octint("0o0000") === UInt16(0) @test octint("0o000000") === UInt16(0) @test octint("0o0000000") === UInt32(0) @test octint("0o00000000000") === UInt32(0) @test octint("0o000000000000") === UInt64(0) @test octint("0o0000000000000000000000") === UInt64(0) @test octint("0o00000000000000000000000") === UInt128(0) @test octint("0o0000000000000000000000000000000000000000000") === UInt128(0) @test begin n = octint("0o00000000000000000000000000000000000000000000") n isa BigInt && n == 0 end end @testset "Underscore separators" begin @test parse_int_literal("10_000") === 10000 @test parse_uint_literal("0xff_ff", K"HexInt") === 0xffff @test parse_uint_literal("0b1111_1111", K"BinInt") === 0xff @test parse_uint_literal("0o177_777", K"OctInt") === 0xffff end @testset "\\minus ('\\u2212' / '−') allowed in numbers" begin @test parse_int_literal("−10") === -10 end end Parsing files in Base: Test Failed at /home/pkgeval/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:166 Expression: false Stacktrace: [1] macro expansion @ /opt/julia/share/julia/stdlib/v1.14/Test/src/Test.jl:782 [inlined] [2] top-level scope @ ~/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:166 Parsing files in Base: Test Failed at /home/pkgeval/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:143 Expression: cst_err == meta_err Evaluated: true == false Stacktrace: [1] macro expansion @ /opt/julia/share/julia/stdlib/v1.14/Test/src/Test.jl:782 [inlined] [2] top-level scope @ ~/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:143 ┌ Error: CSTParser.parse errored, but Meta.parse didn't. │ file = "/opt/julia/bin/../share/julia/base/binaryplatforms.jl" └ @ Main.var"##302" ~/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:149 ┌ Error: parsing difference │ file = "/opt/julia/bin/../share/julia/base/gmp.jl" └ @ Main.var"##302" ~/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:157 begin RoundToZero end RoundToZero $(Expr(:kw, :(::typeof(RoundToZero)), quote RoundToZero end)) $(Expr(:kw, :(::typeof(RoundToZero)), :RoundToZero)) divrem(x::BigInt, y::BigInt, ::typeof(RoundToZero) = begin RoundToZero end) divrem(x::BigInt, y::BigInt, ::typeof(RoundToZero) = RoundToZero) divrem(x::BigInt, y::BigInt, ::typeof(RoundToZero) = begin RoundToZero end) = begin MPZ.tdiv_qr(x, y) end divrem(x::BigInt, y::BigInt, ::typeof(RoundToZero) = RoundToZero) = begin MPZ.tdiv_qr(x, y) end begin RoundToZero end RoundToZero $(Expr(:kw, :(::typeof(RoundToZero)), quote RoundToZero end)) $(Expr(:kw, :(::typeof(RoundToZero)), :RoundToZero)) divrem(x::BigInt, y::Integer, ::typeof(RoundToZero) = begin RoundToZero end) divrem(x::BigInt, y::Integer, ::typeof(RoundToZero) = RoundToZero) divrem(x::BigInt, y::Integer, ::typeof(RoundToZero) = begin RoundToZero end) = begin MPZ.tdiv_qr(x, BigInt(y)) end divrem(x::BigInt, y::Integer, ::typeof(RoundToZero) = RoundToZero) = begin MPZ.tdiv_qr(x, BigInt(y)) end begin export BigInt import .Base: *, +, -, /, <, <<, >>, >>>, <=, ==, >, >=, ^, ~, &, |, xor, nand, nor, binomial, cmp, convert, div, divrem, factorial, cld, fld, gcd, gcdx, lcm, mod, ndigits, promote_rule, rem, show, isqrt, string, powermod, sum, prod, trailing_zeros, trailing_ones, count_ones, count_zeros, tryparse_internal, bin, oct, dec, hex, isequal, invmod, _prevpow2, _nextpow2, ndigits0zpb, widen, signed, unsafe_trunc, trunc, iszero, isone, big, flipsign, signbit, sign, isodd, iseven, digits!, hash, hash_integer, top_set_bit, ispositive, isnegative, clamp import Core: Signed, Float16, Float32, Float64 if Clong == Int32 const ClongMax = Union{Int8, Int16, Int32} const CulongMax = Union{UInt8, UInt16, UInt32} else const ClongMax = Union{Int8, Int16, Int32, Int64} const CulongMax = Union{UInt8, UInt16, UInt32, UInt64} end const CdoubleMax = Union{Float16, Float32, Float64} if Sys.iswindows() const libgmp = "libgmp-10.dll" elseif Sys.isapple() const libgmp = "@rpath/libgmp.10.dylib" else const libgmp = "libgmp.so.10" end _version() = begin unsafe_string(unsafe_load(cglobal((:__gmp_version, libgmp), Ptr{Cchar}))) end version() = begin VersionNumber(_version()) end major_version() = begin (_version())[1] end bits_per_limb() = begin Int(unsafe_load(cglobal((:__gmp_bits_per_limb, libgmp), Cint))) end const VERSION = version() const MAJOR_VERSION = major_version() const BITS_PER_LIMB = bits_per_limb() if BITS_PER_LIMB == 32 const Limb = UInt32 const SLimbMax = Union{Int8, Int16, Int32} const ULimbMax = Union{UInt8, UInt16, UInt32} elseif BITS_PER_LIMB == 64 const Limb = UInt64 const SLimbMax = Union{Int8, Int16, Int32, Int64} const ULimbMax = Union{UInt8, UInt16, UInt32, UInt64} else error("GMP: cannot determine the type mp_limb_t (__gmp_bits_per_limb == $(BITS_PER_LIMB))") end Core.@doc " BigInt <: Signed\n\nArbitrary precision integer type.\n" mutable struct BigInt <: Signed alloc::Cint size::Cint d::Ptr{Limb} function BigInt(; nbits::Integer = 0) b = MPZ.init2!(new(), nbits) finalizer(cglobal((:__gmpz_clear, libgmp)), b) return b end end Core.@doc " BigInt(x)\n\nCreate an arbitrary precision integer. `x` may be an `Int` (or anything that can be\nconverted to an `Int`). The usual mathematical operators are defined for this type, and\nresults are promoted to a [`BigInt`](@ref).\n\nInstances can be constructed from strings via [`parse`](@ref), or using the `big`\nstring literal.\n\n# Examples\n```jldoctest\njulia> parse(BigInt, \"42\")\n42\n\njulia> big\"313\"\n313\n\njulia> BigInt(10)^19\n10000000000000000000\n```\n" BigInt(x) Core.@doc " ALLOC_OVERFLOW_FUNCTION\n\nA reference that holds a boolean, if true, indicating julia is linked with a patched GMP that\ndoes not abort on huge allocation and throws OutOfMemoryError instead.\n" const ALLOC_OVERFLOW_FUNCTION = Ref(false) function __init__() try if major_version() != MAJOR_VERSION || bits_per_limb() != BITS_PER_LIMB msg = "The dynamically loaded GMP library (v\"$(version())\" with __gmp_bits_per_limb == $(bits_per_limb()))\ndoes not correspond to the compile time version (v\"$(VERSION)\" with __gmp_bits_per_limb == $(BITS_PER_LIMB)).\nPlease rebuild Julia." if bits_per_limb() != BITS_PER_LIMB @error msg else @warn msg end end ccall((:__gmp_set_memory_functions, libgmp), Cvoid, (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), cglobal(:jl_gc_counted_malloc), cglobal(:jl_gc_counted_realloc_with_old_size), cglobal(:jl_gc_counted_free_with_size)) (ZERO.alloc, ZERO.size, ZERO.d) = (0, 0, C_NULL) (ONE.alloc, ONE.size, ONE.d) = (1, 1, pointer(_ONE)) catch ex Base.showerror_nostdio(ex, "WARNING: Error during initialization of module GMP") end try ccall((:__gmp_set_alloc_overflow_function, libgmp), Cvoid, (Ptr{Cvoid},), cglobal(:jl_throw_out_of_memory_error)) ALLOC_OVERFLOW_FUNCTION[] = true catch ex if typeof(ex) != ErrorException rethrow() end end end module MPZ using ..GMP: BigInt, Limb, BITS_PER_LIMB, libgmp const mpz_t = Ref{BigInt} const bitcnt_t = Culong gmpz(op::Symbol) = begin Expr(:tuple, QuoteNode(Symbol(:__gmpz_, op)), GlobalRef(MPZ, :libgmp)) end init!(x::BigInt) = begin ccall((:__gmpz_init, libgmp), Cvoid, (mpz_t,), x) x end init2!(x::BigInt, a) = begin ccall((:__gmpz_init2, libgmp), Cvoid, (mpz_t, bitcnt_t), x, a) x end realloc2!(x, a) = begin ccall((:__gmpz_realloc2, libgmp), Cvoid, (mpz_t, bitcnt_t), x, a) x end realloc2(a) = begin realloc2!(BigInt(), a) end sizeinbase(a::BigInt, b) = begin Int(ccall((:__gmpz_sizeinbase, libgmp), Csize_t, (mpz_t, Cint), a, b)) end for (op, nbits) = (:add => :(BITS_PER_LIMB * (1 + max(abs(a.size), abs(b.size)))), :sub => :(BITS_PER_LIMB * (1 + max(abs(a.size), abs(b.size)))), :mul => 0, :fdiv_q => 0, :tdiv_q => 0, :cdiv_q => 0, :fdiv_r => 0, :tdiv_r => 0, :cdiv_r => 0, :gcd => 0, :lcm => 0, :and => 0, :ior => 0, :xor => 0) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a::BigInt, b::BigInt) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, mpz_t, mpz_t), x, a, b) x end ($op)(a::BigInt, b::BigInt) = begin ($op!)(BigInt(nbits = $nbits), a, b) end ($op!)(x::BigInt, b::BigInt) = begin ($op!)(x, x, b) end end end invert!(x::BigInt, a::BigInt, b::BigInt) = begin ccall((:__gmpz_invert, libgmp), Cint, (mpz_t, mpz_t, mpz_t), x, a, b) end invert!(x::BigInt, b::BigInt) = begin invert!(x, x, b) end invert(a::BigInt, b::BigInt) = begin ret = BigInt() invert!(ret, a, b) ret end for op = (:add_ui, :sub_ui, :mul_ui, :mul_2exp, :fdiv_q_2exp, :pow_ui, :bin_ui) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a::BigInt, b) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, mpz_t, Culong), x, a, b) x end ($op)(a::BigInt, b) = begin ($op!)(BigInt(), a, b) end ($op!)(x::BigInt, b) = begin ($op!)(x, x, b) end end end ui_sub!(x::BigInt, a, b::BigInt) = begin ccall((:__gmpz_ui_sub, libgmp), Cvoid, (mpz_t, Culong, mpz_t), x, a, b) x end ui_sub(a, b::BigInt) = begin ui_sub!(BigInt(), a, b) end for op = (:scan1, :scan0) @eval ($op)(a::BigInt, b) = begin Int(signed(ccall($(gmpz(op)), Culong, (mpz_t, Culong), a, b))) end end mul_si!(x::BigInt, a::BigInt, b) = begin ccall((:__gmpz_mul_si, libgmp), Cvoid, (mpz_t, mpz_t, Clong), x, a, b) x end mul_si(a::BigInt, b) = begin mul_si!(BigInt(), a, b) end mul_si!(x::BigInt, b) = begin mul_si!(x, x, b) end for op = (:neg, :com, :sqrt, :set) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a::BigInt) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, mpz_t), x, a) x end ($op)(a::BigInt) = begin ($op!)(BigInt(), a) end end op === :set && continue @eval ($op!)(x::BigInt) = begin ($op!)(x, x) end end for (op, T) = ((:fac_ui, Culong), (:set_ui, Culong), (:set_si, Clong), (:set_d, Cdouble)) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, $T), x, a) x end ($op)(a) = begin ($op!)(BigInt(), a) end end end popcount(a::BigInt) = begin Int(signed(ccall((:__gmpz_popcount, libgmp), Culong, (mpz_t,), a))) end mpn_popcount(d::Ptr{Limb}, s::Integer) = begin Int(ccall((:__gmpn_popcount, libgmp), Culong, (Ptr{Limb}, Csize_t), d, s)) end mpn_popcount(a::BigInt) = begin mpn_popcount(a.d, abs(a.size)) end function tdiv_qr!(x::BigInt, y::BigInt, a::BigInt, b::BigInt) ccall((:__gmpz_tdiv_qr, libgmp), Cvoid, (mpz_t, mpz_t, mpz_t, mpz_t), x, y, a, b) (x, y) end tdiv_qr(a::BigInt, b::BigInt) = begin tdiv_qr!(BigInt(), BigInt(), a, b) end powm!(x::BigInt, a::BigInt, b::BigInt, c::BigInt) = begin ccall((:__gmpz_powm, libgmp), Cvoid, (mpz_t, mpz_t, mpz_t, mpz_t), x, a, b, c) x end powm(a::BigInt, b::BigInt, c::BigInt) = begin powm!(BigInt(), a, b, c) end powm!(x::BigInt, b::BigInt, c::BigInt) = begin powm!(x, x, b, c) end function gcdext!(x::BigInt, y::BigInt, z::BigInt, a::BigInt, b::BigInt) ccall((:__gmpz_gcdext, libgmp), Cvoid, (mpz_t, mpz_t, mpz_t, mpz_t, mpz_t), x, y, z, a, b) (x, y, z) end gcdext(a::BigInt, b::BigInt) = begin gcdext!(BigInt(), BigInt(), BigInt(), a, b) end cmp(a::BigInt, b::BigInt) = begin Int(ccall((:__gmpz_cmp, libgmp), Cint, (mpz_t, mpz_t), a, b)) end cmp_si(a::BigInt, b) = begin Int(ccall((:__gmpz_cmp_si, libgmp), Cint, (mpz_t, Clong), a, b)) end cmp_ui(a::BigInt, b) = begin Int(ccall((:__gmpz_cmp_ui, libgmp), Cint, (mpz_t, Culong), a, b)) end cmp_d(a::BigInt, b) = begin Int(ccall((:__gmpz_cmp_d, libgmp), Cint, (mpz_t, Cdouble), a, b)) end mpn_cmp(a::Ptr{Limb}, b::Ptr{Limb}, c) = begin ccall((:__gmpn_cmp, libgmp), Cint, (Ptr{Limb}, Ptr{Limb}, Clong), a, b, c) end mpn_cmp(a::BigInt, b::BigInt, c) = begin mpn_cmp(a.d, b.d, c) end get_str!(x, a, b::BigInt) = begin ccall((:__gmpz_get_str, libgmp), Ptr{Cchar}, (Ptr{Cchar}, Cint, mpz_t), x, a, b) x end set_str!(x::BigInt, a, b) = begin Int(ccall((:__gmpz_set_str, libgmp), Cint, (mpz_t, Ptr{UInt8}, Cint), x, a, b)) end get_d(a::BigInt) = begin ccall((:__gmpz_get_d, libgmp), Cdouble, (mpz_t,), a) end function export!(a::AbstractVector{T}, n::BigInt; order::Integer = -1, nails::Integer = 0, endian::Integer = 0) where T <: Base.BitInteger stride(a, 1) == 1 || throw(ArgumentError("a must have stride 1")) ndigits = cld(sizeinbase(n, 2), 8 * sizeof(T) - nails) length(a) < ndigits && resize!(a, ndigits) fill!(a, zero(T)) count = Ref{Csize_t}() ccall((:__gmpz_export, libgmp), Ptr{T}, (Ptr{T}, Ref{Csize_t}, Cint, Csize_t, Cint, Csize_t, mpz_t), a, count, order, sizeof(T), endian, nails, n) @assert count[] ≤ length(a) return (a, Int(count[])) end limbs_write!(x::BigInt, a) = begin ccall((:__gmpz_limbs_write, libgmp), Ptr{Limb}, (mpz_t, Clong), x, a) end limbs_finish!(x::BigInt, a) = begin ccall((:__gmpz_limbs_finish, libgmp), Cvoid, (mpz_t, Clong), x, a) end setbit!(x, a) = begin ccall((:__gmpz_setbit, libgmp), Cvoid, (mpz_t, bitcnt_t), x, a) x end tstbit(a::BigInt, b) = begin ccall((:__gmpz_tstbit, libgmp), Cint, (mpz_t, bitcnt_t), a, b) % Bool end end const ZERO = BigInt() const ONE = BigInt() const _ONE = Limb[1] widen(::Type{Int128}) = begin BigInt end widen(::Type{UInt128}) = begin BigInt end widen(::Type{BigInt}) = begin BigInt end signed(x::BigInt) = begin x end BigInt(x::BigInt) = begin x end Signed(x::BigInt) = begin x end function tryparse_internal(::Type{BigInt}, s::AbstractString, startpos::Int, endpos::Int, base_::Integer, raise::Bool) bstr = if startpos == firstindex(s) && endpos == lastindex(s) String(s) else String(SubString(s, startpos, endpos)) end (sgn, base, i) = Base.parseint_preamble(true, Int(base_), bstr, firstindex(bstr), lastindex(bstr)) if !(2 <= base <= 62) raise && throw(ArgumentError("invalid base: base must be 2 ≤ base ≤ 62, got $(base)")) return nothing end if i == 0 raise && throw(ArgumentError("premature end of integer: $(repr(bstr))")) return nothing end z = BigInt() if Base.containsnul(bstr) err = -1 else err = GC.@preserve(bstr, MPZ.set_str!(z, pointer(bstr) + (i - firstindex(bstr)), base)) end if err != 0 raise && throw(ArgumentError("invalid BigInt: $(repr(bstr))")) return nothing end flipsign!(z, sgn) end BigInt(x::Union{Clong, Int32}) = begin MPZ.set_si(x) end BigInt(x::Union{Culong, UInt32}) = begin MPZ.set_ui(x) end BigInt(x::Bool) = begin BigInt(UInt(x)) end unsafe_trunc(::Type{BigInt}, x::Union{Float16, Float32, Float64}) = begin MPZ.set_d(x) end function BigInt(x::Float64) isinteger(x) || throw(InexactError(:BigInt, BigInt, x)) unsafe_trunc(BigInt, x) end BigInt(x::Float16) = begin BigInt(Float64(x)) end BigInt(x::Float32) = begin BigInt(Float64(x)) end function BigInt(x::Integer) isbits(x) && (typemin(Clong) <= x <= typemax(Clong) && return BigInt((x % Clong)::Clong)) nd = ndigits(x, base = 2) z = MPZ.realloc2(nd) ux = unsigned(if x < 0 -x else x end) size = 0 limbnbits = sizeof(Limb) << 3 while nd > 0 size += 1 unsafe_store!(z.d, ux % Limb, size) ux >>= limbnbits nd -= limbnbits end z.size = if x < 0 -size else size end z end rem(x::BigInt, ::Type{Bool}) = begin (!(iszero(x)) & unsafe_load(x.d)) % Bool end (rem(x::BigInt, ::Type{T}) where T <: Union{SLimbMax, ULimbMax}) = begin if iszero(x) zero(T) else flipsign(unsafe_load(x.d) % T, x.size) end end function rem(x::BigInt, ::Type{T}) where T <: Union{Base.BitUnsigned, Base.BitSigned} u = zero(T) for l = 1:min(abs(x.size), cld(sizeof(T), sizeof(Limb))) u += (unsafe_load(x.d, l) % T) << (sizeof(Limb) << 3 * (l - 1)) end flipsign(u, x.size) end rem(x::Integer, ::Type{BigInt}) = begin BigInt(x) end clamp(x, ::Type{BigInt}) = begin convert(BigInt, x) end isodd(x::BigInt) = begin MPZ.tstbit(x, 0) end iseven(x::BigInt) = begin !(isodd(x)) end function (::Type{T})(x::BigInt) where T <: Base.BitUnsigned if sizeof(T) < sizeof(Limb) convert(T, convert(Limb, x)) else 0 <= x.size <= cld(sizeof(T), sizeof(Limb)) || throw(InexactError(nameof(T), T, x)) x % T end end function (::Type{T})(x::BigInt) where T <: Base.BitSigned n = abs(x.size) if sizeof(T) < sizeof(Limb) SLimb = typeof(Signed(one(Limb))) convert(T, convert(SLimb, x)) else 0 <= n <= cld(sizeof(T), sizeof(Limb)) || throw(InexactError(nameof(T), T, x)) y = x % T ispositive(x) ⊻ (y > 0) && throw(InexactError(nameof(T), T, x)) y end end Float64(n::BigInt, ::RoundingMode{:ToZero}) = begin MPZ.get_d(n) end function (::Type{T})(n::BigInt, ::RoundingMode{:ToZero}) where T <: Union{Float16, Float32} T(Float64(n, RoundToZero), RoundToZero) end function (::Type{T})(n::BigInt, ::RoundingMode{:Down}) where T <: CdoubleMax x = T(n, RoundToZero) if x > n prevfloat(x) else x end end function (::Type{T})(n::BigInt, ::RoundingMode{:Up}) where T <: CdoubleMax x = T(n, RoundToZero) if x < n nextfloat(x) else x end end function Float64(x::BigInt, ::RoundingMode{:Nearest}) x == 0 && return 0.0 xsize = abs(x.size) if xsize * BITS_PER_LIMB > 1024 z = Inf64 elseif xsize == 1 z = Float64(unsafe_load(x.d)) elseif Limb == UInt32 && xsize == 2 z = Float64((unsafe_load(x.d, 2) % UInt64) << BITS_PER_LIMB + unsafe_load(x.d)) else y1 = unsafe_load(x.d, xsize) % UInt64 n = top_set_bit(y1) y = y1 >> (n - (precision(Float64) + 1)) if Limb == UInt64 y += if n > precision(Float64) 0 else unsafe_load(x.d, xsize - 1) >> (10 + n) end else y += (unsafe_load(x.d, xsize - 1) % UInt64) >> (n - 22) y += if n > precision(Float64) - 32 0 else unsafe_load(x.d, xsize - 2) >> (10 + n) end end y = (y + 1) >> 1 y &= ~(UInt64(trailing_zeros(x) == (n - 54) + (xsize - 1) * BITS_PER_LIMB)) d = ((n + 1021) % UInt64) << 52 z = reinterpret(Float64, d + y) z = ldexp(z, (xsize - 1) * BITS_PER_LIMB) end return flipsign(z, x.size) end function Float32(x::BigInt, ::RoundingMode{:Nearest}) x == 0 && return 0.0f0 xsize = abs(x.size) if xsize * BITS_PER_LIMB > 128 z = Inf32 elseif xsize == 1 z = Float32(unsafe_load(x.d)) else y1 = unsafe_load(x.d, xsize) n = BITS_PER_LIMB - leading_zeros(y1) y = y1 >> (n - (precision(Float32) + 1)) % UInt32 y += if n > precision(Float32) 0 else unsafe_load(x.d, xsize - 1) >> (BITS_PER_LIMB - -25) end % UInt32 y = (y + one(UInt32)) >> 1 y &= ~(UInt32(trailing_zeros(x) == (n - 25) + (xsize - 1) * BITS_PER_LIMB)) d = ((n + 125) % UInt32) << 23 z = reinterpret(Float32, d + y) z = ldexp(z, (xsize - 1) * BITS_PER_LIMB) end return flipsign(z, x.size) end function Float16(x::BigInt, ::RoundingMode{:Nearest}) x == 0 && return Float16(0.0) y1 = unsafe_load(x.d) n = BITS_PER_LIMB - leading_zeros(y1) if n > 16 || abs(x.size) > 1 z = Inf16 else y = y1 >> (n - (precision(Float16) + 1)) % UInt16 y = (y + one(UInt16)) >> 1 y &= ~(UInt16(trailing_zeros(x) == n - 12)) d = ((n + 13) % UInt16) << 10 z = reinterpret(Float16, d + y) end return flipsign(z, x.size) end Float64(n::BigInt) = begin Float64(n, RoundNearest) end Float32(n::BigInt) = begin Float32(n, RoundNearest) end Float16(n::BigInt) = begin Float16(n, RoundNearest) end promote_rule(::Type{BigInt}, ::Type{<:Integer}) = begin BigInt end Core.@doc " big(x)\n\nConvert a number to a maximum precision representation (typically [`BigInt`](@ref) or\n`BigFloat`). See [`BigFloat`](@ref BigFloat(::Any, rounding::RoundingMode)) for\ninformation about some pitfalls with floating-point numbers.\n" function big end big(::Type{<:Integer}) = begin BigInt end big(::Type{<:Rational}) = begin Rational{BigInt} end big(n::Integer) = begin convert(BigInt, n) end for (fJ, fC) = ((:+, :add), (:-, :sub), (:*, :mul), (:mod, :fdiv_r), (:rem, :tdiv_r), (:gcd, :gcd), (:lcm, :lcm), (:&, :and), (:|, :ior), (:xor, :xor)) @eval begin ($fJ)(x::BigInt, y::BigInt) = begin MPZ.:($fC)(x, y) end end end for (r, f) = ((RoundToZero, :tdiv_q), (RoundDown, :fdiv_q), (RoundUp, :cdiv_q)) @eval div(x::BigInt, y::BigInt, ::typeof($r)) = begin MPZ.:($f)(x, y) end end div(x::BigInt, y::BigInt) = begin div(x, y, RoundToZero) end fld(x::BigInt, y::BigInt) = begin div(x, y, RoundDown) end cld(x::BigInt, y::BigInt) = begin div(x, y, RoundUp) end x::BigInt / y::BigInt = begin float(x) / float(y) end function invmod(x::BigInt, y::BigInt) z = zero(BigInt) ya = abs(y) if ya == 1 return z end if y == 0 || MPZ.invert!(z, x, ya) == 0 throw(DomainError(y)) end if y < 0 MPZ.add!(z, y) end return z end for (fJ, fC) = ((:+, :add), (:*, :mul), (:&, :and), (:|, :ior), (:xor, :xor)) fC! = Symbol(fC, :!) @eval begin ($fJ)(a::BigInt, b::BigInt, c::BigInt) = begin MPZ.:($fC!)(MPZ.:($fC)(a, b), c) end ($fJ)(a::BigInt, b::BigInt, c::BigInt, d::BigInt) = begin MPZ.:($fC!)(MPZ.:($fC!)(MPZ.:($fC)(a, b), c), d) end ($fJ)(a::BigInt, b::BigInt, c::BigInt, d::BigInt, e::BigInt) = begin MPZ.:($fC!)(MPZ.:($fC!)(MPZ.:($fC!)(MPZ.:($fC)(a, b), c), d), e) end end end x::BigInt + c::CulongMax = begin MPZ.add_ui(x, c) end c::CulongMax + x::BigInt = begin x + c end x::BigInt - c::CulongMax = begin MPZ.sub_ui(x, c) end c::CulongMax - x::BigInt = begin MPZ.ui_sub(c, x) end x::BigInt + c::ClongMax = begin if c < 0 x - -(c % Culong) else x + convert(Culong, c) end end c::ClongMax + x::BigInt = begin if c < 0 x - -(c % Culong) else x + convert(Culong, c) end end x::BigInt - c::ClongMax = begin if c < 0 x + -(c % Culong) else x - convert(Culong, c) end end c::ClongMax - x::BigInt = begin if c < 0 -((x + -(c % Culong))) else convert(Culong, c) - x end end x::BigInt * c::CulongMax = begin MPZ.mul_ui(x, c) end c::CulongMax * x::BigInt = begin x * c end x::BigInt * c::ClongMax = begin MPZ.mul_si(x, c) end c::ClongMax * x::BigInt = begin x * c end x::BigInt / y::Union{ClongMax, CulongMax} = begin float(x) / y end x::Union{ClongMax, CulongMax} / y::BigInt = begin x / float(y) end -(x::BigInt) = begin MPZ.neg(x) end ~(x::BigInt) = begin MPZ.com(x) end x::BigInt << c::UInt = begin if c == 0 x else MPZ.mul_2exp(x, c) end end x::BigInt >> c::UInt = begin if c == 0 x else MPZ.fdiv_q_2exp(x, c) end end x::BigInt >>> c::UInt = begin x >> c end function trailing_zeros(x::BigInt) c = MPZ.scan1(x, 0) c == -1 && throw(DomainError(x, "`x` must be non-zero")) c end function trailing_ones(x::BigInt) c = MPZ.scan0(x, 0) c == -1 && throw(DomainError(x, "`x` must not be equal to -1")) c end function count_ones(x::BigInt) c = MPZ.popcount(x) c == -1 && throw(DomainError(x, "`x` cannot be negative")) c end function count_zeros(x::BigInt) c = MPZ.popcount(~x) c == -1 && throw(DomainError(x, "`x` must be negative")) c end Core.@doc " count_ones_abs(x::BigInt)\n\nNumber of ones in the binary representation of abs(x).\n" count_ones_abs(x::BigInt) = begin if iszero(x) 0 else MPZ.mpn_popcount(x) end end _bit_magnitude(x::BigInt) = begin x.size * sizeof(Limb) << 3 - leading_zeros(GC.@preserve(x, unsafe_load(x.d, x.size))) end function exponent(x::BigInt) iszero(x) && throw(DomainError(x, "cannot be zero")) ux = abs(x) return _bit_magnitude(ux) - 1 end function top_set_bit(x::BigInt) isnegative(x) && throw(DomainError(x, "top_set_bit only supports negative arguments when they have type BitSigned.")) iszero(x) && return 0 return _bit_magnitude(x) end divrem(x::BigInt, y::BigInt, ::typeof(RoundToZero) = begin RoundToZero end) = begin MPZ.tdiv_qr(x, y) end divrem(x::BigInt, y::Integer, ::typeof(RoundToZero) = begin RoundToZero end) = begin MPZ.tdiv_qr(x, BigInt(y)) end cmp(x::BigInt, y::BigInt) = begin sign(MPZ.cmp(x, y)) end cmp(x::BigInt, y::ClongMax) = begin sign(MPZ.cmp_si(x, y)) end cmp(x::BigInt, y::CulongMax) = begin sign(MPZ.cmp_ui(x, y)) end cmp(x::BigInt, y::Integer) = begin cmp(x, big(y)) end cmp(x::Integer, y::BigInt) = begin -(cmp(y, x)) end cmp(x::BigInt, y::CdoubleMax) = begin if isnan(y) -1 else sign(MPZ.cmp_d(x, y)) end end cmp(x::CdoubleMax, y::BigInt) = begin -(cmp(y, x)) end isqrt(x::BigInt) = begin MPZ.sqrt(x) end x::BigInt ^ y::Culong = begin MPZ.pow_ui(x, y) end function bigint_pow(x::BigInt, y::Integer) x == 1 && return x x == -1 && return if isodd(y) x else -x end if y < 0 throw(DomainError(y, "`y` cannot be negative.")) end @noinline throw1(y) = begin throw(OverflowError("exponent $(y) is too large and computation will overflow")) end if y > typemax(Culong) x == 0 && return x throw1(y) end return x ^ convert(Culong, y) end x::BigInt ^ y::BigInt = begin bigint_pow(x, y) end x::BigInt ^ y::Bool = begin if y x else one(x) end end x::BigInt ^ y::Integer = begin bigint_pow(x, y) end x::Integer ^ y::BigInt = begin bigint_pow(BigInt(x), y) end x::Bool ^ y::BigInt = begin Base.power_by_squaring(x, y) end function powermod(x::BigInt, p::BigInt, m::BigInt) r = MPZ.powm(x, p, m) return if m < 0 && r > 0 MPZ.add!(r, m) else r end end powermod(x::Integer, p::Integer, m::BigInt) = begin powermod(big(x), big(p), m) end function gcdx(a::BigInt, b::BigInt) (g, s, t) = MPZ.gcdext(a, b) if t == 0 if a == b return (g, t, s) elseif abs(a) == abs(b) return (g, t, -s) end end (g, s, t) end +(x::BigInt, y::BigInt, rest::BigInt...) = begin sum(tuple(x, y, rest...)) end sum(arr::Union{AbstractArray{BigInt}, Tuple{BigInt, Vararg{BigInt}}}) = begin foldl(MPZ.add!, arr; init = BigInt(0)) end function prod(arr::AbstractArray{BigInt}) any(iszero, arr) && return zero(BigInt) _prod(arr, firstindex(arr), lastindex(arr)) end function _prod(arr::AbstractArray{BigInt}, lo, hi) if (hi - lo) + 1 <= 16 nlimbs = 0 for i = lo:hi nlimbs += abs((arr[i]).size) end init = BigInt(; nbits = nlimbs * BITS_PER_LIMB) MPZ.set_si!(init, 1) for i = lo:hi MPZ.mul!(init, arr[i]) end init else mid = (lo + hi) ÷ 2 MPZ.mul!(_prod(arr, lo, mid), _prod(arr, mid + 1, hi)) end end factorial(n::BigInt) = begin if !(isnegative(n)) MPZ.fac_ui(n) else throw(DomainError(n, "`n` must not be negative.")) end end function binomial(n::BigInt, k::Integer) k < 0 && return BigInt(0) k <= typemax(Culong) && return binomial(n, Culong(k)) n < 0 && return if isodd(k) -(binomial((k - n) - 1, k)) else binomial((k - n) - 1, k) end κ = n - k κ < 0 && return BigInt(0) κ <= typemax(Culong) && return binomial(n, Culong(κ)) throw(OverflowError("Computation would exceed memory")) end binomial(n::BigInt, k::Culong) = begin MPZ.bin_ui(n, k) end x::BigInt == y::BigInt = begin cmp(x, y) == 0 end x::BigInt == i::Integer = begin cmp(x, i) == 0 end i::Integer == x::BigInt = begin cmp(x, i) == 0 end x::BigInt == f::CdoubleMax = begin if isnan(f) false else cmp(x, f) == 0 end end f::CdoubleMax == x::BigInt = begin if isnan(f) false else cmp(x, f) == 0 end end iszero(x::BigInt) = begin x.size == 0 end isone(x::BigInt) = begin x == Culong(1) end x::BigInt <= y::BigInt = begin cmp(x, y) <= 0 end x::BigInt <= i::Integer = begin cmp(x, i) <= 0 end i::Integer <= x::BigInt = begin cmp(x, i) >= 0 end x::BigInt <= f::CdoubleMax = begin if isnan(f) false else cmp(x, f) <= 0 end end f::CdoubleMax <= x::BigInt = begin if isnan(f) false else cmp(x, f) >= 0 end end x::BigInt < y::BigInt = begin cmp(x, y) < 0 end x::BigInt < i::Integer = begin cmp(x, i) < 0 end i::Integer < x::BigInt = begin cmp(x, i) > 0 end x::BigInt < f::CdoubleMax = begin if isnan(f) false else cmp(x, f) < 0 end end f::CdoubleMax < x::BigInt = begin if isnan(f) false else cmp(x, f) > 0 end end isnegative(x::BigInt) = begin x.size < 0 end ispositive(x::BigInt) = begin x.size > 0 end signbit(x::BigInt) = begin isnegative(x) end flipsign!(x::BigInt, y::Integer) = begin signbit(y) && (x.size = -(x.size)) x end flipsign(x::BigInt, y::Integer) = begin if signbit(y) -x else x end end flipsign(x::BigInt, y::BigInt) = begin if signbit(y) -x else x end end function sign(x::BigInt) isnegative(x) && return -(one(x)) ispositive(x) && return one(x) return x end show(io::IO, x::BigInt) = begin print(io, string(x)) end function string(n::BigInt; base::Integer = 10, pad::Integer = 1) base < 0 && return Base._base(Int(base), n, pad, (base > 0) & (n.size < 0)) 2 <= base <= 62 || throw(ArgumentError("base must be 2 ≤ base ≤ 62, got $(base)")) iszero(n) && (pad < 1 && return "") nd1 = ndigits(n, base = base) nd = max(nd1, pad) str = Base._string_n(nd + isnegative(n)) GC.@preserve str begin p = pointer(str) MPZ.get_str!((p + nd) - nd1, base, n) pad_len = nd - nd1 if pad_len > 0 Base.memset(p + isnegative(n), UInt8('0'), pad_len) end isnegative(n) && unsafe_store!(p, UInt8('-')) end return str end function digits!(a::AbstractVector{T}, n::BigInt; base::Integer = 10) where T <: Integer if base ≥ 2 if base ≤ 62 s = codeunits(string(n; base)) (i, j) = (firstindex(a) - 1, length(s) + 1) lasti = min(lastindex(a), ((firstindex(a) + length(s)) - 1) - isnegative(n)) while i < lasti x = s[j -= 1] a[i += 1] = if base ≤ 36 if x > 0x39 x - 0x57 else x - 0x30 end else if x > 0x39 if x > 0x60 x - 0x3d else x - 0x37 end else x - 0x30 end end end lasti = lastindex(a) while i < lasti a[i += 1] = zero(T) end return if isnegative(n) map!(-, a, a) else a end elseif a isa StridedVector{<:Base.BitInteger} && (stride(a, 1) == 1 && (ispow2(base) && base - 1 ≤ typemax(T))) origlen = length(a) (_, writelen) = MPZ.export!(a, n; nails = 8 * sizeof(T) - trailing_zeros(base)) length(a) != origlen && resize!(a, origlen) a[var"begin" + writelen:var"end"] .= zero(T) return if isnegative(n) map!(-, a, a) else a end end end return invoke(digits!, Tuple{typeof(a), Integer}, a, n; base) end function ndigits0zpb(x::BigInt, b::Integer) b < 2 && throw(DomainError(b, "`b` cannot be less than 2.")) x.size == 0 && return 0 if ispow2(b) && 2 <= b <= 62 MPZ.sizeinbase(x, b) else n = MPZ.sizeinbase(x, 2) lb = log2(b) (q, r) = divrem(n, lb) iq = Int(q) maxerr = q * eps(lb) if r - 1.0 < maxerr if abs(x) >= big(b) ^ iq iq + 1 else iq end elseif lb - r < maxerr if abs(x) >= big(b) ^ (iq + 1) iq + 2 else iq + 1 end else iq + 1 end end end _prevpow2(x::BigInt) = begin if -2 <= x <= 2 x else flipsign!(ONE << (ndigits(x, base = 2) - 1), x) end end _nextpow2(x::BigInt) = begin if count_ones_abs(x) <= 1 x else flipsign!(ONE << ndigits(x, base = 2), x) end end Base.checked_abs(x::BigInt) = begin abs(x) end Base.checked_neg(x::BigInt) = begin -x end Base.checked_add(a::BigInt, b::BigInt) = begin a + b end Base.checked_sub(a::BigInt, b::BigInt) = begin a - b end Base.checked_mul(a::BigInt, b::BigInt) = begin a * b end Base.checked_div(a::BigInt, b::BigInt) = begin div(a, b) end Base.checked_rem(a::BigInt, b::BigInt) = begin rem(a, b) end Base.checked_fld(a::BigInt, b::BigInt) = begin fld(a, b) end Base.checked_mod(a::BigInt, b::BigInt) = begin mod(a, b) end Base.checked_cld(a::BigInt, b::BigInt) = begin cld(a, b) end Base.add_with_overflow(a::BigInt, b::BigInt) = begin (a + b, false) end Base.sub_with_overflow(a::BigInt, b::BigInt) = begin (a - b, false) end Base.mul_with_overflow(a::BigInt, b::BigInt) = begin (a * b, false) end Base.checked_pow(x::BigInt, p::Integer) = begin x ^ p end Base.checked_pow(x::Integer, p::BigInt) = begin x ^ p end Base.checked_pow(x::BigInt, p::BigInt) = begin x ^ p end Base.deepcopy_internal(x::BigInt, stackdict::IdDict) = begin get!((()->begin MPZ.set(x) end), stackdict, x)::BigInt end Base._hash_shl!(x::BigInt, n) = begin MPZ.mul_2exp!(x, n) end if Limb === UInt64 === UInt using .Base: HASH_SECRET, hash_bytes, hash_finalizer struct UnsafeLimbView <: AbstractVector{UInt8} bigint::BigInt start_byte::Int num_bytes::Int end function Base.size(view::UnsafeLimbView) return (view.num_bytes,) end function Base.getindex(view::UnsafeLimbView, i::Int) @boundscheck checkbounds(view, i) GC.@preserve view begin limb_index = div((view.start_byte + i) - 2, 8) + 1 byte_in_limb = ((view.start_byte + i) - 2) % 8 limb = unsafe_load(view.bigint.d, limb_index) return UInt8(limb >> (8byte_in_limb) & 0xff) end end function Base.iterate(view::UnsafeLimbView, state::Int = 1) state > view.num_bytes && return nothing return (@inbounds(view[state]), state + 1) end function Base.length(view::UnsafeLimbView) return view.num_bytes end function hash_integer(n::BigInt, h::UInt) iszero(n) && return hash_integer(0, h) s = n.size h ⊻= s < 0 us = abs(s) leading_zero_bytes = div(leading_zeros(unsafe_load(n.d, us)), 8) num_bytes = 8us - leading_zero_bytes limb_view = UnsafeLimbView(n, 1, num_bytes) return hash_bytes(limb_view, h, HASH_SECRET) end function hash(x::BigInt, h::UInt) GC.@preserve x begin sz = x.size sz == 0 && return hash(0, h) ptr = Ptr{UInt64}(x.d) if sz == 1 return hash(unsafe_load(ptr), h) elseif sz == -1 limb = unsafe_load(ptr) limb <= typemin(Int) % UInt && return hash(-(limb % Int), h) end pow = trailing_zeros(x) nd = Base.ndigits0z(x, 2) idx = pow >>> 6 + 1 shift = (pow & 63) % UInt upshift = BITS_PER_LIMB - shift asz = abs(sz) if shift == 0 limb = unsafe_load(ptr, idx) else limb1 = unsafe_load(ptr, idx) limb2 = if idx < asz unsafe_load(ptr, idx + 1) else UInt(0) end limb = limb2 << upshift | limb1 >> shift end if nd <= 1024 && nd - pow <= 53 return hash(ldexp(flipsign(Float64(limb), sz), pow), h) end h = hash_integer(pow, h) h ⊻= sz < 0 leading_zero_bytes = div(leading_zeros(unsafe_load(x.d, asz)), 8) trailing_zero_bytes = div(pow, 8) num_bytes = 8asz - (leading_zero_bytes + trailing_zero_bytes) limb_view = UnsafeLimbView(x, trailing_zero_bytes + 1, num_bytes) return hash_bytes(limb_view, h, HASH_SECRET) end end end module MPQ import .Base: unsafe_rational, __throw_rational_argerror_zero import ..GMP: BigInt, MPZ, Limb, libgmp gmpq(op::Symbol) = begin Expr(:tuple, QuoteNode(Symbol(:__gmpq_, op)), GlobalRef(MPZ, :libgmp)) end mutable struct _MPQ num_alloc::Cint num_size::Cint num_d::Ptr{Limb} den_alloc::Cint den_size::Cint den_d::Ptr{Limb} rat::Rational{BigInt} end const mpq_t = Ref{_MPQ} _MPQ(x::BigInt, y::BigInt) = begin _MPQ(x.alloc, x.size, x.d, y.alloc, y.size, y.d, unsafe_rational(BigInt, x, y)) end _MPQ() = begin _MPQ(BigInt(), BigInt()) end _MPQ(x::Rational{BigInt}) = begin _MPQ(x.num, x.den) end function sync_rational!(xq::_MPQ) xq.rat.num.alloc = xq.num_alloc xq.rat.num.size = xq.num_size xq.rat.num.d = xq.num_d xq.rat.den.alloc = xq.den_alloc xq.rat.den.size = xq.den_size xq.rat.den.d = xq.den_d return xq.rat end function Rational{BigInt}(num::BigInt, den::BigInt) if iszero(den) iszero(num) && __throw_rational_argerror_zero(BigInt) return set_si(flipsign(1, num), 0) end xq = _MPQ(MPZ.set(num), MPZ.set(den)) ccall((:__gmpq_canonicalize, libgmp), Cvoid, (mpq_t,), xq) return sync_rational!(xq) end function set!(z::Rational{BigInt}, x::Rational{BigInt}) zq = _MPQ(z) ccall((:__gmpq_set, libgmp), Cvoid, (mpq_t, mpq_t), zq, _MPQ(x)) return sync_rational!(zq) end function set_z!(z::Rational{BigInt}, x::BigInt) zq = _MPQ(z) ccall((:__gmpq_set_z, libgmp), Cvoid, (mpq_t, MPZ.mpz_t), zq, x) return sync_rational!(zq) end for (op, T) = ((:set, Rational{BigInt}), (:set_z, BigInt)) op! = Symbol(op, :!) @eval ($op)(a::$T) = begin ($op!)(unsafe_rational(BigInt(), BigInt()), a) end end for (op, T1, T2) = ((:set_ui, Culong, Culong), (:set_si, Clong, Culong)) op! = Symbol(op, :!) @eval begin function ($op!)(z::Rational{BigInt}, a, b) zq = _MPQ(z) ccall($(gmpq(op)), Cvoid, (mpq_t, $T1, $T2), zq, a, b) return sync_rational!(zq) end ($op)(a, b) = begin ($op!)(unsafe_rational(BigInt(), BigInt()), a, b) end end end function add!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) || iszero(y.den) if iszero(x.den) && (iszero(y.den) && isnegative(x.num) != isnegative(y.num)) throw(DivideError()) end return set!(z, if iszero(x.den) x else y end) end zq = _MPQ(z) ccall((:__gmpq_add, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end function sub!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) || iszero(y.den) if iszero(x.den) && (iszero(y.den) && isnegative(x.num) == isnegative(y.num)) throw(DivideError()) end iszero(x.den) && return set!(z, x) return set_si!(z, flipsign(-1, y.num), 0) end zq = _MPQ(z) ccall((:__gmpq_sub, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end function mul!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) || iszero(y.den) if iszero(x.num) || iszero(y.num) throw(DivideError()) end return set_si!(z, ifelse(xor(isnegative(x.num), isnegative(y.num)), -1, 1), 0) end zq = _MPQ(z) ccall((:__gmpq_mul, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end function div!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) if iszero(y.den) throw(DivideError()) end isnegative(y.num) || return set!(z, x) return set_si!(z, flipsign(-1, x.num), 0) elseif iszero(y.den) return set_si!(z, 0, 1) elseif iszero(y.num) if iszero(x.num) throw(DivideError()) end return set_si!(z, flipsign(1, x.num), 0) end zq = _MPQ(z) ccall((:__gmpq_div, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end for (fJ, fC) = ((:+, :add), (:-, :sub), (:*, :mul), (://, :div)) fC! = Symbol(fC, :!) @eval begin ($fC!)(x::Rational{BigInt}, y::Rational{BigInt}) = begin ($fC!)(x, x, y) end Base.:($fJ)(x::Rational{BigInt}, y::Rational{BigInt}) = begin ($fC!)(unsafe_rational(BigInt(), BigInt()), x, y) end end end function Base.cmp(x::Rational{BigInt}, y::Rational{BigInt}) Int(ccall((:__gmpq_cmp, libgmp), Cint, (mpq_t, mpq_t), _MPQ(x), _MPQ(y))) end end end begin export BigInt import .Base: *, +, -, /, <, <<, >>, >>>, <=, ==, >, >=, ^, ~, &, |, xor, nand, nor, binomial, cmp, convert, div, divrem, factorial, cld, fld, gcd, gcdx, lcm, mod, ndigits, promote_rule, rem, show, isqrt, string, powermod, sum, prod, trailing_zeros, trailing_ones, count_ones, count_zeros, tryparse_internal, bin, oct, dec, hex, isequal, invmod, _prevpow2, _nextpow2, ndigits0zpb, widen, signed, unsafe_trunc, trunc, iszero, isone, big, flipsign, signbit, sign, isodd, iseven, digits!, hash, hash_integer, top_set_bit, ispositive, isnegative, clamp import Core: Signed, Float16, Float32, Float64 if Clong == Int32 const ClongMax = Union{Int8, Int16, Int32} const CulongMax = Union{UInt8, UInt16, UInt32} else const ClongMax = Union{Int8, Int16, Int32, Int64} const CulongMax = Union{UInt8, UInt16, UInt32, UInt64} end const CdoubleMax = Union{Float16, Float32, Float64} if Sys.iswindows() const libgmp = "libgmp-10.dll" elseif Sys.isapple() const libgmp = "@rpath/libgmp.10.dylib" else const libgmp = "libgmp.so.10" end _version() = begin unsafe_string(unsafe_load(cglobal((:__gmp_version, libgmp), Ptr{Cchar}))) end version() = begin VersionNumber(_version()) end major_version() = begin (_version())[1] end bits_per_limb() = begin Int(unsafe_load(cglobal((:__gmp_bits_per_limb, libgmp), Cint))) end const VERSION = version() const MAJOR_VERSION = major_version() const BITS_PER_LIMB = bits_per_limb() if BITS_PER_LIMB == 32 const Limb = UInt32 const SLimbMax = Union{Int8, Int16, Int32} const ULimbMax = Union{UInt8, UInt16, UInt32} elseif BITS_PER_LIMB == 64 const Limb = UInt64 const SLimbMax = Union{Int8, Int16, Int32, Int64} const ULimbMax = Union{UInt8, UInt16, UInt32, UInt64} else error("GMP: cannot determine the type mp_limb_t (__gmp_bits_per_limb == $(BITS_PER_LIMB))") end Core.@doc " BigInt <: Signed\n\nArbitrary precision integer type.\n" mutable struct BigInt <: Signed alloc::Cint size::Cint d::Ptr{Limb} function BigInt(; nbits::Integer = 0) b = MPZ.init2!(new(), nbits) finalizer(cglobal((:__gmpz_clear, libgmp)), b) return b end end Core.@doc " BigInt(x)\n\nCreate an arbitrary precision integer. `x` may be an `Int` (or anything that can be\nconverted to an `Int`). The usual mathematical operators are defined for this type, and\nresults are promoted to a [`BigInt`](@ref).\n\nInstances can be constructed from strings via [`parse`](@ref), or using the `big`\nstring literal.\n\n# Examples\n```jldoctest\njulia> parse(BigInt, \"42\")\n42\n\njulia> big\"313\"\n313\n\njulia> BigInt(10)^19\n10000000000000000000\n```\n" BigInt(x) Core.@doc " ALLOC_OVERFLOW_FUNCTION\n\nA reference that holds a boolean, if true, indicating julia is linked with a patched GMP that\ndoes not abort on huge allocation and throws OutOfMemoryError instead.\n" const ALLOC_OVERFLOW_FUNCTION = Ref(false) function __init__() try if major_version() != MAJOR_VERSION || bits_per_limb() != BITS_PER_LIMB msg = "The dynamically loaded GMP library (v\"$(version())\" with __gmp_bits_per_limb == $(bits_per_limb()))\ndoes not correspond to the compile time version (v\"$(VERSION)\" with __gmp_bits_per_limb == $(BITS_PER_LIMB)).\nPlease rebuild Julia." if bits_per_limb() != BITS_PER_LIMB @error msg else @warn msg end end ccall((:__gmp_set_memory_functions, libgmp), Cvoid, (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), cglobal(:jl_gc_counted_malloc), cglobal(:jl_gc_counted_realloc_with_old_size), cglobal(:jl_gc_counted_free_with_size)) (ZERO.alloc, ZERO.size, ZERO.d) = (0, 0, C_NULL) (ONE.alloc, ONE.size, ONE.d) = (1, 1, pointer(_ONE)) catch ex Base.showerror_nostdio(ex, "WARNING: Error during initialization of module GMP") end try ccall((:__gmp_set_alloc_overflow_function, libgmp), Cvoid, (Ptr{Cvoid},), cglobal(:jl_throw_out_of_memory_error)) ALLOC_OVERFLOW_FUNCTION[] = true catch ex if typeof(ex) != ErrorException rethrow() end end end module MPZ using ..GMP: BigInt, Limb, BITS_PER_LIMB, libgmp const mpz_t = Ref{BigInt} const bitcnt_t = Culong gmpz(op::Symbol) = begin Expr(:tuple, QuoteNode(Symbol(:__gmpz_, op)), GlobalRef(MPZ, :libgmp)) end init!(x::BigInt) = begin ccall((:__gmpz_init, libgmp), Cvoid, (mpz_t,), x) x end init2!(x::BigInt, a) = begin ccall((:__gmpz_init2, libgmp), Cvoid, (mpz_t, bitcnt_t), x, a) x end realloc2!(x, a) = begin ccall((:__gmpz_realloc2, libgmp), Cvoid, (mpz_t, bitcnt_t), x, a) x end realloc2(a) = begin realloc2!(BigInt(), a) end sizeinbase(a::BigInt, b) = begin Int(ccall((:__gmpz_sizeinbase, libgmp), Csize_t, (mpz_t, Cint), a, b)) end for (op, nbits) = (:add => :(BITS_PER_LIMB * (1 + max(abs(a.size), abs(b.size)))), :sub => :(BITS_PER_LIMB * (1 + max(abs(a.size), abs(b.size)))), :mul => 0, :fdiv_q => 0, :tdiv_q => 0, :cdiv_q => 0, :fdiv_r => 0, :tdiv_r => 0, :cdiv_r => 0, :gcd => 0, :lcm => 0, :and => 0, :ior => 0, :xor => 0) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a::BigInt, b::BigInt) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, mpz_t, mpz_t), x, a, b) x end ($op)(a::BigInt, b::BigInt) = begin ($op!)(BigInt(nbits = $nbits), a, b) end ($op!)(x::BigInt, b::BigInt) = begin ($op!)(x, x, b) end end end invert!(x::BigInt, a::BigInt, b::BigInt) = begin ccall((:__gmpz_invert, libgmp), Cint, (mpz_t, mpz_t, mpz_t), x, a, b) end invert!(x::BigInt, b::BigInt) = begin invert!(x, x, b) end invert(a::BigInt, b::BigInt) = begin ret = BigInt() invert!(ret, a, b) ret end for op = (:add_ui, :sub_ui, :mul_ui, :mul_2exp, :fdiv_q_2exp, :pow_ui, :bin_ui) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a::BigInt, b) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, mpz_t, Culong), x, a, b) x end ($op)(a::BigInt, b) = begin ($op!)(BigInt(), a, b) end ($op!)(x::BigInt, b) = begin ($op!)(x, x, b) end end end ui_sub!(x::BigInt, a, b::BigInt) = begin ccall((:__gmpz_ui_sub, libgmp), Cvoid, (mpz_t, Culong, mpz_t), x, a, b) x end ui_sub(a, b::BigInt) = begin ui_sub!(BigInt(), a, b) end for op = (:scan1, :scan0) @eval ($op)(a::BigInt, b) = begin Int(signed(ccall($(gmpz(op)), Culong, (mpz_t, Culong), a, b))) end end mul_si!(x::BigInt, a::BigInt, b) = begin ccall((:__gmpz_mul_si, libgmp), Cvoid, (mpz_t, mpz_t, Clong), x, a, b) x end mul_si(a::BigInt, b) = begin mul_si!(BigInt(), a, b) end mul_si!(x::BigInt, b) = begin mul_si!(x, x, b) end for op = (:neg, :com, :sqrt, :set) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a::BigInt) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, mpz_t), x, a) x end ($op)(a::BigInt) = begin ($op!)(BigInt(), a) end end op === :set && continue @eval ($op!)(x::BigInt) = begin ($op!)(x, x) end end for (op, T) = ((:fac_ui, Culong), (:set_ui, Culong), (:set_si, Clong), (:set_d, Cdouble)) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, $T), x, a) x end ($op)(a) = begin ($op!)(BigInt(), a) end end end popcount(a::BigInt) = begin Int(signed(ccall((:__gmpz_popcount, libgmp), Culong, (mpz_t,), a))) end mpn_popcount(d::Ptr{Limb}, s::Integer) = begin Int(ccall((:__gmpn_popcount, libgmp), Culong, (Ptr{Limb}, Csize_t), d, s)) end mpn_popcount(a::BigInt) = begin mpn_popcount(a.d, abs(a.size)) end function tdiv_qr!(x::BigInt, y::BigInt, a::BigInt, b::BigInt) ccall((:__gmpz_tdiv_qr, libgmp), Cvoid, (mpz_t, mpz_t, mpz_t, mpz_t), x, y, a, b) (x, y) end tdiv_qr(a::BigInt, b::BigInt) = begin tdiv_qr!(BigInt(), BigInt(), a, b) end powm!(x::BigInt, a::BigInt, b::BigInt, c::BigInt) = begin ccall((:__gmpz_powm, libgmp), Cvoid, (mpz_t, mpz_t, mpz_t, mpz_t), x, a, b, c) x end powm(a::BigInt, b::BigInt, c::BigInt) = begin powm!(BigInt(), a, b, c) end powm!(x::BigInt, b::BigInt, c::BigInt) = begin powm!(x, x, b, c) end function gcdext!(x::BigInt, y::BigInt, z::BigInt, a::BigInt, b::BigInt) ccall((:__gmpz_gcdext, libgmp), Cvoid, (mpz_t, mpz_t, mpz_t, mpz_t, mpz_t), x, y, z, a, b) (x, y, z) end gcdext(a::BigInt, b::BigInt) = begin gcdext!(BigInt(), BigInt(), BigInt(), a, b) end cmp(a::BigInt, b::BigInt) = begin Int(ccall((:__gmpz_cmp, libgmp), Cint, (mpz_t, mpz_t), a, b)) end cmp_si(a::BigInt, b) = begin Int(ccall((:__gmpz_cmp_si, libgmp), Cint, (mpz_t, Clong), a, b)) end cmp_ui(a::BigInt, b) = begin Int(ccall((:__gmpz_cmp_ui, libgmp), Cint, (mpz_t, Culong), a, b)) end cmp_d(a::BigInt, b) = begin Int(ccall((:__gmpz_cmp_d, libgmp), Cint, (mpz_t, Cdouble), a, b)) end mpn_cmp(a::Ptr{Limb}, b::Ptr{Limb}, c) = begin ccall((:__gmpn_cmp, libgmp), Cint, (Ptr{Limb}, Ptr{Limb}, Clong), a, b, c) end mpn_cmp(a::BigInt, b::BigInt, c) = begin mpn_cmp(a.d, b.d, c) end get_str!(x, a, b::BigInt) = begin ccall((:__gmpz_get_str, libgmp), Ptr{Cchar}, (Ptr{Cchar}, Cint, mpz_t), x, a, b) x end set_str!(x::BigInt, a, b) = begin Int(ccall((:__gmpz_set_str, libgmp), Cint, (mpz_t, Ptr{UInt8}, Cint), x, a, b)) end get_d(a::BigInt) = begin ccall((:__gmpz_get_d, libgmp), Cdouble, (mpz_t,), a) end function export!(a::AbstractVector{T}, n::BigInt; order::Integer = -1, nails::Integer = 0, endian::Integer = 0) where T <: Base.BitInteger stride(a, 1) == 1 || throw(ArgumentError("a must have stride 1")) ndigits = cld(sizeinbase(n, 2), 8 * sizeof(T) - nails) length(a) < ndigits && resize!(a, ndigits) fill!(a, zero(T)) count = Ref{Csize_t}() ccall((:__gmpz_export, libgmp), Ptr{T}, (Ptr{T}, Ref{Csize_t}, Cint, Csize_t, Cint, Csize_t, mpz_t), a, count, order, sizeof(T), endian, nails, n) @assert count[] ≤ length(a) return (a, Int(count[])) end limbs_write!(x::BigInt, a) = begin ccall((:__gmpz_limbs_write, libgmp), Ptr{Limb}, (mpz_t, Clong), x, a) end limbs_finish!(x::BigInt, a) = begin ccall((:__gmpz_limbs_finish, libgmp), Cvoid, (mpz_t, Clong), x, a) end setbit!(x, a) = begin ccall((:__gmpz_setbit, libgmp), Cvoid, (mpz_t, bitcnt_t), x, a) x end tstbit(a::BigInt, b) = begin ccall((:__gmpz_tstbit, libgmp), Cint, (mpz_t, bitcnt_t), a, b) % Bool end end const ZERO = BigInt() const ONE = BigInt() const _ONE = Limb[1] widen(::Type{Int128}) = begin BigInt end widen(::Type{UInt128}) = begin BigInt end widen(::Type{BigInt}) = begin BigInt end signed(x::BigInt) = begin x end BigInt(x::BigInt) = begin x end Signed(x::BigInt) = begin x end function tryparse_internal(::Type{BigInt}, s::AbstractString, startpos::Int, endpos::Int, base_::Integer, raise::Bool) bstr = if startpos == firstindex(s) && endpos == lastindex(s) String(s) else String(SubString(s, startpos, endpos)) end (sgn, base, i) = Base.parseint_preamble(true, Int(base_), bstr, firstindex(bstr), lastindex(bstr)) if !(2 <= base <= 62) raise && throw(ArgumentError("invalid base: base must be 2 ≤ base ≤ 62, got $(base)")) return nothing end if i == 0 raise && throw(ArgumentError("premature end of integer: $(repr(bstr))")) return nothing end z = BigInt() if Base.containsnul(bstr) err = -1 else err = GC.@preserve(bstr, MPZ.set_str!(z, pointer(bstr) + (i - firstindex(bstr)), base)) end if err != 0 raise && throw(ArgumentError("invalid BigInt: $(repr(bstr))")) return nothing end flipsign!(z, sgn) end BigInt(x::Union{Clong, Int32}) = begin MPZ.set_si(x) end BigInt(x::Union{Culong, UInt32}) = begin MPZ.set_ui(x) end BigInt(x::Bool) = begin BigInt(UInt(x)) end unsafe_trunc(::Type{BigInt}, x::Union{Float16, Float32, Float64}) = begin MPZ.set_d(x) end function BigInt(x::Float64) isinteger(x) || throw(InexactError(:BigInt, BigInt, x)) unsafe_trunc(BigInt, x) end BigInt(x::Float16) = begin BigInt(Float64(x)) end BigInt(x::Float32) = begin BigInt(Float64(x)) end function BigInt(x::Integer) isbits(x) && (typemin(Clong) <= x <= typemax(Clong) && return BigInt((x % Clong)::Clong)) nd = ndigits(x, base = 2) z = MPZ.realloc2(nd) ux = unsigned(if x < 0 -x else x end) size = 0 limbnbits = sizeof(Limb) << 3 while nd > 0 size += 1 unsafe_store!(z.d, ux % Limb, size) ux >>= limbnbits nd -= limbnbits end z.size = if x < 0 -size else size end z end rem(x::BigInt, ::Type{Bool}) = begin (!(iszero(x)) & unsafe_load(x.d)) % Bool end (rem(x::BigInt, ::Type{T}) where T <: Union{SLimbMax, ULimbMax}) = begin if iszero(x) zero(T) else flipsign(unsafe_load(x.d) % T, x.size) end end function rem(x::BigInt, ::Type{T}) where T <: Union{Base.BitUnsigned, Base.BitSigned} u = zero(T) for l = 1:min(abs(x.size), cld(sizeof(T), sizeof(Limb))) u += (unsafe_load(x.d, l) % T) << (sizeof(Limb) << 3 * (l - 1)) end flipsign(u, x.size) end rem(x::Integer, ::Type{BigInt}) = begin BigInt(x) end clamp(x, ::Type{BigInt}) = begin convert(BigInt, x) end isodd(x::BigInt) = begin MPZ.tstbit(x, 0) end iseven(x::BigInt) = begin !(isodd(x)) end function (::Type{T})(x::BigInt) where T <: Base.BitUnsigned if sizeof(T) < sizeof(Limb) convert(T, convert(Limb, x)) else 0 <= x.size <= cld(sizeof(T), sizeof(Limb)) || throw(InexactError(nameof(T), T, x)) x % T end end function (::Type{T})(x::BigInt) where T <: Base.BitSigned n = abs(x.size) if sizeof(T) < sizeof(Limb) SLimb = typeof(Signed(one(Limb))) convert(T, convert(SLimb, x)) else 0 <= n <= cld(sizeof(T), sizeof(Limb)) || throw(InexactError(nameof(T), T, x)) y = x % T ispositive(x) ⊻ (y > 0) && throw(InexactError(nameof(T), T, x)) y end end Float64(n::BigInt, ::RoundingMode{:ToZero}) = begin MPZ.get_d(n) end function (::Type{T})(n::BigInt, ::RoundingMode{:ToZero}) where T <: Union{Float16, Float32} T(Float64(n, RoundToZero), RoundToZero) end function (::Type{T})(n::BigInt, ::RoundingMode{:Down}) where T <: CdoubleMax x = T(n, RoundToZero) if x > n prevfloat(x) else x end end function (::Type{T})(n::BigInt, ::RoundingMode{:Up}) where T <: CdoubleMax x = T(n, RoundToZero) if x < n nextfloat(x) else x end end function Float64(x::BigInt, ::RoundingMode{:Nearest}) x == 0 && return 0.0 xsize = abs(x.size) if xsize * BITS_PER_LIMB > 1024 z = Inf64 elseif xsize == 1 z = Float64(unsafe_load(x.d)) elseif Limb == UInt32 && xsize == 2 z = Float64((unsafe_load(x.d, 2) % UInt64) << BITS_PER_LIMB + unsafe_load(x.d)) else y1 = unsafe_load(x.d, xsize) % UInt64 n = top_set_bit(y1) y = y1 >> (n - (precision(Float64) + 1)) if Limb == UInt64 y += if n > precision(Float64) 0 else unsafe_load(x.d, xsize - 1) >> (10 + n) end else y += (unsafe_load(x.d, xsize - 1) % UInt64) >> (n - 22) y += if n > precision(Float64) - 32 0 else unsafe_load(x.d, xsize - 2) >> (10 + n) end end y = (y + 1) >> 1 y &= ~(UInt64(trailing_zeros(x) == (n - 54) + (xsize - 1) * BITS_PER_LIMB)) d = ((n + 1021) % UInt64) << 52 z = reinterpret(Float64, d + y) z = ldexp(z, (xsize - 1) * BITS_PER_LIMB) end return flipsign(z, x.size) end function Float32(x::BigInt, ::RoundingMode{:Nearest}) x == 0 && return 0.0f0 xsize = abs(x.size) if xsize * BITS_PER_LIMB > 128 z = Inf32 elseif xsize == 1 z = Float32(unsafe_load(x.d)) else y1 = unsafe_load(x.d, xsize) n = BITS_PER_LIMB - leading_zeros(y1) y = y1 >> (n - (precision(Float32) + 1)) % UInt32 y += if n > precision(Float32) 0 else unsafe_load(x.d, xsize - 1) >> (BITS_PER_LIMB - -25) end % UInt32 y = (y + one(UInt32)) >> 1 y &= ~(UInt32(trailing_zeros(x) == (n - 25) + (xsize - 1) * BITS_PER_LIMB)) d = ((n + 125) % UInt32) << 23 z = reinterpret(Float32, d + y) z = ldexp(z, (xsize - 1) * BITS_PER_LIMB) end return flipsign(z, x.size) end function Float16(x::BigInt, ::RoundingMode{:Nearest}) x == 0 && return Float16(0.0) y1 = unsafe_load(x.d) n = BITS_PER_LIMB - leading_zeros(y1) if n > 16 || abs(x.size) > 1 z = Inf16 else y = y1 >> (n - (precision(Float16) + 1)) % UInt16 y = (y + one(UInt16)) >> 1 y &= ~(UInt16(trailing_zeros(x) == n - 12)) d = ((n + 13) % UInt16) << 10 z = reinterpret(Float16, d + y) end return flipsign(z, x.size) end Float64(n::BigInt) = begin Float64(n, RoundNearest) end Float32(n::BigInt) = begin Float32(n, RoundNearest) end Float16(n::BigInt) = begin Float16(n, RoundNearest) end promote_rule(::Type{BigInt}, ::Type{<:Integer}) = begin BigInt end Core.@doc " big(x)\n\nConvert a number to a maximum precision representation (typically [`BigInt`](@ref) or\n`BigFloat`). See [`BigFloat`](@ref BigFloat(::Any, rounding::RoundingMode)) for\ninformation about some pitfalls with floating-point numbers.\n" function big end big(::Type{<:Integer}) = begin BigInt end big(::Type{<:Rational}) = begin Rational{BigInt} end big(n::Integer) = begin convert(BigInt, n) end for (fJ, fC) = ((:+, :add), (:-, :sub), (:*, :mul), (:mod, :fdiv_r), (:rem, :tdiv_r), (:gcd, :gcd), (:lcm, :lcm), (:&, :and), (:|, :ior), (:xor, :xor)) @eval begin ($fJ)(x::BigInt, y::BigInt) = begin MPZ.:($fC)(x, y) end end end for (r, f) = ((RoundToZero, :tdiv_q), (RoundDown, :fdiv_q), (RoundUp, :cdiv_q)) @eval div(x::BigInt, y::BigInt, ::typeof($r)) = begin MPZ.:($f)(x, y) end end div(x::BigInt, y::BigInt) = begin div(x, y, RoundToZero) end fld(x::BigInt, y::BigInt) = begin div(x, y, RoundDown) end cld(x::BigInt, y::BigInt) = begin div(x, y, RoundUp) end x::BigInt / y::BigInt = begin float(x) / float(y) end function invmod(x::BigInt, y::BigInt) z = zero(BigInt) ya = abs(y) if ya == 1 return z end if y == 0 || MPZ.invert!(z, x, ya) == 0 throw(DomainError(y)) end if y < 0 MPZ.add!(z, y) end return z end for (fJ, fC) = ((:+, :add), (:*, :mul), (:&, :and), (:|, :ior), (:xor, :xor)) fC! = Symbol(fC, :!) @eval begin ($fJ)(a::BigInt, b::BigInt, c::BigInt) = begin MPZ.:($fC!)(MPZ.:($fC)(a, b), c) end ($fJ)(a::BigInt, b::BigInt, c::BigInt, d::BigInt) = begin MPZ.:($fC!)(MPZ.:($fC!)(MPZ.:($fC)(a, b), c), d) end ($fJ)(a::BigInt, b::BigInt, c::BigInt, d::BigInt, e::BigInt) = begin MPZ.:($fC!)(MPZ.:($fC!)(MPZ.:($fC!)(MPZ.:($fC)(a, b), c), d), e) end end end x::BigInt + c::CulongMax = begin MPZ.add_ui(x, c) end c::CulongMax + x::BigInt = begin x + c end x::BigInt - c::CulongMax = begin MPZ.sub_ui(x, c) end c::CulongMax - x::BigInt = begin MPZ.ui_sub(c, x) end x::BigInt + c::ClongMax = begin if c < 0 x - -(c % Culong) else x + convert(Culong, c) end end c::ClongMax + x::BigInt = begin if c < 0 x - -(c % Culong) else x + convert(Culong, c) end end x::BigInt - c::ClongMax = begin if c < 0 x + -(c % Culong) else x - convert(Culong, c) end end c::ClongMax - x::BigInt = begin if c < 0 -((x + -(c % Culong))) else convert(Culong, c) - x end end x::BigInt * c::CulongMax = begin MPZ.mul_ui(x, c) end c::CulongMax * x::BigInt = begin x * c end x::BigInt * c::ClongMax = begin MPZ.mul_si(x, c) end c::ClongMax * x::BigInt = begin x * c end x::BigInt / y::Union{ClongMax, CulongMax} = begin float(x) / y end x::Union{ClongMax, CulongMax} / y::BigInt = begin x / float(y) end -(x::BigInt) = begin MPZ.neg(x) end ~(x::BigInt) = begin MPZ.com(x) end x::BigInt << c::UInt = begin if c == 0 x else MPZ.mul_2exp(x, c) end end x::BigInt >> c::UInt = begin if c == 0 x else MPZ.fdiv_q_2exp(x, c) end end x::BigInt >>> c::UInt = begin x >> c end function trailing_zeros(x::BigInt) c = MPZ.scan1(x, 0) c == -1 && throw(DomainError(x, "`x` must be non-zero")) c end function trailing_ones(x::BigInt) c = MPZ.scan0(x, 0) c == -1 && throw(DomainError(x, "`x` must not be equal to -1")) c end function count_ones(x::BigInt) c = MPZ.popcount(x) c == -1 && throw(DomainError(x, "`x` cannot be negative")) c end function count_zeros(x::BigInt) c = MPZ.popcount(~x) c == -1 && throw(DomainError(x, "`x` must be negative")) c end Core.@doc " count_ones_abs(x::BigInt)\n\nNumber of ones in the binary representation of abs(x).\n" count_ones_abs(x::BigInt) = begin if iszero(x) 0 else MPZ.mpn_popcount(x) end end _bit_magnitude(x::BigInt) = begin x.size * sizeof(Limb) << 3 - leading_zeros(GC.@preserve(x, unsafe_load(x.d, x.size))) end function exponent(x::BigInt) iszero(x) && throw(DomainError(x, "cannot be zero")) ux = abs(x) return _bit_magnitude(ux) - 1 end function top_set_bit(x::BigInt) isnegative(x) && throw(DomainError(x, "top_set_bit only supports negative arguments when they have type BitSigned.")) iszero(x) && return 0 return _bit_magnitude(x) end divrem(x::BigInt, y::BigInt, ::typeof(RoundToZero) = RoundToZero) = begin MPZ.tdiv_qr(x, y) end divrem(x::BigInt, y::Integer, ::typeof(RoundToZero) = RoundToZero) = begin MPZ.tdiv_qr(x, BigInt(y)) end cmp(x::BigInt, y::BigInt) = begin sign(MPZ.cmp(x, y)) end cmp(x::BigInt, y::ClongMax) = begin sign(MPZ.cmp_si(x, y)) end cmp(x::BigInt, y::CulongMax) = begin sign(MPZ.cmp_ui(x, y)) end cmp(x::BigInt, y::Integer) = begin cmp(x, big(y)) end cmp(x::Integer, y::BigInt) = begin -(cmp(y, x)) end cmp(x::BigInt, y::CdoubleMax) = begin if isnan(y) -1 else sign(MPZ.cmp_d(x, y)) end end cmp(x::CdoubleMax, y::BigInt) = begin -(cmp(y, x)) end isqrt(x::BigInt) = begin MPZ.sqrt(x) end x::BigInt ^ y::Culong = begin MPZ.pow_ui(x, y) end function bigint_pow(x::BigInt, y::Integer) x == 1 && return x x == -1 && return if isodd(y) x else -x end if y < 0 throw(DomainError(y, "`y` cannot be negative.")) end @noinline throw1(y) = begin throw(OverflowError("exponent $(y) is too large and computation will overflow")) end if y > typemax(Culong) x == 0 && return x throw1(y) end return x ^ convert(Culong, y) end x::BigInt ^ y::BigInt = begin bigint_pow(x, y) end x::BigInt ^ y::Bool = begin if y x else one(x) end end x::BigInt ^ y::Integer = begin bigint_pow(x, y) end x::Integer ^ y::BigInt = begin bigint_pow(BigInt(x), y) end x::Bool ^ y::BigInt = begin Base.power_by_squaring(x, y) end function powermod(x::BigInt, p::BigInt, m::BigInt) r = MPZ.powm(x, p, m) return if m < 0 && r > 0 MPZ.add!(r, m) else r end end powermod(x::Integer, p::Integer, m::BigInt) = begin powermod(big(x), big(p), m) end function gcdx(a::BigInt, b::BigInt) (g, s, t) = MPZ.gcdext(a, b) if t == 0 if a == b return (g, t, s) elseif abs(a) == abs(b) return (g, t, -s) end end (g, s, t) end +(x::BigInt, y::BigInt, rest::BigInt...) = begin sum(tuple(x, y, rest...)) end sum(arr::Union{AbstractArray{BigInt}, Tuple{BigInt, Vararg{BigInt}}}) = begin foldl(MPZ.add!, arr; init = BigInt(0)) end function prod(arr::AbstractArray{BigInt}) any(iszero, arr) && return zero(BigInt) _prod(arr, firstindex(arr), lastindex(arr)) end function _prod(arr::AbstractArray{BigInt}, lo, hi) if (hi - lo) + 1 <= 16 nlimbs = 0 for i = lo:hi nlimbs += abs((arr[i]).size) end init = BigInt(; nbits = nlimbs * BITS_PER_LIMB) MPZ.set_si!(init, 1) for i = lo:hi MPZ.mul!(init, arr[i]) end init else mid = (lo + hi) ÷ 2 MPZ.mul!(_prod(arr, lo, mid), _prod(arr, mid + 1, hi)) end end factorial(n::BigInt) = begin if !(isnegative(n)) MPZ.fac_ui(n) else throw(DomainError(n, "`n` must not be negative.")) end end function binomial(n::BigInt, k::Integer) k < 0 && return BigInt(0) k <= typemax(Culong) && return binomial(n, Culong(k)) n < 0 && return if isodd(k) -(binomial((k - n) - 1, k)) else binomial((k - n) - 1, k) end κ = n - k κ < 0 && return BigInt(0) κ <= typemax(Culong) && return binomial(n, Culong(κ)) throw(OverflowError("Computation would exceed memory")) end binomial(n::BigInt, k::Culong) = begin MPZ.bin_ui(n, k) end x::BigInt == y::BigInt = begin cmp(x, y) == 0 end x::BigInt == i::Integer = begin cmp(x, i) == 0 end i::Integer == x::BigInt = begin cmp(x, i) == 0 end x::BigInt == f::CdoubleMax = begin if isnan(f) false else cmp(x, f) == 0 end end f::CdoubleMax == x::BigInt = begin if isnan(f) false else cmp(x, f) == 0 end end iszero(x::BigInt) = begin x.size == 0 end isone(x::BigInt) = begin x == Culong(1) end x::BigInt <= y::BigInt = begin cmp(x, y) <= 0 end x::BigInt <= i::Integer = begin cmp(x, i) <= 0 end i::Integer <= x::BigInt = begin cmp(x, i) >= 0 end x::BigInt <= f::CdoubleMax = begin if isnan(f) false else cmp(x, f) <= 0 end end f::CdoubleMax <= x::BigInt = begin if isnan(f) false else cmp(x, f) >= 0 end end x::BigInt < y::BigInt = begin cmp(x, y) < 0 end x::BigInt < i::Integer = begin cmp(x, i) < 0 end i::Integer < x::BigInt = begin cmp(x, i) > 0 end x::BigInt < f::CdoubleMax = begin if isnan(f) false else cmp(x, f) < 0 end end f::CdoubleMax < x::BigInt = begin if isnan(f) false else cmp(x, f) > 0 end end isnegative(x::BigInt) = begin x.size < 0 end ispositive(x::BigInt) = begin x.size > 0 end signbit(x::BigInt) = begin isnegative(x) end flipsign!(x::BigInt, y::Integer) = begin signbit(y) && (x.size = -(x.size)) x end flipsign(x::BigInt, y::Integer) = begin if signbit(y) -x else x end end flipsign(x::BigInt, y::BigInt) = begin if signbit(y) -x else x end end function sign(x::BigInt) isnegative(x) && return -(one(x)) ispositive(x) && return one(x) return x end show(io::IO, x::BigInt) = begin print(io, string(x)) end function string(n::BigInt; base::Integer = 10, pad::Integer = 1) base < 0 && return Base._base(Int(base), n, pad, (base > 0) & (n.size < 0)) 2 <= base <= 62 || throw(ArgumentError("base must be 2 ≤ base ≤ 62, got $(base)")) iszero(n) && (pad < 1 && return "") nd1 = ndigits(n, base = base) nd = max(nd1, pad) str = Base._string_n(nd + isnegative(n)) GC.@preserve str begin p = pointer(str) MPZ.get_str!((p + nd) - nd1, base, n) pad_len = nd - nd1 if pad_len > 0 Base.memset(p + isnegative(n), UInt8('0'), pad_len) end isnegative(n) && unsafe_store!(p, UInt8('-')) end return str end function digits!(a::AbstractVector{T}, n::BigInt; base::Integer = 10) where T <: Integer if base ≥ 2 if base ≤ 62 s = codeunits(string(n; base)) (i, j) = (firstindex(a) - 1, length(s) + 1) lasti = min(lastindex(a), ((firstindex(a) + length(s)) - 1) - isnegative(n)) while i < lasti x = s[j -= 1] a[i += 1] = if base ≤ 36 if x > 0x39 x - 0x57 else x - 0x30 end else if x > 0x39 if x > 0x60 x - 0x3d else x - 0x37 end else x - 0x30 end end end lasti = lastindex(a) while i < lasti a[i += 1] = zero(T) end return if isnegative(n) map!(-, a, a) else a end elseif a isa StridedVector{<:Base.BitInteger} && (stride(a, 1) == 1 && (ispow2(base) && base - 1 ≤ typemax(T))) origlen = length(a) (_, writelen) = MPZ.export!(a, n; nails = 8 * sizeof(T) - trailing_zeros(base)) length(a) != origlen && resize!(a, origlen) a[var"begin" + writelen:var"end"] .= zero(T) return if isnegative(n) map!(-, a, a) else a end end end return invoke(digits!, Tuple{typeof(a), Integer}, a, n; base) end function ndigits0zpb(x::BigInt, b::Integer) b < 2 && throw(DomainError(b, "`b` cannot be less than 2.")) x.size == 0 && return 0 if ispow2(b) && 2 <= b <= 62 MPZ.sizeinbase(x, b) else n = MPZ.sizeinbase(x, 2) lb = log2(b) (q, r) = divrem(n, lb) iq = Int(q) maxerr = q * eps(lb) if r - 1.0 < maxerr if abs(x) >= big(b) ^ iq iq + 1 else iq end elseif lb - r < maxerr if abs(x) >= big(b) ^ (iq + 1) iq + 2 else iq + 1 end else iq + 1 end end end _prevpow2(x::BigInt) = begin if -2 <= x <= 2 x else flipsign!(ONE << (ndigits(x, base = 2) - 1), x) end end _nextpow2(x::BigInt) = begin if count_ones_abs(x) <= 1 x else flipsign!(ONE << ndigits(x, base = 2), x) end end Base.checked_abs(x::BigInt) = begin abs(x) end Base.checked_neg(x::BigInt) = begin -x end Base.checked_add(a::BigInt, b::BigInt) = begin a + b end Base.checked_sub(a::BigInt, b::BigInt) = begin a - b end Base.checked_mul(a::BigInt, b::BigInt) = begin a * b end Base.checked_div(a::BigInt, b::BigInt) = begin div(a, b) end Base.checked_rem(a::BigInt, b::BigInt) = begin rem(a, b) end Base.checked_fld(a::BigInt, b::BigInt) = begin fld(a, b) end Base.checked_mod(a::BigInt, b::BigInt) = begin mod(a, b) end Base.checked_cld(a::BigInt, b::BigInt) = begin cld(a, b) end Base.add_with_overflow(a::BigInt, b::BigInt) = begin (a + b, false) end Base.sub_with_overflow(a::BigInt, b::BigInt) = begin (a - b, false) end Base.mul_with_overflow(a::BigInt, b::BigInt) = begin (a * b, false) end Base.checked_pow(x::BigInt, p::Integer) = begin x ^ p end Base.checked_pow(x::Integer, p::BigInt) = begin x ^ p end Base.checked_pow(x::BigInt, p::BigInt) = begin x ^ p end Base.deepcopy_internal(x::BigInt, stackdict::IdDict) = begin get!((()->begin MPZ.set(x) end), stackdict, x)::BigInt end Base._hash_shl!(x::BigInt, n) = begin MPZ.mul_2exp!(x, n) end if Limb === UInt64 === UInt using .Base: HASH_SECRET, hash_bytes, hash_finalizer struct UnsafeLimbView <: AbstractVector{UInt8} bigint::BigInt start_byte::Int num_bytes::Int end function Base.size(view::UnsafeLimbView) return (view.num_bytes,) end function Base.getindex(view::UnsafeLimbView, i::Int) @boundscheck checkbounds(view, i) GC.@preserve view begin limb_index = div((view.start_byte + i) - 2, 8) + 1 byte_in_limb = ((view.start_byte + i) - 2) % 8 limb = unsafe_load(view.bigint.d, limb_index) return UInt8(limb >> (8byte_in_limb) & 0xff) end end function Base.iterate(view::UnsafeLimbView, state::Int = 1) state > view.num_bytes && return nothing return (@inbounds(view[state]), state + 1) end function Base.length(view::UnsafeLimbView) return view.num_bytes end function hash_integer(n::BigInt, h::UInt) iszero(n) && return hash_integer(0, h) s = n.size h ⊻= s < 0 us = abs(s) leading_zero_bytes = div(leading_zeros(unsafe_load(n.d, us)), 8) num_bytes = 8us - leading_zero_bytes limb_view = UnsafeLimbView(n, 1, num_bytes) return hash_bytes(limb_view, h, HASH_SECRET) end function hash(x::BigInt, h::UInt) GC.@preserve x begin sz = x.size sz == 0 && return hash(0, h) ptr = Ptr{UInt64}(x.d) if sz == 1 return hash(unsafe_load(ptr), h) elseif sz == -1 limb = unsafe_load(ptr) limb <= typemin(Int) % UInt && return hash(-(limb % Int), h) end pow = trailing_zeros(x) nd = Base.ndigits0z(x, 2) idx = pow >>> 6 + 1 shift = (pow & 63) % UInt upshift = BITS_PER_LIMB - shift asz = abs(sz) if shift == 0 limb = unsafe_load(ptr, idx) else limb1 = unsafe_load(ptr, idx) limb2 = if idx < asz unsafe_load(ptr, idx + 1) else UInt(0) end limb = limb2 << upshift | limb1 >> shift end if nd <= 1024 && nd - pow <= 53 return hash(ldexp(flipsign(Float64(limb), sz), pow), h) end h = hash_integer(pow, h) h ⊻= sz < 0 leading_zero_bytes = div(leading_zeros(unsafe_load(x.d, asz)), 8) trailing_zero_bytes = div(pow, 8) num_bytes = 8asz - (leading_zero_bytes + trailing_zero_bytes) limb_view = UnsafeLimbView(x, trailing_zero_bytes + 1, num_bytes) return hash_bytes(limb_view, h, HASH_SECRET) end end end module MPQ import .Base: unsafe_rational, __throw_rational_argerror_zero import ..GMP: BigInt, MPZ, Limb, libgmp gmpq(op::Symbol) = begin Expr(:tuple, QuoteNode(Symbol(:__gmpq_, op)), GlobalRef(MPZ, :libgmp)) end mutable struct _MPQ num_alloc::Cint num_size::Cint num_d::Ptr{Limb} den_alloc::Cint den_size::Cint den_d::Ptr{Limb} rat::Rational{BigInt} end const mpq_t = Ref{_MPQ} _MPQ(x::BigInt, y::BigInt) = begin _MPQ(x.alloc, x.size, x.d, y.alloc, y.size, y.d, unsafe_rational(BigInt, x, y)) end _MPQ() = begin _MPQ(BigInt(), BigInt()) end _MPQ(x::Rational{BigInt}) = begin _MPQ(x.num, x.den) end function sync_rational!(xq::_MPQ) xq.rat.num.alloc = xq.num_alloc xq.rat.num.size = xq.num_size xq.rat.num.d = xq.num_d xq.rat.den.alloc = xq.den_alloc xq.rat.den.size = xq.den_size xq.rat.den.d = xq.den_d return xq.rat end function Rational{BigInt}(num::BigInt, den::BigInt) if iszero(den) iszero(num) && __throw_rational_argerror_zero(BigInt) return set_si(flipsign(1, num), 0) end xq = _MPQ(MPZ.set(num), MPZ.set(den)) ccall((:__gmpq_canonicalize, libgmp), Cvoid, (mpq_t,), xq) return sync_rational!(xq) end function set!(z::Rational{BigInt}, x::Rational{BigInt}) zq = _MPQ(z) ccall((:__gmpq_set, libgmp), Cvoid, (mpq_t, mpq_t), zq, _MPQ(x)) return sync_rational!(zq) end function set_z!(z::Rational{BigInt}, x::BigInt) zq = _MPQ(z) ccall((:__gmpq_set_z, libgmp), Cvoid, (mpq_t, MPZ.mpz_t), zq, x) return sync_rational!(zq) end for (op, T) = ((:set, Rational{BigInt}), (:set_z, BigInt)) op! = Symbol(op, :!) @eval ($op)(a::$T) = begin ($op!)(unsafe_rational(BigInt(), BigInt()), a) end end for (op, T1, T2) = ((:set_ui, Culong, Culong), (:set_si, Clong, Culong)) op! = Symbol(op, :!) @eval begin function ($op!)(z::Rational{BigInt}, a, b) zq = _MPQ(z) ccall($(gmpq(op)), Cvoid, (mpq_t, $T1, $T2), zq, a, b) return sync_rational!(zq) end ($op)(a, b) = begin ($op!)(unsafe_rational(BigInt(), BigInt()), a, b) end end end function add!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) || iszero(y.den) if iszero(x.den) && (iszero(y.den) && isnegative(x.num) != isnegative(y.num)) throw(DivideError()) end return set!(z, if iszero(x.den) x else y end) end zq = _MPQ(z) ccall((:__gmpq_add, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end function sub!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) || iszero(y.den) if iszero(x.den) && (iszero(y.den) && isnegative(x.num) == isnegative(y.num)) throw(DivideError()) end iszero(x.den) && return set!(z, x) return set_si!(z, flipsign(-1, y.num), 0) end zq = _MPQ(z) ccall((:__gmpq_sub, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end function mul!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) || iszero(y.den) if iszero(x.num) || iszero(y.num) throw(DivideError()) end return set_si!(z, ifelse(xor(isnegative(x.num), isnegative(y.num)), -1, 1), 0) end zq = _MPQ(z) ccall((:__gmpq_mul, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end function div!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) if iszero(y.den) throw(DivideError()) end isnegative(y.num) || return set!(z, x) return set_si!(z, flipsign(-1, x.num), 0) elseif iszero(y.den) return set_si!(z, 0, 1) elseif iszero(y.num) if iszero(x.num) throw(DivideError()) end return set_si!(z, flipsign(1, x.num), 0) end zq = _MPQ(z) ccall((:__gmpq_div, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end for (fJ, fC) = ((:+, :add), (:-, :sub), (:*, :mul), (://, :div)) fC! = Symbol(fC, :!) @eval begin ($fC!)(x::Rational{BigInt}, y::Rational{BigInt}) = begin ($fC!)(x, x, y) end Base.:($fJ)(x::Rational{BigInt}, y::Rational{BigInt}) = begin ($fC!)(unsafe_rational(BigInt(), BigInt()), x, y) end end end function Base.cmp(x::Rational{BigInt}, y::Rational{BigInt}) Int(ccall((:__gmpq_cmp, libgmp), Cint, (mpq_t, mpq_t), _MPQ(x), _MPQ(y))) end end end module GMP export BigInt import .Base: *, +, -, /, <, <<, >>, >>>, <=, ==, >, >=, ^, ~, &, |, xor, nand, nor, binomial, cmp, convert, div, divrem, factorial, cld, fld, gcd, gcdx, lcm, mod, ndigits, promote_rule, rem, show, isqrt, string, powermod, sum, prod, trailing_zeros, trailing_ones, count_ones, count_zeros, tryparse_internal, bin, oct, dec, hex, isequal, invmod, _prevpow2, _nextpow2, ndigits0zpb, widen, signed, unsafe_trunc, trunc, iszero, isone, big, flipsign, signbit, sign, isodd, iseven, digits!, hash, hash_integer, top_set_bit, ispositive, isnegative, clamp import Core: Signed, Float16, Float32, Float64 if Clong == Int32 const ClongMax = Union{Int8, Int16, Int32} const CulongMax = Union{UInt8, UInt16, UInt32} else const ClongMax = Union{Int8, Int16, Int32, Int64} const CulongMax = Union{UInt8, UInt16, UInt32, UInt64} end const CdoubleMax = Union{Float16, Float32, Float64} if Sys.iswindows() const libgmp = "libgmp-10.dll" elseif Sys.isapple() const libgmp = "@rpath/libgmp.10.dylib" else const libgmp = "libgmp.so.10" end _version() = begin unsafe_string(unsafe_load(cglobal((:__gmp_version, libgmp), Ptr{Cchar}))) end version() = begin VersionNumber(_version()) end major_version() = begin (_version())[1] end bits_per_limb() = begin Int(unsafe_load(cglobal((:__gmp_bits_per_limb, libgmp), Cint))) end const VERSION = version() const MAJOR_VERSION = major_version() const BITS_PER_LIMB = bits_per_limb() if BITS_PER_LIMB == 32 const Limb = UInt32 const SLimbMax = Union{Int8, Int16, Int32} const ULimbMax = Union{UInt8, UInt16, UInt32} elseif BITS_PER_LIMB == 64 const Limb = UInt64 const SLimbMax = Union{Int8, Int16, Int32, Int64} const ULimbMax = Union{UInt8, UInt16, UInt32, UInt64} else error("GMP: cannot determine the type mp_limb_t (__gmp_bits_per_limb == $(BITS_PER_LIMB))") end Core.@doc " BigInt <: Signed\n\nArbitrary precision integer type.\n" mutable struct BigInt <: Signed alloc::Cint size::Cint d::Ptr{Limb} function BigInt(; nbits::Integer = 0) b = MPZ.init2!(new(), nbits) finalizer(cglobal((:__gmpz_clear, libgmp)), b) return b end end Core.@doc " BigInt(x)\n\nCreate an arbitrary precision integer. `x` may be an `Int` (or anything that can be\nconverted to an `Int`). The usual mathematical operators are defined for this type, and\nresults are promoted to a [`BigInt`](@ref).\n\nInstances can be constructed from strings via [`parse`](@ref), or using the `big`\nstring literal.\n\n# Examples\n```jldoctest\njulia> parse(BigInt, \"42\")\n42\n\njulia> big\"313\"\n313\n\njulia> BigInt(10)^19\n10000000000000000000\n```\n" BigInt(x) Core.@doc " ALLOC_OVERFLOW_FUNCTION\n\nA reference that holds a boolean, if true, indicating julia is linked with a patched GMP that\ndoes not abort on huge allocation and throws OutOfMemoryError instead.\n" const ALLOC_OVERFLOW_FUNCTION = Ref(false) function __init__() try if major_version() != MAJOR_VERSION || bits_per_limb() != BITS_PER_LIMB msg = "The dynamically loaded GMP library (v\"$(version())\" with __gmp_bits_per_limb == $(bits_per_limb()))\ndoes not correspond to the compile time version (v\"$(VERSION)\" with __gmp_bits_per_limb == $(BITS_PER_LIMB)).\nPlease rebuild Julia." if bits_per_limb() != BITS_PER_LIMB @error msg else @warn msg end end ccall((:__gmp_set_memory_functions, libgmp), Cvoid, (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), cglobal(:jl_gc_counted_malloc), cglobal(:jl_gc_counted_realloc_with_old_size), cglobal(:jl_gc_counted_free_with_size)) (ZERO.alloc, ZERO.size, ZERO.d) = (0, 0, C_NULL) (ONE.alloc, ONE.size, ONE.d) = (1, 1, pointer(_ONE)) catch ex Base.showerror_nostdio(ex, "WARNING: Error during initialization of module GMP") end try ccall((:__gmp_set_alloc_overflow_function, libgmp), Cvoid, (Ptr{Cvoid},), cglobal(:jl_throw_out_of_memory_error)) ALLOC_OVERFLOW_FUNCTION[] = true catch ex if typeof(ex) != ErrorException rethrow() end end end module MPZ using ..GMP: BigInt, Limb, BITS_PER_LIMB, libgmp const mpz_t = Ref{BigInt} const bitcnt_t = Culong gmpz(op::Symbol) = begin Expr(:tuple, QuoteNode(Symbol(:__gmpz_, op)), GlobalRef(MPZ, :libgmp)) end init!(x::BigInt) = begin ccall((:__gmpz_init, libgmp), Cvoid, (mpz_t,), x) x end init2!(x::BigInt, a) = begin ccall((:__gmpz_init2, libgmp), Cvoid, (mpz_t, bitcnt_t), x, a) x end realloc2!(x, a) = begin ccall((:__gmpz_realloc2, libgmp), Cvoid, (mpz_t, bitcnt_t), x, a) x end realloc2(a) = begin realloc2!(BigInt(), a) end sizeinbase(a::BigInt, b) = begin Int(ccall((:__gmpz_sizeinbase, libgmp), Csize_t, (mpz_t, Cint), a, b)) end for (op, nbits) = (:add => :(BITS_PER_LIMB * (1 + max(abs(a.size), abs(b.size)))), :sub => :(BITS_PER_LIMB * (1 + max(abs(a.size), abs(b.size)))), :mul => 0, :fdiv_q => 0, :tdiv_q => 0, :cdiv_q => 0, :fdiv_r => 0, :tdiv_r => 0, :cdiv_r => 0, :gcd => 0, :lcm => 0, :and => 0, :ior => 0, :xor => 0) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a::BigInt, b::BigInt) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, mpz_t, mpz_t), x, a, b) x end ($op)(a::BigInt, b::BigInt) = begin ($op!)(BigInt(nbits = $nbits), a, b) end ($op!)(x::BigInt, b::BigInt) = begin ($op!)(x, x, b) end end end invert!(x::BigInt, a::BigInt, b::BigInt) = begin ccall((:__gmpz_invert, libgmp), Cint, (mpz_t, mpz_t, mpz_t), x, a, b) end invert!(x::BigInt, b::BigInt) = begin invert!(x, x, b) end invert(a::BigInt, b::BigInt) = begin ret = BigInt() invert!(ret, a, b) ret end for op = (:add_ui, :sub_ui, :mul_ui, :mul_2exp, :fdiv_q_2exp, :pow_ui, :bin_ui) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a::BigInt, b) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, mpz_t, Culong), x, a, b) x end ($op)(a::BigInt, b) = begin ($op!)(BigInt(), a, b) end ($op!)(x::BigInt, b) = begin ($op!)(x, x, b) end end end ui_sub!(x::BigInt, a, b::BigInt) = begin ccall((:__gmpz_ui_sub, libgmp), Cvoid, (mpz_t, Culong, mpz_t), x, a, b) x end ui_sub(a, b::BigInt) = begin ui_sub!(BigInt(), a, b) end for op = (:scan1, :scan0) @eval ($op)(a::BigInt, b) = begin Int(signed(ccall($(gmpz(op)), Culong, (mpz_t, Culong), a, b))) end end mul_si!(x::BigInt, a::BigInt, b) = begin ccall((:__gmpz_mul_si, libgmp), Cvoid, (mpz_t, mpz_t, Clong), x, a, b) x end mul_si(a::BigInt, b) = begin mul_si!(BigInt(), a, b) end mul_si!(x::BigInt, b) = begin mul_si!(x, x, b) end for op = (:neg, :com, :sqrt, :set) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a::BigInt) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, mpz_t), x, a) x end ($op)(a::BigInt) = begin ($op!)(BigInt(), a) end end op === :set && continue @eval ($op!)(x::BigInt) = begin ($op!)(x, x) end end for (op, T) = ((:fac_ui, Culong), (:set_ui, Culong), (:set_si, Clong), (:set_d, Cdouble)) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, $T), x, a) x end ($op)(a) = begin ($op!)(BigInt(), a) end end end popcount(a::BigInt) = begin Int(signed(ccall((:__gmpz_popcount, libgmp), Culong, (mpz_t,), a))) end mpn_popcount(d::Ptr{Limb}, s::Integer) = begin Int(ccall((:__gmpn_popcount, libgmp), Culong, (Ptr{Limb}, Csize_t), d, s)) end mpn_popcount(a::BigInt) = begin mpn_popcount(a.d, abs(a.size)) end function tdiv_qr!(x::BigInt, y::BigInt, a::BigInt, b::BigInt) ccall((:__gmpz_tdiv_qr, libgmp), Cvoid, (mpz_t, mpz_t, mpz_t, mpz_t), x, y, a, b) (x, y) end tdiv_qr(a::BigInt, b::BigInt) = begin tdiv_qr!(BigInt(), BigInt(), a, b) end powm!(x::BigInt, a::BigInt, b::BigInt, c::BigInt) = begin ccall((:__gmpz_powm, libgmp), Cvoid, (mpz_t, mpz_t, mpz_t, mpz_t), x, a, b, c) x end powm(a::BigInt, b::BigInt, c::BigInt) = begin powm!(BigInt(), a, b, c) end powm!(x::BigInt, b::BigInt, c::BigInt) = begin powm!(x, x, b, c) end function gcdext!(x::BigInt, y::BigInt, z::BigInt, a::BigInt, b::BigInt) ccall((:__gmpz_gcdext, libgmp), Cvoid, (mpz_t, mpz_t, mpz_t, mpz_t, mpz_t), x, y, z, a, b) (x, y, z) end gcdext(a::BigInt, b::BigInt) = begin gcdext!(BigInt(), BigInt(), BigInt(), a, b) end cmp(a::BigInt, b::BigInt) = begin Int(ccall((:__gmpz_cmp, libgmp), Cint, (mpz_t, mpz_t), a, b)) end cmp_si(a::BigInt, b) = begin Int(ccall((:__gmpz_cmp_si, libgmp), Cint, (mpz_t, Clong), a, b)) end cmp_ui(a::BigInt, b) = begin Int(ccall((:__gmpz_cmp_ui, libgmp), Cint, (mpz_t, Culong), a, b)) end cmp_d(a::BigInt, b) = begin Int(ccall((:__gmpz_cmp_d, libgmp), Cint, (mpz_t, Cdouble), a, b)) end mpn_cmp(a::Ptr{Limb}, b::Ptr{Limb}, c) = begin ccall((:__gmpn_cmp, libgmp), Cint, (Ptr{Limb}, Ptr{Limb}, Clong), a, b, c) end mpn_cmp(a::BigInt, b::BigInt, c) = begin mpn_cmp(a.d, b.d, c) end get_str!(x, a, b::BigInt) = begin ccall((:__gmpz_get_str, libgmp), Ptr{Cchar}, (Ptr{Cchar}, Cint, mpz_t), x, a, b) x end set_str!(x::BigInt, a, b) = begin Int(ccall((:__gmpz_set_str, libgmp), Cint, (mpz_t, Ptr{UInt8}, Cint), x, a, b)) end get_d(a::BigInt) = begin ccall((:__gmpz_get_d, libgmp), Cdouble, (mpz_t,), a) end function export!(a::AbstractVector{T}, n::BigInt; order::Integer = -1, nails::Integer = 0, endian::Integer = 0) where T <: Base.BitInteger stride(a, 1) == 1 || throw(ArgumentError("a must have stride 1")) ndigits = cld(sizeinbase(n, 2), 8 * sizeof(T) - nails) length(a) < ndigits && resize!(a, ndigits) fill!(a, zero(T)) count = Ref{Csize_t}() ccall((:__gmpz_export, libgmp), Ptr{T}, (Ptr{T}, Ref{Csize_t}, Cint, Csize_t, Cint, Csize_t, mpz_t), a, count, order, sizeof(T), endian, nails, n) @assert count[] ≤ length(a) return (a, Int(count[])) end limbs_write!(x::BigInt, a) = begin ccall((:__gmpz_limbs_write, libgmp), Ptr{Limb}, (mpz_t, Clong), x, a) end limbs_finish!(x::BigInt, a) = begin ccall((:__gmpz_limbs_finish, libgmp), Cvoid, (mpz_t, Clong), x, a) end setbit!(x, a) = begin ccall((:__gmpz_setbit, libgmp), Cvoid, (mpz_t, bitcnt_t), x, a) x end tstbit(a::BigInt, b) = begin ccall((:__gmpz_tstbit, libgmp), Cint, (mpz_t, bitcnt_t), a, b) % Bool end end const ZERO = BigInt() const ONE = BigInt() const _ONE = Limb[1] widen(::Type{Int128}) = begin BigInt end widen(::Type{UInt128}) = begin BigInt end widen(::Type{BigInt}) = begin BigInt end signed(x::BigInt) = begin x end BigInt(x::BigInt) = begin x end Signed(x::BigInt) = begin x end function tryparse_internal(::Type{BigInt}, s::AbstractString, startpos::Int, endpos::Int, base_::Integer, raise::Bool) bstr = if startpos == firstindex(s) && endpos == lastindex(s) String(s) else String(SubString(s, startpos, endpos)) end (sgn, base, i) = Base.parseint_preamble(true, Int(base_), bstr, firstindex(bstr), lastindex(bstr)) if !(2 <= base <= 62) raise && throw(ArgumentError("invalid base: base must be 2 ≤ base ≤ 62, got $(base)")) return nothing end if i == 0 raise && throw(ArgumentError("premature end of integer: $(repr(bstr))")) return nothing end z = BigInt() if Base.containsnul(bstr) err = -1 else err = GC.@preserve(bstr, MPZ.set_str!(z, pointer(bstr) + (i - firstindex(bstr)), base)) end if err != 0 raise && throw(ArgumentError("invalid BigInt: $(repr(bstr))")) return nothing end flipsign!(z, sgn) end BigInt(x::Union{Clong, Int32}) = begin MPZ.set_si(x) end BigInt(x::Union{Culong, UInt32}) = begin MPZ.set_ui(x) end BigInt(x::Bool) = begin BigInt(UInt(x)) end unsafe_trunc(::Type{BigInt}, x::Union{Float16, Float32, Float64}) = begin MPZ.set_d(x) end function BigInt(x::Float64) isinteger(x) || throw(InexactError(:BigInt, BigInt, x)) unsafe_trunc(BigInt, x) end BigInt(x::Float16) = begin BigInt(Float64(x)) end BigInt(x::Float32) = begin BigInt(Float64(x)) end function BigInt(x::Integer) isbits(x) && (typemin(Clong) <= x <= typemax(Clong) && return BigInt((x % Clong)::Clong)) nd = ndigits(x, base = 2) z = MPZ.realloc2(nd) ux = unsigned(if x < 0 -x else x end) size = 0 limbnbits = sizeof(Limb) << 3 while nd > 0 size += 1 unsafe_store!(z.d, ux % Limb, size) ux >>= limbnbits nd -= limbnbits end z.size = if x < 0 -size else size end z end rem(x::BigInt, ::Type{Bool}) = begin (!(iszero(x)) & unsafe_load(x.d)) % Bool end (rem(x::BigInt, ::Type{T}) where T <: Union{SLimbMax, ULimbMax}) = begin if iszero(x) zero(T) else flipsign(unsafe_load(x.d) % T, x.size) end end function rem(x::BigInt, ::Type{T}) where T <: Union{Base.BitUnsigned, Base.BitSigned} u = zero(T) for l = 1:min(abs(x.size), cld(sizeof(T), sizeof(Limb))) u += (unsafe_load(x.d, l) % T) << (sizeof(Limb) << 3 * (l - 1)) end flipsign(u, x.size) end rem(x::Integer, ::Type{BigInt}) = begin BigInt(x) end clamp(x, ::Type{BigInt}) = begin convert(BigInt, x) end isodd(x::BigInt) = begin MPZ.tstbit(x, 0) end iseven(x::BigInt) = begin !(isodd(x)) end function (::Type{T})(x::BigInt) where T <: Base.BitUnsigned if sizeof(T) < sizeof(Limb) convert(T, convert(Limb, x)) else 0 <= x.size <= cld(sizeof(T), sizeof(Limb)) || throw(InexactError(nameof(T), T, x)) x % T end end function (::Type{T})(x::BigInt) where T <: Base.BitSigned n = abs(x.size) if sizeof(T) < sizeof(Limb) SLimb = typeof(Signed(one(Limb))) convert(T, convert(SLimb, x)) else 0 <= n <= cld(sizeof(T), sizeof(Limb)) || throw(InexactError(nameof(T), T, x)) y = x % T ispositive(x) ⊻ (y > 0) && throw(InexactError(nameof(T), T, x)) y end end Float64(n::BigInt, ::RoundingMode{:ToZero}) = begin MPZ.get_d(n) end function (::Type{T})(n::BigInt, ::RoundingMode{:ToZero}) where T <: Union{Float16, Float32} T(Float64(n, RoundToZero), RoundToZero) end function (::Type{T})(n::BigInt, ::RoundingMode{:Down}) where T <: CdoubleMax x = T(n, RoundToZero) if x > n prevfloat(x) else x end end function (::Type{T})(n::BigInt, ::RoundingMode{:Up}) where T <: CdoubleMax x = T(n, RoundToZero) if x < n nextfloat(x) else x end end function Float64(x::BigInt, ::RoundingMode{:Nearest}) x == 0 && return 0.0 xsize = abs(x.size) if xsize * BITS_PER_LIMB > 1024 z = Inf64 elseif xsize == 1 z = Float64(unsafe_load(x.d)) elseif Limb == UInt32 && xsize == 2 z = Float64((unsafe_load(x.d, 2) % UInt64) << BITS_PER_LIMB + unsafe_load(x.d)) else y1 = unsafe_load(x.d, xsize) % UInt64 n = top_set_bit(y1) y = y1 >> (n - (precision(Float64) + 1)) if Limb == UInt64 y += if n > precision(Float64) 0 else unsafe_load(x.d, xsize - 1) >> (10 + n) end else y += (unsafe_load(x.d, xsize - 1) % UInt64) >> (n - 22) y += if n > precision(Float64) - 32 0 else unsafe_load(x.d, xsize - 2) >> (10 + n) end end y = (y + 1) >> 1 y &= ~(UInt64(trailing_zeros(x) == (n - 54) + (xsize - 1) * BITS_PER_LIMB)) d = ((n + 1021) % UInt64) << 52 z = reinterpret(Float64, d + y) z = ldexp(z, (xsize - 1) * BITS_PER_LIMB) end return flipsign(z, x.size) end function Float32(x::BigInt, ::RoundingMode{:Nearest}) x == 0 && return 0.0f0 xsize = abs(x.size) if xsize * BITS_PER_LIMB > 128 z = Inf32 elseif xsize == 1 z = Float32(unsafe_load(x.d)) else y1 = unsafe_load(x.d, xsize) n = BITS_PER_LIMB - leading_zeros(y1) y = y1 >> (n - (precision(Float32) + 1)) % UInt32 y += if n > precision(Float32) 0 else unsafe_load(x.d, xsize - 1) >> (BITS_PER_LIMB - -25) end % UInt32 y = (y + one(UInt32)) >> 1 y &= ~(UInt32(trailing_zeros(x) == (n - 25) + (xsize - 1) * BITS_PER_LIMB)) d = ((n + 125) % UInt32) << 23 z = reinterpret(Float32, d + y) z = ldexp(z, (xsize - 1) * BITS_PER_LIMB) end return flipsign(z, x.size) end function Float16(x::BigInt, ::RoundingMode{:Nearest}) x == 0 && return Float16(0.0) y1 = unsafe_load(x.d) n = BITS_PER_LIMB - leading_zeros(y1) if n > 16 || abs(x.size) > 1 z = Inf16 else y = y1 >> (n - (precision(Float16) + 1)) % UInt16 y = (y + one(UInt16)) >> 1 y &= ~(UInt16(trailing_zeros(x) == n - 12)) d = ((n + 13) % UInt16) << 10 z = reinterpret(Float16, d + y) end return flipsign(z, x.size) end Float64(n::BigInt) = begin Float64(n, RoundNearest) end Float32(n::BigInt) = begin Float32(n, RoundNearest) end Float16(n::BigInt) = begin Float16(n, RoundNearest) end promote_rule(::Type{BigInt}, ::Type{<:Integer}) = begin BigInt end Core.@doc " big(x)\n\nConvert a number to a maximum precision representation (typically [`BigInt`](@ref) or\n`BigFloat`). See [`BigFloat`](@ref BigFloat(::Any, rounding::RoundingMode)) for\ninformation about some pitfalls with floating-point numbers.\n" function big end big(::Type{<:Integer}) = begin BigInt end big(::Type{<:Rational}) = begin Rational{BigInt} end big(n::Integer) = begin convert(BigInt, n) end for (fJ, fC) = ((:+, :add), (:-, :sub), (:*, :mul), (:mod, :fdiv_r), (:rem, :tdiv_r), (:gcd, :gcd), (:lcm, :lcm), (:&, :and), (:|, :ior), (:xor, :xor)) @eval begin ($fJ)(x::BigInt, y::BigInt) = begin MPZ.:($fC)(x, y) end end end for (r, f) = ((RoundToZero, :tdiv_q), (RoundDown, :fdiv_q), (RoundUp, :cdiv_q)) @eval div(x::BigInt, y::BigInt, ::typeof($r)) = begin MPZ.:($f)(x, y) end end div(x::BigInt, y::BigInt) = begin div(x, y, RoundToZero) end fld(x::BigInt, y::BigInt) = begin div(x, y, RoundDown) end cld(x::BigInt, y::BigInt) = begin div(x, y, RoundUp) end x::BigInt / y::BigInt = begin float(x) / float(y) end function invmod(x::BigInt, y::BigInt) z = zero(BigInt) ya = abs(y) if ya == 1 return z end if y == 0 || MPZ.invert!(z, x, ya) == 0 throw(DomainError(y)) end if y < 0 MPZ.add!(z, y) end return z end for (fJ, fC) = ((:+, :add), (:*, :mul), (:&, :and), (:|, :ior), (:xor, :xor)) fC! = Symbol(fC, :!) @eval begin ($fJ)(a::BigInt, b::BigInt, c::BigInt) = begin MPZ.:($fC!)(MPZ.:($fC)(a, b), c) end ($fJ)(a::BigInt, b::BigInt, c::BigInt, d::BigInt) = begin MPZ.:($fC!)(MPZ.:($fC!)(MPZ.:($fC)(a, b), c), d) end ($fJ)(a::BigInt, b::BigInt, c::BigInt, d::BigInt, e::BigInt) = begin MPZ.:($fC!)(MPZ.:($fC!)(MPZ.:($fC!)(MPZ.:($fC)(a, b), c), d), e) end end end x::BigInt + c::CulongMax = begin MPZ.add_ui(x, c) end c::CulongMax + x::BigInt = begin x + c end x::BigInt - c::CulongMax = begin MPZ.sub_ui(x, c) end c::CulongMax - x::BigInt = begin MPZ.ui_sub(c, x) end x::BigInt + c::ClongMax = begin if c < 0 x - -(c % Culong) else x + convert(Culong, c) end end c::ClongMax + x::BigInt = begin if c < 0 x - -(c % Culong) else x + convert(Culong, c) end end x::BigInt - c::ClongMax = begin if c < 0 x + -(c % Culong) else x - convert(Culong, c) end end c::ClongMax - x::BigInt = begin if c < 0 -((x + -(c % Culong))) else convert(Culong, c) - x end end x::BigInt * c::CulongMax = begin MPZ.mul_ui(x, c) end c::CulongMax * x::BigInt = begin x * c end x::BigInt * c::ClongMax = begin MPZ.mul_si(x, c) end c::ClongMax * x::BigInt = begin x * c end x::BigInt / y::Union{ClongMax, CulongMax} = begin float(x) / y end x::Union{ClongMax, CulongMax} / y::BigInt = begin x / float(y) end -(x::BigInt) = begin MPZ.neg(x) end ~(x::BigInt) = begin MPZ.com(x) end x::BigInt << c::UInt = begin if c == 0 x else MPZ.mul_2exp(x, c) end end x::BigInt >> c::UInt = begin if c == 0 x else MPZ.fdiv_q_2exp(x, c) end end x::BigInt >>> c::UInt = begin x >> c end function trailing_zeros(x::BigInt) c = MPZ.scan1(x, 0) c == -1 && throw(DomainError(x, "`x` must be non-zero")) c end function trailing_ones(x::BigInt) c = MPZ.scan0(x, 0) c == -1 && throw(DomainError(x, "`x` must not be equal to -1")) c end function count_ones(x::BigInt) c = MPZ.popcount(x) c == -1 && throw(DomainError(x, "`x` cannot be negative")) c end function count_zeros(x::BigInt) c = MPZ.popcount(~x) c == -1 && throw(DomainError(x, "`x` must be negative")) c end Core.@doc " count_ones_abs(x::BigInt)\n\nNumber of ones in the binary representation of abs(x).\n" count_ones_abs(x::BigInt) = begin if iszero(x) 0 else MPZ.mpn_popcount(x) end end _bit_magnitude(x::BigInt) = begin x.size * sizeof(Limb) << 3 - leading_zeros(GC.@preserve(x, unsafe_load(x.d, x.size))) end function exponent(x::BigInt) iszero(x) && throw(DomainError(x, "cannot be zero")) ux = abs(x) return _bit_magnitude(ux) - 1 end function top_set_bit(x::BigInt) isnegative(x) && throw(DomainError(x, "top_set_bit only supports negative arguments when they have type BitSigned.")) iszero(x) && return 0 return _bit_magnitude(x) end divrem(x::BigInt, y::BigInt, ::typeof(RoundToZero) = begin RoundToZero end) = begin MPZ.tdiv_qr(x, y) end divrem(x::BigInt, y::Integer, ::typeof(RoundToZero) = begin RoundToZero end) = begin MPZ.tdiv_qr(x, BigInt(y)) end cmp(x::BigInt, y::BigInt) = begin sign(MPZ.cmp(x, y)) end cmp(x::BigInt, y::ClongMax) = begin sign(MPZ.cmp_si(x, y)) end cmp(x::BigInt, y::CulongMax) = begin sign(MPZ.cmp_ui(x, y)) end cmp(x::BigInt, y::Integer) = begin cmp(x, big(y)) end cmp(x::Integer, y::BigInt) = begin -(cmp(y, x)) end cmp(x::BigInt, y::CdoubleMax) = begin if isnan(y) -1 else sign(MPZ.cmp_d(x, y)) end end cmp(x::CdoubleMax, y::BigInt) = begin -(cmp(y, x)) end isqrt(x::BigInt) = begin MPZ.sqrt(x) end x::BigInt ^ y::Culong = begin MPZ.pow_ui(x, y) end function bigint_pow(x::BigInt, y::Integer) x == 1 && return x x == -1 && return if isodd(y) x else -x end if y < 0 throw(DomainError(y, "`y` cannot be negative.")) end @noinline throw1(y) = begin throw(OverflowError("exponent $(y) is too large and computation will overflow")) end if y > typemax(Culong) x == 0 && return x throw1(y) end return x ^ convert(Culong, y) end x::BigInt ^ y::BigInt = begin bigint_pow(x, y) end x::BigInt ^ y::Bool = begin if y x else one(x) end end x::BigInt ^ y::Integer = begin bigint_pow(x, y) end x::Integer ^ y::BigInt = begin bigint_pow(BigInt(x), y) end x::Bool ^ y::BigInt = begin Base.power_by_squaring(x, y) end function powermod(x::BigInt, p::BigInt, m::BigInt) r = MPZ.powm(x, p, m) return if m < 0 && r > 0 MPZ.add!(r, m) else r end end powermod(x::Integer, p::Integer, m::BigInt) = begin powermod(big(x), big(p), m) end function gcdx(a::BigInt, b::BigInt) (g, s, t) = MPZ.gcdext(a, b) if t == 0 if a == b return (g, t, s) elseif abs(a) == abs(b) return (g, t, -s) end end (g, s, t) end +(x::BigInt, y::BigInt, rest::BigInt...) = begin sum(tuple(x, y, rest...)) end sum(arr::Union{AbstractArray{BigInt}, Tuple{BigInt, Vararg{BigInt}}}) = begin foldl(MPZ.add!, arr; init = BigInt(0)) end function prod(arr::AbstractArray{BigInt}) any(iszero, arr) && return zero(BigInt) _prod(arr, firstindex(arr), lastindex(arr)) end function _prod(arr::AbstractArray{BigInt}, lo, hi) if (hi - lo) + 1 <= 16 nlimbs = 0 for i = lo:hi nlimbs += abs((arr[i]).size) end init = BigInt(; nbits = nlimbs * BITS_PER_LIMB) MPZ.set_si!(init, 1) for i = lo:hi MPZ.mul!(init, arr[i]) end init else mid = (lo + hi) ÷ 2 MPZ.mul!(_prod(arr, lo, mid), _prod(arr, mid + 1, hi)) end end factorial(n::BigInt) = begin if !(isnegative(n)) MPZ.fac_ui(n) else throw(DomainError(n, "`n` must not be negative.")) end end function binomial(n::BigInt, k::Integer) k < 0 && return BigInt(0) k <= typemax(Culong) && return binomial(n, Culong(k)) n < 0 && return if isodd(k) -(binomial((k - n) - 1, k)) else binomial((k - n) - 1, k) end κ = n - k κ < 0 && return BigInt(0) κ <= typemax(Culong) && return binomial(n, Culong(κ)) throw(OverflowError("Computation would exceed memory")) end binomial(n::BigInt, k::Culong) = begin MPZ.bin_ui(n, k) end x::BigInt == y::BigInt = begin cmp(x, y) == 0 end x::BigInt == i::Integer = begin cmp(x, i) == 0 end i::Integer == x::BigInt = begin cmp(x, i) == 0 end x::BigInt == f::CdoubleMax = begin if isnan(f) false else cmp(x, f) == 0 end end f::CdoubleMax == x::BigInt = begin if isnan(f) false else cmp(x, f) == 0 end end iszero(x::BigInt) = begin x.size == 0 end isone(x::BigInt) = begin x == Culong(1) end x::BigInt <= y::BigInt = begin cmp(x, y) <= 0 end x::BigInt <= i::Integer = begin cmp(x, i) <= 0 end i::Integer <= x::BigInt = begin cmp(x, i) >= 0 end x::BigInt <= f::CdoubleMax = begin if isnan(f) false else cmp(x, f) <= 0 end end f::CdoubleMax <= x::BigInt = begin if isnan(f) false else cmp(x, f) >= 0 end end x::BigInt < y::BigInt = begin cmp(x, y) < 0 end x::BigInt < i::Integer = begin cmp(x, i) < 0 end i::Integer < x::BigInt = begin cmp(x, i) > 0 end x::BigInt < f::CdoubleMax = begin if isnan(f) false else cmp(x, f) < 0 end end f::CdoubleMax < x::BigInt = begin if isnan(f) false else cmp(x, f) > 0 end end isnegative(x::BigInt) = begin x.size < 0 end ispositive(x::BigInt) = begin x.size > 0 end signbit(x::BigInt) = begin isnegative(x) end flipsign!(x::BigInt, y::Integer) = begin signbit(y) && (x.size = -(x.size)) x end flipsign(x::BigInt, y::Integer) = begin if signbit(y) -x else x end end flipsign(x::BigInt, y::BigInt) = begin if signbit(y) -x else x end end function sign(x::BigInt) isnegative(x) && return -(one(x)) ispositive(x) && return one(x) return x end show(io::IO, x::BigInt) = begin print(io, string(x)) end function string(n::BigInt; base::Integer = 10, pad::Integer = 1) base < 0 && return Base._base(Int(base), n, pad, (base > 0) & (n.size < 0)) 2 <= base <= 62 || throw(ArgumentError("base must be 2 ≤ base ≤ 62, got $(base)")) iszero(n) && (pad < 1 && return "") nd1 = ndigits(n, base = base) nd = max(nd1, pad) str = Base._string_n(nd + isnegative(n)) GC.@preserve str begin p = pointer(str) MPZ.get_str!((p + nd) - nd1, base, n) pad_len = nd - nd1 if pad_len > 0 Base.memset(p + isnegative(n), UInt8('0'), pad_len) end isnegative(n) && unsafe_store!(p, UInt8('-')) end return str end function digits!(a::AbstractVector{T}, n::BigInt; base::Integer = 10) where T <: Integer if base ≥ 2 if base ≤ 62 s = codeunits(string(n; base)) (i, j) = (firstindex(a) - 1, length(s) + 1) lasti = min(lastindex(a), ((firstindex(a) + length(s)) - 1) - isnegative(n)) while i < lasti x = s[j -= 1] a[i += 1] = if base ≤ 36 if x > 0x39 x - 0x57 else x - 0x30 end else if x > 0x39 if x > 0x60 x - 0x3d else x - 0x37 end else x - 0x30 end end end lasti = lastindex(a) while i < lasti a[i += 1] = zero(T) end return if isnegative(n) map!(-, a, a) else a end elseif a isa StridedVector{<:Base.BitInteger} && (stride(a, 1) == 1 && (ispow2(base) && base - 1 ≤ typemax(T))) origlen = length(a) (_, writelen) = MPZ.export!(a, n; nails = 8 * sizeof(T) - trailing_zeros(base)) length(a) != origlen && resize!(a, origlen) a[var"begin" + writelen:var"end"] .= zero(T) return if isnegative(n) map!(-, a, a) else a end end end return invoke(digits!, Tuple{typeof(a), Integer}, a, n; base) end function ndigits0zpb(x::BigInt, b::Integer) b < 2 && throw(DomainError(b, "`b` cannot be less than 2.")) x.size == 0 && return 0 if ispow2(b) && 2 <= b <= 62 MPZ.sizeinbase(x, b) else n = MPZ.sizeinbase(x, 2) lb = log2(b) (q, r) = divrem(n, lb) iq = Int(q) maxerr = q * eps(lb) if r - 1.0 < maxerr if abs(x) >= big(b) ^ iq iq + 1 else iq end elseif lb - r < maxerr if abs(x) >= big(b) ^ (iq + 1) iq + 2 else iq + 1 end else iq + 1 end end end _prevpow2(x::BigInt) = begin if -2 <= x <= 2 x else flipsign!(ONE << (ndigits(x, base = 2) - 1), x) end end _nextpow2(x::BigInt) = begin if count_ones_abs(x) <= 1 x else flipsign!(ONE << ndigits(x, base = 2), x) end end Base.checked_abs(x::BigInt) = begin abs(x) end Base.checked_neg(x::BigInt) = begin -x end Base.checked_add(a::BigInt, b::BigInt) = begin a + b end Base.checked_sub(a::BigInt, b::BigInt) = begin a - b end Base.checked_mul(a::BigInt, b::BigInt) = begin a * b end Base.checked_div(a::BigInt, b::BigInt) = begin div(a, b) end Base.checked_rem(a::BigInt, b::BigInt) = begin rem(a, b) end Base.checked_fld(a::BigInt, b::BigInt) = begin fld(a, b) end Base.checked_mod(a::BigInt, b::BigInt) = begin mod(a, b) end Base.checked_cld(a::BigInt, b::BigInt) = begin cld(a, b) end Base.add_with_overflow(a::BigInt, b::BigInt) = begin (a + b, false) end Base.sub_with_overflow(a::BigInt, b::BigInt) = begin (a - b, false) end Base.mul_with_overflow(a::BigInt, b::BigInt) = begin (a * b, false) end Base.checked_pow(x::BigInt, p::Integer) = begin x ^ p end Base.checked_pow(x::Integer, p::BigInt) = begin x ^ p end Base.checked_pow(x::BigInt, p::BigInt) = begin x ^ p end Base.deepcopy_internal(x::BigInt, stackdict::IdDict) = begin get!((()->begin MPZ.set(x) end), stackdict, x)::BigInt end Base._hash_shl!(x::BigInt, n) = begin MPZ.mul_2exp!(x, n) end if Limb === UInt64 === UInt using .Base: HASH_SECRET, hash_bytes, hash_finalizer struct UnsafeLimbView <: AbstractVector{UInt8} bigint::BigInt start_byte::Int num_bytes::Int end function Base.size(view::UnsafeLimbView) return (view.num_bytes,) end function Base.getindex(view::UnsafeLimbView, i::Int) @boundscheck checkbounds(view, i) GC.@preserve view begin limb_index = div((view.start_byte + i) - 2, 8) + 1 byte_in_limb = ((view.start_byte + i) - 2) % 8 limb = unsafe_load(view.bigint.d, limb_index) return UInt8(limb >> (8byte_in_limb) & 0xff) end end function Base.iterate(view::UnsafeLimbView, state::Int = 1) state > view.num_bytes && return nothing return (@inbounds(view[state]), state + 1) end function Base.length(view::UnsafeLimbView) return view.num_bytes end function hash_integer(n::BigInt, h::UInt) iszero(n) && return hash_integer(0, h) s = n.size h ⊻= s < 0 us = abs(s) leading_zero_bytes = div(leading_zeros(unsafe_load(n.d, us)), 8) num_bytes = 8us - leading_zero_bytes limb_view = UnsafeLimbView(n, 1, num_bytes) return hash_bytes(limb_view, h, HASH_SECRET) end function hash(x::BigInt, h::UInt) GC.@preserve x begin sz = x.size sz == 0 && return hash(0, h) ptr = Ptr{UInt64}(x.d) if sz == 1 return hash(unsafe_load(ptr), h) elseif sz == -1 limb = unsafe_load(ptr) limb <= typemin(Int) % UInt && return hash(-(limb % Int), h) end pow = trailing_zeros(x) nd = Base.ndigits0z(x, 2) idx = pow >>> 6 + 1 shift = (pow & 63) % UInt upshift = BITS_PER_LIMB - shift asz = abs(sz) if shift == 0 limb = unsafe_load(ptr, idx) else limb1 = unsafe_load(ptr, idx) limb2 = if idx < asz unsafe_load(ptr, idx + 1) else UInt(0) end limb = limb2 << upshift | limb1 >> shift end if nd <= 1024 && nd - pow <= 53 return hash(ldexp(flipsign(Float64(limb), sz), pow), h) end h = hash_integer(pow, h) h ⊻= sz < 0 leading_zero_bytes = div(leading_zeros(unsafe_load(x.d, asz)), 8) trailing_zero_bytes = div(pow, 8) num_bytes = 8asz - (leading_zero_bytes + trailing_zero_bytes) limb_view = UnsafeLimbView(x, trailing_zero_bytes + 1, num_bytes) return hash_bytes(limb_view, h, HASH_SECRET) end end end module MPQ import .Base: unsafe_rational, __throw_rational_argerror_zero import ..GMP: BigInt, MPZ, Limb, libgmp gmpq(op::Symbol) = begin Expr(:tuple, QuoteNode(Symbol(:__gmpq_, op)), GlobalRef(MPZ, :libgmp)) end mutable struct _MPQ num_alloc::Cint num_size::Cint num_d::Ptr{Limb} den_alloc::Cint den_size::Cint den_d::Ptr{Limb} rat::Rational{BigInt} end const mpq_t = Ref{_MPQ} _MPQ(x::BigInt, y::BigInt) = begin _MPQ(x.alloc, x.size, x.d, y.alloc, y.size, y.d, unsafe_rational(BigInt, x, y)) end _MPQ() = begin _MPQ(BigInt(), BigInt()) end _MPQ(x::Rational{BigInt}) = begin _MPQ(x.num, x.den) end function sync_rational!(xq::_MPQ) xq.rat.num.alloc = xq.num_alloc xq.rat.num.size = xq.num_size xq.rat.num.d = xq.num_d xq.rat.den.alloc = xq.den_alloc xq.rat.den.size = xq.den_size xq.rat.den.d = xq.den_d return xq.rat end function Rational{BigInt}(num::BigInt, den::BigInt) if iszero(den) iszero(num) && __throw_rational_argerror_zero(BigInt) return set_si(flipsign(1, num), 0) end xq = _MPQ(MPZ.set(num), MPZ.set(den)) ccall((:__gmpq_canonicalize, libgmp), Cvoid, (mpq_t,), xq) return sync_rational!(xq) end function set!(z::Rational{BigInt}, x::Rational{BigInt}) zq = _MPQ(z) ccall((:__gmpq_set, libgmp), Cvoid, (mpq_t, mpq_t), zq, _MPQ(x)) return sync_rational!(zq) end function set_z!(z::Rational{BigInt}, x::BigInt) zq = _MPQ(z) ccall((:__gmpq_set_z, libgmp), Cvoid, (mpq_t, MPZ.mpz_t), zq, x) return sync_rational!(zq) end for (op, T) = ((:set, Rational{BigInt}), (:set_z, BigInt)) op! = Symbol(op, :!) @eval ($op)(a::$T) = begin ($op!)(unsafe_rational(BigInt(), BigInt()), a) end end for (op, T1, T2) = ((:set_ui, Culong, Culong), (:set_si, Clong, Culong)) op! = Symbol(op, :!) @eval begin function ($op!)(z::Rational{BigInt}, a, b) zq = _MPQ(z) ccall($(gmpq(op)), Cvoid, (mpq_t, $T1, $T2), zq, a, b) return sync_rational!(zq) end ($op)(a, b) = begin ($op!)(unsafe_rational(BigInt(), BigInt()), a, b) end end end function add!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) || iszero(y.den) if iszero(x.den) && (iszero(y.den) && isnegative(x.num) != isnegative(y.num)) throw(DivideError()) end return set!(z, if iszero(x.den) x else y end) end zq = _MPQ(z) ccall((:__gmpq_add, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end function sub!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) || iszero(y.den) if iszero(x.den) && (iszero(y.den) && isnegative(x.num) == isnegative(y.num)) throw(DivideError()) end iszero(x.den) && return set!(z, x) return set_si!(z, flipsign(-1, y.num), 0) end zq = _MPQ(z) ccall((:__gmpq_sub, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end function mul!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) || iszero(y.den) if iszero(x.num) || iszero(y.num) throw(DivideError()) end return set_si!(z, ifelse(xor(isnegative(x.num), isnegative(y.num)), -1, 1), 0) end zq = _MPQ(z) ccall((:__gmpq_mul, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end function div!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) if iszero(y.den) throw(DivideError()) end isnegative(y.num) || return set!(z, x) return set_si!(z, flipsign(-1, x.num), 0) elseif iszero(y.den) return set_si!(z, 0, 1) elseif iszero(y.num) if iszero(x.num) throw(DivideError()) end return set_si!(z, flipsign(1, x.num), 0) end zq = _MPQ(z) ccall((:__gmpq_div, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end for (fJ, fC) = ((:+, :add), (:-, :sub), (:*, :mul), (://, :div)) fC! = Symbol(fC, :!) @eval begin ($fC!)(x::Rational{BigInt}, y::Rational{BigInt}) = begin ($fC!)(x, x, y) end Base.:($fJ)(x::Rational{BigInt}, y::Rational{BigInt}) = begin ($fC!)(unsafe_rational(BigInt(), BigInt()), x, y) end end end function Base.cmp(x::Rational{BigInt}, y::Rational{BigInt}) Int(ccall((:__gmpq_cmp, libgmp), Cint, (mpq_t, mpq_t), _MPQ(x), _MPQ(y))) end end end module GMP export BigInt import .Base: *, +, -, /, <, <<, >>, >>>, <=, ==, >, >=, ^, ~, &, |, xor, nand, nor, binomial, cmp, convert, div, divrem, factorial, cld, fld, gcd, gcdx, lcm, mod, ndigits, promote_rule, rem, show, isqrt, string, powermod, sum, prod, trailing_zeros, trailing_ones, count_ones, count_zeros, tryparse_internal, bin, oct, dec, hex, isequal, invmod, _prevpow2, _nextpow2, ndigits0zpb, widen, signed, unsafe_trunc, trunc, iszero, isone, big, flipsign, signbit, sign, isodd, iseven, digits!, hash, hash_integer, top_set_bit, ispositive, isnegative, clamp import Core: Signed, Float16, Float32, Float64 if Clong == Int32 const ClongMax = Union{Int8, Int16, Int32} const CulongMax = Union{UInt8, UInt16, UInt32} else const ClongMax = Union{Int8, Int16, Int32, Int64} const CulongMax = Union{UInt8, UInt16, UInt32, UInt64} end const CdoubleMax = Union{Float16, Float32, Float64} if Sys.iswindows() const libgmp = "libgmp-10.dll" elseif Sys.isapple() const libgmp = "@rpath/libgmp.10.dylib" else const libgmp = "libgmp.so.10" end _version() = begin unsafe_string(unsafe_load(cglobal((:__gmp_version, libgmp), Ptr{Cchar}))) end version() = begin VersionNumber(_version()) end major_version() = begin (_version())[1] end bits_per_limb() = begin Int(unsafe_load(cglobal((:__gmp_bits_per_limb, libgmp), Cint))) end const VERSION = version() const MAJOR_VERSION = major_version() const BITS_PER_LIMB = bits_per_limb() if BITS_PER_LIMB == 32 const Limb = UInt32 const SLimbMax = Union{Int8, Int16, Int32} const ULimbMax = Union{UInt8, UInt16, UInt32} elseif BITS_PER_LIMB == 64 const Limb = UInt64 const SLimbMax = Union{Int8, Int16, Int32, Int64} const ULimbMax = Union{UInt8, UInt16, UInt32, UInt64} else error("GMP: cannot determine the type mp_limb_t (__gmp_bits_per_limb == $(BITS_PER_LIMB))") end Core.@doc " BigInt <: Signed\n\nArbitrary precision integer type.\n" mutable struct BigInt <: Signed alloc::Cint size::Cint d::Ptr{Limb} function BigInt(; nbits::Integer = 0) b = MPZ.init2!(new(), nbits) finalizer(cglobal((:__gmpz_clear, libgmp)), b) return b end end Core.@doc " BigInt(x)\n\nCreate an arbitrary precision integer. `x` may be an `Int` (or anything that can be\nconverted to an `Int`). The usual mathematical operators are defined for this type, and\nresults are promoted to a [`BigInt`](@ref).\n\nInstances can be constructed from strings via [`parse`](@ref), or using the `big`\nstring literal.\n\n# Examples\n```jldoctest\njulia> parse(BigInt, \"42\")\n42\n\njulia> big\"313\"\n313\n\njulia> BigInt(10)^19\n10000000000000000000\n```\n" BigInt(x) Core.@doc " ALLOC_OVERFLOW_FUNCTION\n\nA reference that holds a boolean, if true, indicating julia is linked with a patched GMP that\ndoes not abort on huge allocation and throws OutOfMemoryError instead.\n" const ALLOC_OVERFLOW_FUNCTION = Ref(false) function __init__() try if major_version() != MAJOR_VERSION || bits_per_limb() != BITS_PER_LIMB msg = "The dynamically loaded GMP library (v\"$(version())\" with __gmp_bits_per_limb == $(bits_per_limb()))\ndoes not correspond to the compile time version (v\"$(VERSION)\" with __gmp_bits_per_limb == $(BITS_PER_LIMB)).\nPlease rebuild Julia." if bits_per_limb() != BITS_PER_LIMB @error msg else @warn msg end end ccall((:__gmp_set_memory_functions, libgmp), Cvoid, (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), cglobal(:jl_gc_counted_malloc), cglobal(:jl_gc_counted_realloc_with_old_size), cglobal(:jl_gc_counted_free_with_size)) (ZERO.alloc, ZERO.size, ZERO.d) = (0, 0, C_NULL) (ONE.alloc, ONE.size, ONE.d) = (1, 1, pointer(_ONE)) catch ex Base.showerror_nostdio(ex, "WARNING: Error during initialization of module GMP") end try ccall((:__gmp_set_alloc_overflow_function, libgmp), Cvoid, (Ptr{Cvoid},), cglobal(:jl_throw_out_of_memory_error)) ALLOC_OVERFLOW_FUNCTION[] = true catch ex if typeof(ex) != ErrorException rethrow() end end end module MPZ using ..GMP: BigInt, Limb, BITS_PER_LIMB, libgmp const mpz_t = Ref{BigInt} const bitcnt_t = Culong gmpz(op::Symbol) = begin Expr(:tuple, QuoteNode(Symbol(:__gmpz_, op)), GlobalRef(MPZ, :libgmp)) end init!(x::BigInt) = begin ccall((:__gmpz_init, libgmp), Cvoid, (mpz_t,), x) x end init2!(x::BigInt, a) = begin ccall((:__gmpz_init2, libgmp), Cvoid, (mpz_t, bitcnt_t), x, a) x end realloc2!(x, a) = begin ccall((:__gmpz_realloc2, libgmp), Cvoid, (mpz_t, bitcnt_t), x, a) x end realloc2(a) = begin realloc2!(BigInt(), a) end sizeinbase(a::BigInt, b) = begin Int(ccall((:__gmpz_sizeinbase, libgmp), Csize_t, (mpz_t, Cint), a, b)) end for (op, nbits) = (:add => :(BITS_PER_LIMB * (1 + max(abs(a.size), abs(b.size)))), :sub => :(BITS_PER_LIMB * (1 + max(abs(a.size), abs(b.size)))), :mul => 0, :fdiv_q => 0, :tdiv_q => 0, :cdiv_q => 0, :fdiv_r => 0, :tdiv_r => 0, :cdiv_r => 0, :gcd => 0, :lcm => 0, :and => 0, :ior => 0, :xor => 0) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a::BigInt, b::BigInt) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, mpz_t, mpz_t), x, a, b) x end ($op)(a::BigInt, b::BigInt) = begin ($op!)(BigInt(nbits = $nbits), a, b) end ($op!)(x::BigInt, b::BigInt) = begin ($op!)(x, x, b) end end end invert!(x::BigInt, a::BigInt, b::BigInt) = begin ccall((:__gmpz_invert, libgmp), Cint, (mpz_t, mpz_t, mpz_t), x, a, b) end invert!(x::BigInt, b::BigInt) = begin invert!(x, x, b) end invert(a::BigInt, b::BigInt) = begin ret = BigInt() invert!(ret, a, b) ret end for op = (:add_ui, :sub_ui, :mul_ui, :mul_2exp, :fdiv_q_2exp, :pow_ui, :bin_ui) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a::BigInt, b) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, mpz_t, Culong), x, a, b) x end ($op)(a::BigInt, b) = begin ($op!)(BigInt(), a, b) end ($op!)(x::BigInt, b) = begin ($op!)(x, x, b) end end end ui_sub!(x::BigInt, a, b::BigInt) = begin ccall((:__gmpz_ui_sub, libgmp), Cvoid, (mpz_t, Culong, mpz_t), x, a, b) x end ui_sub(a, b::BigInt) = begin ui_sub!(BigInt(), a, b) end for op = (:scan1, :scan0) @eval ($op)(a::BigInt, b) = begin Int(signed(ccall($(gmpz(op)), Culong, (mpz_t, Culong), a, b))) end end mul_si!(x::BigInt, a::BigInt, b) = begin ccall((:__gmpz_mul_si, libgmp), Cvoid, (mpz_t, mpz_t, Clong), x, a, b) x end mul_si(a::BigInt, b) = begin mul_si!(BigInt(), a, b) end mul_si!(x::BigInt, b) = begin mul_si!(x, x, b) end for op = (:neg, :com, :sqrt, :set) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a::BigInt) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, mpz_t), x, a) x end ($op)(a::BigInt) = begin ($op!)(BigInt(), a) end end op === :set && continue @eval ($op!)(x::BigInt) = begin ($op!)(x, x) end end for (op, T) = ((:fac_ui, Culong), (:set_ui, Culong), (:set_si, Clong), (:set_d, Cdouble)) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, $T), x, a) x end ($op)(a) = begin ($op!)(BigInt(), a) end end end popcount(a::BigInt) = begin Int(signed(ccall((:__gmpz_popcount, libgmp), Culong, (mpz_t,), a))) end mpn_popcount(d::Ptr{Limb}, s::Integer) = begin Int(ccall((:__gmpn_popcount, libgmp), Culong, (Ptr{Limb}, Csize_t), d, s)) end mpn_popcount(a::BigInt) = begin mpn_popcount(a.d, abs(a.size)) end function tdiv_qr!(x::BigInt, y::BigInt, a::BigInt, b::BigInt) ccall((:__gmpz_tdiv_qr, libgmp), Cvoid, (mpz_t, mpz_t, mpz_t, mpz_t), x, y, a, b) (x, y) end tdiv_qr(a::BigInt, b::BigInt) = begin tdiv_qr!(BigInt(), BigInt(), a, b) end powm!(x::BigInt, a::BigInt, b::BigInt, c::BigInt) = begin ccall((:__gmpz_powm, libgmp), Cvoid, (mpz_t, mpz_t, mpz_t, mpz_t), x, a, b, c) x end powm(a::BigInt, b::BigInt, c::BigInt) = begin powm!(BigInt(), a, b, c) end powm!(x::BigInt, b::BigInt, c::BigInt) = begin powm!(x, x, b, c) end function gcdext!(x::BigInt, y::BigInt, z::BigInt, a::BigInt, b::BigInt) ccall((:__gmpz_gcdext, libgmp), Cvoid, (mpz_t, mpz_t, mpz_t, mpz_t, mpz_t), x, y, z, a, b) (x, y, z) end gcdext(a::BigInt, b::BigInt) = begin gcdext!(BigInt(), BigInt(), BigInt(), a, b) end cmp(a::BigInt, b::BigInt) = begin Int(ccall((:__gmpz_cmp, libgmp), Cint, (mpz_t, mpz_t), a, b)) end cmp_si(a::BigInt, b) = begin Int(ccall((:__gmpz_cmp_si, libgmp), Cint, (mpz_t, Clong), a, b)) end cmp_ui(a::BigInt, b) = begin Int(ccall((:__gmpz_cmp_ui, libgmp), Cint, (mpz_t, Culong), a, b)) end cmp_d(a::BigInt, b) = begin Int(ccall((:__gmpz_cmp_d, libgmp), Cint, (mpz_t, Cdouble), a, b)) end mpn_cmp(a::Ptr{Limb}, b::Ptr{Limb}, c) = begin ccall((:__gmpn_cmp, libgmp), Cint, (Ptr{Limb}, Ptr{Limb}, Clong), a, b, c) end mpn_cmp(a::BigInt, b::BigInt, c) = begin mpn_cmp(a.d, b.d, c) end get_str!(x, a, b::BigInt) = begin ccall((:__gmpz_get_str, libgmp), Ptr{Cchar}, (Ptr{Cchar}, Cint, mpz_t), x, a, b) x end set_str!(x::BigInt, a, b) = begin Int(ccall((:__gmpz_set_str, libgmp), Cint, (mpz_t, Ptr{UInt8}, Cint), x, a, b)) end get_d(a::BigInt) = begin ccall((:__gmpz_get_d, libgmp), Cdouble, (mpz_t,), a) end function export!(a::AbstractVector{T}, n::BigInt; order::Integer = -1, nails::Integer = 0, endian::Integer = 0) where T <: Base.BitInteger stride(a, 1) == 1 || throw(ArgumentError("a must have stride 1")) ndigits = cld(sizeinbase(n, 2), 8 * sizeof(T) - nails) length(a) < ndigits && resize!(a, ndigits) fill!(a, zero(T)) count = Ref{Csize_t}() ccall((:__gmpz_export, libgmp), Ptr{T}, (Ptr{T}, Ref{Csize_t}, Cint, Csize_t, Cint, Csize_t, mpz_t), a, count, order, sizeof(T), endian, nails, n) @assert count[] ≤ length(a) return (a, Int(count[])) end limbs_write!(x::BigInt, a) = begin ccall((:__gmpz_limbs_write, libgmp), Ptr{Limb}, (mpz_t, Clong), x, a) end limbs_finish!(x::BigInt, a) = begin ccall((:__gmpz_limbs_finish, libgmp), Cvoid, (mpz_t, Clong), x, a) end setbit!(x, a) = begin ccall((:__gmpz_setbit, libgmp), Cvoid, (mpz_t, bitcnt_t), x, a) x end tstbit(a::BigInt, b) = begin ccall((:__gmpz_tstbit, libgmp), Cint, (mpz_t, bitcnt_t), a, b) % Bool end end const ZERO = BigInt() const ONE = BigInt() const _ONE = Limb[1] widen(::Type{Int128}) = begin BigInt end widen(::Type{UInt128}) = begin BigInt end widen(::Type{BigInt}) = begin BigInt end signed(x::BigInt) = begin x end BigInt(x::BigInt) = begin x end Signed(x::BigInt) = begin x end function tryparse_internal(::Type{BigInt}, s::AbstractString, startpos::Int, endpos::Int, base_::Integer, raise::Bool) bstr = if startpos == firstindex(s) && endpos == lastindex(s) String(s) else String(SubString(s, startpos, endpos)) end (sgn, base, i) = Base.parseint_preamble(true, Int(base_), bstr, firstindex(bstr), lastindex(bstr)) if !(2 <= base <= 62) raise && throw(ArgumentError("invalid base: base must be 2 ≤ base ≤ 62, got $(base)")) return nothing end if i == 0 raise && throw(ArgumentError("premature end of integer: $(repr(bstr))")) return nothing end z = BigInt() if Base.containsnul(bstr) err = -1 else err = GC.@preserve(bstr, MPZ.set_str!(z, pointer(bstr) + (i - firstindex(bstr)), base)) end if err != 0 raise && throw(ArgumentError("invalid BigInt: $(repr(bstr))")) return nothing end flipsign!(z, sgn) end BigInt(x::Union{Clong, Int32}) = begin MPZ.set_si(x) end BigInt(x::Union{Culong, UInt32}) = begin MPZ.set_ui(x) end BigInt(x::Bool) = begin BigInt(UInt(x)) end unsafe_trunc(::Type{BigInt}, x::Union{Float16, Float32, Float64}) = begin MPZ.set_d(x) end function BigInt(x::Float64) isinteger(x) || throw(InexactError(:BigInt, BigInt, x)) unsafe_trunc(BigInt, x) end BigInt(x::Float16) = begin BigInt(Float64(x)) end BigInt(x::Float32) = begin BigInt(Float64(x)) end function BigInt(x::Integer) isbits(x) && (typemin(Clong) <= x <= typemax(Clong) && return BigInt((x % Clong)::Clong)) nd = ndigits(x, base = 2) z = MPZ.realloc2(nd) ux = unsigned(if x < 0 -x else x end) size = 0 limbnbits = sizeof(Limb) << 3 while nd > 0 size += 1 unsafe_store!(z.d, ux % Limb, size) ux >>= limbnbits nd -= limbnbits end z.size = if x < 0 -size else size end z end rem(x::BigInt, ::Type{Bool}) = begin (!(iszero(x)) & unsafe_load(x.d)) % Bool end (rem(x::BigInt, ::Type{T}) where T <: Union{SLimbMax, ULimbMax}) = begin if iszero(x) zero(T) else flipsign(unsafe_load(x.d) % T, x.size) end end function rem(x::BigInt, ::Type{T}) where T <: Union{Base.BitUnsigned, Base.BitSigned} u = zero(T) for l = 1:min(abs(x.size), cld(sizeof(T), sizeof(Limb))) u += (unsafe_load(x.d, l) % T) << (sizeof(Limb) << 3 * (l - 1)) end flipsign(u, x.size) end rem(x::Integer, ::Type{BigInt}) = begin BigInt(x) end clamp(x, ::Type{BigInt}) = begin convert(BigInt, x) end isodd(x::BigInt) = begin MPZ.tstbit(x, 0) end iseven(x::BigInt) = begin !(isodd(x)) end function (::Type{T})(x::BigInt) where T <: Base.BitUnsigned if sizeof(T) < sizeof(Limb) convert(T, convert(Limb, x)) else 0 <= x.size <= cld(sizeof(T), sizeof(Limb)) || throw(InexactError(nameof(T), T, x)) x % T end end function (::Type{T})(x::BigInt) where T <: Base.BitSigned n = abs(x.size) if sizeof(T) < sizeof(Limb) SLimb = typeof(Signed(one(Limb))) convert(T, convert(SLimb, x)) else 0 <= n <= cld(sizeof(T), sizeof(Limb)) || throw(InexactError(nameof(T), T, x)) y = x % T ispositive(x) ⊻ (y > 0) && throw(InexactError(nameof(T), T, x)) y end end Float64(n::BigInt, ::RoundingMode{:ToZero}) = begin MPZ.get_d(n) end function (::Type{T})(n::BigInt, ::RoundingMode{:ToZero}) where T <: Union{Float16, Float32} T(Float64(n, RoundToZero), RoundToZero) end function (::Type{T})(n::BigInt, ::RoundingMode{:Down}) where T <: CdoubleMax x = T(n, RoundToZero) if x > n prevfloat(x) else x end end function (::Type{T})(n::BigInt, ::RoundingMode{:Up}) where T <: CdoubleMax x = T(n, RoundToZero) if x < n nextfloat(x) else x end end function Float64(x::BigInt, ::RoundingMode{:Nearest}) x == 0 && return 0.0 xsize = abs(x.size) if xsize * BITS_PER_LIMB > 1024 z = Inf64 elseif xsize == 1 z = Float64(unsafe_load(x.d)) elseif Limb == UInt32 && xsize == 2 z = Float64((unsafe_load(x.d, 2) % UInt64) << BITS_PER_LIMB + unsafe_load(x.d)) else y1 = unsafe_load(x.d, xsize) % UInt64 n = top_set_bit(y1) y = y1 >> (n - (precision(Float64) + 1)) if Limb == UInt64 y += if n > precision(Float64) 0 else unsafe_load(x.d, xsize - 1) >> (10 + n) end else y += (unsafe_load(x.d, xsize - 1) % UInt64) >> (n - 22) y += if n > precision(Float64) - 32 0 else unsafe_load(x.d, xsize - 2) >> (10 + n) end end y = (y + 1) >> 1 y &= ~(UInt64(trailing_zeros(x) == (n - 54) + (xsize - 1) * BITS_PER_LIMB)) d = ((n + 1021) % UInt64) << 52 z = reinterpret(Float64, d + y) z = ldexp(z, (xsize - 1) * BITS_PER_LIMB) end return flipsign(z, x.size) end function Float32(x::BigInt, ::RoundingMode{:Nearest}) x == 0 && return 0.0f0 xsize = abs(x.size) if xsize * BITS_PER_LIMB > 128 z = Inf32 elseif xsize == 1 z = Float32(unsafe_load(x.d)) else y1 = unsafe_load(x.d, xsize) n = BITS_PER_LIMB - leading_zeros(y1) y = y1 >> (n - (precision(Float32) + 1)) % UInt32 y += if n > precision(Float32) 0 else unsafe_load(x.d, xsize - 1) >> (BITS_PER_LIMB - -25) end % UInt32 y = (y + one(UInt32)) >> 1 y &= ~(UInt32(trailing_zeros(x) == (n - 25) + (xsize - 1) * BITS_PER_LIMB)) d = ((n + 125) % UInt32) << 23 z = reinterpret(Float32, d + y) z = ldexp(z, (xsize - 1) * BITS_PER_LIMB) end return flipsign(z, x.size) end function Float16(x::BigInt, ::RoundingMode{:Nearest}) x == 0 && return Float16(0.0) y1 = unsafe_load(x.d) n = BITS_PER_LIMB - leading_zeros(y1) if n > 16 || abs(x.size) > 1 z = Inf16 else y = y1 >> (n - (precision(Float16) + 1)) % UInt16 y = (y + one(UInt16)) >> 1 y &= ~(UInt16(trailing_zeros(x) == n - 12)) d = ((n + 13) % UInt16) << 10 z = reinterpret(Float16, d + y) end return flipsign(z, x.size) end Float64(n::BigInt) = begin Float64(n, RoundNearest) end Float32(n::BigInt) = begin Float32(n, RoundNearest) end Float16(n::BigInt) = begin Float16(n, RoundNearest) end promote_rule(::Type{BigInt}, ::Type{<:Integer}) = begin BigInt end Core.@doc " big(x)\n\nConvert a number to a maximum precision representation (typically [`BigInt`](@ref) or\n`BigFloat`). See [`BigFloat`](@ref BigFloat(::Any, rounding::RoundingMode)) for\ninformation about some pitfalls with floating-point numbers.\n" function big end big(::Type{<:Integer}) = begin BigInt end big(::Type{<:Rational}) = begin Rational{BigInt} end big(n::Integer) = begin convert(BigInt, n) end for (fJ, fC) = ((:+, :add), (:-, :sub), (:*, :mul), (:mod, :fdiv_r), (:rem, :tdiv_r), (:gcd, :gcd), (:lcm, :lcm), (:&, :and), (:|, :ior), (:xor, :xor)) @eval begin ($fJ)(x::BigInt, y::BigInt) = begin MPZ.:($fC)(x, y) end end end for (r, f) = ((RoundToZero, :tdiv_q), (RoundDown, :fdiv_q), (RoundUp, :cdiv_q)) @eval div(x::BigInt, y::BigInt, ::typeof($r)) = begin MPZ.:($f)(x, y) end end div(x::BigInt, y::BigInt) = begin div(x, y, RoundToZero) end fld(x::BigInt, y::BigInt) = begin div(x, y, RoundDown) end cld(x::BigInt, y::BigInt) = begin div(x, y, RoundUp) end x::BigInt / y::BigInt = begin float(x) / float(y) end function invmod(x::BigInt, y::BigInt) z = zero(BigInt) ya = abs(y) if ya == 1 return z end if y == 0 || MPZ.invert!(z, x, ya) == 0 throw(DomainError(y)) end if y < 0 MPZ.add!(z, y) end return z end for (fJ, fC) = ((:+, :add), (:*, :mul), (:&, :and), (:|, :ior), (:xor, :xor)) fC! = Symbol(fC, :!) @eval begin ($fJ)(a::BigInt, b::BigInt, c::BigInt) = begin MPZ.:($fC!)(MPZ.:($fC)(a, b), c) end ($fJ)(a::BigInt, b::BigInt, c::BigInt, d::BigInt) = begin MPZ.:($fC!)(MPZ.:($fC!)(MPZ.:($fC)(a, b), c), d) end ($fJ)(a::BigInt, b::BigInt, c::BigInt, d::BigInt, e::BigInt) = begin MPZ.:($fC!)(MPZ.:($fC!)(MPZ.:($fC!)(MPZ.:($fC)(a, b), c), d), e) end end end x::BigInt + c::CulongMax = begin MPZ.add_ui(x, c) end c::CulongMax + x::BigInt = begin x + c end x::BigInt - c::CulongMax = begin MPZ.sub_ui(x, c) end c::CulongMax - x::BigInt = begin MPZ.ui_sub(c, x) end x::BigInt + c::ClongMax = begin if c < 0 x - -(c % Culong) else x + convert(Culong, c) end end c::ClongMax + x::BigInt = begin if c < 0 x - -(c % Culong) else x + convert(Culong, c) end end x::BigInt - c::ClongMax = begin if c < 0 x + -(c % Culong) else x - convert(Culong, c) end end c::ClongMax - x::BigInt = begin if c < 0 -((x + -(c % Culong))) else convert(Culong, c) - x end end x::BigInt * c::CulongMax = begin MPZ.mul_ui(x, c) end c::CulongMax * x::BigInt = begin x * c end x::BigInt * c::ClongMax = begin MPZ.mul_si(x, c) end c::ClongMax * x::BigInt = begin x * c end x::BigInt / y::Union{ClongMax, CulongMax} = begin float(x) / y end x::Union{ClongMax, CulongMax} / y::BigInt = begin x / float(y) end -(x::BigInt) = begin MPZ.neg(x) end ~(x::BigInt) = begin MPZ.com(x) end x::BigInt << c::UInt = begin if c == 0 x else MPZ.mul_2exp(x, c) end end x::BigInt >> c::UInt = begin if c == 0 x else MPZ.fdiv_q_2exp(x, c) end end x::BigInt >>> c::UInt = begin x >> c end function trailing_zeros(x::BigInt) c = MPZ.scan1(x, 0) c == -1 && throw(DomainError(x, "`x` must be non-zero")) c end function trailing_ones(x::BigInt) c = MPZ.scan0(x, 0) c == -1 && throw(DomainError(x, "`x` must not be equal to -1")) c end function count_ones(x::BigInt) c = MPZ.popcount(x) c == -1 && throw(DomainError(x, "`x` cannot be negative")) c end function count_zeros(x::BigInt) c = MPZ.popcount(~x) c == -1 && throw(DomainError(x, "`x` must be negative")) c end Core.@doc " count_ones_abs(x::BigInt)\n\nNumber of ones in the binary representation of abs(x).\n" count_ones_abs(x::BigInt) = begin if iszero(x) 0 else MPZ.mpn_popcount(x) end end _bit_magnitude(x::BigInt) = begin x.size * sizeof(Limb) << 3 - leading_zeros(GC.@preserve(x, unsafe_load(x.d, x.size))) end function exponent(x::BigInt) iszero(x) && throw(DomainError(x, "cannot be zero")) ux = abs(x) return _bit_magnitude(ux) - 1 end function top_set_bit(x::BigInt) isnegative(x) && throw(DomainError(x, "top_set_bit only supports negative arguments when they have type BitSigned.")) iszero(x) && return 0 return _bit_magnitude(x) end divrem(x::BigInt, y::BigInt, ::typeof(RoundToZero) = RoundToZero) = begin MPZ.tdiv_qr(x, y) end divrem(x::BigInt, y::Integer, ::typeof(RoundToZero) = RoundToZero) = begin MPZ.tdiv_qr(x, BigInt(y)) end cmp(x::BigInt, y::BigInt) = begin sign(MPZ.cmp(x, y)) end cmp(x::BigInt, y::ClongMax) = begin sign(MPZ.cmp_si(x, y)) end cmp(x::BigInt, y::CulongMax) = begin sign(MPZ.cmp_ui(x, y)) end cmp(x::BigInt, y::Integer) = begin cmp(x, big(y)) end cmp(x::Integer, y::BigInt) = begin -(cmp(y, x)) end cmp(x::BigInt, y::CdoubleMax) = begin if isnan(y) -1 else sign(MPZ.cmp_d(x, y)) end end cmp(x::CdoubleMax, y::BigInt) = begin -(cmp(y, x)) end isqrt(x::BigInt) = begin MPZ.sqrt(x) end x::BigInt ^ y::Culong = begin MPZ.pow_ui(x, y) end function bigint_pow(x::BigInt, y::Integer) x == 1 && return x x == -1 && return if isodd(y) x else -x end if y < 0 throw(DomainError(y, "`y` cannot be negative.")) end @noinline throw1(y) = begin throw(OverflowError("exponent $(y) is too large and computation will overflow")) end if y > typemax(Culong) x == 0 && return x throw1(y) end return x ^ convert(Culong, y) end x::BigInt ^ y::BigInt = begin bigint_pow(x, y) end x::BigInt ^ y::Bool = begin if y x else one(x) end end x::BigInt ^ y::Integer = begin bigint_pow(x, y) end x::Integer ^ y::BigInt = begin bigint_pow(BigInt(x), y) end x::Bool ^ y::BigInt = begin Base.power_by_squaring(x, y) end function powermod(x::BigInt, p::BigInt, m::BigInt) r = MPZ.powm(x, p, m) return if m < 0 && r > 0 MPZ.add!(r, m) else r end end powermod(x::Integer, p::Integer, m::BigInt) = begin powermod(big(x), big(p), m) end function gcdx(a::BigInt, b::BigInt) (g, s, t) = MPZ.gcdext(a, b) if t == 0 if a == b return (g, t, s) elseif abs(a) == abs(b) return (g, t, -s) end end (g, s, t) end +(x::BigInt, y::BigInt, rest::BigInt...) = begin sum(tuple(x, y, rest...)) end sum(arr::Union{AbstractArray{BigInt}, Tuple{BigInt, Vararg{BigInt}}}) = begin foldl(MPZ.add!, arr; init = BigInt(0)) end function prod(arr::AbstractArray{BigInt}) any(iszero, arr) && return zero(BigInt) _prod(arr, firstindex(arr), lastindex(arr)) end function _prod(arr::AbstractArray{BigInt}, lo, hi) if (hi - lo) + 1 <= 16 nlimbs = 0 for i = lo:hi nlimbs += abs((arr[i]).size) end init = BigInt(; nbits = nlimbs * BITS_PER_LIMB) MPZ.set_si!(init, 1) for i = lo:hi MPZ.mul!(init, arr[i]) end init else mid = (lo + hi) ÷ 2 MPZ.mul!(_prod(arr, lo, mid), _prod(arr, mid + 1, hi)) end end factorial(n::BigInt) = begin if !(isnegative(n)) MPZ.fac_ui(n) else throw(DomainError(n, "`n` must not be negative.")) end end function binomial(n::BigInt, k::Integer) k < 0 && return BigInt(0) k <= typemax(Culong) && return binomial(n, Culong(k)) n < 0 && return if isodd(k) -(binomial((k - n) - 1, k)) else binomial((k - n) - 1, k) end κ = n - k κ < 0 && return BigInt(0) κ <= typemax(Culong) && return binomial(n, Culong(κ)) throw(OverflowError("Computation would exceed memory")) end binomial(n::BigInt, k::Culong) = begin MPZ.bin_ui(n, k) end x::BigInt == y::BigInt = begin cmp(x, y) == 0 end x::BigInt == i::Integer = begin cmp(x, i) == 0 end i::Integer == x::BigInt = begin cmp(x, i) == 0 end x::BigInt == f::CdoubleMax = begin if isnan(f) false else cmp(x, f) == 0 end end f::CdoubleMax == x::BigInt = begin if isnan(f) false else cmp(x, f) == 0 end end iszero(x::BigInt) = begin x.size == 0 end isone(x::BigInt) = begin x == Culong(1) end x::BigInt <= y::BigInt = begin cmp(x, y) <= 0 end x::BigInt <= i::Integer = begin cmp(x, i) <= 0 end i::Integer <= x::BigInt = begin cmp(x, i) >= 0 end x::BigInt <= f::CdoubleMax = begin if isnan(f) false else cmp(x, f) <= 0 end end f::CdoubleMax <= x::BigInt = begin if isnan(f) false else cmp(x, f) >= 0 end end x::BigInt < y::BigInt = begin cmp(x, y) < 0 end x::BigInt < i::Integer = begin cmp(x, i) < 0 end i::Integer < x::BigInt = begin cmp(x, i) > 0 end x::BigInt < f::CdoubleMax = begin if isnan(f) false else cmp(x, f) < 0 end end f::CdoubleMax < x::BigInt = begin if isnan(f) false else cmp(x, f) > 0 end end isnegative(x::BigInt) = begin x.size < 0 end ispositive(x::BigInt) = begin x.size > 0 end signbit(x::BigInt) = begin isnegative(x) end flipsign!(x::BigInt, y::Integer) = begin signbit(y) && (x.size = -(x.size)) x end flipsign(x::BigInt, y::Integer) = begin if signbit(y) -x else x end end flipsign(x::BigInt, y::BigInt) = begin if signbit(y) -x else x end end function sign(x::BigInt) isnegative(x) && return -(one(x)) ispositive(x) && return one(x) return x end show(io::IO, x::BigInt) = begin print(io, string(x)) end function string(n::BigInt; base::Integer = 10, pad::Integer = 1) base < 0 && return Base._base(Int(base), n, pad, (base > 0) & (n.size < 0)) 2 <= base <= 62 || throw(ArgumentError("base must be 2 ≤ base ≤ 62, got $(base)")) iszero(n) && (pad < 1 && return "") nd1 = ndigits(n, base = base) nd = max(nd1, pad) str = Base._string_n(nd + isnegative(n)) GC.@preserve str begin p = pointer(str) MPZ.get_str!((p + nd) - nd1, base, n) pad_len = nd - nd1 if pad_len > 0 Base.memset(p + isnegative(n), UInt8('0'), pad_len) end isnegative(n) && unsafe_store!(p, UInt8('-')) end return str end function digits!(a::AbstractVector{T}, n::BigInt; base::Integer = 10) where T <: Integer if base ≥ 2 if base ≤ 62 s = codeunits(string(n; base)) (i, j) = (firstindex(a) - 1, length(s) + 1) lasti = min(lastindex(a), ((firstindex(a) + length(s)) - 1) - isnegative(n)) while i < lasti x = s[j -= 1] a[i += 1] = if base ≤ 36 if x > 0x39 x - 0x57 else x - 0x30 end else if x > 0x39 if x > 0x60 x - 0x3d else x - 0x37 end else x - 0x30 end end end lasti = lastindex(a) while i < lasti a[i += 1] = zero(T) end return if isnegative(n) map!(-, a, a) else a end elseif a isa StridedVector{<:Base.BitInteger} && (stride(a, 1) == 1 && (ispow2(base) && base - 1 ≤ typemax(T))) origlen = length(a) (_, writelen) = MPZ.export!(a, n; nails = 8 * sizeof(T) - trailing_zeros(base)) length(a) != origlen && resize!(a, origlen) a[var"begin" + writelen:var"end"] .= zero(T) return if isnegative(n) map!(-, a, a) else a end end end return invoke(digits!, Tuple{typeof(a), Integer}, a, n; base) end function ndigits0zpb(x::BigInt, b::Integer) b < 2 && throw(DomainError(b, "`b` cannot be less than 2.")) x.size == 0 && return 0 if ispow2(b) && 2 <= b <= 62 MPZ.sizeinbase(x, b) else n = MPZ.sizeinbase(x, 2) lb = log2(b) (q, r) = divrem(n, lb) iq = Int(q) maxerr = q * eps(lb) if r - 1.0 < maxerr if abs(x) >= big(b) ^ iq iq + 1 else iq end elseif lb - r < maxerr if abs(x) >= big(b) ^ (iq + 1) iq + 2 else iq + 1 end else iq + 1 end end end _prevpow2(x::BigInt) = begin if -2 <= x <= 2 x else flipsign!(ONE << (ndigits(x, base = 2) - 1), x) end end _nextpow2(x::BigInt) = begin if count_ones_abs(x) <= 1 x else flipsign!(ONE << ndigits(x, base = 2), x) end end Base.checked_abs(x::BigInt) = begin abs(x) end Base.checked_neg(x::BigInt) = begin -x end Base.checked_add(a::BigInt, b::BigInt) = begin a + b end Base.checked_sub(a::BigInt, b::BigInt) = begin a - b end Base.checked_mul(a::BigInt, b::BigInt) = begin a * b end Base.checked_div(a::BigInt, b::BigInt) = begin div(a, b) end Base.checked_rem(a::BigInt, b::BigInt) = begin rem(a, b) end Base.checked_fld(a::BigInt, b::BigInt) = begin fld(a, b) end Base.checked_mod(a::BigInt, b::BigInt) = begin mod(a, b) end Base.checked_cld(a::BigInt, b::BigInt) = begin cld(a, b) end Base.add_with_overflow(a::BigInt, b::BigInt) = begin (a + b, false) end Base.sub_with_overflow(a::BigInt, b::BigInt) = begin (a - b, false) end Base.mul_with_overflow(a::BigInt, b::BigInt) = begin (a * b, false) end Base.checked_pow(x::BigInt, p::Integer) = begin x ^ p end Base.checked_pow(x::Integer, p::BigInt) = begin x ^ p end Base.checked_pow(x::BigInt, p::BigInt) = begin x ^ p end Base.deepcopy_internal(x::BigInt, stackdict::IdDict) = begin get!((()->begin MPZ.set(x) end), stackdict, x)::BigInt end Base._hash_shl!(x::BigInt, n) = begin MPZ.mul_2exp!(x, n) end if Limb === UInt64 === UInt using .Base: HASH_SECRET, hash_bytes, hash_finalizer struct UnsafeLimbView <: AbstractVector{UInt8} bigint::BigInt start_byte::Int num_bytes::Int end function Base.size(view::UnsafeLimbView) return (view.num_bytes,) end function Base.getindex(view::UnsafeLimbView, i::Int) @boundscheck checkbounds(view, i) GC.@preserve view begin limb_index = div((view.start_byte + i) - 2, 8) + 1 byte_in_limb = ((view.start_byte + i) - 2) % 8 limb = unsafe_load(view.bigint.d, limb_index) return UInt8(limb >> (8byte_in_limb) & 0xff) end end function Base.iterate(view::UnsafeLimbView, state::Int = 1) state > view.num_bytes && return nothing return (@inbounds(view[state]), state + 1) end function Base.length(view::UnsafeLimbView) return view.num_bytes end function hash_integer(n::BigInt, h::UInt) iszero(n) && return hash_integer(0, h) s = n.size h ⊻= s < 0 us = abs(s) leading_zero_bytes = div(leading_zeros(unsafe_load(n.d, us)), 8) num_bytes = 8us - leading_zero_bytes limb_view = UnsafeLimbView(n, 1, num_bytes) return hash_bytes(limb_view, h, HASH_SECRET) end function hash(x::BigInt, h::UInt) GC.@preserve x begin sz = x.size sz == 0 && return hash(0, h) ptr = Ptr{UInt64}(x.d) if sz == 1 return hash(unsafe_load(ptr), h) elseif sz == -1 limb = unsafe_load(ptr) limb <= typemin(Int) % UInt && return hash(-(limb % Int), h) end pow = trailing_zeros(x) nd = Base.ndigits0z(x, 2) idx = pow >>> 6 + 1 shift = (pow & 63) % UInt upshift = BITS_PER_LIMB - shift asz = abs(sz) if shift == 0 limb = unsafe_load(ptr, idx) else limb1 = unsafe_load(ptr, idx) limb2 = if idx < asz unsafe_load(ptr, idx + 1) else UInt(0) end limb = limb2 << upshift | limb1 >> shift end if nd <= 1024 && nd - pow <= 53 return hash(ldexp(flipsign(Float64(limb), sz), pow), h) end h = hash_integer(pow, h) h ⊻= sz < 0 leading_zero_bytes = div(leading_zeros(unsafe_load(x.d, asz)), 8) trailing_zero_bytes = div(pow, 8) num_bytes = 8asz - (leading_zero_bytes + trailing_zero_bytes) limb_view = UnsafeLimbView(x, trailing_zero_bytes + 1, num_bytes) return hash_bytes(limb_view, h, HASH_SECRET) end end end module MPQ import .Base: unsafe_rational, __throw_rational_argerror_zero import ..GMP: BigInt, MPZ, Limb, libgmp gmpq(op::Symbol) = begin Expr(:tuple, QuoteNode(Symbol(:__gmpq_, op)), GlobalRef(MPZ, :libgmp)) end mutable struct _MPQ num_alloc::Cint num_size::Cint num_d::Ptr{Limb} den_alloc::Cint den_size::Cint den_d::Ptr{Limb} rat::Rational{BigInt} end const mpq_t = Ref{_MPQ} _MPQ(x::BigInt, y::BigInt) = begin _MPQ(x.alloc, x.size, x.d, y.alloc, y.size, y.d, unsafe_rational(BigInt, x, y)) end _MPQ() = begin _MPQ(BigInt(), BigInt()) end _MPQ(x::Rational{BigInt}) = begin _MPQ(x.num, x.den) end function sync_rational!(xq::_MPQ) xq.rat.num.alloc = xq.num_alloc xq.rat.num.size = xq.num_size xq.rat.num.d = xq.num_d xq.rat.den.alloc = xq.den_alloc xq.rat.den.size = xq.den_size xq.rat.den.d = xq.den_d return xq.rat end function Rational{BigInt}(num::BigInt, den::BigInt) if iszero(den) iszero(num) && __throw_rational_argerror_zero(BigInt) return set_si(flipsign(1, num), 0) end xq = _MPQ(MPZ.set(num), MPZ.set(den)) ccall((:__gmpq_canonicalize, libgmp), Cvoid, (mpq_t,), xq) return sync_rational!(xq) end function set!(z::Rational{BigInt}, x::Rational{BigInt}) zq = _MPQ(z) ccall((:__gmpq_set, libgmp), Cvoid, (mpq_t, mpq_t), zq, _MPQ(x)) return sync_rational!(zq) end function set_z!(z::Rational{BigInt}, x::BigInt) zq = _MPQ(z) ccall((:__gmpq_set_z, libgmp), Cvoid, (mpq_t, MPZ.mpz_t), zq, x) return sync_rational!(zq) end for (op, T) = ((:set, Rational{BigInt}), (:set_z, BigInt)) op! = Symbol(op, :!) @eval ($op)(a::$T) = begin ($op!)(unsafe_rational(BigInt(), BigInt()), a) end end for (op, T1, T2) = ((:set_ui, Culong, Culong), (:set_si, Clong, Culong)) op! = Symbol(op, :!) @eval begin function ($op!)(z::Rational{BigInt}, a, b) zq = _MPQ(z) ccall($(gmpq(op)), Cvoid, (mpq_t, $T1, $T2), zq, a, b) return sync_rational!(zq) end ($op)(a, b) = begin ($op!)(unsafe_rational(BigInt(), BigInt()), a, b) end end end function add!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) || iszero(y.den) if iszero(x.den) && (iszero(y.den) && isnegative(x.num) != isnegative(y.num)) throw(DivideError()) end return set!(z, if iszero(x.den) x else y end) end zq = _MPQ(z) ccall((:__gmpq_add, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end function sub!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) || iszero(y.den) if iszero(x.den) && (iszero(y.den) && isnegative(x.num) == isnegative(y.num)) throw(DivideError()) end iszero(x.den) && return set!(z, x) return set_si!(z, flipsign(-1, y.num), 0) end zq = _MPQ(z) ccall((:__gmpq_sub, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end function mul!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) || iszero(y.den) if iszero(x.num) || iszero(y.num) throw(DivideError()) end return set_si!(z, ifelse(xor(isnegative(x.num), isnegative(y.num)), -1, 1), 0) end zq = _MPQ(z) ccall((:__gmpq_mul, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end function div!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) if iszero(y.den) throw(DivideError()) end isnegative(y.num) || return set!(z, x) return set_si!(z, flipsign(-1, x.num), 0) elseif iszero(y.den) return set_si!(z, 0, 1) elseif iszero(y.num) if iszero(x.num) throw(DivideError()) end return set_si!(z, flipsign(1, x.num), 0) end zq = _MPQ(z) ccall((:__gmpq_div, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end for (fJ, fC) = ((:+, :add), (:-, :sub), (:*, :mul), (://, :div)) fC! = Symbol(fC, :!) @eval begin ($fC!)(x::Rational{BigInt}, y::Rational{BigInt}) = begin ($fC!)(x, x, y) end Base.:($fJ)(x::Rational{BigInt}, y::Rational{BigInt}) = begin ($fC!)(unsafe_rational(BigInt(), BigInt()), x, y) end end end function Base.cmp(x::Rational{BigInt}, y::Rational{BigInt}) Int(ccall((:__gmpq_cmp, libgmp), Cint, (mpq_t, mpq_t), _MPQ(x), _MPQ(y))) end end end Parsing files in Base: Test Failed at /home/pkgeval/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:166 Expression: false Stacktrace: [1] macro expansion @ /opt/julia/share/julia/stdlib/v1.14/Test/src/Test.jl:782 [inlined] [2] top-level scope @ ~/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:166 ┌ Error: parsing difference │ file = "/opt/julia/bin/../share/julia/stdlib/v1.14/Distributed/src/workerpool.jl" └ @ Main.var"##302" ~/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:157 false begin end try wait(x) finally put!(pool, worker) end try wait(x) catch finally put!(pool, worker) end Threads.@spawn Threads.threadpool() try wait(x) finally put!(pool, worker) end Threads.@spawn Threads.threadpool() try wait(x) catch finally put!(pool, worker) end t = Threads.@spawn(Threads.threadpool(), try wait(x) finally put!(pool, worker) end) t = Threads.@spawn(Threads.threadpool(), try wait(x) catch finally put!(pool, worker) end) begin worker = take!(pool) local x try x = rc_f(f, worker, args...; kwargs...) catch put!(pool, worker) rethrow() end t = Threads.@spawn(Threads.threadpool(), try wait(x) finally put!(pool, worker) end) errormonitor(t) return x end begin worker = take!(pool) local x try x = rc_f(f, worker, args...; kwargs...) catch put!(pool, worker) rethrow() end t = Threads.@spawn(Threads.threadpool(), try wait(x) catch finally put!(pool, worker) end) errormonitor(t) return x end function remotecall_pool(rc_f::typeof(remotecall), f, pool::AbstractWorkerPool, args...; kwargs...) worker = take!(pool) local x try x = rc_f(f, worker, args...; kwargs...) catch put!(pool, worker) rethrow() end t = Threads.@spawn(Threads.threadpool(), try wait(x) finally put!(pool, worker) end) errormonitor(t) return x end function remotecall_pool(rc_f::typeof(remotecall), f, pool::AbstractWorkerPool, args...; kwargs...) worker = take!(pool) local x try x = rc_f(f, worker, args...; kwargs...) catch put!(pool, worker) rethrow() end t = Threads.@spawn(Threads.threadpool(), try wait(x) catch finally put!(pool, worker) end) errormonitor(t) return x end false begin end try wait(x) finally put!(pool, worker) end try wait(x) catch finally put!(pool, worker) end Threads.@spawn Threads.threadpool() try wait(x) finally put!(pool, worker) end Threads.@spawn Threads.threadpool() try wait(x) catch finally put!(pool, worker) end t = Threads.@spawn(Threads.threadpool(), try wait(x) finally put!(pool, worker) end) t = Threads.@spawn(Threads.threadpool(), try wait(x) catch finally put!(pool, worker) end) begin worker = take!(pool) f_ref = get(pool.map_obj2ref, (worker, f), (f, RemoteChannel(worker))) f_ref isa Tuple && (pool.map_obj2ref[(worker, f)] = f_ref[2]) local x try x = rc_f(exec_from_cache, worker, f_ref, args...; kwargs...) catch put!(pool, worker) rethrow() end t = Threads.@spawn(Threads.threadpool(), try wait(x) finally put!(pool, worker) end) errormonitor(t) return x end begin worker = take!(pool) f_ref = get(pool.map_obj2ref, (worker, f), (f, RemoteChannel(worker))) f_ref isa Tuple && (pool.map_obj2ref[(worker, f)] = f_ref[2]) local x try x = rc_f(exec_from_cache, worker, f_ref, args...; kwargs...) catch put!(pool, worker) rethrow() end t = Threads.@spawn(Threads.threadpool(), try wait(x) catch finally put!(pool, worker) end) errormonitor(t) return x end function remotecall_pool(rc_f::typeof(remotecall), f, pool::CachingPool, args...; kwargs...) worker = take!(pool) f_ref = get(pool.map_obj2ref, (worker, f), (f, RemoteChannel(worker))) f_ref isa Tuple && (pool.map_obj2ref[(worker, f)] = f_ref[2]) local x try x = rc_f(exec_from_cache, worker, f_ref, args...; kwargs...) catch put!(pool, worker) rethrow() end t = Threads.@spawn(Threads.threadpool(), try wait(x) finally put!(pool, worker) end) errormonitor(t) return x end function remotecall_pool(rc_f::typeof(remotecall), f, pool::CachingPool, args...; kwargs...) worker = take!(pool) f_ref = get(pool.map_obj2ref, (worker, f), (f, RemoteChannel(worker))) f_ref isa Tuple && (pool.map_obj2ref[(worker, f)] = f_ref[2]) local x try x = rc_f(exec_from_cache, worker, f_ref, args...; kwargs...) catch put!(pool, worker) rethrow() end t = Threads.@spawn(Threads.threadpool(), try wait(x) catch finally put!(pool, worker) end) errormonitor(t) return x end Parsing files in Base: Test Failed at /home/pkgeval/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:166 Expression: false Stacktrace: [1] macro expansion @ /opt/julia/share/julia/stdlib/v1.14/Test/src/Test.jl:782 [inlined] [2] top-level scope @ ~/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:166 ┌ Error: parsing difference │ file = "/opt/julia/bin/../share/julia/stdlib/v1.14/InteractiveUtils/test/runtests.jl" └ @ Main.var"##302" ~/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:157 @code_typed optimize = false ::Vector{Int} .= ::Int @code_typed optimize = (false::Vector{Int} .= ::Int) false false::Vector{Int} .= ::Int optimize = false optimize = (false::Vector{Int} .= ::Int) @code_typed optimize = false ::Vector{Int} .= ::Int @code_typed optimize = (false::Vector{Int} .= ::Int) (@code_typed(optimize = false, ::Vector{Int} .= ::Int))[2] (@code_typed(optimize = (false::Vector{Int} .= ::Int)))[2] (@code_typed(optimize = false, ::Vector{Int} .= ::Int))[2] == Vector{Int} (@code_typed(optimize = (false::Vector{Int} .= ::Int)))[2] == Vector{Int} @test (@code_typed(optimize = false, ::Vector{Int} .= ::Int))[2] == Vector{Int} @test (@code_typed(optimize = (false::Vector{Int} .= ::Int)))[2] == Vector{Int} @code_typed optimize = false ::Vector{Float64} .= 1 .+ ::Vector{Int} @code_typed optimize = (false::Vector{Float64} .= 1 .+ ::Vector{Int}) false false::Vector{Float64} .= 1 .+ ::Vector{Int} optimize = false optimize = (false::Vector{Float64} .= 1 .+ ::Vector{Int}) @code_typed optimize = false ::Vector{Float64} .= 1 .+ ::Vector{Int} @code_typed optimize = (false::Vector{Float64} .= 1 .+ ::Vector{Int}) (@code_typed(optimize = false, ::Vector{Float64} .= 1 .+ ::Vector{Int}))[2] (@code_typed(optimize = (false::Vector{Float64} .= 1 .+ ::Vector{Int})))[2] (@code_typed(optimize = false, ::Vector{Float64} .= 1 .+ ::Vector{Int}))[2] == Vector{Float64} (@code_typed(optimize = (false::Vector{Float64} .= 1 .+ ::Vector{Int})))[2] == Vector{Float64} @test (@code_typed(optimize = false, ::Vector{Float64} .= 1 .+ ::Vector{Int}))[2] == Vector{Float64} @test (@code_typed(optimize = (false::Vector{Float64} .= 1 .+ ::Vector{Int})))[2] == Vector{Float64} @code_typed optimize = false ::Vector{Float64} .= 1 .+ round.(base = ::Int, ::Vector{Int}; digits = 3) @code_typed optimize = (false::Vector{Float64} .= 1 .+ round.(base = ::Int, ::Vector{Int}; digits = 3)) false false::Vector{Float64} .= 1 .+ round.(base = ::Int, ::Vector{Int}; digits = 3) optimize = false optimize = (false::Vector{Float64} .= 1 .+ round.(base = ::Int, ::Vector{Int}; digits = 3)) @code_typed optimize = false ::Vector{Float64} .= 1 .+ round.(base = ::Int, ::Vector{Int}; digits = 3) @code_typed optimize = (false::Vector{Float64} .= 1 .+ round.(base = ::Int, ::Vector{Int}; digits = 3)) (@code_typed(optimize = false, ::Vector{Float64} .= 1 .+ round.(base = ::Int, ::Vector{Int}; digits = 3)))[2] (@code_typed(optimize = (false::Vector{Float64} .= 1 .+ round.(base = ::Int, ::Vector{Int}; digits = 3))))[2] (@code_typed(optimize = false, ::Vector{Float64} .= 1 .+ round.(base = ::Int, ::Vector{Int}; digits = 3)))[2] == Vector{Float64} (@code_typed(optimize = (false::Vector{Float64} .= 1 .+ round.(base = ::Int, ::Vector{Int}; digits = 3))))[2] == Vector{Float64} @test (@code_typed(optimize = false, ::Vector{Float64} .= 1 .+ round.(base = ::Int, ::Vector{Int}; digits = 3)))[2] == Vector{Float64} @test (@code_typed(optimize = (false::Vector{Float64} .= 1 .+ round.(base = ::Int, ::Vector{Int}; digits = 3))))[2] == Vector{Float64} begin @test (@code_typed(optimize = false, round.([1.0, 2.0]; digits = ::Int64)))[2] == Vector{Float64} @test (@code_typed(optimize = false, round.(::Vector{Float64}, base = 2; digits = ::Int64)))[2] == Vector{Float64} @test (@code_typed(optimize = false, round.(base = ::Int64, ::Vector{Float64}; digits = ::Int64)))[2] == Vector{Float64} @test (@code_typed(optimize = false, [1, 2] .= ::Int))[2] == Vector{Int} @test (@code_typed(optimize = false, ::Vector{Int} .= ::Int))[2] == Vector{Int} @test (@code_typed(optimize = false, ::Vector{Float64} .= 1 .+ ::Vector{Int}))[2] == Vector{Float64} @test (@code_typed(optimize = false, ::Vector{Float64} .= 1 .+ round.(base = ::Int, ::Vector{Int}; digits = 3)))[2] == Vector{Float64} end begin @test (@code_typed(optimize = false, round.([1.0, 2.0]; digits = ::Int64)))[2] == Vector{Float64} @test (@code_typed(optimize = false, round.(::Vector{Float64}, base = 2; digits = ::Int64)))[2] == Vector{Float64} @test (@code_typed(optimize = false, round.(base = ::Int64, ::Vector{Float64}; digits = ::Int64)))[2] == Vector{Float64} @test (@code_typed(optimize = false, [1, 2] .= ::Int))[2] == Vector{Int} @test (@code_typed(optimize = (false::Vector{Int} .= ::Int)))[2] == Vector{Int} @test (@code_typed(optimize = (false::Vector{Float64} .= 1 .+ ::Vector{Int})))[2] == Vector{Float64} @test (@code_typed(optimize = (false::Vector{Float64} .= 1 .+ round.(base = ::Int, ::Vector{Int}; digits = 3))))[2] == Vector{Float64} end @testset "Broadcasting" begin @test (@code_typed(optimize = false, round.([1.0, 2.0]; digits = ::Int64)))[2] == Vector{Float64} @test (@code_typed(optimize = false, round.(::Vector{Float64}, base = 2; digits = ::Int64)))[2] == Vector{Float64} @test (@code_typed(optimize = false, round.(base = ::Int64, ::Vector{Float64}; digits = ::Int64)))[2] == Vector{Float64} @test (@code_typed(optimize = false, [1, 2] .= ::Int))[2] == Vector{Int} @test (@code_typed(optimize = false, ::Vector{Int} .= ::Int))[2] == Vector{Int} @test (@code_typed(optimize = false, ::Vector{Float64} .= 1 .+ ::Vector{Int}))[2] == Vector{Float64} @test (@code_typed(optimize = false, ::Vector{Float64} .= 1 .+ round.(base = ::Int, ::Vector{Int}; digits = 3)))[2] == Vector{Float64} end @testset "Broadcasting" begin @test (@code_typed(optimize = false, round.([1.0, 2.0]; digits = ::Int64)))[2] == Vector{Float64} @test (@code_typed(optimize = false, round.(::Vector{Float64}, base = 2; digits = ::Int64)))[2] == Vector{Float64} @test (@code_typed(optimize = false, round.(base = ::Int64, ::Vector{Float64}; digits = ::Int64)))[2] == Vector{Float64} @test (@code_typed(optimize = false, [1, 2] .= ::Int))[2] == Vector{Int} @test (@code_typed(optimize = (false::Vector{Int} .= ::Int)))[2] == Vector{Int} @test (@code_typed(optimize = (false::Vector{Float64} .= 1 .+ ::Vector{Int})))[2] == Vector{Float64} @test (@code_typed(optimize = (false::Vector{Float64} .= 1 .+ round.(base = ::Int, ::Vector{Int}; digits = 3))))[2] == Vector{Float64} end begin @testset "`getindex`/`setindex!`" begin @test (@which((::Vector{Int})[::Int])).name === :getindex @test (@which(([1, 2])[::Int])).name === :getindex @test (@which(([1 2])[var"begin", ::Int])).name === :getindex @test (@which(([1 2])[::Int, var"end"])).name === :getindex @test (@which(([1 2])[var"begin", var"end"])).name === :getindex @test (@which(([1 2])[1:var"end"])).name === :getindex @test (@which(([1 2])[var"begin":var"end"])).name === :getindex @test_throws "`begin` or `end` cannot be used" @which((::Vector{Int})[var"begin"]) @test_throws "`begin` or `end` cannot be used" @which((::Vector{Int})[var"end"]) @test (@which((::Vector{Int})[::Int] = ::Int)).name === :setindex! end @testset "`getproperty`/`setproperty!`" begin @test (@which((::Base.RefValue{Int}).x)).name === :getproperty @test (@which((::Base.RefValue{Int}).x = ::Int)).name === :setproperty! end @testset "Array syntax" begin @test (@which([::Int])).name === :vect @test (@which([undef_var::Int])).name === :vect @test (@which([::Int 2])).name === :hcat @test (@which([::Int; 2])).name === :vcat @test (@which(Int[::Int 2])).name === :typed_hcat @test (@which(Int[::Int; 2])).name === :typed_vcat @test (@which([::Int 2; 3 ::Int])).name === :hvcat @test (@which(Int[::Int 2; 3 ::Int])).name === :typed_hvcat @test (@which(::Type{Int}[::Int 2; 3 ::Int])).name === :typed_hvcat @test (@which(::Type{T}[::T 2; 3 ::T] where T <: Real)).name === :typed_hvcat end @test (@which(::Float64 ^ 2)).name === :literal_pow @test (@which((::Vector{Float64})')).name === :adjoint @test (@which("$(::Symbol) is a symbol")).sig === Tuple{typeof(string), Vararg{Union{Char, String, Symbol}}} @test (@which(::Int ^ 4)).name === :literal_pow @test (@which(some_x::Int + some_y::Float64)).name === :+ @test (@which(+(::Any, ::Any, ::Any, ::Any...))).sig === Tuple{typeof(+), Any, Any, Any, Vararg{Any}} @test (@which(::Any + ::Any + ::Any + ::Vararg{Any})).sig === Tuple{typeof(+), Any, Any, Any, Vararg{Any}} n = length(@code_typed(::Float64 + ::Vararg{Float64})) @test n ≥ 2 @test length(@code_typed(+(::Float64, ::Float64...))) == n @test (@which(1 + ::Float64)).sig === Tuple{typeof(+), Number, Number} @test (@which(+(((1, 2)...)))).name === :+ @test (@which((::typeof(+))(::Int, ::Float64))).sig === Tuple{typeof(+), Number, Number} @test @code_typed(::Float64 .+ ::Vector{Float64}) isa Pair @test @code_typed(::Float64 .+ ::Vector{Float64} .* ::Int) isa Pair @test (@which((::T + ::T) where T <: Number)).sig === (Tuple{typeof(+), T, T} where T <: Number) @testset "Keyword arguments" begin @test (@which(round(::Float64; digits = 3))).name === :round @test (@which(round(1.2; digits = ::Int))).name === :round @test (@which(round(1.2; digits::Int))).name === :round @test (@code_typed(round(::T; digits = ::T) where T <: Float64))[2] === Union{} @test (@code_typed(round(::T; digits = ::T) where T <: Int))[2] === Float64 base = 10 kwargs_1 = (; digits = 3) kwargs_2 = (; sigdigits = 3) @test (@which(round(1.2; kwargs_1...))).name === :round @test (@which(round(1.2; digits = 1, kwargs_1...))).name === :round @test (@code_typed(round(1.2; digits = ::Float64, kwargs_1...)))[2] === Float64 @test (@code_typed(round(1.2; kwargs_1..., digits = ::Float64)))[2] === Union{} @test (@which(round(1.2; digits = ::Float64, kwargs_1...))).name === :round @test (@which(round(1.2; sigdigits = ::Int, kwargs_1...))).name === :round @test (@which(round(1.2; kwargs_1..., kwargs_2..., base))).name === :round end @testset "Broadcasting" begin @test (@code_typed(optimize = false, round.([1.0, 2.0]; digits = ::Int64)))[2] == Vector{Float64} @test (@code_typed(optimize = false, round.(::Vector{Float64}, base = 2; digits = ::Int64)))[2] == Vector{Float64} @test (@code_typed(optimize = false, round.(base = ::Int64, ::Vector{Float64}; digits = ::Int64)))[2] == Vector{Float64} @test (@code_typed(optimize = false, [1, 2] .= ::Int))[2] == Vector{Int} @test (@code_typed(optimize = false, ::Vector{Int} .= ::Int))[2] == Vector{Int} @test (@code_typed(optimize = false, ::Vector{Float64} .= 1 .+ ::Vector{Int}))[2] == Vector{Float64} @test (@code_typed(optimize = false, ::Vector{Float64} .= 1 .+ round.(base = ::Int, ::Vector{Int}; digits = 3)))[2] == Vector{Float64} end @testset "Callable objects" begin @test (@code_typed((::Base.Fix2{typeof(+), Float64})(3)))[2] === Float64 @test (@code_typed(optimize = false, (::Returns{Float64})(::Int64; name::String)))[2] === Float64 @test (@code_typed((::Returns{T})(3.0) where T <: Real))[2] === Real end @testset "Opaque closures" begin opaque_f(@nospecialize(x::Type), @nospecialize(y::Type)) = begin sizeof(x) == sizeof(y) end (src, _) = only(code_typed(opaque_f, (Type, Type))) src.slottypes[1] = Tuple{} oc = Core.OpaqueClosure(src; sig = Tuple{Type, Type}, rettype = Bool, nargs = 2) ret = @code_typed(oc(Int64, Float64)) @test [ret] == code_typed(oc) (_, rt) = ret @test rt === Bool ir = Core.Compiler.inflate_ir(src) oc = Core.OpaqueClosure(ir) ret = @code_typed(oc(Int64, Float64)) @test [ret] == code_typed(oc) (_, rt) = ret @test rt === Bool end @testset "Vararg handling" begin @test_throws "More than one `Core.Vararg`" @eval(@code_typed(1 + 2::Vararg{Int} + 3 + 4::Vararg{Float64})) @test_throws "Inconsistent type `Float64`" @eval(@code_typed(1 + 2 + 3 + 4::Vararg{Int} + 5.0)) @test_throws "Inconsistent type `Float64`" @eval(@code_typed(+(1, 2, 3, 4::Int..., 5.0))) @test_throws "Inconsistent type `Float64`" @eval(@code_typed(1 + 2 + 3 + 4::Vararg{Int} + ::Float64)) @test_throws "Inconsistent type `Any`" @eval(@code_typed(1 + 2 + 3 + 4::Vararg{Int} + ::Any)) @test_throws r"at most 2 types .* found 3 instead" @eval(@code_typed(1 + 2 + 3 + 4::Vararg{Int, 2} + 5 + 6)) @test (@code_typed(1 + 2 + 3 + 4::Vararg{Int}))[2] === Int @test (@code_typed(1 + 2 + 3 + 4::Vararg{Int} + 5))[2] === Int @test (@code_typed(1 + 2 + 3 + 4::Vararg{Int, 3}))[2] === Int @test (@code_typed(1 + 2 + 3 + 4::Vararg{Int, 3} + 5))[2] === Int @test (@code_typed(1 + 2 + 3 + 4::Vararg{Int, 3} + 5 + 6))[2] === Int @test (@code_typed(1 + 2 + 3 + 4::Vararg))[2] === Any @test (@code_typed(1 + 2 + 3 + 4::Vararg + 5.0))[2] === Any @test (@code_typed(+(1, 2, 3, ::Int...)))[2] === Int @test (@code_typed(+(1, 2, 3, ::Int..., 5)))[2] === Int @test @code_typed((::T + ::Vararg{T} + ::T) where T) isa Vector{Any} @test @code_typed((::T + ::Vararg{T} + ::Float64) where T <: Real) isa Vector{Any} @test @code_typed((::T + ::Vararg{T} + ::Float64) where T <: Real) isa Vector{Any} @test @code_typed((::T + ::Vararg{T} + ::Int) where T <: Real) isa Vector{Any} @test @code_typed((::T + ::Vararg{Vector{T}} + ::Int) where T <: Real) isa Vector{Any} @test @code_typed((::T + ::Vararg{Int} + ::T) where T <: Real) isa Vector{Any} end end begin @testset "`getindex`/`setindex!`" begin @test (@which((::Vector{Int})[::Int])).name === :getindex @test (@which(([1, 2])[::Int])).name === :getindex @test (@which(([1 2])[var"begin", ::Int])).name === :getindex @test (@which(([1 2])[::Int, var"end"])).name === :getindex @test (@which(([1 2])[var"begin", var"end"])).name === :getindex @test (@which(([1 2])[1:var"end"])).name === :getindex @test (@which(([1 2])[var"begin":var"end"])).name === :getindex @test_throws "`begin` or `end` cannot be used" @which((::Vector{Int})[var"begin"]) @test_throws "`begin` or `end` cannot be used" @which((::Vector{Int})[var"end"]) @test (@which((::Vector{Int})[::Int] = ::Int)).name === :setindex! end @testset "`getproperty`/`setproperty!`" begin @test (@which((::Base.RefValue{Int}).x)).name === :getproperty @test (@which((::Base.RefValue{Int}).x = ::Int)).name === :setproperty! end @testset "Array syntax" begin @test (@which([::Int])).name === :vect @test (@which([undef_var::Int])).name === :vect @test (@which([::Int 2])).name === :hcat @test (@which([::Int; 2])).name === :vcat @test (@which(Int[::Int 2])).name === :typed_hcat @test (@which(Int[::Int; 2])).name === :typed_vcat @test (@which([::Int 2; 3 ::Int])).name === :hvcat @test (@which(Int[::Int 2; 3 ::Int])).name === :typed_hvcat @test (@which(::Type{Int}[::Int 2; 3 ::Int])).name === :typed_hvcat @test (@which(::Type{T}[::T 2; 3 ::T] where T <: Real)).name === :typed_hvcat end @test (@which(::Float64 ^ 2)).name === :literal_pow @test (@which((::Vector{Float64})')).name === :adjoint @test (@which("$(::Symbol) is a symbol")).sig === Tuple{typeof(string), Vararg{Union{Char, String, Symbol}}} @test (@which(::Int ^ 4)).name === :literal_pow @test (@which(some_x::Int + some_y::Float64)).name === :+ @test (@which(+(::Any, ::Any, ::Any, ::Any...))).sig === Tuple{typeof(+), Any, Any, Any, Vararg{Any}} @test (@which(::Any + ::Any + ::Any + ::Vararg{Any})).sig === Tuple{typeof(+), Any, Any, Any, Vararg{Any}} n = length(@code_typed(::Float64 + ::Vararg{Float64})) @test n ≥ 2 @test length(@code_typed(+(::Float64, ::Float64...))) == n @test (@which(1 + ::Float64)).sig === Tuple{typeof(+), Number, Number} @test (@which(+(((1, 2)...)))).name === :+ @test (@which((::typeof(+))(::Int, ::Float64))).sig === Tuple{typeof(+), Number, Number} @test @code_typed(::Float64 .+ ::Vector{Float64}) isa Pair @test @code_typed(::Float64 .+ ::Vector{Float64} .* ::Int) isa Pair @test (@which((::T + ::T) where T <: Number)).sig === (Tuple{typeof(+), T, T} where T <: Number) @testset "Keyword arguments" begin @test (@which(round(::Float64; digits = 3))).name === :round @test (@which(round(1.2; digits = ::Int))).name === :round @test (@which(round(1.2; digits::Int))).name === :round @test (@code_typed(round(::T; digits = ::T) where T <: Float64))[2] === Union{} @test (@code_typed(round(::T; digits = ::T) where T <: Int))[2] === Float64 base = 10 kwargs_1 = (; digits = 3) kwargs_2 = (; sigdigits = 3) @test (@which(round(1.2; kwargs_1...))).name === :round @test (@which(round(1.2; digits = 1, kwargs_1...))).name === :round @test (@code_typed(round(1.2; digits = ::Float64, kwargs_1...)))[2] === Float64 @test (@code_typed(round(1.2; kwargs_1..., digits = ::Float64)))[2] === Union{} @test (@which(round(1.2; digits = ::Float64, kwargs_1...))).name === :round @test (@which(round(1.2; sigdigits = ::Int, kwargs_1...))).name === :round @test (@which(round(1.2; kwargs_1..., kwargs_2..., base))).name === :round end @testset "Broadcasting" begin @test (@code_typed(optimize = false, round.([1.0, 2.0]; digits = ::Int64)))[2] == Vector{Float64} @test (@code_typed(optimize = false, round.(::Vector{Float64}, base = 2; digits = ::Int64)))[2] == Vector{Float64} @test (@code_typed(optimize = false, round.(base = ::Int64, ::Vector{Float64}; digits = ::Int64)))[2] == Vector{Float64} @test (@code_typed(optimize = false, [1, 2] .= ::Int))[2] == Vector{Int} @test (@code_typed(optimize = (false::Vector{Int} .= ::Int)))[2] == Vector{Int} @test (@code_typed(optimize = (false::Vector{Float64} .= 1 .+ ::Vector{Int})))[2] == Vector{Float64} @test (@code_typed(optimize = (false::Vector{Float64} .= 1 .+ round.(base = ::Int, ::Vector{Int}; digits = 3))))[2] == Vector{Float64} end @testset "Callable objects" begin @test (@code_typed((::Base.Fix2{typeof(+), Float64})(3)))[2] === Float64 @test (@code_typed(optimize = false, (::Returns{Float64})(::Int64; name::String)))[2] === Float64 @test (@code_typed((::Returns{T})(3.0) where T <: Real))[2] === Real end @testset "Opaque closures" begin opaque_f(@nospecialize(x::Type), @nospecialize(y::Type)) = begin sizeof(x) == sizeof(y) end (src, _) = only(code_typed(opaque_f, (Type, Type))) src.slottypes[1] = Tuple{} oc = Core.OpaqueClosure(src; sig = Tuple{Type, Type}, rettype = Bool, nargs = 2) ret = @code_typed(oc(Int64, Float64)) @test [ret] == code_typed(oc) (_, rt) = ret @test rt === Bool ir = Core.Compiler.inflate_ir(src) oc = Core.OpaqueClosure(ir) ret = @code_typed(oc(Int64, Float64)) @test [ret] == code_typed(oc) (_, rt) = ret @test rt === Bool end @testset "Vararg handling" begin @test_throws "More than one `Core.Vararg`" @eval(@code_typed(1 + 2::Vararg{Int} + 3 + 4::Vararg{Float64})) @test_throws "Inconsistent type `Float64`" @eval(@code_typed(1 + 2 + 3 + 4::Vararg{Int} + 5.0)) @test_throws "Inconsistent type `Float64`" @eval(@code_typed(+(1, 2, 3, 4::Int..., 5.0))) @test_throws "Inconsistent type `Float64`" @eval(@code_typed(1 + 2 + 3 + 4::Vararg{Int} + ::Float64)) @test_throws "Inconsistent type `Any`" @eval(@code_typed(1 + 2 + 3 + 4::Vararg{Int} + ::Any)) @test_throws r"at most 2 types .* found 3 instead" @eval(@code_typed(1 + 2 + 3 + 4::Vararg{Int, 2} + 5 + 6)) @test (@code_typed(1 + 2 + 3 + 4::Vararg{Int}))[2] === Int @test (@code_typed(1 + 2 + 3 + 4::Vararg{Int} + 5))[2] === Int @test (@code_typed(1 + 2 + 3 + 4::Vararg{Int, 3}))[2] === Int @test (@code_typed(1 + 2 + 3 + 4::Vararg{Int, 3} + 5))[2] === Int @test (@code_typed(1 + 2 + 3 + 4::Vararg{Int, 3} + 5 + 6))[2] === Int @test (@code_typed(1 + 2 + 3 + 4::Vararg))[2] === Any @test (@code_typed(1 + 2 + 3 + 4::Vararg + 5.0))[2] === Any @test (@code_typed(+(1, 2, 3, ::Int...)))[2] === Int @test (@code_typed(+(1, 2, 3, ::Int..., 5)))[2] === Int @test @code_typed((::T + ::Vararg{T} + ::T) where T) isa Vector{Any} @test @code_typed((::T + ::Vararg{T} + ::Float64) where T <: Real) isa Vector{Any} @test @code_typed((::T + ::Vararg{T} + ::Float64) where T <: Real) isa Vector{Any} @test @code_typed((::T + ::Vararg{T} + ::Int) where T <: Real) isa Vector{Any} @test @code_typed((::T + ::Vararg{Vector{T}} + ::Int) where T <: Real) isa Vector{Any} @test @code_typed((::T + ::Vararg{Int} + ::T) where T <: Real) isa Vector{Any} end end @testset "Support for type annotations as arguments" begin @testset "`getindex`/`setindex!`" begin @test (@which((::Vector{Int})[::Int])).name === :getindex @test (@which(([1, 2])[::Int])).name === :getindex @test (@which(([1 2])[var"begin", ::Int])).name === :getindex @test (@which(([1 2])[::Int, var"end"])).name === :getindex @test (@which(([1 2])[var"begin", var"end"])).name === :getindex @test (@which(([1 2])[1:var"end"])).name === :getindex @test (@which(([1 2])[var"begin":var"end"])).name === :getindex @test_throws "`begin` or `end` cannot be used" @which((::Vector{Int})[var"begin"]) @test_throws "`begin` or `end` cannot be used" @which((::Vector{Int})[var"end"]) @test (@which((::Vector{Int})[::Int] = ::Int)).name === :setindex! end @testset "`getproperty`/`setproperty!`" begin @test (@which((::Base.RefValue{Int}).x)).name === :getproperty @test (@which((::Base.RefValue{Int}).x = ::Int)).name === :setproperty! end @testset "Array syntax" begin @test (@which([::Int])).name === :vect @test (@which([undef_var::Int])).name === :vect @test (@which([::Int 2])).name === :hcat @test (@which([::Int; 2])).name === :vcat @test (@which(Int[::Int 2])).name === :typed_hcat @test (@which(Int[::Int; 2])).name === :typed_vcat @test (@which([::Int 2; 3 ::Int])).name === :hvcat @test (@which(Int[::Int 2; 3 ::Int])).name === :typed_hvcat @test (@which(::Type{Int}[::Int 2; 3 ::Int])).name === :typed_hvcat @test (@which(::Type{T}[::T 2; 3 ::T] where T <: Real)).name === :typed_hvcat end @test (@which(::Float64 ^ 2)).name === :literal_pow @test (@which((::Vector{Float64})')).name === :adjoint @test (@which("$(::Symbol) is a symbol")).sig === Tuple{typeof(string), Vararg{Union{Char, String, Symbol}}} @test (@which(::Int ^ 4)).name === :literal_pow @test (@which(some_x::Int + some_y::Float64)).name === :+ @test (@which(+(::Any, ::Any, ::Any, ::Any...))).sig === Tuple{typeof(+), Any, Any, Any, Vararg{Any}} @test (@which(::Any + ::Any + ::Any + ::Vararg{Any})).sig === Tuple{typeof(+), Any, Any, Any, Vararg{Any}} n = length(@code_typed(::Float64 + ::Vararg{Float64})) @test n ≥ 2 @test length(@code_typed(+(::Float64, ::Float64...))) == n @test (@which(1 + ::Float64)).sig === Tuple{typeof(+), Number, Number} @test (@which(+(((1, 2)...)))).name === :+ @test (@which((::typeof(+))(::Int, ::Float64))).sig === Tuple{typeof(+), Number, Number} @test @code_typed(::Float64 .+ ::Vector{Float64}) isa Pair @test @code_typed(::Float64 .+ ::Vector{Float64} .* ::Int) isa Pair @test (@which((::T + ::T) where T <: Number)).sig === (Tuple{typeof(+), T, T} where T <: Number) @testset "Keyword arguments" begin @test (@which(round(::Float64; digits = 3))).name === :round @test (@which(round(1.2; digits = ::Int))).name === :round @test (@which(round(1.2; digits::Int))).name === :round @test (@code_typed(round(::T; digits = ::T) where T <: Float64))[2] === Union{} @test (@code_typed(round(::T; digits = ::T) where T <: Int))[2] === Float64 base = 10 kwargs_1 = (; digits = 3) kwargs_2 = (; sigdigits = 3) @test (@which(round(1.2; kwargs_1...))).name === :round @test (@which(round(1.2; digits = 1, kwargs_1...))).name === :round @test (@code_typed(round(1.2; digits = ::Float64, kwargs_1...)))[2] === Float64 @test (@code_typed(round(1.2; kwargs_1..., digits = ::Float64)))[2] === Union{} @test (@which(round(1.2; digits = ::Float64, kwargs_1...))).name === :round @test (@which(round(1.2; sigdigits = ::Int, kwargs_1...))).name === :round @test (@which(round(1.2; kwargs_1..., kwargs_2..., base))).name === :round end @testset "Broadcasting" begin @test (@code_typed(optimize = false, round.([1.0, 2.0]; digits = ::Int64)))[2] == Vector{Float64} @test (@code_typed(optimize = false, round.(::Vector{Float64}, base = 2; digits = ::Int64)))[2] == Vector{Float64} @test (@code_typed(optimize = false, round.(base = ::Int64, ::Vector{Float64}; digits = ::Int64)))[2] == Vector{Float64} @test (@code_typed(optimize = false, [1, 2] .= ::Int))[2] == Vector{Int} @test (@code_typed(optimize = false, ::Vector{Int} .= ::Int))[2] == Vector{Int} @test (@code_typed(optimize = false, ::Vector{Float64} .= 1 .+ ::Vector{Int}))[2] == Vector{Float64} @test (@code_typed(optimize = false, ::Vector{Float64} .= 1 .+ round.(base = ::Int, ::Vector{Int}; digits = 3)))[2] == Vector{Float64} end @testset "Callable objects" begin @test (@code_typed((::Base.Fix2{typeof(+), Float64})(3)))[2] === Float64 @test (@code_typed(optimize = false, (::Returns{Float64})(::Int64; name::String)))[2] === Float64 @test (@code_typed((::Returns{T})(3.0) where T <: Real))[2] === Real end @testset "Opaque closures" begin opaque_f(@nospecialize(x::Type), @nospecialize(y::Type)) = begin sizeof(x) == sizeof(y) end (src, _) = only(code_typed(opaque_f, (Type, Type))) src.slottypes[1] = Tuple{} oc = Core.OpaqueClosure(src; sig = Tuple{Type, Type}, rettype = Bool, nargs = 2) ret = @code_typed(oc(Int64, Float64)) @test [ret] == code_typed(oc) (_, rt) = ret @test rt === Bool ir = Core.Compiler.inflate_ir(src) oc = Core.OpaqueClosure(ir) ret = @code_typed(oc(Int64, Float64)) @test [ret] == code_typed(oc) (_, rt) = ret @test rt === Bool end @testset "Vararg handling" begin @test_throws "More than one `Core.Vararg`" @eval(@code_typed(1 + 2::Vararg{Int} + 3 + 4::Vararg{Float64})) @test_throws "Inconsistent type `Float64`" @eval(@code_typed(1 + 2 + 3 + 4::Vararg{Int} + 5.0)) @test_throws "Inconsistent type `Float64`" @eval(@code_typed(+(1, 2, 3, 4::Int..., 5.0))) @test_throws "Inconsistent type `Float64`" @eval(@code_typed(1 + 2 + 3 + 4::Vararg{Int} + ::Float64)) @test_throws "Inconsistent type `Any`" @eval(@code_typed(1 + 2 + 3 + 4::Vararg{Int} + ::Any)) @test_throws r"at most 2 types .* found 3 instead" @eval(@code_typed(1 + 2 + 3 + 4::Vararg{Int, 2} + 5 + 6)) @test (@code_typed(1 + 2 + 3 + 4::Vararg{Int}))[2] === Int @test (@code_typed(1 + 2 + 3 + 4::Vararg{Int} + 5))[2] === Int @test (@code_typed(1 + 2 + 3 + 4::Vararg{Int, 3}))[2] === Int @test (@code_typed(1 + 2 + 3 + 4::Vararg{Int, 3} + 5))[2] === Int @test (@code_typed(1 + 2 + 3 + 4::Vararg{Int, 3} + 5 + 6))[2] === Int @test (@code_typed(1 + 2 + 3 + 4::Vararg))[2] === Any @test (@code_typed(1 + 2 + 3 + 4::Vararg + 5.0))[2] === Any @test (@code_typed(+(1, 2, 3, ::Int...)))[2] === Int @test (@code_typed(+(1, 2, 3, ::Int..., 5)))[2] === Int @test @code_typed((::T + ::Vararg{T} + ::T) where T) isa Vector{Any} @test @code_typed((::T + ::Vararg{T} + ::Float64) where T <: Real) isa Vector{Any} @test @code_typed((::T + ::Vararg{T} + ::Float64) where T <: Real) isa Vector{Any} @test @code_typed((::T + ::Vararg{T} + ::Int) where T <: Real) isa Vector{Any} @test @code_typed((::T + ::Vararg{Vector{T}} + ::Int) where T <: Real) isa Vector{Any} @test @code_typed((::T + ::Vararg{Int} + ::T) where T <: Real) isa Vector{Any} end end @testset "Support for type annotations as arguments" begin @testset "`getindex`/`setindex!`" begin @test (@which((::Vector{Int})[::Int])).name === :getindex @test (@which(([1, 2])[::Int])).name === :getindex @test (@which(([1 2])[var"begin", ::Int])).name === :getindex @test (@which(([1 2])[::Int, var"end"])).name === :getindex @test (@which(([1 2])[var"begin", var"end"])).name === :getindex @test (@which(([1 2])[1:var"end"])).name === :getindex @test (@which(([1 2])[var"begin":var"end"])).name === :getindex @test_throws "`begin` or `end` cannot be used" @which((::Vector{Int})[var"begin"]) @test_throws "`begin` or `end` cannot be used" @which((::Vector{Int})[var"end"]) @test (@which((::Vector{Int})[::Int] = ::Int)).name === :setindex! end @testset "`getproperty`/`setproperty!`" begin @test (@which((::Base.RefValue{Int}).x)).name === :getproperty @test (@which((::Base.RefValue{Int}).x = ::Int)).name === :setproperty! end @testset "Array syntax" begin @test (@which([::Int])).name === :vect @test (@which([undef_var::Int])).name === :vect @test (@which([::Int 2])).name === :hcat @test (@which([::Int; 2])).name === :vcat @test (@which(Int[::Int 2])).name === :typed_hcat @test (@which(Int[::Int; 2])).name === :typed_vcat @test (@which([::Int 2; 3 ::Int])).name === :hvcat @test (@which(Int[::Int 2; 3 ::Int])).name === :typed_hvcat @test (@which(::Type{Int}[::Int 2; 3 ::Int])).name === :typed_hvcat @test (@which(::Type{T}[::T 2; 3 ::T] where T <: Real)).name === :typed_hvcat end @test (@which(::Float64 ^ 2)).name === :literal_pow @test (@which((::Vector{Float64})')).name === :adjoint @test (@which("$(::Symbol) is a symbol")).sig === Tuple{typeof(string), Vararg{Union{Char, String, Symbol}}} @test (@which(::Int ^ 4)).name === :literal_pow @test (@which(some_x::Int + some_y::Float64)).name === :+ @test (@which(+(::Any, ::Any, ::Any, ::Any...))).sig === Tuple{typeof(+), Any, Any, Any, Vararg{Any}} @test (@which(::Any + ::Any + ::Any + ::Vararg{Any})).sig === Tuple{typeof(+), Any, Any, Any, Vararg{Any}} n = length(@code_typed(::Float64 + ::Vararg{Float64})) @test n ≥ 2 @test length(@code_typed(+(::Float64, ::Float64...))) == n @test (@which(1 + ::Float64)).sig === Tuple{typeof(+), Number, Number} @test (@which(+(((1, 2)...)))).name === :+ @test (@which((::typeof(+))(::Int, ::Float64))).sig === Tuple{typeof(+), Number, Number} @test @code_typed(::Float64 .+ ::Vector{Float64}) isa Pair @test @code_typed(::Float64 .+ ::Vector{Float64} .* ::Int) isa Pair @test (@which((::T + ::T) where T <: Number)).sig === (Tuple{typeof(+), T, T} where T <: Number) @testset "Keyword arguments" begin @test (@which(round(::Float64; digits = 3))).name === :round @test (@which(round(1.2; digits = ::Int))).name === :round @test (@which(round(1.2; digits::Int))).name === :round @test (@code_typed(round(::T; digits = ::T) where T <: Float64))[2] === Union{} @test (@code_typed(round(::T; digits = ::T) where T <: Int))[2] === Float64 base = 10 kwargs_1 = (; digits = 3) kwargs_2 = (; sigdigits = 3) @test (@which(round(1.2; kwargs_1...))).name === :round @test (@which(round(1.2; digits = 1, kwargs_1...))).name === :round @test (@code_typed(round(1.2; digits = ::Float64, kwargs_1...)))[2] === Float64 @test (@code_typed(round(1.2; kwargs_1..., digits = ::Float64)))[2] === Union{} @test (@which(round(1.2; digits = ::Float64, kwargs_1...))).name === :round @test (@which(round(1.2; sigdigits = ::Int, kwargs_1...))).name === :round @test (@which(round(1.2; kwargs_1..., kwargs_2..., base))).name === :round end @testset "Broadcasting" begin @test (@code_typed(optimize = false, round.([1.0, 2.0]; digits = ::Int64)))[2] == Vector{Float64} @test (@code_typed(optimize = false, round.(::Vector{Float64}, base = 2; digits = ::Int64)))[2] == Vector{Float64} @test (@code_typed(optimize = false, round.(base = ::Int64, ::Vector{Float64}; digits = ::Int64)))[2] == Vector{Float64} @test (@code_typed(optimize = false, [1, 2] .= ::Int))[2] == Vector{Int} @test (@code_typed(optimize = (false::Vector{Int} .= ::Int)))[2] == Vector{Int} @test (@code_typed(optimize = (false::Vector{Float64} .= 1 .+ ::Vector{Int})))[2] == Vector{Float64} @test (@code_typed(optimize = (false::Vector{Float64} .= 1 .+ round.(base = ::Int, ::Vector{Int}; digits = 3))))[2] == Vector{Float64} end @testset "Callable objects" begin @test (@code_typed((::Base.Fix2{typeof(+), Float64})(3)))[2] === Float64 @test (@code_typed(optimize = false, (::Returns{Float64})(::Int64; name::String)))[2] === Float64 @test (@code_typed((::Returns{T})(3.0) where T <: Real))[2] === Real end @testset "Opaque closures" begin opaque_f(@nospecialize(x::Type), @nospecialize(y::Type)) = begin sizeof(x) == sizeof(y) end (src, _) = only(code_typed(opaque_f, (Type, Type))) src.slottypes[1] = Tuple{} oc = Core.OpaqueClosure(src; sig = Tuple{Type, Type}, rettype = Bool, nargs = 2) ret = @code_typed(oc(Int64, Float64)) @test [ret] == code_typed(oc) (_, rt) = ret @test rt === Bool ir = Core.Compiler.inflate_ir(src) oc = Core.OpaqueClosure(ir) ret = @code_typed(oc(Int64, Float64)) @test [ret] == code_typed(oc) (_, rt) = ret @test rt === Bool end @testset "Vararg handling" begin @test_throws "More than one `Core.Vararg`" @eval(@code_typed(1 + 2::Vararg{Int} + 3 + 4::Vararg{Float64})) @test_throws "Inconsistent type `Float64`" @eval(@code_typed(1 + 2 + 3 + 4::Vararg{Int} + 5.0)) @test_throws "Inconsistent type `Float64`" @eval(@code_typed(+(1, 2, 3, 4::Int..., 5.0))) @test_throws "Inconsistent type `Float64`" @eval(@code_typed(1 + 2 + 3 + 4::Vararg{Int} + ::Float64)) @test_throws "Inconsistent type `Any`" @eval(@code_typed(1 + 2 + 3 + 4::Vararg{Int} + ::Any)) @test_throws r"at most 2 types .* found 3 instead" @eval(@code_typed(1 + 2 + 3 + 4::Vararg{Int, 2} + 5 + 6)) @test (@code_typed(1 + 2 + 3 + 4::Vararg{Int}))[2] === Int @test (@code_typed(1 + 2 + 3 + 4::Vararg{Int} + 5))[2] === Int @test (@code_typed(1 + 2 + 3 + 4::Vararg{Int, 3}))[2] === Int @test (@code_typed(1 + 2 + 3 + 4::Vararg{Int, 3} + 5))[2] === Int @test (@code_typed(1 + 2 + 3 + 4::Vararg{Int, 3} + 5 + 6))[2] === Int @test (@code_typed(1 + 2 + 3 + 4::Vararg))[2] === Any @test (@code_typed(1 + 2 + 3 + 4::Vararg + 5.0))[2] === Any @test (@code_typed(+(1, 2, 3, ::Int...)))[2] === Int @test (@code_typed(+(1, 2, 3, ::Int..., 5)))[2] === Int @test @code_typed((::T + ::Vararg{T} + ::T) where T) isa Vector{Any} @test @code_typed((::T + ::Vararg{T} + ::Float64) where T <: Real) isa Vector{Any} @test @code_typed((::T + ::Vararg{T} + ::Float64) where T <: Real) isa Vector{Any} @test @code_typed((::T + ::Vararg{T} + ::Int) where T <: Real) isa Vector{Any} @test @code_typed((::T + ::Vararg{Vector{T}} + ::Int) where T <: Real) isa Vector{Any} @test @code_typed((::T + ::Vararg{Int} + ::T) where T <: Real) isa Vector{Any} end end Parsing files in Base: Test Failed at /home/pkgeval/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:166 Expression: false Stacktrace: [1] macro expansion @ /opt/julia/share/julia/stdlib/v1.14/Test/src/Test.jl:782 [inlined] [2] top-level scope @ ~/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:166 ┌ Error: parsing difference │ file = "/opt/julia/bin/../share/julia/stdlib/v1.14/Printf/test/runtests.jl" └ @ Main.var"##302" ~/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:157 Printf.@sprintf "%a" 1.5 Printf.@sprintf "%a" 1.5 Printf.@sprintf("%a", 1.5) == "0x1.8p+0" Printf.@sprintf("%a", 1.5) == "0x1.8p+0" @test Printf.@sprintf("%a", 1.5) == "0x1.8p+0" @test Printf.@sprintf("%a", 1.5) == "0x1.8p+0" begin @test Printf.@sprintf("%a", 0.0) == "0x0p+0" @test Printf.@sprintf("%a", -0.0) == "-0x0p+0" @test Printf.@sprintf("%.3a", 0.0) == "0x0.000p+0" @test Printf.@sprintf("%a", 1.5) == "0x1.8p+0" @test Printf.@sprintf("%a", 1.5f0) == "0x1.8p+0" @test Printf.@sprintf("%a", 1.5) == "0x1.8p+0" @test Printf.@sprintf("%#.0a", 1.5) == "0x2.p+0" @test Printf.@sprintf("%+30a", 1 / 3) == " +0x1.5555555555555p-2" @test Printf.@sprintf("%a", 1.5) == "0x1.8p+0" @test Printf.@sprintf("%a", 3.14) == "0x1.91eb851eb851fp+1" @test Printf.@sprintf("%.0a", 3.14) == "0x2p+1" @test Printf.@sprintf("%.1a", 3.14) == "0x1.9p+1" @test Printf.@sprintf("%.2a", 3.14) == "0x1.92p+1" @test Printf.@sprintf("%#a", 3.14) == "0x1.91eb851eb851fp+1" @test Printf.@sprintf("%#.0a", 3.14) == "0x2.p+1" @test Printf.@sprintf("%#.1a", 3.14) == "0x1.9p+1" @test Printf.@sprintf("%#.2a", 3.14) == "0x1.92p+1" @test Printf.@sprintf("%.6a", 1.5) == "0x1.800000p+0" end begin @test Printf.@sprintf("%a", 0.0) == "0x0p+0" @test Printf.@sprintf("%a", -0.0) == "-0x0p+0" @test Printf.@sprintf("%.3a", 0.0) == "0x0.000p+0" @test Printf.@sprintf("%a", 1.5) == "0x1.8p+0" @test Printf.@sprintf("%a", 1.5f0) == "0x1.8p+0" @test Printf.@sprintf("%a", 1.5) == "0x1.8p+0" @test Printf.@sprintf("%#.0a", 1.5) == "0x2.p+0" @test Printf.@sprintf("%+30a", 1 / 3) == " +0x1.5555555555555p-2" @test Printf.@sprintf("%a", 1.5) == "0x1.8p+0" @test Printf.@sprintf("%a", 3.14) == "0x1.91eb851eb851fp+1" @test Printf.@sprintf("%.0a", 3.14) == "0x2p+1" @test Printf.@sprintf("%.1a", 3.14) == "0x1.9p+1" @test Printf.@sprintf("%.2a", 3.14) == "0x1.92p+1" @test Printf.@sprintf("%#a", 3.14) == "0x1.91eb851eb851fp+1" @test Printf.@sprintf("%#.0a", 3.14) == "0x2.p+1" @test Printf.@sprintf("%#.1a", 3.14) == "0x1.9p+1" @test Printf.@sprintf("%#.2a", 3.14) == "0x1.92p+1" @test Printf.@sprintf("%.6a", 1.5) == "0x1.800000p+0" end @testset "%a" begin @test Printf.@sprintf("%a", 0.0) == "0x0p+0" @test Printf.@sprintf("%a", -0.0) == "-0x0p+0" @test Printf.@sprintf("%.3a", 0.0) == "0x0.000p+0" @test Printf.@sprintf("%a", 1.5) == "0x1.8p+0" @test Printf.@sprintf("%a", 1.5f0) == "0x1.8p+0" @test Printf.@sprintf("%a", 1.5) == "0x1.8p+0" @test Printf.@sprintf("%#.0a", 1.5) == "0x2.p+0" @test Printf.@sprintf("%+30a", 1 / 3) == " +0x1.5555555555555p-2" @test Printf.@sprintf("%a", 1.5) == "0x1.8p+0" @test Printf.@sprintf("%a", 3.14) == "0x1.91eb851eb851fp+1" @test Printf.@sprintf("%.0a", 3.14) == "0x2p+1" @test Printf.@sprintf("%.1a", 3.14) == "0x1.9p+1" @test Printf.@sprintf("%.2a", 3.14) == "0x1.92p+1" @test Printf.@sprintf("%#a", 3.14) == "0x1.91eb851eb851fp+1" @test Printf.@sprintf("%#.0a", 3.14) == "0x2.p+1" @test Printf.@sprintf("%#.1a", 3.14) == "0x1.9p+1" @test Printf.@sprintf("%#.2a", 3.14) == "0x1.92p+1" @test Printf.@sprintf("%.6a", 1.5) == "0x1.800000p+0" end @testset "%a" begin @test Printf.@sprintf("%a", 0.0) == "0x0p+0" @test Printf.@sprintf("%a", -0.0) == "-0x0p+0" @test Printf.@sprintf("%.3a", 0.0) == "0x0.000p+0" @test Printf.@sprintf("%a", 1.5) == "0x1.8p+0" @test Printf.@sprintf("%a", 1.5f0) == "0x1.8p+0" @test Printf.@sprintf("%a", 1.5) == "0x1.8p+0" @test Printf.@sprintf("%#.0a", 1.5) == "0x2.p+0" @test Printf.@sprintf("%+30a", 1 / 3) == " +0x1.5555555555555p-2" @test Printf.@sprintf("%a", 1.5) == "0x1.8p+0" @test Printf.@sprintf("%a", 3.14) == "0x1.91eb851eb851fp+1" @test Printf.@sprintf("%.0a", 3.14) == "0x2p+1" @test Printf.@sprintf("%.1a", 3.14) == "0x1.9p+1" @test Printf.@sprintf("%.2a", 3.14) == "0x1.92p+1" @test Printf.@sprintf("%#a", 3.14) == "0x1.91eb851eb851fp+1" @test Printf.@sprintf("%#.0a", 3.14) == "0x2.p+1" @test Printf.@sprintf("%#.1a", 3.14) == "0x1.9p+1" @test Printf.@sprintf("%#.2a", 3.14) == "0x1.92p+1" @test Printf.@sprintf("%.6a", 1.5) == "0x1.800000p+0" end (1.2345678e7, "1.23457e+07") (1.2345678e7, "1.23457e+07") (1.234567799999999999999999999999999999999999999999999999999999999999999999999993e6, "1.23457e+06") (1.234567799999999999999999999999999999999999999999999999999999999999999999999993e6, "1.23457e+06") (123456.7800000000000000000000000000000000000000000000000000000000000000000000004, "123457") (123456.7800000000000000000000000000000000000000000000000000000000000000000000004, "123457") (12345.67800000000000000000000000000000000000000000000000000000000000000000000007, "12345.7") (12345.67800000000000000000000000000000000000000000000000000000000000000000000007, "12345.7") ((1.2345678e7, "1.23457e+07"), (1.234567799999999999999999999999999999999999999999999999999999999999999999999993e6, "1.23457e+06"), (123456.7800000000000000000000000000000000000000000000000000000000000000000000004, "123457"), (12345.67800000000000000000000000000000000000000000000000000000000000000000000007, "12345.7")) ((1.2345678e7, "1.23457e+07"), (1.234567799999999999999999999999999999999999999999999999999999999999999999999993e6, "1.23457e+06"), (123456.7800000000000000000000000000000000000000000000000000000000000000000000004, "123457"), (12345.67800000000000000000000000000000000000000000000000000000000000000000000007, "12345.7")) (val, res) = ((1.2345678e7, "1.23457e+07"), (1.234567799999999999999999999999999999999999999999999999999999999999999999999993e6, "1.23457e+06"), (123456.7800000000000000000000000000000000000000000000000000000000000000000000004, "123457"), (12345.67800000000000000000000000000000000000000000000000000000000000000000000007, "12345.7")) (val, res) = ((1.2345678e7, "1.23457e+07"), (1.234567799999999999999999999999999999999999999999999999999999999999999999999993e6, "1.23457e+06"), (123456.7800000000000000000000000000000000000000000000000000000000000000000000004, "123457"), (12345.67800000000000000000000000000000000000000000000000000000000000000000000007, "12345.7")) for (val, res) = ((1.2345678e7, "1.23457e+07"), (1.234567799999999999999999999999999999999999999999999999999999999999999999999993e6, "1.23457e+06"), (123456.7800000000000000000000000000000000000000000000000000000000000000000000004, "123457"), (12345.67800000000000000000000000000000000000000000000000000000000000000000000007, "12345.7")) @test Printf.@sprintf("%.6g", val) == res end for (val, res) = ((1.2345678e7, "1.23457e+07"), (1.234567799999999999999999999999999999999999999999999999999999999999999999999993e6, "1.23457e+06"), (123456.7800000000000000000000000000000000000000000000000000000000000000000000004, "123457"), (12345.67800000000000000000000000000000000000000000000000000000000000000000000007, "12345.7")) @test Printf.@sprintf("%.6g", val) == res end (123.4, 123.4000000000000000000000000000000000000000000000000000000000000000000000000002) (123.4, 123.4000000000000000000000000000000000000000000000000000000000000000000000000002) num = (123.4, 123.4000000000000000000000000000000000000000000000000000000000000000000000000002) num = (123.4, 123.4000000000000000000000000000000000000000000000000000000000000000000000000002) begin (fmt, val) = (("%10.5g", " 123.4"), ("%+10.5g", " +123.4"), ("% 10.5g", " 123.4"), ("%#10.5g", " 123.40"), ("%-10.5g", "123.4 "), ("%-+10.5g", "+123.4 "), ("%010.5g", "00000123.4")) num = (123.4, 123.4000000000000000000000000000000000000000000000000000000000000000000000000002) end begin (fmt, val) = (("%10.5g", " 123.4"), ("%+10.5g", " +123.4"), ("% 10.5g", " 123.4"), ("%#10.5g", " 123.40"), ("%-10.5g", "123.4 "), ("%-+10.5g", "+123.4 "), ("%010.5g", "00000123.4")) num = (123.4, 123.4000000000000000000000000000000000000000000000000000000000000000000000000002) end for (fmt, val) = (("%10.5g", " 123.4"), ("%+10.5g", " +123.4"), ("% 10.5g", " 123.4"), ("%#10.5g", " 123.40"), ("%-10.5g", "123.4 "), ("%-+10.5g", "+123.4 "), ("%010.5g", "00000123.4")), num = (123.4, 123.4000000000000000000000000000000000000000000000000000000000000000000000000002) @test Printf.format(Printf.Format(fmt), num) == val end for (fmt, val) = (("%10.5g", " 123.4"), ("%+10.5g", " +123.4"), ("% 10.5g", " 123.4"), ("%#10.5g", " 123.40"), ("%-10.5g", "123.4 "), ("%-+10.5g", "+123.4 "), ("%010.5g", "00000123.4")), num = (123.4, 123.4000000000000000000000000000000000000000000000000000000000000000000000000002) @test Printf.format(Printf.Format(fmt), num) == val end Printf.@sprintf "%10.5g" -123.4000000000000000000000000000000000000000000000000000000000000000000000000002 Printf.@sprintf "%10.5g" -123.4000000000000000000000000000000000000000000000000000000000000000000000000002 Printf.@sprintf("%10.5g", -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) == " -123.4" Printf.@sprintf("%10.5g", -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) == " -123.4" @test Printf.@sprintf("%10.5g", -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) == " -123.4" @test Printf.@sprintf("%10.5g", -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) == " -123.4" Printf.@sprintf "%010.5g" -123.4000000000000000000000000000000000000000000000000000000000000000000000000002 Printf.@sprintf "%010.5g" -123.4000000000000000000000000000000000000000000000000000000000000000000000000002 Printf.@sprintf("%010.5g", -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) == "-0000123.4" Printf.@sprintf("%010.5g", -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) == "-0000123.4" @test Printf.@sprintf("%010.5g", -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) == "-0000123.4" @test Printf.@sprintf("%010.5g", -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) == "-0000123.4" Printf.@sprintf "%.6g" 1.234e7 Printf.@sprintf "%.6g" 1.234e7 Printf.@sprintf("%.6g", 1.234e7) == "1.234e+07" Printf.@sprintf("%.6g", 1.234e7) == "1.234e+07" @test Printf.@sprintf("%.6g", 1.234e7) == "1.234e+07" @test Printf.@sprintf("%.6g", 1.234e7) == "1.234e+07" Printf.@sprintf "%#.6g" 1.234e7 Printf.@sprintf "%#.6g" 1.234e7 Printf.@sprintf("%#.6g", 1.234e7) == "1.23400e+07" Printf.@sprintf("%#.6g", 1.234e7) == "1.23400e+07" @test Printf.@sprintf("%#.6g", 1.234e7) == "1.23400e+07" @test Printf.@sprintf("%#.6g", 1.234e7) == "1.23400e+07" begin for (val, res) = ((1.2345678e7, "1.23457e+07"), (1.2345678e6, "1.23457e+06"), (123456.78, "123457"), (12345.678, "12345.7"), (1.234e7, "1.234e+07")) @test Printf.@sprintf("%.6g", val) == res end for (val, res) = ((1.2345678e7, "1.23457e+07"), (1.234567799999999999999999999999999999999999999999999999999999999999999999999993e6, "1.23457e+06"), (123456.7800000000000000000000000000000000000000000000000000000000000000000000004, "123457"), (12345.67800000000000000000000000000000000000000000000000000000000000000000000007, "12345.7")) @test Printf.@sprintf("%.6g", val) == res end for (fmt, val) = (("%10.5g", " 123.4"), ("%+10.5g", " +123.4"), ("% 10.5g", " 123.4"), ("%#10.5g", " 123.40"), ("%-10.5g", "123.4 "), ("%-+10.5g", "+123.4 "), ("%010.5g", "00000123.4")), num = (123.4, 123.4000000000000000000000000000000000000000000000000000000000000000000000000002) @test Printf.format(Printf.Format(fmt), num) == val end @test Printf.@sprintf("%10.5g", -123.4) == " -123.4" @test Printf.@sprintf("%010.5g", -123.4) == "-0000123.4" @test Printf.@sprintf("%.6g", 1.234e7) == "1.234e+07" @test Printf.@sprintf("%#.6g", 1.234e7) == "1.23400e+07" @test Printf.@sprintf("%10.5g", -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) == " -123.4" @test Printf.@sprintf("%010.5g", -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) == "-0000123.4" @test Printf.@sprintf("%.6g", 1.234e7) == "1.234e+07" @test Printf.@sprintf("%#.6g", 1.234e7) == "1.23400e+07" @test Printf.@sprintf("%.5g", 42) == "42" @test Printf.@sprintf("%#.2g", 42) == "42." @test Printf.@sprintf("%#.5g", 42) == "42.000" @test Printf.@sprintf("%g", 0.00012) == "0.00012" @test Printf.@sprintf("%g", 1.2e-5) == "1.2e-05" @test Printf.@sprintf("%g", 123456.7) == "123457" @test Printf.@sprintf("%g", 1.2345678e6) == "1.23457e+06" for (val, res) = ((Inf, "Inf"), (-Inf, "-Inf"), (NaN, "NaN"), (-NaN, "NaN")) @test Printf.@sprintf("%g", val) == res @test Printf.@sprintf("%G", val) == res end @test Printf.@sprintf("%.15g", 0) == "0" @test Printf.@sprintf("%#.15g", 0) == "0.00000000000000" end begin for (val, res) = ((1.2345678e7, "1.23457e+07"), (1.2345678e6, "1.23457e+06"), (123456.78, "123457"), (12345.678, "12345.7"), (1.234e7, "1.234e+07")) @test Printf.@sprintf("%.6g", val) == res end for (val, res) = ((1.2345678e7, "1.23457e+07"), (1.234567799999999999999999999999999999999999999999999999999999999999999999999993e6, "1.23457e+06"), (123456.7800000000000000000000000000000000000000000000000000000000000000000000004, "123457"), (12345.67800000000000000000000000000000000000000000000000000000000000000000000007, "12345.7")) @test Printf.@sprintf("%.6g", val) == res end for (fmt, val) = (("%10.5g", " 123.4"), ("%+10.5g", " +123.4"), ("% 10.5g", " 123.4"), ("%#10.5g", " 123.40"), ("%-10.5g", "123.4 "), ("%-+10.5g", "+123.4 "), ("%010.5g", "00000123.4")), num = (123.4, 123.4000000000000000000000000000000000000000000000000000000000000000000000000002) @test Printf.format(Printf.Format(fmt), num) == val end @test Printf.@sprintf("%10.5g", -123.4) == " -123.4" @test Printf.@sprintf("%010.5g", -123.4) == "-0000123.4" @test Printf.@sprintf("%.6g", 1.234e7) == "1.234e+07" @test Printf.@sprintf("%#.6g", 1.234e7) == "1.23400e+07" @test Printf.@sprintf("%10.5g", -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) == " -123.4" @test Printf.@sprintf("%010.5g", -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) == "-0000123.4" @test Printf.@sprintf("%.6g", 1.234e7) == "1.234e+07" @test Printf.@sprintf("%#.6g", 1.234e7) == "1.23400e+07" @test Printf.@sprintf("%.5g", 42) == "42" @test Printf.@sprintf("%#.2g", 42) == "42." @test Printf.@sprintf("%#.5g", 42) == "42.000" @test Printf.@sprintf("%g", 0.00012) == "0.00012" @test Printf.@sprintf("%g", 1.2e-5) == "1.2e-05" @test Printf.@sprintf("%g", 123456.7) == "123457" @test Printf.@sprintf("%g", 1.2345678e6) == "1.23457e+06" for (val, res) = ((Inf, "Inf"), (-Inf, "-Inf"), (NaN, "NaN"), (-NaN, "NaN")) @test Printf.@sprintf("%g", val) == res @test Printf.@sprintf("%G", val) == res end @test Printf.@sprintf("%.15g", 0) == "0" @test Printf.@sprintf("%#.15g", 0) == "0.00000000000000" end @testset "%g" begin for (val, res) = ((1.2345678e7, "1.23457e+07"), (1.2345678e6, "1.23457e+06"), (123456.78, "123457"), (12345.678, "12345.7"), (1.234e7, "1.234e+07")) @test Printf.@sprintf("%.6g", val) == res end for (val, res) = ((1.2345678e7, "1.23457e+07"), (1.234567799999999999999999999999999999999999999999999999999999999999999999999993e6, "1.23457e+06"), (123456.7800000000000000000000000000000000000000000000000000000000000000000000004, "123457"), (12345.67800000000000000000000000000000000000000000000000000000000000000000000007, "12345.7")) @test Printf.@sprintf("%.6g", val) == res end for (fmt, val) = (("%10.5g", " 123.4"), ("%+10.5g", " +123.4"), ("% 10.5g", " 123.4"), ("%#10.5g", " 123.40"), ("%-10.5g", "123.4 "), ("%-+10.5g", "+123.4 "), ("%010.5g", "00000123.4")), num = (123.4, 123.4000000000000000000000000000000000000000000000000000000000000000000000000002) @test Printf.format(Printf.Format(fmt), num) == val end @test Printf.@sprintf("%10.5g", -123.4) == " -123.4" @test Printf.@sprintf("%010.5g", -123.4) == "-0000123.4" @test Printf.@sprintf("%.6g", 1.234e7) == "1.234e+07" @test Printf.@sprintf("%#.6g", 1.234e7) == "1.23400e+07" @test Printf.@sprintf("%10.5g", -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) == " -123.4" @test Printf.@sprintf("%010.5g", -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) == "-0000123.4" @test Printf.@sprintf("%.6g", 1.234e7) == "1.234e+07" @test Printf.@sprintf("%#.6g", 1.234e7) == "1.23400e+07" @test Printf.@sprintf("%.5g", 42) == "42" @test Printf.@sprintf("%#.2g", 42) == "42." @test Printf.@sprintf("%#.5g", 42) == "42.000" @test Printf.@sprintf("%g", 0.00012) == "0.00012" @test Printf.@sprintf("%g", 1.2e-5) == "1.2e-05" @test Printf.@sprintf("%g", 123456.7) == "123457" @test Printf.@sprintf("%g", 1.2345678e6) == "1.23457e+06" for (val, res) = ((Inf, "Inf"), (-Inf, "-Inf"), (NaN, "NaN"), (-NaN, "NaN")) @test Printf.@sprintf("%g", val) == res @test Printf.@sprintf("%G", val) == res end @test Printf.@sprintf("%.15g", 0) == "0" @test Printf.@sprintf("%#.15g", 0) == "0.00000000000000" end @testset "%g" begin for (val, res) = ((1.2345678e7, "1.23457e+07"), (1.2345678e6, "1.23457e+06"), (123456.78, "123457"), (12345.678, "12345.7"), (1.234e7, "1.234e+07")) @test Printf.@sprintf("%.6g", val) == res end for (val, res) = ((1.2345678e7, "1.23457e+07"), (1.234567799999999999999999999999999999999999999999999999999999999999999999999993e6, "1.23457e+06"), (123456.7800000000000000000000000000000000000000000000000000000000000000000000004, "123457"), (12345.67800000000000000000000000000000000000000000000000000000000000000000000007, "12345.7")) @test Printf.@sprintf("%.6g", val) == res end for (fmt, val) = (("%10.5g", " 123.4"), ("%+10.5g", " +123.4"), ("% 10.5g", " 123.4"), ("%#10.5g", " 123.40"), ("%-10.5g", "123.4 "), ("%-+10.5g", "+123.4 "), ("%010.5g", "00000123.4")), num = (123.4, 123.4000000000000000000000000000000000000000000000000000000000000000000000000002) @test Printf.format(Printf.Format(fmt), num) == val end @test Printf.@sprintf("%10.5g", -123.4) == " -123.4" @test Printf.@sprintf("%010.5g", -123.4) == "-0000123.4" @test Printf.@sprintf("%.6g", 1.234e7) == "1.234e+07" @test Printf.@sprintf("%#.6g", 1.234e7) == "1.23400e+07" @test Printf.@sprintf("%10.5g", -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) == " -123.4" @test Printf.@sprintf("%010.5g", -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) == "-0000123.4" @test Printf.@sprintf("%.6g", 1.234e7) == "1.234e+07" @test Printf.@sprintf("%#.6g", 1.234e7) == "1.23400e+07" @test Printf.@sprintf("%.5g", 42) == "42" @test Printf.@sprintf("%#.2g", 42) == "42." @test Printf.@sprintf("%#.5g", 42) == "42.000" @test Printf.@sprintf("%g", 0.00012) == "0.00012" @test Printf.@sprintf("%g", 1.2e-5) == "1.2e-05" @test Printf.@sprintf("%g", 123456.7) == "123457" @test Printf.@sprintf("%g", 1.2345678e6) == "1.23457e+06" for (val, res) = ((Inf, "Inf"), (-Inf, "-Inf"), (NaN, "NaN"), (-NaN, "NaN")) @test Printf.@sprintf("%g", val) == res @test Printf.@sprintf("%G", val) == res end @test Printf.@sprintf("%.15g", 0) == "0" @test Printf.@sprintf("%#.15g", 0) == "0.00000000000000" end Printf.@sprintf "%e" Inf Printf.@sprintf "%e" Inf Printf.@sprintf("%e", Inf) == "Inf" Printf.@sprintf("%e", Inf) == "Inf" @test Printf.@sprintf("%e", Inf) == "Inf" @test Printf.@sprintf("%e", Inf) == "Inf" begin @test Printf.@sprintf("%f", Inf) == "Inf" @test Printf.@sprintf("%+f", Inf) == "+Inf" @test Printf.@sprintf("% f", Inf) == " Inf" @test Printf.@sprintf("% #f", Inf) == " Inf" @test Printf.@sprintf("%07f", Inf) == " Inf" @test Printf.@sprintf("%f", -Inf) == "-Inf" @test Printf.@sprintf("%+f", -Inf) == "-Inf" @test Printf.@sprintf("%07f", -Inf) == " -Inf" @test Printf.@sprintf("%f", NaN) == "NaN" @test Printf.@sprintf("%+f", NaN) == "+NaN" @test Printf.@sprintf("% f", NaN) == " NaN" @test Printf.@sprintf("% #f", NaN) == " NaN" @test Printf.@sprintf("%07f", NaN) == " NaN" @test Printf.@sprintf("%e", Inf) == "Inf" @test Printf.@sprintf("%e", NaN) == "NaN" @test Printf.@sprintf("%.0f", 3.0e142) == "29999999999999997463140672961703247153805615792184250659629251954072073858354858644285983761764971823910371920726635399393477049701891710124032" @test Printf.@sprintf("%f", 1.234) == "1.234000" @test Printf.@sprintf("%F", 1.234) == "1.234000" @test Printf.@sprintf("%+f", 1.234) == "+1.234000" @test Printf.@sprintf("% f", 1.234) == " 1.234000" @test Printf.@sprintf("%f", -1.234) == "-1.234000" @test Printf.@sprintf("%+f", -1.234) == "-1.234000" @test Printf.@sprintf("% f", -1.234) == "-1.234000" @test Printf.@sprintf("%#f", 1.234) == "1.234000" @test Printf.@sprintf("%.2f", 1.234) == "1.23" @test Printf.@sprintf("%.2f", 1.235) == "1.24" @test Printf.@sprintf("%.2f", 0.235) == "0.23" @test Printf.@sprintf("%4.1f", 1.234) == " 1.2" @test Printf.@sprintf("%8.1f", 1.234) == " 1.2" @test Printf.@sprintf("%+8.1f", 1.234) == " +1.2" @test Printf.@sprintf("% 8.1f", 1.234) == " 1.2" @test Printf.@sprintf("% 7.1f", 1.234) == " 1.2" @test Printf.@sprintf("% 08.1f", 1.234) == " 00001.2" @test Printf.@sprintf("%08.1f", 1.234) == "000001.2" @test Printf.@sprintf("%-08.1f", 1.234) == "1.2 " @test Printf.@sprintf("%-8.1f", 1.234) == "1.2 " @test Printf.@sprintf("%08.1f", -1.234) == "-00001.2" @test Printf.@sprintf("%09.1f", -1.234) == "-000001.2" @test Printf.@sprintf("%09.1f", 1.234) == "0000001.2" @test Printf.@sprintf("%+09.1f", 1.234) == "+000001.2" @test Printf.@sprintf("% 09.1f", 1.234) == " 000001.2" @test Printf.@sprintf("%+ 09.1f", 1.234) == "+000001.2" @test Printf.@sprintf("%+ 09.1f", 1.234) == "+000001.2" @test Printf.@sprintf("%+ 09.0f", 1.234) == "+00000001" @test Printf.@sprintf("%+ #09.0f", 1.234) == "+0000001." @test Printf.@sprintf("%+7.1f", 9.96) == " +10.0" @test Printf.@sprintf("% 7.1f", 9.96) == " 10.0" end begin @test Printf.@sprintf("%f", Inf) == "Inf" @test Printf.@sprintf("%+f", Inf) == "+Inf" @test Printf.@sprintf("% f", Inf) == " Inf" @test Printf.@sprintf("% #f", Inf) == " Inf" @test Printf.@sprintf("%07f", Inf) == " Inf" @test Printf.@sprintf("%f", -Inf) == "-Inf" @test Printf.@sprintf("%+f", -Inf) == "-Inf" @test Printf.@sprintf("%07f", -Inf) == " -Inf" @test Printf.@sprintf("%f", NaN) == "NaN" @test Printf.@sprintf("%+f", NaN) == "+NaN" @test Printf.@sprintf("% f", NaN) == " NaN" @test Printf.@sprintf("% #f", NaN) == " NaN" @test Printf.@sprintf("%07f", NaN) == " NaN" @test Printf.@sprintf("%e", Inf) == "Inf" @test Printf.@sprintf("%e", NaN) == "NaN" @test Printf.@sprintf("%.0f", 3.0e142) == "29999999999999997463140672961703247153805615792184250659629251954072073858354858644285983761764971823910371920726635399393477049701891710124032" @test Printf.@sprintf("%f", 1.234) == "1.234000" @test Printf.@sprintf("%F", 1.234) == "1.234000" @test Printf.@sprintf("%+f", 1.234) == "+1.234000" @test Printf.@sprintf("% f", 1.234) == " 1.234000" @test Printf.@sprintf("%f", -1.234) == "-1.234000" @test Printf.@sprintf("%+f", -1.234) == "-1.234000" @test Printf.@sprintf("% f", -1.234) == "-1.234000" @test Printf.@sprintf("%#f", 1.234) == "1.234000" @test Printf.@sprintf("%.2f", 1.234) == "1.23" @test Printf.@sprintf("%.2f", 1.235) == "1.24" @test Printf.@sprintf("%.2f", 0.235) == "0.23" @test Printf.@sprintf("%4.1f", 1.234) == " 1.2" @test Printf.@sprintf("%8.1f", 1.234) == " 1.2" @test Printf.@sprintf("%+8.1f", 1.234) == " +1.2" @test Printf.@sprintf("% 8.1f", 1.234) == " 1.2" @test Printf.@sprintf("% 7.1f", 1.234) == " 1.2" @test Printf.@sprintf("% 08.1f", 1.234) == " 00001.2" @test Printf.@sprintf("%08.1f", 1.234) == "000001.2" @test Printf.@sprintf("%-08.1f", 1.234) == "1.2 " @test Printf.@sprintf("%-8.1f", 1.234) == "1.2 " @test Printf.@sprintf("%08.1f", -1.234) == "-00001.2" @test Printf.@sprintf("%09.1f", -1.234) == "-000001.2" @test Printf.@sprintf("%09.1f", 1.234) == "0000001.2" @test Printf.@sprintf("%+09.1f", 1.234) == "+000001.2" @test Printf.@sprintf("% 09.1f", 1.234) == " 000001.2" @test Printf.@sprintf("%+ 09.1f", 1.234) == "+000001.2" @test Printf.@sprintf("%+ 09.1f", 1.234) == "+000001.2" @test Printf.@sprintf("%+ 09.0f", 1.234) == "+00000001" @test Printf.@sprintf("%+ #09.0f", 1.234) == "+0000001." @test Printf.@sprintf("%+7.1f", 9.96) == " +10.0" @test Printf.@sprintf("% 7.1f", 9.96) == " 10.0" end @testset "%f" begin @test Printf.@sprintf("%f", Inf) == "Inf" @test Printf.@sprintf("%+f", Inf) == "+Inf" @test Printf.@sprintf("% f", Inf) == " Inf" @test Printf.@sprintf("% #f", Inf) == " Inf" @test Printf.@sprintf("%07f", Inf) == " Inf" @test Printf.@sprintf("%f", -Inf) == "-Inf" @test Printf.@sprintf("%+f", -Inf) == "-Inf" @test Printf.@sprintf("%07f", -Inf) == " -Inf" @test Printf.@sprintf("%f", NaN) == "NaN" @test Printf.@sprintf("%+f", NaN) == "+NaN" @test Printf.@sprintf("% f", NaN) == " NaN" @test Printf.@sprintf("% #f", NaN) == " NaN" @test Printf.@sprintf("%07f", NaN) == " NaN" @test Printf.@sprintf("%e", Inf) == "Inf" @test Printf.@sprintf("%e", NaN) == "NaN" @test Printf.@sprintf("%.0f", 3.0e142) == "29999999999999997463140672961703247153805615792184250659629251954072073858354858644285983761764971823910371920726635399393477049701891710124032" @test Printf.@sprintf("%f", 1.234) == "1.234000" @test Printf.@sprintf("%F", 1.234) == "1.234000" @test Printf.@sprintf("%+f", 1.234) == "+1.234000" @test Printf.@sprintf("% f", 1.234) == " 1.234000" @test Printf.@sprintf("%f", -1.234) == "-1.234000" @test Printf.@sprintf("%+f", -1.234) == "-1.234000" @test Printf.@sprintf("% f", -1.234) == "-1.234000" @test Printf.@sprintf("%#f", 1.234) == "1.234000" @test Printf.@sprintf("%.2f", 1.234) == "1.23" @test Printf.@sprintf("%.2f", 1.235) == "1.24" @test Printf.@sprintf("%.2f", 0.235) == "0.23" @test Printf.@sprintf("%4.1f", 1.234) == " 1.2" @test Printf.@sprintf("%8.1f", 1.234) == " 1.2" @test Printf.@sprintf("%+8.1f", 1.234) == " +1.2" @test Printf.@sprintf("% 8.1f", 1.234) == " 1.2" @test Printf.@sprintf("% 7.1f", 1.234) == " 1.2" @test Printf.@sprintf("% 08.1f", 1.234) == " 00001.2" @test Printf.@sprintf("%08.1f", 1.234) == "000001.2" @test Printf.@sprintf("%-08.1f", 1.234) == "1.2 " @test Printf.@sprintf("%-8.1f", 1.234) == "1.2 " @test Printf.@sprintf("%08.1f", -1.234) == "-00001.2" @test Printf.@sprintf("%09.1f", -1.234) == "-000001.2" @test Printf.@sprintf("%09.1f", 1.234) == "0000001.2" @test Printf.@sprintf("%+09.1f", 1.234) == "+000001.2" @test Printf.@sprintf("% 09.1f", 1.234) == " 000001.2" @test Printf.@sprintf("%+ 09.1f", 1.234) == "+000001.2" @test Printf.@sprintf("%+ 09.1f", 1.234) == "+000001.2" @test Printf.@sprintf("%+ 09.0f", 1.234) == "+00000001" @test Printf.@sprintf("%+ #09.0f", 1.234) == "+0000001." @test Printf.@sprintf("%+7.1f", 9.96) == " +10.0" @test Printf.@sprintf("% 7.1f", 9.96) == " 10.0" end @testset "%f" begin @test Printf.@sprintf("%f", Inf) == "Inf" @test Printf.@sprintf("%+f", Inf) == "+Inf" @test Printf.@sprintf("% f", Inf) == " Inf" @test Printf.@sprintf("% #f", Inf) == " Inf" @test Printf.@sprintf("%07f", Inf) == " Inf" @test Printf.@sprintf("%f", -Inf) == "-Inf" @test Printf.@sprintf("%+f", -Inf) == "-Inf" @test Printf.@sprintf("%07f", -Inf) == " -Inf" @test Printf.@sprintf("%f", NaN) == "NaN" @test Printf.@sprintf("%+f", NaN) == "+NaN" @test Printf.@sprintf("% f", NaN) == " NaN" @test Printf.@sprintf("% #f", NaN) == " NaN" @test Printf.@sprintf("%07f", NaN) == " NaN" @test Printf.@sprintf("%e", Inf) == "Inf" @test Printf.@sprintf("%e", NaN) == "NaN" @test Printf.@sprintf("%.0f", 3.0e142) == "29999999999999997463140672961703247153805615792184250659629251954072073858354858644285983761764971823910371920726635399393477049701891710124032" @test Printf.@sprintf("%f", 1.234) == "1.234000" @test Printf.@sprintf("%F", 1.234) == "1.234000" @test Printf.@sprintf("%+f", 1.234) == "+1.234000" @test Printf.@sprintf("% f", 1.234) == " 1.234000" @test Printf.@sprintf("%f", -1.234) == "-1.234000" @test Printf.@sprintf("%+f", -1.234) == "-1.234000" @test Printf.@sprintf("% f", -1.234) == "-1.234000" @test Printf.@sprintf("%#f", 1.234) == "1.234000" @test Printf.@sprintf("%.2f", 1.234) == "1.23" @test Printf.@sprintf("%.2f", 1.235) == "1.24" @test Printf.@sprintf("%.2f", 0.235) == "0.23" @test Printf.@sprintf("%4.1f", 1.234) == " 1.2" @test Printf.@sprintf("%8.1f", 1.234) == " 1.2" @test Printf.@sprintf("%+8.1f", 1.234) == " +1.2" @test Printf.@sprintf("% 8.1f", 1.234) == " 1.2" @test Printf.@sprintf("% 7.1f", 1.234) == " 1.2" @test Printf.@sprintf("% 08.1f", 1.234) == " 00001.2" @test Printf.@sprintf("%08.1f", 1.234) == "000001.2" @test Printf.@sprintf("%-08.1f", 1.234) == "1.2 " @test Printf.@sprintf("%-8.1f", 1.234) == "1.2 " @test Printf.@sprintf("%08.1f", -1.234) == "-00001.2" @test Printf.@sprintf("%09.1f", -1.234) == "-000001.2" @test Printf.@sprintf("%09.1f", 1.234) == "0000001.2" @test Printf.@sprintf("%+09.1f", 1.234) == "+000001.2" @test Printf.@sprintf("% 09.1f", 1.234) == " 000001.2" @test Printf.@sprintf("%+ 09.1f", 1.234) == "+000001.2" @test Printf.@sprintf("%+ 09.1f", 1.234) == "+000001.2" @test Printf.@sprintf("%+ 09.0f", 1.234) == "+00000001" @test Printf.@sprintf("%+ #09.0f", 1.234) == "+0000001." @test Printf.@sprintf("%+7.1f", 9.96) == " +10.0" @test Printf.@sprintf("% 7.1f", 9.96) == " 10.0" end Printf.@sprintf "%e" Inf Printf.@sprintf "%e" Inf Printf.@sprintf("%e", Inf) == "Inf" Printf.@sprintf("%e", Inf) == "Inf" @test Printf.@sprintf("%e", Inf) == "Inf" @test Printf.@sprintf("%e", Inf) == "Inf" Printf.@sprintf "%.0e" 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142 Printf.@sprintf "%.0e" 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142 Printf.@sprintf("%.0e", 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) == "3e+142" Printf.@sprintf("%.0e", 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) == "3e+142" @test Printf.@sprintf("%.0e", 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) == "3e+142" @test Printf.@sprintf("%.0e", 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) == "3e+142" Printf.@sprintf "%#.0e" 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142 Printf.@sprintf "%#.0e" 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142 Printf.@sprintf("%#.0e", 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) == "3.e+142" Printf.@sprintf("%#.0e", 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) == "3.e+142" @test Printf.@sprintf("%#.0e", 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) == "3.e+142" @test Printf.@sprintf("%#.0e", 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) == "3.e+142" Printf.@sprintf "%.0e" 3.000000000000000000000000000000000000000000000000000000000000000000000000000024e1042 Printf.@sprintf "%.0e" 3.000000000000000000000000000000000000000000000000000000000000000000000000000024e1042 Printf.@sprintf("%.0e", 3.000000000000000000000000000000000000000000000000000000000000000000000000000024e1042) == "3e+1042" Printf.@sprintf("%.0e", 3.000000000000000000000000000000000000000000000000000000000000000000000000000024e1042) == "3e+1042" @test Printf.@sprintf("%.0e", 3.000000000000000000000000000000000000000000000000000000000000000000000000000024e1042) == "3e+1042" @test Printf.@sprintf("%.0e", 3.000000000000000000000000000000000000000000000000000000000000000000000000000024e1042) == "3e+1042" begin @test Printf.@sprintf("%e", Inf) == "Inf" @test Printf.@sprintf("%+e", Inf) == "+Inf" @test Printf.@sprintf("% e", Inf) == " Inf" @test Printf.@sprintf("% #e", Inf) == " Inf" @test Printf.@sprintf("%07e", Inf) == " Inf" @test Printf.@sprintf("%e", -Inf) == "-Inf" @test Printf.@sprintf("%+e", -Inf) == "-Inf" @test Printf.@sprintf("%07e", -Inf) == " -Inf" @test Printf.@sprintf("%e", NaN) == "NaN" @test Printf.@sprintf("%+e", NaN) == "+NaN" @test Printf.@sprintf("% e", NaN) == " NaN" @test Printf.@sprintf("% #e", NaN) == " NaN" @test Printf.@sprintf("%07e", NaN) == " NaN" @test Printf.@sprintf("%e", Inf) == "Inf" @test Printf.@sprintf("%e", NaN) == "NaN" @test Printf.@sprintf("%.0e", 3.0e142) == "3e+142" @test Printf.@sprintf("%#.0e", 3.0e142) == "3.e+142" @test Printf.@sprintf("%.0e", 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) == "3e+142" @test Printf.@sprintf("%#.0e", 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) == "3.e+142" @test Printf.@sprintf("%.0e", 3.000000000000000000000000000000000000000000000000000000000000000000000000000024e1042) == "3e+1042" @test Printf.@sprintf("%e", 3.0e42) == "3.000000e+42" @test Printf.@sprintf("%E", 3.0e42) == "3.000000E+42" @test Printf.@sprintf("%e", 3.0e-42) == "3.000000e-42" @test Printf.@sprintf("%E", 3.0e-42) == "3.000000E-42" @test Printf.@sprintf("%e", 1.234) == "1.234000e+00" @test Printf.@sprintf("%E", 1.234) == "1.234000E+00" @test Printf.@sprintf("%+e", 1.234) == "+1.234000e+00" @test Printf.@sprintf("% e", 1.234) == " 1.234000e+00" @test Printf.@sprintf("%e", -1.234) == "-1.234000e+00" @test Printf.@sprintf("%+e", -1.234) == "-1.234000e+00" @test Printf.@sprintf("% e", -1.234) == "-1.234000e+00" @test Printf.@sprintf("%#e", 1.234) == "1.234000e+00" @test Printf.@sprintf("%.2e", 1.234) == "1.23e+00" @test Printf.@sprintf("%.2e", 1.235) == "1.24e+00" @test Printf.@sprintf("%.2e", 0.235) == "2.35e-01" @test Printf.@sprintf("%4.1e", 1.234) == "1.2e+00" @test Printf.@sprintf("%8.1e", 1.234) == " 1.2e+00" @test Printf.@sprintf("%+8.1e", 1.234) == "+1.2e+00" @test Printf.@sprintf("% 8.1e", 1.234) == " 1.2e+00" @test Printf.@sprintf("% 7.1e", 1.234) == " 1.2e+00" @test Printf.@sprintf("% 08.1e", 1.234) == " 1.2e+00" @test Printf.@sprintf("%08.1e", 1.234) == "01.2e+00" @test Printf.@sprintf("%-08.1e", 1.234) == "1.2e+00 " @test Printf.@sprintf("%-8.1e", 1.234) == "1.2e+00 " @test Printf.@sprintf("%-8.1e", 1.234) == "1.2e+00 " @test Printf.@sprintf("%08.1e", -1.234) == "-1.2e+00" @test Printf.@sprintf("%09.1e", -1.234) == "-01.2e+00" @test Printf.@sprintf("%09.1e", 1.234) == "001.2e+00" @test Printf.@sprintf("%+09.1e", 1.234) == "+01.2e+00" @test Printf.@sprintf("% 09.1e", 1.234) == " 01.2e+00" @test Printf.@sprintf("%+ 09.1e", 1.234) == "+01.2e+00" @test Printf.@sprintf("%+ 09.1e", 1.234) == "+01.2e+00" @test Printf.@sprintf("%+ 09.0e", 1.234) == "+0001e+00" @test Printf.@sprintf("%+ #09.0e", 1.234) == "+001.e+00" @test Printf.@sprintf("%+9.1e", 9.96) == " +1.0e+01" @test Printf.@sprintf("% 9.1e", 9.96) == " 1.0e+01" end begin @test Printf.@sprintf("%e", Inf) == "Inf" @test Printf.@sprintf("%+e", Inf) == "+Inf" @test Printf.@sprintf("% e", Inf) == " Inf" @test Printf.@sprintf("% #e", Inf) == " Inf" @test Printf.@sprintf("%07e", Inf) == " Inf" @test Printf.@sprintf("%e", -Inf) == "-Inf" @test Printf.@sprintf("%+e", -Inf) == "-Inf" @test Printf.@sprintf("%07e", -Inf) == " -Inf" @test Printf.@sprintf("%e", NaN) == "NaN" @test Printf.@sprintf("%+e", NaN) == "+NaN" @test Printf.@sprintf("% e", NaN) == " NaN" @test Printf.@sprintf("% #e", NaN) == " NaN" @test Printf.@sprintf("%07e", NaN) == " NaN" @test Printf.@sprintf("%e", Inf) == "Inf" @test Printf.@sprintf("%e", NaN) == "NaN" @test Printf.@sprintf("%.0e", 3.0e142) == "3e+142" @test Printf.@sprintf("%#.0e", 3.0e142) == "3.e+142" @test Printf.@sprintf("%.0e", 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) == "3e+142" @test Printf.@sprintf("%#.0e", 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) == "3.e+142" @test Printf.@sprintf("%.0e", 3.000000000000000000000000000000000000000000000000000000000000000000000000000024e1042) == "3e+1042" @test Printf.@sprintf("%e", 3.0e42) == "3.000000e+42" @test Printf.@sprintf("%E", 3.0e42) == "3.000000E+42" @test Printf.@sprintf("%e", 3.0e-42) == "3.000000e-42" @test Printf.@sprintf("%E", 3.0e-42) == "3.000000E-42" @test Printf.@sprintf("%e", 1.234) == "1.234000e+00" @test Printf.@sprintf("%E", 1.234) == "1.234000E+00" @test Printf.@sprintf("%+e", 1.234) == "+1.234000e+00" @test Printf.@sprintf("% e", 1.234) == " 1.234000e+00" @test Printf.@sprintf("%e", -1.234) == "-1.234000e+00" @test Printf.@sprintf("%+e", -1.234) == "-1.234000e+00" @test Printf.@sprintf("% e", -1.234) == "-1.234000e+00" @test Printf.@sprintf("%#e", 1.234) == "1.234000e+00" @test Printf.@sprintf("%.2e", 1.234) == "1.23e+00" @test Printf.@sprintf("%.2e", 1.235) == "1.24e+00" @test Printf.@sprintf("%.2e", 0.235) == "2.35e-01" @test Printf.@sprintf("%4.1e", 1.234) == "1.2e+00" @test Printf.@sprintf("%8.1e", 1.234) == " 1.2e+00" @test Printf.@sprintf("%+8.1e", 1.234) == "+1.2e+00" @test Printf.@sprintf("% 8.1e", 1.234) == " 1.2e+00" @test Printf.@sprintf("% 7.1e", 1.234) == " 1.2e+00" @test Printf.@sprintf("% 08.1e", 1.234) == " 1.2e+00" @test Printf.@sprintf("%08.1e", 1.234) == "01.2e+00" @test Printf.@sprintf("%-08.1e", 1.234) == "1.2e+00 " @test Printf.@sprintf("%-8.1e", 1.234) == "1.2e+00 " @test Printf.@sprintf("%-8.1e", 1.234) == "1.2e+00 " @test Printf.@sprintf("%08.1e", -1.234) == "-1.2e+00" @test Printf.@sprintf("%09.1e", -1.234) == "-01.2e+00" @test Printf.@sprintf("%09.1e", 1.234) == "001.2e+00" @test Printf.@sprintf("%+09.1e", 1.234) == "+01.2e+00" @test Printf.@sprintf("% 09.1e", 1.234) == " 01.2e+00" @test Printf.@sprintf("%+ 09.1e", 1.234) == "+01.2e+00" @test Printf.@sprintf("%+ 09.1e", 1.234) == "+01.2e+00" @test Printf.@sprintf("%+ 09.0e", 1.234) == "+0001e+00" @test Printf.@sprintf("%+ #09.0e", 1.234) == "+001.e+00" @test Printf.@sprintf("%+9.1e", 9.96) == " +1.0e+01" @test Printf.@sprintf("% 9.1e", 9.96) == " 1.0e+01" end @testset "%e" begin @test Printf.@sprintf("%e", Inf) == "Inf" @test Printf.@sprintf("%+e", Inf) == "+Inf" @test Printf.@sprintf("% e", Inf) == " Inf" @test Printf.@sprintf("% #e", Inf) == " Inf" @test Printf.@sprintf("%07e", Inf) == " Inf" @test Printf.@sprintf("%e", -Inf) == "-Inf" @test Printf.@sprintf("%+e", -Inf) == "-Inf" @test Printf.@sprintf("%07e", -Inf) == " -Inf" @test Printf.@sprintf("%e", NaN) == "NaN" @test Printf.@sprintf("%+e", NaN) == "+NaN" @test Printf.@sprintf("% e", NaN) == " NaN" @test Printf.@sprintf("% #e", NaN) == " NaN" @test Printf.@sprintf("%07e", NaN) == " NaN" @test Printf.@sprintf("%e", Inf) == "Inf" @test Printf.@sprintf("%e", NaN) == "NaN" @test Printf.@sprintf("%.0e", 3.0e142) == "3e+142" @test Printf.@sprintf("%#.0e", 3.0e142) == "3.e+142" @test Printf.@sprintf("%.0e", 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) == "3e+142" @test Printf.@sprintf("%#.0e", 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) == "3.e+142" @test Printf.@sprintf("%.0e", 3.000000000000000000000000000000000000000000000000000000000000000000000000000024e1042) == "3e+1042" @test Printf.@sprintf("%e", 3.0e42) == "3.000000e+42" @test Printf.@sprintf("%E", 3.0e42) == "3.000000E+42" @test Printf.@sprintf("%e", 3.0e-42) == "3.000000e-42" @test Printf.@sprintf("%E", 3.0e-42) == "3.000000E-42" @test Printf.@sprintf("%e", 1.234) == "1.234000e+00" @test Printf.@sprintf("%E", 1.234) == "1.234000E+00" @test Printf.@sprintf("%+e", 1.234) == "+1.234000e+00" @test Printf.@sprintf("% e", 1.234) == " 1.234000e+00" @test Printf.@sprintf("%e", -1.234) == "-1.234000e+00" @test Printf.@sprintf("%+e", -1.234) == "-1.234000e+00" @test Printf.@sprintf("% e", -1.234) == "-1.234000e+00" @test Printf.@sprintf("%#e", 1.234) == "1.234000e+00" @test Printf.@sprintf("%.2e", 1.234) == "1.23e+00" @test Printf.@sprintf("%.2e", 1.235) == "1.24e+00" @test Printf.@sprintf("%.2e", 0.235) == "2.35e-01" @test Printf.@sprintf("%4.1e", 1.234) == "1.2e+00" @test Printf.@sprintf("%8.1e", 1.234) == " 1.2e+00" @test Printf.@sprintf("%+8.1e", 1.234) == "+1.2e+00" @test Printf.@sprintf("% 8.1e", 1.234) == " 1.2e+00" @test Printf.@sprintf("% 7.1e", 1.234) == " 1.2e+00" @test Printf.@sprintf("% 08.1e", 1.234) == " 1.2e+00" @test Printf.@sprintf("%08.1e", 1.234) == "01.2e+00" @test Printf.@sprintf("%-08.1e", 1.234) == "1.2e+00 " @test Printf.@sprintf("%-8.1e", 1.234) == "1.2e+00 " @test Printf.@sprintf("%-8.1e", 1.234) == "1.2e+00 " @test Printf.@sprintf("%08.1e", -1.234) == "-1.2e+00" @test Printf.@sprintf("%09.1e", -1.234) == "-01.2e+00" @test Printf.@sprintf("%09.1e", 1.234) == "001.2e+00" @test Printf.@sprintf("%+09.1e", 1.234) == "+01.2e+00" @test Printf.@sprintf("% 09.1e", 1.234) == " 01.2e+00" @test Printf.@sprintf("%+ 09.1e", 1.234) == "+01.2e+00" @test Printf.@sprintf("%+ 09.1e", 1.234) == "+01.2e+00" @test Printf.@sprintf("%+ 09.0e", 1.234) == "+0001e+00" @test Printf.@sprintf("%+ #09.0e", 1.234) == "+001.e+00" @test Printf.@sprintf("%+9.1e", 9.96) == " +1.0e+01" @test Printf.@sprintf("% 9.1e", 9.96) == " 1.0e+01" end @testset "%e" begin @test Printf.@sprintf("%e", Inf) == "Inf" @test Printf.@sprintf("%+e", Inf) == "+Inf" @test Printf.@sprintf("% e", Inf) == " Inf" @test Printf.@sprintf("% #e", Inf) == " Inf" @test Printf.@sprintf("%07e", Inf) == " Inf" @test Printf.@sprintf("%e", -Inf) == "-Inf" @test Printf.@sprintf("%+e", -Inf) == "-Inf" @test Printf.@sprintf("%07e", -Inf) == " -Inf" @test Printf.@sprintf("%e", NaN) == "NaN" @test Printf.@sprintf("%+e", NaN) == "+NaN" @test Printf.@sprintf("% e", NaN) == " NaN" @test Printf.@sprintf("% #e", NaN) == " NaN" @test Printf.@sprintf("%07e", NaN) == " NaN" @test Printf.@sprintf("%e", Inf) == "Inf" @test Printf.@sprintf("%e", NaN) == "NaN" @test Printf.@sprintf("%.0e", 3.0e142) == "3e+142" @test Printf.@sprintf("%#.0e", 3.0e142) == "3.e+142" @test Printf.@sprintf("%.0e", 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) == "3e+142" @test Printf.@sprintf("%#.0e", 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) == "3.e+142" @test Printf.@sprintf("%.0e", 3.000000000000000000000000000000000000000000000000000000000000000000000000000024e1042) == "3e+1042" @test Printf.@sprintf("%e", 3.0e42) == "3.000000e+42" @test Printf.@sprintf("%E", 3.0e42) == "3.000000E+42" @test Printf.@sprintf("%e", 3.0e-42) == "3.000000e-42" @test Printf.@sprintf("%E", 3.0e-42) == "3.000000E-42" @test Printf.@sprintf("%e", 1.234) == "1.234000e+00" @test Printf.@sprintf("%E", 1.234) == "1.234000E+00" @test Printf.@sprintf("%+e", 1.234) == "+1.234000e+00" @test Printf.@sprintf("% e", 1.234) == " 1.234000e+00" @test Printf.@sprintf("%e", -1.234) == "-1.234000e+00" @test Printf.@sprintf("%+e", -1.234) == "-1.234000e+00" @test Printf.@sprintf("% e", -1.234) == "-1.234000e+00" @test Printf.@sprintf("%#e", 1.234) == "1.234000e+00" @test Printf.@sprintf("%.2e", 1.234) == "1.23e+00" @test Printf.@sprintf("%.2e", 1.235) == "1.24e+00" @test Printf.@sprintf("%.2e", 0.235) == "2.35e-01" @test Printf.@sprintf("%4.1e", 1.234) == "1.2e+00" @test Printf.@sprintf("%8.1e", 1.234) == " 1.2e+00" @test Printf.@sprintf("%+8.1e", 1.234) == "+1.2e+00" @test Printf.@sprintf("% 8.1e", 1.234) == " 1.2e+00" @test Printf.@sprintf("% 7.1e", 1.234) == " 1.2e+00" @test Printf.@sprintf("% 08.1e", 1.234) == " 1.2e+00" @test Printf.@sprintf("%08.1e", 1.234) == "01.2e+00" @test Printf.@sprintf("%-08.1e", 1.234) == "1.2e+00 " @test Printf.@sprintf("%-8.1e", 1.234) == "1.2e+00 " @test Printf.@sprintf("%-8.1e", 1.234) == "1.2e+00 " @test Printf.@sprintf("%08.1e", -1.234) == "-1.2e+00" @test Printf.@sprintf("%09.1e", -1.234) == "-01.2e+00" @test Printf.@sprintf("%09.1e", 1.234) == "001.2e+00" @test Printf.@sprintf("%+09.1e", 1.234) == "+01.2e+00" @test Printf.@sprintf("% 09.1e", 1.234) == " 01.2e+00" @test Printf.@sprintf("%+ 09.1e", 1.234) == "+01.2e+00" @test Printf.@sprintf("%+ 09.1e", 1.234) == "+01.2e+00" @test Printf.@sprintf("%+ 09.0e", 1.234) == "+0001e+00" @test Printf.@sprintf("%+ #09.0e", 1.234) == "+001.e+00" @test Printf.@sprintf("%+9.1e", 9.96) == " +1.0e+01" @test Printf.@sprintf("% 9.1e", 9.96) == " 1.0e+01" end (1.2345, 1.234499999999999999999999999999999999999999999999999999999999999999999999999991) (1.2345, 1.234499999999999999999999999999999999999999999999999999999999999999999999999991) num = (1.2345, 1.234499999999999999999999999999999999999999999999999999999999999999999999999991) num = (1.2345, 1.234499999999999999999999999999999999999999999999999999999999999999999999999991) begin (fmt, val) = (("%7.2f", " 1.23"), ("%-7.2f", "1.23 "), ("%07.2f", "0001.23"), ("%.0f", "1"), ("%#.0f", "1."), ("%.4e", "1.2345e+00"), ("%.4E", "1.2345E+00"), ("%.2a", "0x1.3cp+0"), ("%.2A", "0X1.3CP+0")) num = (1.2345, 1.234499999999999999999999999999999999999999999999999999999999999999999999999991) end begin (fmt, val) = (("%7.2f", " 1.23"), ("%-7.2f", "1.23 "), ("%07.2f", "0001.23"), ("%.0f", "1"), ("%#.0f", "1."), ("%.4e", "1.2345e+00"), ("%.4E", "1.2345E+00"), ("%.2a", "0x1.3cp+0"), ("%.2A", "0X1.3CP+0")) num = (1.2345, 1.234499999999999999999999999999999999999999999999999999999999999999999999999991) end for (fmt, val) = (("%7.2f", " 1.23"), ("%-7.2f", "1.23 "), ("%07.2f", "0001.23"), ("%.0f", "1"), ("%#.0f", "1."), ("%.4e", "1.2345e+00"), ("%.4E", "1.2345E+00"), ("%.2a", "0x1.3cp+0"), ("%.2A", "0X1.3CP+0")), num = (1.2345, 1.234499999999999999999999999999999999999999999999999999999999999999999999999991) @test Printf.format(Printf.Format(fmt), num) == val end for (fmt, val) = (("%7.2f", " 1.23"), ("%-7.2f", "1.23 "), ("%07.2f", "0001.23"), ("%.0f", "1"), ("%#.0f", "1."), ("%.4e", "1.2345e+00"), ("%.4E", "1.2345E+00"), ("%.2a", "0x1.3cp+0"), ("%.2A", "0X1.3CP+0")), num = (1.2345, 1.234499999999999999999999999999999999999999999999999999999999999999999999999991) @test Printf.format(Printf.Format(fmt), num) == val end (UInt16(42), UInt32(42), UInt64(42), UInt128(42), Int16(42), Int32(42), Int64(42), Int128(42), 42) (UInt16(42), UInt32(42), UInt64(42), UInt128(42), Int16(42), Int32(42), Int64(42), Int128(42), 42) num = (UInt16(42), UInt32(42), UInt64(42), UInt128(42), Int16(42), Int32(42), Int64(42), Int128(42), 42) num = (UInt16(42), UInt32(42), UInt64(42), UInt128(42), Int16(42), Int32(42), Int64(42), Int128(42), 42) begin (fmt, val) = (("%i", "42"), ("%u", "42"), ("Test: %i", "Test: 42"), ("%#x", "0x2a"), ("%x", "2a"), ("%X", "2A"), ("% i", " 42"), ("%+i", "+42"), ("%4i", " 42"), ("%-4i", "42 "), ("%f", "42.000000"), ("%g", "42"), ("%e", "4.200000e+01")) num = (UInt16(42), UInt32(42), UInt64(42), UInt128(42), Int16(42), Int32(42), Int64(42), Int128(42), 42) end begin (fmt, val) = (("%i", "42"), ("%u", "42"), ("Test: %i", "Test: 42"), ("%#x", "0x2a"), ("%x", "2a"), ("%X", "2A"), ("% i", " 42"), ("%+i", "+42"), ("%4i", " 42"), ("%-4i", "42 "), ("%f", "42.000000"), ("%g", "42"), ("%e", "4.200000e+01")) num = (UInt16(42), UInt32(42), UInt64(42), UInt128(42), Int16(42), Int32(42), Int64(42), Int128(42), 42) end for (fmt, val) = (("%i", "42"), ("%u", "42"), ("Test: %i", "Test: 42"), ("%#x", "0x2a"), ("%x", "2a"), ("%X", "2A"), ("% i", " 42"), ("%+i", "+42"), ("%4i", " 42"), ("%-4i", "42 "), ("%f", "42.000000"), ("%g", "42"), ("%e", "4.200000e+01")), num = (UInt16(42), UInt32(42), UInt64(42), UInt128(42), Int16(42), Int32(42), Int64(42), Int128(42), 42) @test Printf.format(Printf.Format(fmt), num) == val end for (fmt, val) = (("%i", "42"), ("%u", "42"), ("Test: %i", "Test: 42"), ("%#x", "0x2a"), ("%x", "2a"), ("%X", "2A"), ("% i", " 42"), ("%+i", "+42"), ("%4i", " 42"), ("%-4i", "42 "), ("%f", "42.000000"), ("%g", "42"), ("%e", "4.200000e+01")), num = (UInt16(42), UInt32(42), UInt64(42), UInt128(42), Int16(42), Int32(42), Int64(42), Int128(42), 42) @test Printf.format(Printf.Format(fmt), num) == val end begin @test Printf.@sprintf("%%") == "%" @test Printf.@sprintf("1%%") == "1%" @test Printf.@sprintf("%%1") == "%1" @test Printf.@sprintf("1%%2") == "1%2" @test Printf.@sprintf("1%%%d", 2) == "1%2" @test Printf.@sprintf("1%%2%%3") == "1%2%3" @test Printf.@sprintf("GAP[%%]") == "GAP[%]" @test Printf.@sprintf("hey there") == "hey there" @test_throws Printf.InvalidFormatStringError Printf.Format("%+") @test_throws Printf.InvalidFormatStringError Printf.Format("%.") @test_throws Printf.InvalidFormatStringError Printf.Format("%.0") @test isempty((Printf.Format("%%")).formats) @test Printf.@sprintf("%d%d", 1, 2) == "12" @test Printf.@sprintf("%d%d", [1 2]...) == "12" @test Printf.@sprintf("X%d", 2) == "X2" @test Printf.@sprintf("Ð%d", 2) == "Ð2" @test Printf.@sprintf("ༀ%d", 2) == "ༀ2" @test Printf.@sprintf("\U1ffff%d", 2) == "\U0001ffff2" @test Printf.@sprintf("%dX%d", 1, 2) == "1X2" @test Printf.@sprintf("%dÐ%d", 1, 2) == "1Ð2" @test Printf.@sprintf("%dༀ%d", 1, 2) == "1ༀ2" @test Printf.@sprintf("%d\U1ffff%d", 1, 2) == "1\U0001ffff2" @test Printf.@sprintf("%d∃%dȃ", 1, 2) == "1∃2ȃ" @test_throws Printf.InvalidFormatStringError Printf.Format("%y%d") @test_throws Printf.InvalidFormatStringError Printf.Format("%Ð%d") @test_throws Printf.InvalidFormatStringError Printf.Format("%ༀ%d") @test_throws Printf.InvalidFormatStringError Printf.Format("%\U1ffff%d") @test Printf.@sprintf("%10.5d", 4) == " 00004" @test Printf.@sprintf("%d", typemax(Int64)) == "9223372036854775807" for (fmt, val) = (("%7.2f", " 1.23"), ("%-7.2f", "1.23 "), ("%07.2f", "0001.23"), ("%.0f", "1"), ("%#.0f", "1."), ("%.4e", "1.2345e+00"), ("%.4E", "1.2345E+00"), ("%.2a", "0x1.3cp+0"), ("%.2A", "0X1.3CP+0")), num = (1.2345, 1.234499999999999999999999999999999999999999999999999999999999999999999999999991) @test Printf.format(Printf.Format(fmt), num) == val end for (fmt, val) = (("%i", "42"), ("%u", "42"), ("Test: %i", "Test: 42"), ("%#x", "0x2a"), ("%x", "2a"), ("%X", "2A"), ("% i", " 42"), ("%+i", "+42"), ("%4i", " 42"), ("%-4i", "42 "), ("%f", "42.000000"), ("%g", "42"), ("%e", "4.200000e+01")), num = (UInt16(42), UInt32(42), UInt64(42), UInt128(42), Int16(42), Int32(42), Int64(42), Int128(42), 42) @test Printf.format(Printf.Format(fmt), num) == val end for i = ((42, "", "i", "42", ""), (42, "", "d", "42", ""), (42, "", "u", "42", ""), (42, "", "x", "2a", ""), (42, "", "X", "2A", ""), (42, "", "o", "52", ""), (42, "#", "x", "2a", "0x"), (42, "#", "X", "2A", "0X"), (42, "#", "o", "052", ""), (1.2345, "", ".2f", "1.23", ""), (1.2345, "", ".2e", "1.23e+00", ""), (1.2345, "", ".2E", "1.23E+00", ""), (1.2345, "#", ".0f", "1.", ""), (1.2345, "#", ".0e", "1.e+00", ""), (1.2345, "#", ".0E", "1.E+00", ""), (1.2345, "", ".2a", "1.3cp+0", "0x"), (1.2345, "", ".2A", "1.3CP+0", "0X")) _test_flags(i...) _test_flags(-(i[1]), i[2:5]...) end @test Printf.@sprintf("Test: %s%c%C%c%#-.0f.", "t", 65, 66, 67, -42) == "Test: tABC-42.." @test Printf.@sprintf("%f %d %d %f", 1.0, [3 4]..., 5) == "1.000000 3 4 5.000000" @test Printf.@sprintf("%s %f %9.5f %d %d %d %d%d%d%d", [1:6;]..., [7, 8, 9, 10]...) == "1 2.000000 3.00000 4 5 6 78910" @test Printf.@sprintf("%s %s %s %d %d %d %f %f %f", Any[10 ^ x + y for x = 1:3, y = 1:3]...) == "11 101 1001 12 102 1002 13.000000 103.000000 1003.000000" @test Printf.@sprintf("%s %s %s %d %d %d %f %f %f %s %s %s %d %d %d %f %f %f", Any[10x + (x + 1) for x = 1:18]...) == "12 23 34 45 56 67 78.000000 89.000000 100.000000 111 122 133 144 155 166 177.000000 188.000000 199.000000" @test (Printf.@sprintf("%.330f", BigFloat(1)))[var"end"] != '\0' @test Printf.@sprintf("%f", parse(BigFloat, "1e400")) == "10000000000000000000000000000000000000000000000000000000000000000000000000000025262527574416492004687051900140830217136998040684679611623086405387447100385714565637522507383770691831689647535911648520404034824470543643098638520633064715221151920028135130764414460468236314621044034960475540018328999334468948008954289495190631358190153259681118693204411689043999084305348398480210026863210192871358464.000000" @test_throws ArgumentError Printf.@sprintf("%f", parse(BigFloat, "1e99999")) @test Printf.@sprintf("%4.2s", "a") == " a" @test Printf.@sprintf("%12.3e", pi * 1.0e100) == " 3.142e+100" @test string((Printf.Format("%a")).formats[1]) == "%a" @test string((Printf.Format("%a")).formats[1]; modifier = "R") == "%Ra" @test Printf.@sprintf("%d", 3.14) == "3" @test Printf.@sprintf("%2d", 3.14) == " 3" @test Printf.@sprintf("%2d", big(3.14)) == " 3" @test Printf.@sprintf("%s", 1) == "1" @test Printf.@sprintf("%f", 1) == "1.000000" @test Printf.@sprintf("%e", 1) == "1.000000e+00" @test Printf.@sprintf("%g", 1) == "1" @test Printf.@sprintf("%.16g", 194.4778127560983) == "194.4778127560983" @test Printf.@sprintf("%.17g", 194.4778127560983) == "194.4778127560983" @test Printf.@sprintf("%.18g", 194.4778127560983) == "194.477812756098302" @test Printf.@sprintf("%.1g", 1.7976931348623157e308) == "2e+308" @test Printf.@sprintf("%.2g", 1.7976931348623157e308) == "1.8e+308" @test Printf.@sprintf("%.3g", 1.7976931348623157e308) == "1.8e+308" @test_throws ArgumentError @sprintf("%s%%%s", "a") @test @sprintf("%s%%%s", "a", "b") == "a%b" @test @sprintf("%d", 25.5) == "26" @test @sprintf(" %.1e\n", 0.999) == " 1.0e+00\n" @test @sprintf(" %.1f", 9.999) == " 10.0" @test @sprintf("%d", 1.0e100) == "10000000000000000159028911097599180468360808563945281389781327557747838772170381060813469985856815104" @test @sprintf("%d", 3 // 1) == "3" @test @sprintf("%d", Inf) == "Inf" @test @sprintf(" %d", NaN) == " NaN" @test Printf.@sprintf("") == "" @test Printf.format(Printf.Format("")) == "" end begin @test Printf.@sprintf("%%") == "%" @test Printf.@sprintf("1%%") == "1%" @test Printf.@sprintf("%%1") == "%1" @test Printf.@sprintf("1%%2") == "1%2" @test Printf.@sprintf("1%%%d", 2) == "1%2" @test Printf.@sprintf("1%%2%%3") == "1%2%3" @test Printf.@sprintf("GAP[%%]") == "GAP[%]" @test Printf.@sprintf("hey there") == "hey there" @test_throws Printf.InvalidFormatStringError Printf.Format("%+") @test_throws Printf.InvalidFormatStringError Printf.Format("%.") @test_throws Printf.InvalidFormatStringError Printf.Format("%.0") @test isempty((Printf.Format("%%")).formats) @test Printf.@sprintf("%d%d", 1, 2) == "12" @test Printf.@sprintf("%d%d", [1 2]...) == "12" @test Printf.@sprintf("X%d", 2) == "X2" @test Printf.@sprintf("Ð%d", 2) == "Ð2" @test Printf.@sprintf("ༀ%d", 2) == "ༀ2" @test Printf.@sprintf("\U1ffff%d", 2) == "\U0001ffff2" @test Printf.@sprintf("%dX%d", 1, 2) == "1X2" @test Printf.@sprintf("%dÐ%d", 1, 2) == "1Ð2" @test Printf.@sprintf("%dༀ%d", 1, 2) == "1ༀ2" @test Printf.@sprintf("%d\U1ffff%d", 1, 2) == "1\U0001ffff2" @test Printf.@sprintf("%d∃%dȃ", 1, 2) == "1∃2ȃ" @test_throws Printf.InvalidFormatStringError Printf.Format("%y%d") @test_throws Printf.InvalidFormatStringError Printf.Format("%Ð%d") @test_throws Printf.InvalidFormatStringError Printf.Format("%ༀ%d") @test_throws Printf.InvalidFormatStringError Printf.Format("%\U1ffff%d") @test Printf.@sprintf("%10.5d", 4) == " 00004" @test Printf.@sprintf("%d", typemax(Int64)) == "9223372036854775807" for (fmt, val) = (("%7.2f", " 1.23"), ("%-7.2f", "1.23 "), ("%07.2f", "0001.23"), ("%.0f", "1"), ("%#.0f", "1."), ("%.4e", "1.2345e+00"), ("%.4E", "1.2345E+00"), ("%.2a", "0x1.3cp+0"), ("%.2A", "0X1.3CP+0")), num = (1.2345, 1.234499999999999999999999999999999999999999999999999999999999999999999999999991) @test Printf.format(Printf.Format(fmt), num) == val end for (fmt, val) = (("%i", "42"), ("%u", "42"), ("Test: %i", "Test: 42"), ("%#x", "0x2a"), ("%x", "2a"), ("%X", "2A"), ("% i", " 42"), ("%+i", "+42"), ("%4i", " 42"), ("%-4i", "42 "), ("%f", "42.000000"), ("%g", "42"), ("%e", "4.200000e+01")), num = (UInt16(42), UInt32(42), UInt64(42), UInt128(42), Int16(42), Int32(42), Int64(42), Int128(42), 42) @test Printf.format(Printf.Format(fmt), num) == val end for i = ((42, "", "i", "42", ""), (42, "", "d", "42", ""), (42, "", "u", "42", ""), (42, "", "x", "2a", ""), (42, "", "X", "2A", ""), (42, "", "o", "52", ""), (42, "#", "x", "2a", "0x"), (42, "#", "X", "2A", "0X"), (42, "#", "o", "052", ""), (1.2345, "", ".2f", "1.23", ""), (1.2345, "", ".2e", "1.23e+00", ""), (1.2345, "", ".2E", "1.23E+00", ""), (1.2345, "#", ".0f", "1.", ""), (1.2345, "#", ".0e", "1.e+00", ""), (1.2345, "#", ".0E", "1.E+00", ""), (1.2345, "", ".2a", "1.3cp+0", "0x"), (1.2345, "", ".2A", "1.3CP+0", "0X")) _test_flags(i...) _test_flags(-(i[1]), i[2:5]...) end @test Printf.@sprintf("Test: %s%c%C%c%#-.0f.", "t", 65, 66, 67, -42) == "Test: tABC-42.." @test Printf.@sprintf("%f %d %d %f", 1.0, [3 4]..., 5) == "1.000000 3 4 5.000000" @test Printf.@sprintf("%s %f %9.5f %d %d %d %d%d%d%d", [1:6;]..., [7, 8, 9, 10]...) == "1 2.000000 3.00000 4 5 6 78910" @test Printf.@sprintf("%s %s %s %d %d %d %f %f %f", Any[10 ^ x + y for x = 1:3, y = 1:3]...) == "11 101 1001 12 102 1002 13.000000 103.000000 1003.000000" @test Printf.@sprintf("%s %s %s %d %d %d %f %f %f %s %s %s %d %d %d %f %f %f", Any[10x + (x + 1) for x = 1:18]...) == "12 23 34 45 56 67 78.000000 89.000000 100.000000 111 122 133 144 155 166 177.000000 188.000000 199.000000" @test (Printf.@sprintf("%.330f", BigFloat(1)))[var"end"] != '\0' @test Printf.@sprintf("%f", parse(BigFloat, "1e400")) == "10000000000000000000000000000000000000000000000000000000000000000000000000000025262527574416492004687051900140830217136998040684679611623086405387447100385714565637522507383770691831689647535911648520404034824470543643098638520633064715221151920028135130764414460468236314621044034960475540018328999334468948008954289495190631358190153259681118693204411689043999084305348398480210026863210192871358464.000000" @test_throws ArgumentError Printf.@sprintf("%f", parse(BigFloat, "1e99999")) @test Printf.@sprintf("%4.2s", "a") == " a" @test Printf.@sprintf("%12.3e", pi * 1.0e100) == " 3.142e+100" @test string((Printf.Format("%a")).formats[1]) == "%a" @test string((Printf.Format("%a")).formats[1]; modifier = "R") == "%Ra" @test Printf.@sprintf("%d", 3.14) == "3" @test Printf.@sprintf("%2d", 3.14) == " 3" @test Printf.@sprintf("%2d", big(3.14)) == " 3" @test Printf.@sprintf("%s", 1) == "1" @test Printf.@sprintf("%f", 1) == "1.000000" @test Printf.@sprintf("%e", 1) == "1.000000e+00" @test Printf.@sprintf("%g", 1) == "1" @test Printf.@sprintf("%.16g", 194.4778127560983) == "194.4778127560983" @test Printf.@sprintf("%.17g", 194.4778127560983) == "194.4778127560983" @test Printf.@sprintf("%.18g", 194.4778127560983) == "194.477812756098302" @test Printf.@sprintf("%.1g", 1.7976931348623157e308) == "2e+308" @test Printf.@sprintf("%.2g", 1.7976931348623157e308) == "1.8e+308" @test Printf.@sprintf("%.3g", 1.7976931348623157e308) == "1.8e+308" @test_throws ArgumentError @sprintf("%s%%%s", "a") @test @sprintf("%s%%%s", "a", "b") == "a%b" @test @sprintf("%d", 25.5) == "26" @test @sprintf(" %.1e\n", 0.999) == " 1.0e+00\n" @test @sprintf(" %.1f", 9.999) == " 10.0" @test @sprintf("%d", 1.0e100) == "10000000000000000159028911097599180468360808563945281389781327557747838772170381060813469985856815104" @test @sprintf("%d", 3 // 1) == "3" @test @sprintf("%d", Inf) == "Inf" @test @sprintf(" %d", NaN) == " NaN" @test Printf.@sprintf("") == "" @test Printf.format(Printf.Format("")) == "" end @testset "basics" begin @test Printf.@sprintf("%%") == "%" @test Printf.@sprintf("1%%") == "1%" @test Printf.@sprintf("%%1") == "%1" @test Printf.@sprintf("1%%2") == "1%2" @test Printf.@sprintf("1%%%d", 2) == "1%2" @test Printf.@sprintf("1%%2%%3") == "1%2%3" @test Printf.@sprintf("GAP[%%]") == "GAP[%]" @test Printf.@sprintf("hey there") == "hey there" @test_throws Printf.InvalidFormatStringError Printf.Format("%+") @test_throws Printf.InvalidFormatStringError Printf.Format("%.") @test_throws Printf.InvalidFormatStringError Printf.Format("%.0") @test isempty((Printf.Format("%%")).formats) @test Printf.@sprintf("%d%d", 1, 2) == "12" @test Printf.@sprintf("%d%d", [1 2]...) == "12" @test Printf.@sprintf("X%d", 2) == "X2" @test Printf.@sprintf("Ð%d", 2) == "Ð2" @test Printf.@sprintf("ༀ%d", 2) == "ༀ2" @test Printf.@sprintf("\U1ffff%d", 2) == "\U0001ffff2" @test Printf.@sprintf("%dX%d", 1, 2) == "1X2" @test Printf.@sprintf("%dÐ%d", 1, 2) == "1Ð2" @test Printf.@sprintf("%dༀ%d", 1, 2) == "1ༀ2" @test Printf.@sprintf("%d\U1ffff%d", 1, 2) == "1\U0001ffff2" @test Printf.@sprintf("%d∃%dȃ", 1, 2) == "1∃2ȃ" @test_throws Printf.InvalidFormatStringError Printf.Format("%y%d") @test_throws Printf.InvalidFormatStringError Printf.Format("%Ð%d") @test_throws Printf.InvalidFormatStringError Printf.Format("%ༀ%d") @test_throws Printf.InvalidFormatStringError Printf.Format("%\U1ffff%d") @test Printf.@sprintf("%10.5d", 4) == " 00004" @test Printf.@sprintf("%d", typemax(Int64)) == "9223372036854775807" for (fmt, val) = (("%7.2f", " 1.23"), ("%-7.2f", "1.23 "), ("%07.2f", "0001.23"), ("%.0f", "1"), ("%#.0f", "1."), ("%.4e", "1.2345e+00"), ("%.4E", "1.2345E+00"), ("%.2a", "0x1.3cp+0"), ("%.2A", "0X1.3CP+0")), num = (1.2345, 1.234499999999999999999999999999999999999999999999999999999999999999999999999991) @test Printf.format(Printf.Format(fmt), num) == val end for (fmt, val) = (("%i", "42"), ("%u", "42"), ("Test: %i", "Test: 42"), ("%#x", "0x2a"), ("%x", "2a"), ("%X", "2A"), ("% i", " 42"), ("%+i", "+42"), ("%4i", " 42"), ("%-4i", "42 "), ("%f", "42.000000"), ("%g", "42"), ("%e", "4.200000e+01")), num = (UInt16(42), UInt32(42), UInt64(42), UInt128(42), Int16(42), Int32(42), Int64(42), Int128(42), 42) @test Printf.format(Printf.Format(fmt), num) == val end for i = ((42, "", "i", "42", ""), (42, "", "d", "42", ""), (42, "", "u", "42", ""), (42, "", "x", "2a", ""), (42, "", "X", "2A", ""), (42, "", "o", "52", ""), (42, "#", "x", "2a", "0x"), (42, "#", "X", "2A", "0X"), (42, "#", "o", "052", ""), (1.2345, "", ".2f", "1.23", ""), (1.2345, "", ".2e", "1.23e+00", ""), (1.2345, "", ".2E", "1.23E+00", ""), (1.2345, "#", ".0f", "1.", ""), (1.2345, "#", ".0e", "1.e+00", ""), (1.2345, "#", ".0E", "1.E+00", ""), (1.2345, "", ".2a", "1.3cp+0", "0x"), (1.2345, "", ".2A", "1.3CP+0", "0X")) _test_flags(i...) _test_flags(-(i[1]), i[2:5]...) end @test Printf.@sprintf("Test: %s%c%C%c%#-.0f.", "t", 65, 66, 67, -42) == "Test: tABC-42.." @test Printf.@sprintf("%f %d %d %f", 1.0, [3 4]..., 5) == "1.000000 3 4 5.000000" @test Printf.@sprintf("%s %f %9.5f %d %d %d %d%d%d%d", [1:6;]..., [7, 8, 9, 10]...) == "1 2.000000 3.00000 4 5 6 78910" @test Printf.@sprintf("%s %s %s %d %d %d %f %f %f", Any[10 ^ x + y for x = 1:3, y = 1:3]...) == "11 101 1001 12 102 1002 13.000000 103.000000 1003.000000" @test Printf.@sprintf("%s %s %s %d %d %d %f %f %f %s %s %s %d %d %d %f %f %f", Any[10x + (x + 1) for x = 1:18]...) == "12 23 34 45 56 67 78.000000 89.000000 100.000000 111 122 133 144 155 166 177.000000 188.000000 199.000000" @test (Printf.@sprintf("%.330f", BigFloat(1)))[var"end"] != '\0' @test Printf.@sprintf("%f", parse(BigFloat, "1e400")) == "10000000000000000000000000000000000000000000000000000000000000000000000000000025262527574416492004687051900140830217136998040684679611623086405387447100385714565637522507383770691831689647535911648520404034824470543643098638520633064715221151920028135130764414460468236314621044034960475540018328999334468948008954289495190631358190153259681118693204411689043999084305348398480210026863210192871358464.000000" @test_throws ArgumentError Printf.@sprintf("%f", parse(BigFloat, "1e99999")) @test Printf.@sprintf("%4.2s", "a") == " a" @test Printf.@sprintf("%12.3e", pi * 1.0e100) == " 3.142e+100" @test string((Printf.Format("%a")).formats[1]) == "%a" @test string((Printf.Format("%a")).formats[1]; modifier = "R") == "%Ra" @test Printf.@sprintf("%d", 3.14) == "3" @test Printf.@sprintf("%2d", 3.14) == " 3" @test Printf.@sprintf("%2d", big(3.14)) == " 3" @test Printf.@sprintf("%s", 1) == "1" @test Printf.@sprintf("%f", 1) == "1.000000" @test Printf.@sprintf("%e", 1) == "1.000000e+00" @test Printf.@sprintf("%g", 1) == "1" @test Printf.@sprintf("%.16g", 194.4778127560983) == "194.4778127560983" @test Printf.@sprintf("%.17g", 194.4778127560983) == "194.4778127560983" @test Printf.@sprintf("%.18g", 194.4778127560983) == "194.477812756098302" @test Printf.@sprintf("%.1g", 1.7976931348623157e308) == "2e+308" @test Printf.@sprintf("%.2g", 1.7976931348623157e308) == "1.8e+308" @test Printf.@sprintf("%.3g", 1.7976931348623157e308) == "1.8e+308" @test_throws ArgumentError @sprintf("%s%%%s", "a") @test @sprintf("%s%%%s", "a", "b") == "a%b" @test @sprintf("%d", 25.5) == "26" @test @sprintf(" %.1e\n", 0.999) == " 1.0e+00\n" @test @sprintf(" %.1f", 9.999) == " 10.0" @test @sprintf("%d", 1.0e100) == "10000000000000000159028911097599180468360808563945281389781327557747838772170381060813469985856815104" @test @sprintf("%d", 3 // 1) == "3" @test @sprintf("%d", Inf) == "Inf" @test @sprintf(" %d", NaN) == " NaN" @test Printf.@sprintf("") == "" @test Printf.format(Printf.Format("")) == "" end @testset "basics" begin @test Printf.@sprintf("%%") == "%" @test Printf.@sprintf("1%%") == "1%" @test Printf.@sprintf("%%1") == "%1" @test Printf.@sprintf("1%%2") == "1%2" @test Printf.@sprintf("1%%%d", 2) == "1%2" @test Printf.@sprintf("1%%2%%3") == "1%2%3" @test Printf.@sprintf("GAP[%%]") == "GAP[%]" @test Printf.@sprintf("hey there") == "hey there" @test_throws Printf.InvalidFormatStringError Printf.Format("%+") @test_throws Printf.InvalidFormatStringError Printf.Format("%.") @test_throws Printf.InvalidFormatStringError Printf.Format("%.0") @test isempty((Printf.Format("%%")).formats) @test Printf.@sprintf("%d%d", 1, 2) == "12" @test Printf.@sprintf("%d%d", [1 2]...) == "12" @test Printf.@sprintf("X%d", 2) == "X2" @test Printf.@sprintf("Ð%d", 2) == "Ð2" @test Printf.@sprintf("ༀ%d", 2) == "ༀ2" @test Printf.@sprintf("\U1ffff%d", 2) == "\U0001ffff2" @test Printf.@sprintf("%dX%d", 1, 2) == "1X2" @test Printf.@sprintf("%dÐ%d", 1, 2) == "1Ð2" @test Printf.@sprintf("%dༀ%d", 1, 2) == "1ༀ2" @test Printf.@sprintf("%d\U1ffff%d", 1, 2) == "1\U0001ffff2" @test Printf.@sprintf("%d∃%dȃ", 1, 2) == "1∃2ȃ" @test_throws Printf.InvalidFormatStringError Printf.Format("%y%d") @test_throws Printf.InvalidFormatStringError Printf.Format("%Ð%d") @test_throws Printf.InvalidFormatStringError Printf.Format("%ༀ%d") @test_throws Printf.InvalidFormatStringError Printf.Format("%\U1ffff%d") @test Printf.@sprintf("%10.5d", 4) == " 00004" @test Printf.@sprintf("%d", typemax(Int64)) == "9223372036854775807" for (fmt, val) = (("%7.2f", " 1.23"), ("%-7.2f", "1.23 "), ("%07.2f", "0001.23"), ("%.0f", "1"), ("%#.0f", "1."), ("%.4e", "1.2345e+00"), ("%.4E", "1.2345E+00"), ("%.2a", "0x1.3cp+0"), ("%.2A", "0X1.3CP+0")), num = (1.2345, 1.234499999999999999999999999999999999999999999999999999999999999999999999999991) @test Printf.format(Printf.Format(fmt), num) == val end for (fmt, val) = (("%i", "42"), ("%u", "42"), ("Test: %i", "Test: 42"), ("%#x", "0x2a"), ("%x", "2a"), ("%X", "2A"), ("% i", " 42"), ("%+i", "+42"), ("%4i", " 42"), ("%-4i", "42 "), ("%f", "42.000000"), ("%g", "42"), ("%e", "4.200000e+01")), num = (UInt16(42), UInt32(42), UInt64(42), UInt128(42), Int16(42), Int32(42), Int64(42), Int128(42), 42) @test Printf.format(Printf.Format(fmt), num) == val end for i = ((42, "", "i", "42", ""), (42, "", "d", "42", ""), (42, "", "u", "42", ""), (42, "", "x", "2a", ""), (42, "", "X", "2A", ""), (42, "", "o", "52", ""), (42, "#", "x", "2a", "0x"), (42, "#", "X", "2A", "0X"), (42, "#", "o", "052", ""), (1.2345, "", ".2f", "1.23", ""), (1.2345, "", ".2e", "1.23e+00", ""), (1.2345, "", ".2E", "1.23E+00", ""), (1.2345, "#", ".0f", "1.", ""), (1.2345, "#", ".0e", "1.e+00", ""), (1.2345, "#", ".0E", "1.E+00", ""), (1.2345, "", ".2a", "1.3cp+0", "0x"), (1.2345, "", ".2A", "1.3CP+0", "0X")) _test_flags(i...) _test_flags(-(i[1]), i[2:5]...) end @test Printf.@sprintf("Test: %s%c%C%c%#-.0f.", "t", 65, 66, 67, -42) == "Test: tABC-42.." @test Printf.@sprintf("%f %d %d %f", 1.0, [3 4]..., 5) == "1.000000 3 4 5.000000" @test Printf.@sprintf("%s %f %9.5f %d %d %d %d%d%d%d", [1:6;]..., [7, 8, 9, 10]...) == "1 2.000000 3.00000 4 5 6 78910" @test Printf.@sprintf("%s %s %s %d %d %d %f %f %f", Any[10 ^ x + y for x = 1:3, y = 1:3]...) == "11 101 1001 12 102 1002 13.000000 103.000000 1003.000000" @test Printf.@sprintf("%s %s %s %d %d %d %f %f %f %s %s %s %d %d %d %f %f %f", Any[10x + (x + 1) for x = 1:18]...) == "12 23 34 45 56 67 78.000000 89.000000 100.000000 111 122 133 144 155 166 177.000000 188.000000 199.000000" @test (Printf.@sprintf("%.330f", BigFloat(1)))[var"end"] != '\0' @test Printf.@sprintf("%f", parse(BigFloat, "1e400")) == "10000000000000000000000000000000000000000000000000000000000000000000000000000025262527574416492004687051900140830217136998040684679611623086405387447100385714565637522507383770691831689647535911648520404034824470543643098638520633064715221151920028135130764414460468236314621044034960475540018328999334468948008954289495190631358190153259681118693204411689043999084305348398480210026863210192871358464.000000" @test_throws ArgumentError Printf.@sprintf("%f", parse(BigFloat, "1e99999")) @test Printf.@sprintf("%4.2s", "a") == " a" @test Printf.@sprintf("%12.3e", pi * 1.0e100) == " 3.142e+100" @test string((Printf.Format("%a")).formats[1]) == "%a" @test string((Printf.Format("%a")).formats[1]; modifier = "R") == "%Ra" @test Printf.@sprintf("%d", 3.14) == "3" @test Printf.@sprintf("%2d", 3.14) == " 3" @test Printf.@sprintf("%2d", big(3.14)) == " 3" @test Printf.@sprintf("%s", 1) == "1" @test Printf.@sprintf("%f", 1) == "1.000000" @test Printf.@sprintf("%e", 1) == "1.000000e+00" @test Printf.@sprintf("%g", 1) == "1" @test Printf.@sprintf("%.16g", 194.4778127560983) == "194.4778127560983" @test Printf.@sprintf("%.17g", 194.4778127560983) == "194.4778127560983" @test Printf.@sprintf("%.18g", 194.4778127560983) == "194.477812756098302" @test Printf.@sprintf("%.1g", 1.7976931348623157e308) == "2e+308" @test Printf.@sprintf("%.2g", 1.7976931348623157e308) == "1.8e+308" @test Printf.@sprintf("%.3g", 1.7976931348623157e308) == "1.8e+308" @test_throws ArgumentError @sprintf("%s%%%s", "a") @test @sprintf("%s%%%s", "a", "b") == "a%b" @test @sprintf("%d", 25.5) == "26" @test @sprintf(" %.1e\n", 0.999) == " 1.0e+00\n" @test @sprintf(" %.1f", 9.999) == " 10.0" @test @sprintf("%d", 1.0e100) == "10000000000000000159028911097599180468360808563945281389781327557747838772170381060813469985856815104" @test @sprintf("%d", 3 // 1) == "3" @test @sprintf("%d", Inf) == "Inf" @test @sprintf(" %d", NaN) == " NaN" @test Printf.@sprintf("") == "" @test Printf.format(Printf.Format("")) == "" end Printf.@sprintf "%*.*g" 10 5 -123.4000000000000000000000000000000000000000000000000000000000000000000000000002 Printf.@sprintf "%*.*g" 10 5 -123.4000000000000000000000000000000000000000000000000000000000000000000000000002 Printf.@sprintf "%10.5g" -123.4000000000000000000000000000000000000000000000000000000000000000000000000002 Printf.@sprintf "%10.5g" -123.4000000000000000000000000000000000000000000000000000000000000000000000000002 Printf.@sprintf("%*.*g", 10, 5, -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) == Printf.@sprintf("%10.5g", -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) Printf.@sprintf("%*.*g", 10, 5, -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) == Printf.@sprintf("%10.5g", -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) @test Printf.@sprintf("%*.*g", 10, 5, -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) == Printf.@sprintf("%10.5g", -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) @test Printf.@sprintf("%*.*g", 10, 5, -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) == Printf.@sprintf("%10.5g", -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) Printf.@sprintf "%0*.*g" 10 5 -123.4000000000000000000000000000000000000000000000000000000000000000000000000002 Printf.@sprintf "%0*.*g" 10 5 -123.4000000000000000000000000000000000000000000000000000000000000000000000000002 Printf.@sprintf "%010.5g" -123.4000000000000000000000000000000000000000000000000000000000000000000000000002 Printf.@sprintf "%010.5g" -123.4000000000000000000000000000000000000000000000000000000000000000000000000002 Printf.@sprintf("%0*.*g", 10, 5, -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) == Printf.@sprintf("%010.5g", -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) Printf.@sprintf("%0*.*g", 10, 5, -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) == Printf.@sprintf("%010.5g", -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) @test Printf.@sprintf("%0*.*g", 10, 5, -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) == Printf.@sprintf("%010.5g", -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) @test Printf.@sprintf("%0*.*g", 10, 5, -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) == Printf.@sprintf("%010.5g", -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) Printf.@sprintf "%.*g" 6 1.234e7 Printf.@sprintf "%.*g" 6 1.234e7 Printf.@sprintf "%.6g" 1.234e7 Printf.@sprintf "%.6g" 1.234e7 Printf.@sprintf("%.*g", 6, 1.234e7) == Printf.@sprintf("%.6g", 1.234e7) Printf.@sprintf("%.*g", 6, 1.234e7) == Printf.@sprintf("%.6g", 1.234e7) @test Printf.@sprintf("%.*g", 6, 1.234e7) == Printf.@sprintf("%.6g", 1.234e7) @test Printf.@sprintf("%.*g", 6, 1.234e7) == Printf.@sprintf("%.6g", 1.234e7) Printf.@sprintf "%#.*g" 6 1.234e7 Printf.@sprintf "%#.*g" 6 1.234e7 Printf.@sprintf "%#.6g" 1.234e7 Printf.@sprintf "%#.6g" 1.234e7 Printf.@sprintf("%#.*g", 6, 1.234e7) == Printf.@sprintf("%#.6g", 1.234e7) Printf.@sprintf("%#.*g", 6, 1.234e7) == Printf.@sprintf("%#.6g", 1.234e7) @test Printf.@sprintf("%#.*g", 6, 1.234e7) == Printf.@sprintf("%#.6g", 1.234e7) @test Printf.@sprintf("%#.*g", 6, 1.234e7) == Printf.@sprintf("%#.6g", 1.234e7) Printf.@sprintf "%*.*e" 10 4 Inf Printf.@sprintf "%*.*e" 10 4 Inf Printf.@sprintf "%10.4e" Inf Printf.@sprintf "%10.4e" Inf Printf.@sprintf("%*.*e", 10, 4, Inf) == Printf.@sprintf("%10.4e", Inf) Printf.@sprintf("%*.*e", 10, 4, Inf) == Printf.@sprintf("%10.4e", Inf) @test Printf.@sprintf("%*.*e", 10, 4, Inf) == Printf.@sprintf("%10.4e", Inf) @test Printf.@sprintf("%*.*e", 10, 4, Inf) == Printf.@sprintf("%10.4e", Inf) Printf.@sprintf "%.*e" 0 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142 Printf.@sprintf "%.*e" 0 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142 Printf.@sprintf "%.0e" 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142 Printf.@sprintf "%.0e" 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142 Printf.@sprintf("%.*e", 0, 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) == Printf.@sprintf("%.0e", 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) Printf.@sprintf("%.*e", 0, 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) == Printf.@sprintf("%.0e", 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) @test Printf.@sprintf("%.*e", 0, 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) == Printf.@sprintf("%.0e", 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) @test Printf.@sprintf("%.*e", 0, 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) == Printf.@sprintf("%.0e", 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) Printf.@sprintf "%#.*e" 0 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142 Printf.@sprintf "%#.*e" 0 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142 Printf.@sprintf "%#.0e" 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142 Printf.@sprintf "%#.0e" 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142 Printf.@sprintf("%#.*e", 0, 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) == Printf.@sprintf("%#.0e", 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) Printf.@sprintf("%#.*e", 0, 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) == Printf.@sprintf("%#.0e", 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) @test Printf.@sprintf("%#.*e", 0, 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) == Printf.@sprintf("%#.0e", 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) @test Printf.@sprintf("%#.*e", 0, 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) == Printf.@sprintf("%#.0e", 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) Printf.@sprintf "%.*e" 0 3.000000000000000000000000000000000000000000000000000000000000000000000000000024e1042 Printf.@sprintf "%.*e" 0 3.000000000000000000000000000000000000000000000000000000000000000000000000000024e1042 Printf.@sprintf "%.0e" 3.000000000000000000000000000000000000000000000000000000000000000000000000000024e1042 Printf.@sprintf "%.0e" 3.000000000000000000000000000000000000000000000000000000000000000000000000000024e1042 Printf.@sprintf("%.*e", 0, 3.000000000000000000000000000000000000000000000000000000000000000000000000000024e1042) == Printf.@sprintf("%.0e", 3.000000000000000000000000000000000000000000000000000000000000000000000000000024e1042) Printf.@sprintf("%.*e", 0, 3.000000000000000000000000000000000000000000000000000000000000000000000000000024e1042) == Printf.@sprintf("%.0e", 3.000000000000000000000000000000000000000000000000000000000000000000000000000024e1042) @test Printf.@sprintf("%.*e", 0, 3.000000000000000000000000000000000000000000000000000000000000000000000000000024e1042) == Printf.@sprintf("%.0e", 3.000000000000000000000000000000000000000000000000000000000000000000000000000024e1042) @test Printf.@sprintf("%.*e", 0, 3.000000000000000000000000000000000000000000000000000000000000000000000000000024e1042) == Printf.@sprintf("%.0e", 3.000000000000000000000000000000000000000000000000000000000000000000000000000024e1042) begin @test Printf.@sprintf("%*d", 10, 12) == " 12" @test Printf.@sprintf("%.*d", 4, 12) == "0012" @test Printf.@sprintf("%*.*d", 10, 4, 12) == " 0012" @test Printf.@sprintf("%+*.*d", 10, 4, 12) == " +0012" @test Printf.@sprintf("%0*.*d", 10, 4, 12) == " 0012" @test Printf.@sprintf("%*d%*d%*d", 4, 12, 4, 13, 4, 14) == " 12 13 14" @test Printf.@sprintf("%*d%*d%*d", 4, 12, 5, 13, 6, 14) == " 12 13 14" @test Printf.@sprintf("%*p", 20, 0) == Printf.@sprintf("%20p", 0) @test Printf.@sprintf("%-*p", 20, 0) == Printf.@sprintf("%-20p", 0) @test Printf.@sprintf("%*p", 20, C_NULL) == Printf.@sprintf("%20p", C_NULL) @test Printf.@sprintf("%-*p", 20, C_NULL) == Printf.@sprintf("%-20p", C_NULL) @test Printf.@sprintf("%.*a", 0, 3.14) == Printf.@sprintf("%.0a", 3.14) @test Printf.@sprintf("%.*a", 1, 3.14) == Printf.@sprintf("%.1a", 3.14) @test Printf.@sprintf("%.*a", 2, 3.14) == Printf.@sprintf("%.2a", 3.14) @test Printf.@sprintf("%#.*a", 0, 3.14) == Printf.@sprintf("%#.0a", 3.14) @test Printf.@sprintf("%#.*a", 1, 3.14) == Printf.@sprintf("%#.1a", 3.14) @test Printf.@sprintf("%#.*a", 2, 3.14) == Printf.@sprintf("%#.2a", 3.14) @test Printf.@sprintf("%.*a", 6, 1.5) == Printf.@sprintf("%.6a", 1.5) @test Printf.@sprintf("%*.*g", 10, 5, -123.4) == Printf.@sprintf("%10.5g", -123.4) @test Printf.@sprintf("%0*.*g", 10, 5, -123.4) == Printf.@sprintf("%010.5g", -123.4) @test Printf.@sprintf("%.*g", 6, 1.234e7) == Printf.@sprintf("%.6g", 1.234e7) @test Printf.@sprintf("%#.*g", 6, 1.234e7) == Printf.@sprintf("%#.6g", 1.234e7) @test Printf.@sprintf("%*.*g", 10, 5, -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) == Printf.@sprintf("%10.5g", -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) @test Printf.@sprintf("%0*.*g", 10, 5, -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) == Printf.@sprintf("%010.5g", -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) @test Printf.@sprintf("%.*g", 6, 1.234e7) == Printf.@sprintf("%.6g", 1.234e7) @test Printf.@sprintf("%#.*g", 6, 1.234e7) == Printf.@sprintf("%#.6g", 1.234e7) @test Printf.@sprintf("%.*g", 5, 42) == Printf.@sprintf("%.5g", 42) @test Printf.@sprintf("%#.*g", 2, 42) == Printf.@sprintf("%#.2g", 42) @test Printf.@sprintf("%#.*g", 5, 42) == Printf.@sprintf("%#.5g", 42) @test Printf.@sprintf("%.*g", 15, 0) == Printf.@sprintf("%.15g", 0) @test Printf.@sprintf("%#.*g", 15, 0) == Printf.@sprintf("%#.15g", 0) @test Printf.@sprintf("%.*f", 0, 3.0e142) == Printf.@sprintf("%.0f", 3.0e142) @test Printf.@sprintf("%.*f", 2, 1.234) == Printf.@sprintf("%.2f", 1.234) @test Printf.@sprintf("%.*f", 2, 1.235) == Printf.@sprintf("%.2f", 1.235) @test Printf.@sprintf("%.*f", 2, 0.235) == Printf.@sprintf("%.2f", 0.235) @test Printf.@sprintf("%*.*f", 4, 1, 1.234) == Printf.@sprintf("%4.1f", 1.234) @test Printf.@sprintf("%*.*f", 8, 1, 1.234) == Printf.@sprintf("%8.1f", 1.234) @test Printf.@sprintf("%+*.*f", 8, 1, 1.234) == Printf.@sprintf("%+8.1f", 1.234) @test Printf.@sprintf("% *.*f", 8, 1, 1.234) == Printf.@sprintf("% 8.1f", 1.234) @test Printf.@sprintf("% *.*f", 7, 1, 1.234) == Printf.@sprintf("% 7.1f", 1.234) @test Printf.@sprintf("% 0*.*f", 8, 1, 1.234) == Printf.@sprintf("% 08.1f", 1.234) @test Printf.@sprintf("%0*.*f", 8, 1, 1.234) == Printf.@sprintf("%08.1f", 1.234) @test Printf.@sprintf("%-0*.*f", 8, 1, 1.234) == Printf.@sprintf("%-08.1f", 1.234) @test Printf.@sprintf("%-*.*f", 8, 1, 1.234) == Printf.@sprintf("%-8.1f", 1.234) @test Printf.@sprintf("%0*.*f", 8, 1, -1.234) == Printf.@sprintf("%08.1f", -1.234) @test Printf.@sprintf("%0*.*f", 9, 1, -1.234) == Printf.@sprintf("%09.1f", -1.234) @test Printf.@sprintf("%0*.*f", 9, 1, 1.234) == Printf.@sprintf("%09.1f", 1.234) @test Printf.@sprintf("%+0*.*f", 9, 1, 1.234) == Printf.@sprintf("%+09.1f", 1.234) @test Printf.@sprintf("% 0*.*f", 9, 1, 1.234) == Printf.@sprintf("% 09.1f", 1.234) @test Printf.@sprintf("%+ 0*.*f", 9, 1, 1.234) == Printf.@sprintf("%+ 09.1f", 1.234) @test Printf.@sprintf("%+ 0*.*f", 9, 1, 1.234) == Printf.@sprintf("%+ 09.1f", 1.234) @test Printf.@sprintf("%+ 0*.*f", 9, 0, 1.234) == Printf.@sprintf("%+ 09.0f", 1.234) @test Printf.@sprintf("%+ #0*.*f", 9, 0, 1.234) == Printf.@sprintf("%+ #09.0f", 1.234) @test Printf.@sprintf("%*.*e", 10, 4, Inf) == Printf.@sprintf("%10.4e", Inf) @test Printf.@sprintf("%*.*e", 10, 4, NaN) == Printf.@sprintf("%10.4e", NaN) @test Printf.@sprintf("%*.*e", 10, 4, Inf) == Printf.@sprintf("%10.4e", Inf) @test Printf.@sprintf("%*.*e", 10, 4, NaN) == Printf.@sprintf("%10.4e", NaN) @test Printf.@sprintf("%.*e", 0, 3.0e142) == Printf.@sprintf("%.0e", 3.0e142) @test Printf.@sprintf("%#.*e", 0, 3.0e142) == Printf.@sprintf("%#.0e", 3.0e142) @test Printf.@sprintf("%.*e", 0, 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) == Printf.@sprintf("%.0e", 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) @test Printf.@sprintf("%#.*e", 0, 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) == Printf.@sprintf("%#.0e", 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) @test Printf.@sprintf("%.*e", 0, 3.000000000000000000000000000000000000000000000000000000000000000000000000000024e1042) == Printf.@sprintf("%.0e", 3.000000000000000000000000000000000000000000000000000000000000000000000000000024e1042) @test Printf.@sprintf("%.*e", 2, 1.234) == Printf.@sprintf("%.2e", 1.234) @test Printf.@sprintf("%.*e", 2, 1.235) == Printf.@sprintf("%.2e", 1.235) @test Printf.@sprintf("%.*e", 2, 0.235) == Printf.@sprintf("%.2e", 0.235) @test Printf.@sprintf("%*.*e", 4, 1, 1.234) == Printf.@sprintf("%4.1e", 1.234) @test Printf.@sprintf("%*.*e", 8, 1, 1.234) == Printf.@sprintf("%8.1e", 1.234) @test Printf.@sprintf("%+*.*e", 8, 1, 1.234) == Printf.@sprintf("%+8.1e", 1.234) @test Printf.@sprintf("% *.*e", 8, 1, 1.234) == Printf.@sprintf("% 8.1e", 1.234) @test Printf.@sprintf("% *.*e", 7, 1, 1.234) == Printf.@sprintf("% 7.1e", 1.234) @test Printf.@sprintf("% 0*.*e", 8, 1, 1.234) == Printf.@sprintf("% 08.1e", 1.234) @test Printf.@sprintf("%0*.*e", 8, 1, 1.234) == Printf.@sprintf("%08.1e", 1.234) @test Printf.@sprintf("%-0*.*e", 8, 1, 1.234) == Printf.@sprintf("%-08.1e", 1.234) @test Printf.@sprintf("%-*.*e", 8, 1, 1.234) == Printf.@sprintf("%-8.1e", 1.234) @test Printf.@sprintf("%-*.*e", 8, 1, 1.234) == Printf.@sprintf("%-8.1e", 1.234) @test Printf.@sprintf("%0*.*e", 8, 1, -1.234) == Printf.@sprintf("%08.1e", -1.234) @test Printf.@sprintf("%0*.*e", 9, 1, -1.234) == Printf.@sprintf("%09.1e", -1.234) @test Printf.@sprintf("%0*.*e", 9, 1, 1.234) == Printf.@sprintf("%09.1e", 1.234) @test Printf.@sprintf("%+0*.*e", 9, 1, 1.234) == Printf.@sprintf("%+09.1e", 1.234) @test Printf.@sprintf("% 0*.*e", 9, 1, 1.234) == Printf.@sprintf("% 09.1e", 1.234) @test Printf.@sprintf("%+ 0*.*e", 9, 1, 1.234) == Printf.@sprintf("%+ 09.1e", 1.234) @test Printf.@sprintf("%+ 0*.*e", 9, 1, 1.234) == Printf.@sprintf("%+ 09.1e", 1.234) @test Printf.@sprintf("%+ 0*.*e", 9, 0, 1.234) == Printf.@sprintf("%+ 09.0e", 1.234) @test Printf.@sprintf("%+ #0*.*e", 9, 0, 1.234) == Printf.@sprintf("%+ #09.0e", 1.234) @test Printf.@sprintf("%.*s", 1, "foo") == Printf.@sprintf("%.1s", "foo") @test Printf.@sprintf("%*s", 1, "Hallo heimur") == Printf.@sprintf("%1s", "Hallo heimur") @test Printf.@sprintf("%*s", 20, "Hallo") == Printf.@sprintf("%20s", "Hallo") @test Printf.@sprintf("%-*s", 20, "Hallo") == Printf.@sprintf("%-20s", "Hallo") @test Printf.@sprintf("%0-*s", 20, "Hallo") == Printf.@sprintf("%0-20s", "Hallo") @test Printf.@sprintf("%.*s", 20, "Hallo heimur") == Printf.@sprintf("%.20s", "Hallo heimur") @test Printf.@sprintf("%*.*s", 20, 5, "Hallo heimur") == Printf.@sprintf("%20.5s", "Hallo heimur") @test Printf.@sprintf("%.*s", 0, "Hallo heimur") == Printf.@sprintf("%.0s", "Hallo heimur") @test Printf.@sprintf("%*.*s", 20, 0, "Hallo heimur") == Printf.@sprintf("%20.0s", "Hallo heimur") @test Printf.@sprintf("%.s", "Hallo heimur") == Printf.@sprintf("%.s", "Hallo heimur") @test Printf.@sprintf("%*.s", 20, "Hallo heimur") == Printf.@sprintf("%20.s", "Hallo heimur") @test Printf.@sprintf("%*sø", 4, "ø") == Printf.@sprintf("%4sø", "ø") @test Printf.@sprintf("%-*sø", 4, "ø") == Printf.@sprintf("%-4sø", "ø") @test Printf.@sprintf("%*s", 8, "test") == Printf.@sprintf("%8s", "test") @test Printf.@sprintf("%-*s", 8, "test") == Printf.@sprintf("%-8s", "test") @test Printf.@sprintf("%#*s", 8, :test) == Printf.@sprintf("%#8s", :test) @test Printf.@sprintf("%#-*s", 8, :test) == Printf.@sprintf("%#-8s", :test) @test Printf.@sprintf("%*.*s", 8, 3, "test") == Printf.@sprintf("%8.3s", "test") @test Printf.@sprintf("%#*.*s", 8, 3, "test") == Printf.@sprintf("%#8.3s", "test") @test Printf.@sprintf("%-*.*s", 8, 3, "test") == Printf.@sprintf("%-8.3s", "test") @test Printf.@sprintf("%#-*.*s", 8, 3, "test") == Printf.@sprintf("%#-8.3s", "test") @test Printf.@sprintf("%.*s", 3, "test") == Printf.@sprintf("%.3s", "test") @test Printf.@sprintf("%#.*s", 3, "test") == Printf.@sprintf("%#.3s", "test") @test Printf.@sprintf("%-.*s", 3, "test") == Printf.@sprintf("%-.3s", "test") @test Printf.@sprintf("%#-.*s", 3, "test") == Printf.@sprintf("%#-.3s", "test") @test Printf.@sprintf("%*c", 3, 'a') == Printf.@sprintf("%3c", 'a') @test Printf.@sprintf("%*c", 1, 'x') == Printf.@sprintf("%1c", 'x') @test Printf.@sprintf("%*c", 20, 'x') == Printf.@sprintf("%20c", 'x') @test Printf.@sprintf("%-*c", 20, 'x') == Printf.@sprintf("%-20c", 'x') @test Printf.@sprintf("%-0*c", 20, 'x') == Printf.@sprintf("%-020c", 'x') @test Printf.@sprintf("%*c", 3, 'A') == Printf.@sprintf("%3c", 'A') @test Printf.@sprintf("%-*c", 3, 'A') == Printf.@sprintf("%-3c", 'A') @test Printf.@sprintf("%*.*f %*.*f %*.*f %*.*f %*.*f %*.*f %*.*f %*.*f %*.*f %*.*f %*.*f %*.*f %*.*f %*.*f %*.*f %*.*f %*.*f %*.*f", 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345) == Printf.@sprintf("%4.2f %4.2f %4.2f %4.2f %4.2f %4.2f %4.2f %4.2f %4.2f %4.2f %4.2f %4.2f %4.2f %4.2f %4.2f %4.2f %4.2f %4.2f", 1.2345, 1.2345, 1.2345, 1.2345, 1.2345, 1.2345, 1.2345, 1.2345, 1.2345, 1.2345, 1.2345, 1.2345, 1.2345, 1.2345, 1.2345, 1.2345, 1.2345, 1.2345) @test (Printf.@sprintf("%.*f", 330, BigFloat(1)))[var"end"] != '\0' @test Printf.@sprintf("%*.*s", 4, 2, "a") == Printf.@sprintf("%4.2s", "a") @test Printf.@sprintf("%*.*e", 12, 3, pi * 1.0e100) == Printf.@sprintf("%12.3e", pi * 1.0e100) @test Printf.@sprintf("%*d", 2, 3.14) == Printf.@sprintf("%*d", 2, 3.14) @test Printf.@sprintf("%*d", 2, big(3.14)) == Printf.@sprintf("%*d", 2, big(3.14)) @test Printf.@sprintf(" %.*e\n", 1, 0.999) == Printf.@sprintf(" %.1e\n", 0.999) @test Printf.@sprintf(" %.*f", 1, 9.999) == Printf.@sprintf(" %.1f", 9.999) @test Printf.@sprintf("%*d", 10, 12) == Printf.@sprintf("%10d", 12) @test Printf.@sprintf("%.*d", 4, 12) == Printf.@sprintf("%.4d", 12) @test Printf.@sprintf("%*.*d", 10, 4, 12) == Printf.@sprintf("%10.4d", 12) @test Printf.@sprintf("%+*.*d", 10, 4, 12) == Printf.@sprintf("%+10.4d", 12) @test Printf.@sprintf("%0*.*d", 10, 4, 12) == Printf.@sprintf("%010.4d", 12) @test Printf.@sprintf("% *d", 5, 42) == Printf.@sprintf("% 5d", 42) @test Printf.@sprintf("% *d", 5, -42) == Printf.@sprintf("% 5d", -42) @test Printf.@sprintf("% *d", 15, 42) == Printf.@sprintf("% 15d", 42) @test Printf.@sprintf("% *d", 15, -42) == Printf.@sprintf("% 15d", -42) @test Printf.@sprintf("%+*d", 5, 42) == Printf.@sprintf("%+5d", 42) @test Printf.@sprintf("%+*d", 5, -42) == Printf.@sprintf("%+5d", -42) @test Printf.@sprintf("%+*d", 15, 42) == Printf.@sprintf("%+15d", 42) @test Printf.@sprintf("%+*d", 15, -42) == Printf.@sprintf("%+15d", -42) @test Printf.@sprintf("%*d", 0, 42) == Printf.@sprintf("%0d", 42) @test Printf.@sprintf("%*d", 0, -42) == Printf.@sprintf("%0d", -42) @test Printf.@sprintf("%-*d", 5, 42) == Printf.@sprintf("%-5d", 42) @test Printf.@sprintf("%-*d", 5, -42) == Printf.@sprintf("%-5d", -42) @test Printf.@sprintf("%-*d", 15, 42) == Printf.@sprintf("%-15d", 42) @test Printf.@sprintf("%-*d", 15, -42) == Printf.@sprintf("%-15d", -42) @test Printf.@sprintf("%+*lld", 8, 100) == Printf.@sprintf("%+8lld", 100) @test Printf.@sprintf("%+.*lld", 8, 100) == Printf.@sprintf("%+.8lld", 100) @test Printf.@sprintf("%+*.*lld", 10, 8, 100) == Printf.@sprintf("%+10.8lld", 100) @test Printf.@sprintf("%-*.*lld", 1, 5, -100) == Printf.@sprintf("%-1.5lld", -100) @test Printf.@sprintf("%*lld", 5, 100) == Printf.@sprintf("%5lld", 100) @test Printf.@sprintf("%*lld", 5, -100) == Printf.@sprintf("%5lld", -100) @test Printf.@sprintf("%-*lld", 5, 100) == Printf.@sprintf("%-5lld", 100) @test Printf.@sprintf("%-*lld", 5, -100) == Printf.@sprintf("%-5lld", -100) @test Printf.@sprintf("%-.*lld", 5, 100) == Printf.@sprintf("%-.5lld", 100) @test Printf.@sprintf("%-.*lld", 5, -100) == Printf.@sprintf("%-.5lld", -100) @test Printf.@sprintf("%-*.*lld", 8, 5, 100) == Printf.@sprintf("%-8.5lld", 100) @test Printf.@sprintf("%-*.*lld", 8, 5, -100) == Printf.@sprintf("%-8.5lld", -100) @test Printf.@sprintf("%0*lld", 5, 100) == Printf.@sprintf("%05lld", 100) @test Printf.@sprintf("%0*lld", 5, -100) == Printf.@sprintf("%05lld", -100) @test Printf.@sprintf("% *lld", 5, 100) == Printf.@sprintf("% 5lld", 100) @test Printf.@sprintf("% *lld", 5, -100) == Printf.@sprintf("% 5lld", -100) @test Printf.@sprintf("% .*lld", 5, 100) == Printf.@sprintf("% .5lld", 100) @test Printf.@sprintf("% .*lld", 5, -100) == Printf.@sprintf("% .5lld", -100) @test Printf.@sprintf("% *.*lld", 8, 5, 100) == Printf.@sprintf("% 8.5lld", 100) @test Printf.@sprintf("% *.*lld", 8, 5, -100) == Printf.@sprintf("% 8.5lld", -100) @test Printf.@sprintf("%.*lld", 0, 0) == Printf.@sprintf("%.0lld", 0) @test Printf.@sprintf("%#+*.*llx", 21, 18, -100) == Printf.@sprintf("%#+21.18llx", -100) @test Printf.@sprintf("%#.*llo", 25, -100) == Printf.@sprintf("%#.25llo", -100) @test Printf.@sprintf("%#+*.*llo", 24, 20, -100) == Printf.@sprintf("%#+24.20llo", -100) @test Printf.@sprintf("%#+*.*llX", 18, 21, -100) == Printf.@sprintf("%#+18.21llX", -100) @test Printf.@sprintf("%#+*.*llo", 20, 24, -100) == Printf.@sprintf("%#+20.24llo", -100) @test Printf.@sprintf("%#+*.*llu", 25, 22, -1) == Printf.@sprintf("%#+25.22llu", -1) @test Printf.@sprintf("%#+*.*llu", 30, 25, -1) == Printf.@sprintf("%#+30.25llu", -1) @test Printf.@sprintf("%+#*.*lld", 25, 22, -1) == Printf.@sprintf("%+#25.22lld", -1) @test Printf.@sprintf("%#-*.*llo", 8, 5, 100) == Printf.@sprintf("%#-8.5llo", 100) @test Printf.@sprintf("%#-+ 0*.*lld", 8, 5, 100) == Printf.@sprintf("%#-+ 08.5lld", 100) @test Printf.@sprintf("%#-+ 0*.*lld", 8, 5, 100) == Printf.@sprintf("%#-+ 08.5lld", 100) @test Printf.@sprintf("%.*lld", 40, 1) == Printf.@sprintf("%.40lld", 1) @test Printf.@sprintf("% .*lld", 40, 1) == Printf.@sprintf("% .40lld", 1) @test Printf.@sprintf("% .*d", 40, 1) == Printf.@sprintf("% .40d", 1) @test Printf.@sprintf("%#0*x", 12, 1) == Printf.@sprintf("%#012x", 1) @test Printf.@sprintf("%#0*.*x", 4, 8, 1) == Printf.@sprintf("%#04.8x", 1) @test Printf.@sprintf("%#-0*.*x", 8, 2, 1) == Printf.@sprintf("%#-08.2x", 1) @test Printf.@sprintf("%#0*o", 8, 1) == Printf.@sprintf("%#08o", 1) @test Printf.@sprintf("%*d", 20, 1024) == Printf.@sprintf("%20d", 1024) @test Printf.@sprintf("%*d", 20, -1024) == Printf.@sprintf("%20d", -1024) @test Printf.@sprintf("%*i", 20, 1024) == Printf.@sprintf("%20i", 1024) @test Printf.@sprintf("%*i", 20, -1024) == Printf.@sprintf("%20i", -1024) @test Printf.@sprintf("%*u", 20, 1024) == Printf.@sprintf("%20u", 1024) @test Printf.@sprintf("%*u", 20, UInt(4294966272)) == Printf.@sprintf("%20u", UInt(4294966272)) @test Printf.@sprintf("%*o", 20, 511) == Printf.@sprintf("%20o", 511) @test Printf.@sprintf("%*o", 20, UInt(4294966785)) == Printf.@sprintf("%20o", UInt(4294966785)) @test Printf.@sprintf("%*x", 20, 305441741) == Printf.@sprintf("%20x", 305441741) @test Printf.@sprintf("%*x", 20, UInt(3989525555)) == Printf.@sprintf("%20x", UInt(3989525555)) @test Printf.@sprintf("%*X", 20, 305441741) == Printf.@sprintf("%20X", 305441741) @test Printf.@sprintf("%*X", 20, UInt(3989525555)) == Printf.@sprintf("%20X", UInt(3989525555)) @test Printf.@sprintf("%-*d", 20, 1024) == Printf.@sprintf("%-20d", 1024) @test Printf.@sprintf("%-*d", 20, -1024) == Printf.@sprintf("%-20d", -1024) @test Printf.@sprintf("%-*i", 20, 1024) == Printf.@sprintf("%-20i", 1024) @test Printf.@sprintf("%-*i", 20, -1024) == Printf.@sprintf("%-20i", -1024) @test Printf.@sprintf("%-*u", 20, 1024) == Printf.@sprintf("%-20u", 1024) @test Printf.@sprintf("%-*u", 20, UInt(4294966272)) == Printf.@sprintf("%-20u", UInt(4294966272)) @test Printf.@sprintf("%-*o", 20, 511) == Printf.@sprintf("%-20o", 511) @test Printf.@sprintf("%-*o", 20, UInt(4294966785)) == Printf.@sprintf("%-20o", UInt(4294966785)) @test Printf.@sprintf("%-*x", 20, 305441741) == Printf.@sprintf("%-20x", 305441741) @test Printf.@sprintf("%-*x", 20, UInt(3989525555)) == Printf.@sprintf("%-20x", UInt(3989525555)) @test Printf.@sprintf("%-*X", 20, 305441741) == Printf.@sprintf("%-20X", 305441741) @test Printf.@sprintf("%-*X", 20, UInt(3989525555)) == Printf.@sprintf("%-20X", UInt(3989525555)) @test Printf.@sprintf("%0*d", 20, 1024) == Printf.@sprintf("%020d", 1024) @test Printf.@sprintf("%0*d", 20, -1024) == Printf.@sprintf("%020d", -1024) @test Printf.@sprintf("%0*i", 20, 1024) == Printf.@sprintf("%020i", 1024) @test Printf.@sprintf("%0*i", 20, -1024) == Printf.@sprintf("%020i", -1024) @test Printf.@sprintf("%0*u", 20, 1024) == Printf.@sprintf("%020u", 1024) @test Printf.@sprintf("%0*u", 20, UInt(4294966272)) == Printf.@sprintf("%020u", UInt(4294966272)) @test Printf.@sprintf("%0*o", 20, 511) == Printf.@sprintf("%020o", 511) @test Printf.@sprintf("%0*o", 20, UInt(4294966785)) == Printf.@sprintf("%020o", UInt(4294966785)) @test Printf.@sprintf("%0*x", 20, 305441741) == Printf.@sprintf("%020x", 305441741) @test Printf.@sprintf("%0*x", 20, UInt(3989525555)) == Printf.@sprintf("%020x", UInt(3989525555)) @test Printf.@sprintf("%0*X", 20, 305441741) == Printf.@sprintf("%020X", 305441741) @test Printf.@sprintf("%0*X", 20, UInt(3989525555)) == Printf.@sprintf("%020X", UInt(3989525555)) @test Printf.@sprintf("%#*o", 20, 511) == Printf.@sprintf("%#20o", 511) @test Printf.@sprintf("%#*o", 20, UInt(4294966785)) == Printf.@sprintf("%#20o", UInt(4294966785)) @test Printf.@sprintf("%#*x", 20, 305441741) == Printf.@sprintf("%#20x", 305441741) @test Printf.@sprintf("%#*x", 20, UInt(3989525555)) == Printf.@sprintf("%#20x", UInt(3989525555)) @test Printf.@sprintf("%#*X", 20, 305441741) == Printf.@sprintf("%#20X", 305441741) @test Printf.@sprintf("%#*X", 20, UInt(3989525555)) == Printf.@sprintf("%#20X", UInt(3989525555)) @test Printf.@sprintf("%#0*o", 20, 511) == Printf.@sprintf("%#020o", 511) @test Printf.@sprintf("%#0*o", 20, UInt(4294966785)) == Printf.@sprintf("%#020o", UInt(4294966785)) @test Printf.@sprintf("%#0*x", 20, 305441741) == Printf.@sprintf("%#020x", 305441741) @test Printf.@sprintf("%#0*x", 20, UInt(3989525555)) == Printf.@sprintf("%#020x", UInt(3989525555)) @test Printf.@sprintf("%#0*X", 20, 305441741) == Printf.@sprintf("%#020X", 305441741) @test Printf.@sprintf("%#0*X", 20, UInt(3989525555)) == Printf.@sprintf("%#020X", UInt(3989525555)) @test Printf.@sprintf("%0-*d", 20, 1024) == Printf.@sprintf("%0-20d", 1024) @test Printf.@sprintf("%0-*d", 20, -1024) == Printf.@sprintf("%0-20d", -1024) @test Printf.@sprintf("%0-*i", 20, 1024) == Printf.@sprintf("%0-20i", 1024) @test Printf.@sprintf("%0-*i", 20, -1024) == Printf.@sprintf("%0-20i", -1024) @test Printf.@sprintf("%0-*u", 20, 1024) == Printf.@sprintf("%0-20u", 1024) @test Printf.@sprintf("%0-*u", 20, UInt(4294966272)) == Printf.@sprintf("%0-20u", UInt(4294966272)) @test Printf.@sprintf("%-0*o", 20, 511) == Printf.@sprintf("%-020o", 511) @test Printf.@sprintf("%-0*o", 20, UInt(4294966785)) == Printf.@sprintf("%-020o", UInt(4294966785)) @test Printf.@sprintf("%-0*x", 20, 305441741) == Printf.@sprintf("%-020x", 305441741) @test Printf.@sprintf("%-0*x", 20, UInt(3989525555)) == Printf.@sprintf("%-020x", UInt(3989525555)) @test Printf.@sprintf("%-0*X", 20, 305441741) == Printf.@sprintf("%-020X", 305441741) @test Printf.@sprintf("%-0*X", 20, UInt(3989525555)) == Printf.@sprintf("%-020X", UInt(3989525555)) @test Printf.@sprintf("%.*d", 20, 1024) == Printf.@sprintf("%.20d", 1024) @test Printf.@sprintf("%.*d", 20, -1024) == Printf.@sprintf("%.20d", -1024) @test Printf.@sprintf("%.*i", 20, 1024) == Printf.@sprintf("%.20i", 1024) @test Printf.@sprintf("%.*i", 20, -1024) == Printf.@sprintf("%.20i", -1024) @test Printf.@sprintf("%.*u", 20, 1024) == Printf.@sprintf("%.20u", 1024) @test Printf.@sprintf("%.*u", 20, UInt(4294966272)) == Printf.@sprintf("%.20u", UInt(4294966272)) @test Printf.@sprintf("%.*o", 20, 511) == Printf.@sprintf("%.20o", 511) @test Printf.@sprintf("%.*o", 20, UInt(4294966785)) == Printf.@sprintf("%.20o", UInt(4294966785)) @test Printf.@sprintf("%.*x", 20, 305441741) == Printf.@sprintf("%.20x", 305441741) @test Printf.@sprintf("%.*x", 20, UInt(3989525555)) == Printf.@sprintf("%.20x", UInt(3989525555)) @test Printf.@sprintf("%.*X", 20, 305441741) == Printf.@sprintf("%.20X", 305441741) @test Printf.@sprintf("%.*X", 20, UInt(3989525555)) == Printf.@sprintf("%.20X", UInt(3989525555)) @test Printf.@sprintf("%*.*d", 20, 5, 1024) == Printf.@sprintf("%20.5d", 1024) @test Printf.@sprintf("%*.*d", 20, 5, -1024) == Printf.@sprintf("%20.5d", -1024) @test Printf.@sprintf("%*.*i", 20, 5, 1024) == Printf.@sprintf("%20.5i", 1024) @test Printf.@sprintf("%*.*i", 20, 5, -1024) == Printf.@sprintf("%20.5i", -1024) @test Printf.@sprintf("%*.*u", 20, 5, 1024) == Printf.@sprintf("%20.5u", 1024) @test Printf.@sprintf("%*.*u", 20, 5, UInt(4294966272)) == Printf.@sprintf("%20.5u", UInt(4294966272)) @test Printf.@sprintf("%*.*o", 20, 5, 511) == Printf.@sprintf("%20.5o", 511) @test Printf.@sprintf("%*.*o", 20, 5, UInt(4294966785)) == Printf.@sprintf("%20.5o", UInt(4294966785)) @test Printf.@sprintf("%*.*x", 20, 5, 305441741) == Printf.@sprintf("%20.5x", 305441741) @test Printf.@sprintf("%*.*x", 20, 10, UInt(3989525555)) == Printf.@sprintf("%20.10x", UInt(3989525555)) @test Printf.@sprintf("%*.*X", 20, 5, 305441741) == Printf.@sprintf("%20.5X", 305441741) @test Printf.@sprintf("%*.*X", 20, 10, UInt(3989525555)) == Printf.@sprintf("%20.10X", UInt(3989525555)) @test Printf.@sprintf("%0*.*d", 20, 5, 1024) == Printf.@sprintf("%020.5d", 1024) @test Printf.@sprintf("%0*.*d", 20, 5, -1024) == Printf.@sprintf("%020.5d", -1024) @test Printf.@sprintf("%0*.*i", 20, 5, 1024) == Printf.@sprintf("%020.5i", 1024) @test Printf.@sprintf("%0*.*i", 20, 5, -1024) == Printf.@sprintf("%020.5i", -1024) @test Printf.@sprintf("%0*.*u", 20, 5, 1024) == Printf.@sprintf("%020.5u", 1024) @test Printf.@sprintf("%0*.*u", 20, 5, UInt(4294966272)) == Printf.@sprintf("%020.5u", UInt(4294966272)) @test Printf.@sprintf("%0*.*o", 20, 5, 511) == Printf.@sprintf("%020.5o", 511) @test Printf.@sprintf("%0*.*o", 20, 5, UInt(4294966785)) == Printf.@sprintf("%020.5o", UInt(4294966785)) @test Printf.@sprintf("%0*.*x", 20, 5, 305441741) == Printf.@sprintf("%020.5x", 305441741) @test Printf.@sprintf("%0*.*x", 20, 10, UInt(3989525555)) == Printf.@sprintf("%020.10x", UInt(3989525555)) @test Printf.@sprintf("%0*.*X", 20, 5, 305441741) == Printf.@sprintf("%020.5X", 305441741) @test Printf.@sprintf("%0*.*X", 20, 10, UInt(3989525555)) == Printf.@sprintf("%020.10X", UInt(3989525555)) @test Printf.@sprintf("%*.0d", 20, 1024) == Printf.@sprintf("%20.0d", 1024) @test Printf.@sprintf("%*.d", 20, -1024) == Printf.@sprintf("%20.d", -1024) @test Printf.@sprintf("%*.d", 20, 0) == Printf.@sprintf("%20.d", 0) @test Printf.@sprintf("%*.0i", 20, 1024) == Printf.@sprintf("%20.0i", 1024) @test Printf.@sprintf("%*.i", 20, -1024) == Printf.@sprintf("%20.i", -1024) @test Printf.@sprintf("%*.i", 20, 0) == Printf.@sprintf("%20.i", 0) @test Printf.@sprintf("%*.u", 20, 1024) == Printf.@sprintf("%20.u", 1024) @test Printf.@sprintf("%*.0u", 20, UInt(4294966272)) == Printf.@sprintf("%20.0u", UInt(4294966272)) @test Printf.@sprintf("%*.u", 20, UInt(0)) == Printf.@sprintf("%20.u", UInt(0)) @test Printf.@sprintf("%*.o", 20, 511) == Printf.@sprintf("%20.o", 511) @test Printf.@sprintf("%*.0o", 20, UInt(4294966785)) == Printf.@sprintf("%20.0o", UInt(4294966785)) @test Printf.@sprintf("%*.o", 20, UInt(0)) == Printf.@sprintf("%20.o", UInt(0)) @test Printf.@sprintf("%*.x", 20, 305441741) == Printf.@sprintf("%20.x", 305441741) @test Printf.@sprintf("%*.0x", 20, UInt(3989525555)) == Printf.@sprintf("%20.0x", UInt(3989525555)) @test Printf.@sprintf("%*.x", 20, UInt(0)) == Printf.@sprintf("%20.x", UInt(0)) @test Printf.@sprintf("%*.X", 20, 305441741) == Printf.@sprintf("%20.X", 305441741) @test Printf.@sprintf("%*.0X", 20, UInt(3989525555)) == Printf.@sprintf("%20.0X", UInt(3989525555)) @test Printf.@sprintf("%*.X", 20, UInt(0)) == Printf.@sprintf("%20.X", UInt(0)) x = Ref{Int}() y = Ref{Int}() @test begin Printf.@sprintf "%10s%n" "😉" x Printf.@sprintf "%*s%n" 10 "😉" y x[] == y[] end @test begin Printf.@sprintf "%10s%n" "1234" x Printf.@sprintf "%*s%n" 10 "1234" y x[] == y[] end end begin @test Printf.@sprintf("%*d", 10, 12) == " 12" @test Printf.@sprintf("%.*d", 4, 12) == "0012" @test Printf.@sprintf("%*.*d", 10, 4, 12) == " 0012" @test Printf.@sprintf("%+*.*d", 10, 4, 12) == " +0012" @test Printf.@sprintf("%0*.*d", 10, 4, 12) == " 0012" @test Printf.@sprintf("%*d%*d%*d", 4, 12, 4, 13, 4, 14) == " 12 13 14" @test Printf.@sprintf("%*d%*d%*d", 4, 12, 5, 13, 6, 14) == " 12 13 14" @test Printf.@sprintf("%*p", 20, 0) == Printf.@sprintf("%20p", 0) @test Printf.@sprintf("%-*p", 20, 0) == Printf.@sprintf("%-20p", 0) @test Printf.@sprintf("%*p", 20, C_NULL) == Printf.@sprintf("%20p", C_NULL) @test Printf.@sprintf("%-*p", 20, C_NULL) == Printf.@sprintf("%-20p", C_NULL) @test Printf.@sprintf("%.*a", 0, 3.14) == Printf.@sprintf("%.0a", 3.14) @test Printf.@sprintf("%.*a", 1, 3.14) == Printf.@sprintf("%.1a", 3.14) @test Printf.@sprintf("%.*a", 2, 3.14) == Printf.@sprintf("%.2a", 3.14) @test Printf.@sprintf("%#.*a", 0, 3.14) == Printf.@sprintf("%#.0a", 3.14) @test Printf.@sprintf("%#.*a", 1, 3.14) == Printf.@sprintf("%#.1a", 3.14) @test Printf.@sprintf("%#.*a", 2, 3.14) == Printf.@sprintf("%#.2a", 3.14) @test Printf.@sprintf("%.*a", 6, 1.5) == Printf.@sprintf("%.6a", 1.5) @test Printf.@sprintf("%*.*g", 10, 5, -123.4) == Printf.@sprintf("%10.5g", -123.4) @test Printf.@sprintf("%0*.*g", 10, 5, -123.4) == Printf.@sprintf("%010.5g", -123.4) @test Printf.@sprintf("%.*g", 6, 1.234e7) == Printf.@sprintf("%.6g", 1.234e7) @test Printf.@sprintf("%#.*g", 6, 1.234e7) == Printf.@sprintf("%#.6g", 1.234e7) @test Printf.@sprintf("%*.*g", 10, 5, -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) == Printf.@sprintf("%10.5g", -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) @test Printf.@sprintf("%0*.*g", 10, 5, -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) == Printf.@sprintf("%010.5g", -123.4000000000000000000000000000000000000000000000000000000000000000000000000002) @test Printf.@sprintf("%.*g", 6, 1.234e7) == Printf.@sprintf("%.6g", 1.234e7) @test Printf.@sprintf("%#.*g", 6, 1.234e7) == Printf.@sprintf("%#.6g", 1.234e7) @test Printf.@sprintf("%.*g", 5, 42) == Printf.@sprintf("%.5g", 42) @test Printf.@sprintf("%#.*g", 2, 42) == Printf.@sprintf("%#.2g", 42) @test Printf.@sprintf("%#.*g", 5, 42) == Printf.@sprintf("%#.5g", 42) @test Printf.@sprintf("%.*g", 15, 0) == Printf.@sprintf("%.15g", 0) @test Printf.@sprintf("%#.*g", 15, 0) == Printf.@sprintf("%#.15g", 0) @test Printf.@sprintf("%.*f", 0, 3.0e142) == Printf.@sprintf("%.0f", 3.0e142) @test Printf.@sprintf("%.*f", 2, 1.234) == Printf.@sprintf("%.2f", 1.234) @test Printf.@sprintf("%.*f", 2, 1.235) == Printf.@sprintf("%.2f", 1.235) @test Printf.@sprintf("%.*f", 2, 0.235) == Printf.@sprintf("%.2f", 0.235) @test Printf.@sprintf("%*.*f", 4, 1, 1.234) == Printf.@sprintf("%4.1f", 1.234) @test Printf.@sprintf("%*.*f", 8, 1, 1.234) == Printf.@sprintf("%8.1f", 1.234) @test Printf.@sprintf("%+*.*f", 8, 1, 1.234) == Printf.@sprintf("%+8.1f", 1.234) @test Printf.@sprintf("% *.*f", 8, 1, 1.234) == Printf.@sprintf("% 8.1f", 1.234) @test Printf.@sprintf("% *.*f", 7, 1, 1.234) == Printf.@sprintf("% 7.1f", 1.234) @test Printf.@sprintf("% 0*.*f", 8, 1, 1.234) == Printf.@sprintf("% 08.1f", 1.234) @test Printf.@sprintf("%0*.*f", 8, 1, 1.234) == Printf.@sprintf("%08.1f", 1.234) @test Printf.@sprintf("%-0*.*f", 8, 1, 1.234) == Printf.@sprintf("%-08.1f", 1.234) @test Printf.@sprintf("%-*.*f", 8, 1, 1.234) == Printf.@sprintf("%-8.1f", 1.234) @test Printf.@sprintf("%0*.*f", 8, 1, -1.234) == Printf.@sprintf("%08.1f", -1.234) @test Printf.@sprintf("%0*.*f", 9, 1, -1.234) == Printf.@sprintf("%09.1f", -1.234) @test Printf.@sprintf("%0*.*f", 9, 1, 1.234) == Printf.@sprintf("%09.1f", 1.234) @test Printf.@sprintf("%+0*.*f", 9, 1, 1.234) == Printf.@sprintf("%+09.1f", 1.234) @test Printf.@sprintf("% 0*.*f", 9, 1, 1.234) == Printf.@sprintf("% 09.1f", 1.234) @test Printf.@sprintf("%+ 0*.*f", 9, 1, 1.234) == Printf.@sprintf("%+ 09.1f", 1.234) @test Printf.@sprintf("%+ 0*.*f", 9, 1, 1.234) == Printf.@sprintf("%+ 09.1f", 1.234) @test Printf.@sprintf("%+ 0*.*f", 9, 0, 1.234) == Printf.@sprintf("%+ 09.0f", 1.234) @test Printf.@sprintf("%+ #0*.*f", 9, 0, 1.234) == Printf.@sprintf("%+ #09.0f", 1.234) @test Printf.@sprintf("%*.*e", 10, 4, Inf) == Printf.@sprintf("%10.4e", Inf) @test Printf.@sprintf("%*.*e", 10, 4, NaN) == Printf.@sprintf("%10.4e", NaN) @test Printf.@sprintf("%*.*e", 10, 4, Inf) == Printf.@sprintf("%10.4e", Inf) @test Printf.@sprintf("%*.*e", 10, 4, NaN) == Printf.@sprintf("%10.4e", NaN) @test Printf.@sprintf("%.*e", 0, 3.0e142) == Printf.@sprintf("%.0e", 3.0e142) @test Printf.@sprintf("%#.*e", 0, 3.0e142) == Printf.@sprintf("%#.0e", 3.0e142) @test Printf.@sprintf("%.*e", 0, 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) == Printf.@sprintf("%.0e", 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) @test Printf.@sprintf("%#.*e", 0, 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) == Printf.@sprintf("%#.0e", 2.999999999999999999999999999999999999999999999999999999999999999999999999999996e142) @test Printf.@sprintf("%.*e", 0, 3.000000000000000000000000000000000000000000000000000000000000000000000000000024e1042) == Printf.@sprintf("%.0e", 3.000000000000000000000000000000000000000000000000000000000000000000000000000024e1042) @test Printf.@sprintf("%.*e", 2, 1.234) == Printf.@sprintf("%.2e", 1.234) @test Printf.@sprintf("%.*e", 2, 1.235) == Printf.@sprintf("%.2e", 1.235) @test Printf.@sprintf("%.*e", 2, 0.235) == Printf.@sprintf("%.2e", 0.235) @test Printf.@sprintf("%*.*e", 4, 1, 1.234) == Printf.@sprintf("%4.1e", 1.234) @test Printf.@sprintf("%*.*e", 8, 1, 1.234) == Printf.@sprintf("%8.1e", 1.234) @test Printf.@sprintf("%+*.*e", 8, 1, 1.234) == Printf.@sprintf("%+8.1e", 1.234) @test Printf.@sprintf("% *.*e", 8, 1, 1.234) == Printf.@sprintf("% 8.1e", 1.234) @test Printf.@sprintf("% *.*e", 7, 1, 1.234) == Printf.@sprintf("% 7.1e", 1.234) @test Printf.@sprintf("% 0*.*e", 8, 1, 1.234) == Printf.@sprintf("% 08.1e", 1.234) @test Printf.@sprintf("%0*.*e", 8, 1, 1.234) == Printf.@sprintf("%08.1e", 1.234) @test Printf.@sprintf("%-0*.*e", 8, 1, 1.234) == Printf.@sprintf("%-08.1e", 1.234) @test Printf.@sprintf("%-*.*e", 8, 1, 1.234) == Printf.@sprintf("%-8.1e", 1.234) @test Printf.@sprintf("%-*.*e", 8, 1, 1.234) == Printf.@sprintf("%-8.1e", 1.234) @test Printf.@sprintf("%0*.*e", 8, 1, -1.234) == Printf.@sprintf("%08.1e", -1.234) @test Printf.@sprintf("%0*.*e", 9, 1, -1.234) == Printf.@sprintf("%09.1e", -1.234) @test Printf.@sprintf("%0*.*e", 9, 1, 1.234) == Printf.@sprintf("%09.1e", 1.234) @test Printf.@sprintf("%+0*.*e", 9, 1, 1.234) == Printf.@sprintf("%+09.1e", 1.234) @test Printf.@sprintf("% 0*.*e", 9, 1, 1.234) == Printf.@sprintf("% 09.1e", 1.234) @test Printf.@sprintf("%+ 0*.*e", 9, 1, 1.234) == Printf.@sprintf("%+ 09.1e", 1.234) @test Printf.@sprintf("%+ 0*.*e", 9, 1, 1.234) == Printf.@sprintf("%+ 09.1e", 1.234) @test Printf.@sprintf("%+ 0*.*e", 9, 0, 1.234) == Printf.@sprintf("%+ 09.0e", 1.234) @test Printf.@sprintf("%+ #0*.*e", 9, 0, 1.234) == Printf.@sprintf("%+ #09.0e", 1.234) @test Printf.@sprintf("%.*s", 1, "foo") == Printf.@sprintf("%.1s", "foo") @test Printf.@sprintf("%*s", 1, "Hallo heimur") == Printf.@sprintf("%1s", "Hallo heimur") @test Printf.@sprintf("%*s", 20, "Hallo") == Printf.@sprintf("%20s", "Hallo") @test Printf.@sprintf("%-*s", 20, "Hallo") == Printf.@sprintf("%-20s", "Hallo") @test Printf.@sprintf("%0-*s", 20, "Hallo") == Printf.@sprintf("%0-20s", "Hallo") @test Printf.@sprintf("%.*s", 20, "Hallo heimur") == Printf.@sprintf("%.20s", "Hallo heimur") @test Printf.@sprintf("%*.*s", 20, 5, "Hallo heimur") == Printf.@sprintf("%20.5s", "Hallo heimur") @test Printf.@sprintf("%.*s", 0, "Hallo heimur") == Printf.@sprintf("%.0s", "Hallo heimur") @test Printf.@sprintf("%*.*s", 20, 0, "Hallo heimur") == Printf.@sprintf("%20.0s", "Hallo heimur") @test Printf.@sprintf("%.s", "Hallo heimur") == Printf.@sprintf("%.s", "Hallo heimur") @test Printf.@sprintf("%*.s", 20, "Hallo heimur") == Printf.@sprintf("%20.s", "Hallo heimur") @test Printf.@sprintf("%*sø", 4, "ø") == Printf.@sprintf("%4sø", "ø") @test Printf.@sprintf("%-*sø", 4, "ø") == Printf.@sprintf("%-4sø", "ø") @test Printf.@sprintf("%*s", 8, "test") == Printf.@sprintf("%8s", "test") @test Printf.@sprintf("%-*s", 8, "test") == Printf.@sprintf("%-8s", "test") @test Printf.@sprintf("%#*s", 8, :test) == Printf.@sprintf("%#8s", :test) @test Printf.@sprintf("%#-*s", 8, :test) == Printf.@sprintf("%#-8s", :test) @test Printf.@sprintf("%*.*s", 8, 3, "test") == Printf.@sprintf("%8.3s", "test") @test Printf.@sprintf("%#*.*s", 8, 3, "test") == Printf.@sprintf("%#8.3s", "test") @test Printf.@sprintf("%-*.*s", 8, 3, "test") == Printf.@sprintf("%-8.3s", "test") @test Printf.@sprintf("%#-*.*s", 8, 3, "test") == Printf.@sprintf("%#-8.3s", "test") @test Printf.@sprintf("%.*s", 3, "test") == Printf.@sprintf("%.3s", "test") @test Printf.@sprintf("%#.*s", 3, "test") == Printf.@sprintf("%#.3s", "test") @test Printf.@sprintf("%-.*s", 3, "test") == Printf.@sprintf("%-.3s", "test") @test Printf.@sprintf("%#-.*s", 3, "test") == Printf.@sprintf("%#-.3s", "test") @test Printf.@sprintf("%*c", 3, 'a') == Printf.@sprintf("%3c", 'a') @test Printf.@sprintf("%*c", 1, 'x') == Printf.@sprintf("%1c", 'x') @test Printf.@sprintf("%*c", 20, 'x') == Printf.@sprintf("%20c", 'x') @test Printf.@sprintf("%-*c", 20, 'x') == Printf.@sprintf("%-20c", 'x') @test Printf.@sprintf("%-0*c", 20, 'x') == Printf.@sprintf("%-020c", 'x') @test Printf.@sprintf("%*c", 3, 'A') == Printf.@sprintf("%3c", 'A') @test Printf.@sprintf("%-*c", 3, 'A') == Printf.@sprintf("%-3c", 'A') @test Printf.@sprintf("%*.*f %*.*f %*.*f %*.*f %*.*f %*.*f %*.*f %*.*f %*.*f %*.*f %*.*f %*.*f %*.*f %*.*f %*.*f %*.*f %*.*f %*.*f", 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345, 4, 2, 1.2345) == Printf.@sprintf("%4.2f %4.2f %4.2f %4.2f %4.2f %4.2f %4.2f %4.2f %4.2f %4.2f %4.2f %4.2f %4.2f %4.2f %4.2f %4.2f %4.2f %4.2f", 1.2345, 1.2345, 1.2345, 1.2345, 1.2345, 1.2345, 1.2345, 1.2345, 1.2345, 1.2345, 1.2345, 1.2345, 1.2345, 1.2345, 1.2345, 1.2345, 1.2345, 1.2345) @test (Printf.@sprintf("%.*f", 330, BigFloat(1)))[var"end"] != '\0' @test Printf.@sprintf("%*.*s", 4, 2, "a") == Printf.@sprintf("%4.2s", "a") @test Printf.@sprintf("%*.*e", 12, 3, pi * 1.0e100) == Printf.@sprintf("%12.3e", pi * 1.0e100) @test Printf.@sprintf("%*d", 2, 3.14) == Printf.@sprintf("%*d", 2, 3.14) @test Printf.@sprintf("%*d", 2, big(3.14)) == Printf.@sprintf("%*d", 2, big(3.14)) @test Printf.@sprintf(" %.*e\n", 1, 0.999) == Printf.@sprintf(" %.1e\n", 0.999) @test Printf.@sprintf(" %.*f", 1, 9.999) == Printf.@sprintf(" %.1f", 9.999) @test Printf.@sprintf("%*d", 10, 12) == Printf.@sprintf("%10d", 12) @test Printf.@sprintf("%.*d", 4, 12) == Printf.@sprintf("%.4d", 12) @test Printf.@sprintf("%*.*d", 10, 4, 12) == Printf.@sprintf("%10.4d", 12) @test Printf.@sprintf("%+*.*d", 10, 4, 12) == Printf.@sprintf("%+10.4d", 12) @test Printf.@sprintf("%0*.*d", 10, 4, 12) == Printf.@sprintf("%010.4d", 12) @test Printf.@sprintf("% *d", 5, 42) == Printf.@sprintf("% 5d", 42) @test Printf.@sprintf("% *d", 5, -42) == Printf.@sprintf("% 5d", -42) @test Printf.@sprintf("% *d", 15, 42) == Printf.@sprintf("% 15d", 42) @test Printf.@sprintf("% *d", 15, -42) == Printf.@sprintf("% 15d", -42) @test Printf.@sprintf("%+*d", 5, 42) == Printf.@sprintf("%+5d", 42) @test Printf.@sprintf("%+*d", 5, -42) == Printf.@sprintf("%+5d", -42) @test Printf.@sprintf("%+*d", 15, 42) == Printf.@sprintf("%+15d", 42) @test Printf.@sprintf("%+*d", 15, -42) == Printf.@sprintf("%+15d", -42) @test Printf.@sprintf("%*d", 0, 42) == Printf.@sprintf("%0d", 42) @test Printf.@sprintf("%*d", 0, -42) == Printf.@sprintf("%0d", -42) @test Printf.@sprintf("%-*d", 5, 42) == Printf.@sprintf("%-5d", 42) @test Printf.@sprintf("%-*d", 5, PkgEval terminated after 218.45s: test log exceeded the size limit