From 3c3ced4153cdc2c75319b41155c38ad1f2545fc2 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 10 May 2017 15:57:32 -0400 Subject: [PATCH] replace current_module() with @__MODULE__ passes macros a __module__ argument, like the __source__ argument, allowing them to inspect and configure themselves based on their evaluation context remove current_module dependence from `include`: instead, we use the same trick as for `eval` (they are basically the same function after all) to create a module-relative function in each non-bare module now puts Module in MethodInstance.def for toplevel thunks to make it convenient to pass around this contextual information --- NEWS.md | 5 + base/Enums.jl | 18 +- base/REPLCompletions.jl | 10 +- base/boot.jl | 8 +- base/client.jl | 22 +- base/coreimg.jl | 6 +- base/deprecated.jl | 49 ++- base/docs/Docs.jl | 89 +++--- base/docs/bindings.jl | 2 +- base/docs/core.jl | 14 +- base/docs/helpdb/Base.jl | 5 +- base/docs/utils.jl | 8 +- base/essentials.jl | 11 +- base/exports.jl | 3 +- base/expr.jl | 26 +- base/inference.jl | 41 +-- base/int.jl | 2 +- base/interactiveutil.jl | 37 ++- base/loading.jl | 44 +-- base/markdown/Markdown.jl | 12 +- base/operators.jl | 2 +- base/osutils.jl | 7 +- base/precompile.jl | 6 +- base/reflection.jl | 31 +- base/serialize.jl | 12 +- base/show.jl | 33 +- base/stacktraces.jl | 5 +- base/sysimg.jl | 48 ++- base/test.jl | 2 +- base/util.jl | 9 +- doc/src/devdocs/ast.md | 4 +- doc/src/manual/calling-c-and-fortran-code.md | 18 +- doc/src/manual/metaprogramming.md | 13 +- doc/src/manual/modules.md | 4 +- doc/src/manual/parallel-computing.md | 4 +- doc/src/stdlib/base.md | 3 +- src/ast.c | 114 +++---- src/builtins.c | 12 +- src/ccall.cpp | 6 +- src/cgutils.cpp | 6 +- src/codegen.cpp | 133 ++++---- src/datatype.c | 40 ++- src/dump.c | 28 +- src/gf.c | 73 ++--- src/init.c | 10 +- src/interpreter.c | 67 ++-- src/jlapi.c | 2 +- src/jlfrontend.scm | 30 +- src/jltypes.c | 315 ++++++++++--------- src/julia-syntax.scm | 1 + src/julia.h | 37 ++- src/julia_internal.h | 33 +- src/method.c | 77 ++--- src/module.c | 9 +- src/rtutils.c | 12 +- src/task.c | 1 + src/toplevel.c | 126 ++++---- test/broadcast.jl | 12 +- test/cmdlineargs.jl | 4 +- test/core.jl | 28 +- test/distributed_exec.jl | 2 +- test/docs.jl | 13 +- test/fastmath.jl | 12 +- test/inline.jl | 4 +- test/loading.jl | 4 +- test/misc.jl | 4 +- test/parse.jl | 79 ++--- test/reflection.jl | 57 ++-- test/repl.jl | 2 +- test/replutil.jl | 8 +- test/stacktraces.jl | 3 +- test/strings/basic.jl | 2 +- test/testenv.jl | 4 +- test/threads.jl | 12 +- test/workspace.jl | 30 +- ui/repl.c | 2 +- 76 files changed, 1106 insertions(+), 921 deletions(-) diff --git a/NEWS.md b/NEWS.md index 8b3cd9626662d..849dda108f0fb 100644 --- a/NEWS.md +++ b/NEWS.md @@ -73,6 +73,11 @@ Deprecated or removed * The `cholfact`/`cholfact!` methods that accepted an `uplo` symbol have been deprecated in favor of using `Hermitian` (or `Symmetric`) views ([#22187], [#22188]). + * The function `current_module` is deprecated and replaced with `@__MODULE__` ([#22064]). + This caused the deprecation of some reflection methods (such as `macroexpand` and `isconst`), + which now require a module argument. + And it caused the bugfix of other default arguments to use the Main module (including `whos`, `which`). + Julia v0.6.0 Release Notes ========================== diff --git a/base/Enums.jl b/base/Enums.jl index 13976a72d8e5f..ea58302001046 100644 --- a/base/Enums.jl +++ b/base/Enums.jl @@ -49,19 +49,19 @@ julia> f(apple) Member values can be converted between the enum type and `BaseType`. `read` and `write` perform these conversions automatically. """ -macro enum(T,syms...) +macro enum(T, syms...) if isempty(syms) throw(ArgumentError("no arguments given for Enum $T")) end basetype = Int32 typename = T - if isa(T,Expr) && T.head == :(::) && length(T.args) == 2 && isa(T.args[1], Symbol) + if isa(T, Expr) && T.head == :(::) && length(T.args) == 2 && isa(T.args[1], Symbol) typename = T.args[1] - basetype = eval(current_module(),T.args[2]) + basetype = eval(__module__, T.args[2]) if !isa(basetype, DataType) || !(basetype <: Integer) || !isbits(basetype) throw(ArgumentError("invalid base type for Enum $typename, $T=::$basetype; base type must be an integer primitive type")) end - elseif !isa(T,Symbol) + elseif !isa(T, Symbol) throw(ArgumentError("invalid type expression for enum $T")) end vals = Vector{Tuple{Symbol,Integer}}(0) @@ -69,14 +69,14 @@ macro enum(T,syms...) i = zero(basetype) hasexpr = false for s in syms - if isa(s,Symbol) + if isa(s, Symbol) if i == typemin(basetype) && !isempty(vals) throw(ArgumentError("overflow in value \"$s\" of Enum $typename")) end - elseif isa(s,Expr) && + elseif isa(s, Expr) && (s.head == :(=) || s.head == :kw) && - length(s.args) == 2 && isa(s.args[1],Symbol) - i = eval(current_module(),s.args[2]) # allow exprs, e.g. uint128"1" + length(s.args) == 2 && isa(s.args[1], Symbol) + i = eval(__module__, s.args[2]) # allow exprs, e.g. uint128"1" if !isa(i, Integer) throw(ArgumentError("invalid value for Enum $typename, $s=$i; values must be integers")) end @@ -144,7 +144,7 @@ macro enum(T,syms...) end end end - if isa(typename,Symbol) + if isa(typename, Symbol) for (sym,i) in vals push!(blk.args, :(const $(esc(sym)) = $(esc(typename))($i))) end diff --git a/base/REPLCompletions.jl b/base/REPLCompletions.jl index d58aebe5f9832..2ba4b24a4c446 100644 --- a/base/REPLCompletions.jl +++ b/base/REPLCompletions.jl @@ -292,9 +292,10 @@ function get_type_call(expr::Expr) return_type === nothing && return (Any, false) return (return_type, true) end -# Returns the return type. example: get_type(:(Base.strip("",' ')),Main) returns (String,true) -function get_type(sym::Expr, fn) - sym=expand(sym) + +# Returns the return type. example: get_type(:(Base.strip("", ' ')), Main) returns (String, true) +function get_type(sym::Expr, fn::Module) + sym = expand(fn, sym) val, found = get_value(sym, fn) found && return Base.typesof(val).parameters[1], found if sym.head === :call @@ -310,10 +311,11 @@ function get_type(sym::Expr, fn) end return (Any, false) end -function get_type(sym, fn) +function get_type(sym, fn::Module) val, found = get_value(sym, fn) return found ? Base.typesof(val).parameters[1] : Any, found end + # Method completion on function call expression that look like :(max(1)) function complete_methods(ex_org::Expr) args_ex = Any[] diff --git a/base/boot.jl b/base/boot.jl index 23e803b81fe06..31255bea909a5 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -230,7 +230,7 @@ String(s::String) = s # no constructor yet # This should always be inlined getptls() = ccall(:jl_get_ptls_states, Ptr{Void}, ()) -include(fname::String) = ccall(:jl_load_, Any, (Any,), fname) +include(m::Module, fname::String) = ccall(:jl_load_, Any, (Any, Any), m, fname) eval(e::ANY) = eval(Main, e) eval(m::Module, e::ANY) = ccall(:jl_toplevel_eval_in, Any, (Any, Any), m, e) @@ -337,7 +337,7 @@ end # docsystem basics macro doc(x...) - atdoc(__source__, x...) + atdoc(__source__, __module__, x...) end macro __doc__(x) Expr(:escape, Expr(:block, Expr(:meta, :doc), x)) @@ -345,7 +345,7 @@ end macro doc_str(s) Expr(:escape, s) end -atdoc = (source, str, expr) -> Expr(:escape, expr) +atdoc = (source, mod, str, expr) -> Expr(:escape, expr) atdoc!(λ) = global atdoc = λ @@ -382,4 +382,4 @@ show(a::ANY) = show(STDOUT, a) print(a::ANY...) = print(STDOUT, a...) println(a::ANY...) = println(STDOUT, a...) -ccall(:jl_set_istopmod, Void, (Bool,), true) +ccall(:jl_set_istopmod, Void, (Any, Bool), Core, true) diff --git a/base/client.jl b/base/client.jl index 2f22a24ca6e7e..1b2f6506911a8 100644 --- a/base/client.jl +++ b/base/client.jl @@ -153,7 +153,7 @@ function eval_user_input(ast::ANY, show_value) display_error(lasterr,bt) errcount, lasterr = 0, () else - ast = expand(ast) + ast = expand(Main, ast) value = eval(Main, ast) eval(Main, Expr(:body, Expr(:(=), :ans, QuoteNode(value)), Expr(:return, nothing))) if !(value === nothing) && show_value @@ -210,7 +210,7 @@ function parse_input_line(s::String; filename::String="none") s, sizeof(s), filename, sizeof(filename)) if ex === :_ # remove with 0.6 deprecation - expand(ex) # to get possible warning about using _ as an rvalue + expand(Main, ex) # to get possible warning about using _ as an rvalue end return ex end @@ -243,7 +243,7 @@ function incomplete_tag(ex::Expr) end # try to include() a file, ignoring if not found -try_include(path::AbstractString) = isfile(path) && include(path) +try_include(mod::Module, path::AbstractString) = isfile(path) && include(mod, path) function process_options(opts::JLOptions) if !isempty(ARGS) @@ -279,7 +279,7 @@ function process_options(opts::JLOptions) # load file immediately on all processors if opts.load != C_NULL @sync for p in procs() - @async remotecall_fetch(include, p, unsafe_string(opts.load)) + @async remotecall_fetch(include, p, Main, unsafe_string(opts.load)) end end # eval expression @@ -304,7 +304,7 @@ function process_options(opts::JLOptions) if !is_interactive ccall(:jl_exit_on_sigint, Void, (Cint,), 1) end - include(PROGRAM_FILE) + include(Main, PROGRAM_FILE) end break end @@ -315,12 +315,13 @@ end function load_juliarc() # If the user built us with a specific Base.SYSCONFDIR, check that location first for a juliarc.jl file # If it is not found, then continue on to the relative path based on JULIA_HOME - if !isempty(Base.SYSCONFDIR) && isfile(joinpath(JULIA_HOME,Base.SYSCONFDIR,"julia","juliarc.jl")) - include(abspath(JULIA_HOME,Base.SYSCONFDIR,"julia","juliarc.jl")) + if !isempty(Base.SYSCONFDIR) && isfile(joinpath(JULIA_HOME, Base.SYSCONFDIR, "julia", "juliarc.jl")) + include(Main, abspath(JULIA_HOME, Base.SYSCONFDIR, "julia", "juliarc.jl")) else - try_include(abspath(JULIA_HOME,"..","etc","julia","juliarc.jl")) + try_include(Main, abspath(JULIA_HOME, "..", "etc", "julia", "juliarc.jl")) end - try_include(abspath(homedir(),".juliarc.jl")) + try_include(Main, abspath(homedir(), ".juliarc.jl")) + nothing end function load_machine_file(path::AbstractString) @@ -363,12 +364,13 @@ function __atreplinit(repl) end end end -_atreplinit(repl) = @eval Main $__atreplinit($repl) +_atreplinit(repl) = invokelatest(__atreplinit, repl) function _start() empty!(ARGS) append!(ARGS, Core.ARGS) opts = JLOptions() + @eval Main include(x) = $include(Main, x) try (quiet,repl,startup,color_set,history_file) = process_options(opts) diff --git a/base/coreimg.jl b/base/coreimg.jl index 8b552d51252e7..5739e8136084f 100644 --- a/base/coreimg.jl +++ b/base/coreimg.jl @@ -4,12 +4,14 @@ Main.Core.eval(Main.Core, :(baremodule Inference using Core.Intrinsics import Core: print, println, show, write, unsafe_write, STDOUT, STDERR -ccall(:jl_set_istopmod, Void, (Bool,), false) +ccall(:jl_set_istopmod, Void, (Any, Bool), Inference, false) eval(x) = Core.eval(Inference, x) eval(m, x) = Core.eval(m, x) -const include = Core.include +include(x) = Core.include(Inference, x) +include(mod, x) = Core.include(mod, x) + # conditional to allow redefining Core.Inference after base exists isdefined(Main, :Base) || ((::Type{T})(arg) where {T} = convert(T, arg)::T) diff --git a/base/deprecated.jl b/base/deprecated.jl index 0038126797536..062456c7146b4 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -103,14 +103,13 @@ function firstcaller(bt::Array{Ptr{Void},1}, funcsyms) return lkup end -deprecate(s::Symbol) = deprecate(current_module(), s) deprecate(m::Module, s::Symbol) = ccall(:jl_deprecate_binding, Void, (Any, Any), m, s) macro deprecate_binding(old, new, export_old=true) - Expr(:toplevel, + return Expr(:toplevel, export_old ? Expr(:export, esc(old)) : nothing, Expr(:const, Expr(:(=), esc(old), esc(new))), - Expr(:call, :deprecate, Expr(:quote, old))) + Expr(:call, :deprecate, __module__, Expr(:quote, old))) end # BEGIN 0.6-alpha deprecations (delete when 0.6 is released) @@ -630,7 +629,7 @@ for (Bsig, A1sig, A2sig, gbb, funcname) in func = @get! cache f gen_broadcast_function_sparse($gbb, f, ($A1sig) <: SparseMatrixCSC) # need eval because func was just created by gen_broadcast_function_sparse # TODO: convert this to a generated function - eval(current_module(), Expr(:body, Expr(:return, Expr(:call, QuoteNode(func), QuoteNode(B), QuoteNode(A1), QuoteNode(A2))))) + eval(_current_module(), Expr(:body, Expr(:return, Expr(:call, QuoteNode(func), QuoteNode(B), QuoteNode(A1), QuoteNode(A2))))) return B end end # let broadcast_cache @@ -1362,6 +1361,48 @@ end @deprecate cholfact!(A::StridedMatrix, uplo::Symbol, ::Type{Val{true}}; tol = 0.0) cholfact!(Hermitian(A, uplo), Val{true}, tol = tol) @deprecate cholfact(A::StridedMatrix, uplo::Symbol, ::Type{Val{true}}; tol = 0.0) cholfact(Hermitian(A, uplo), Val{true}, tol = tol) +# also remove all support machinery in src for current_module when removing this deprecation +# and make Base.include an error +_current_module() = ccall(:jl_get_current_module, Ref{Module}, ()) +@noinline function binding_module(s::Symbol) + depwarn("binding_module(symbol) is deprecated, use `binding_module(module, symbol)` instead.", :binding_module) + return binding_module(_current_module(), s) +end +@noinline function expand(x::ANY) + depwarn("expand(x) is deprecated, use `expand(module, x)` instead.", :expand) + return expand(_current_module(), x) +end +@noinline function macroexpand(x::ANY) + depwarn("macroexpand(x) is deprecated, use `macroexpand(module, x)` instead.", :macroexpand) + return macroexpand(_current_module(), x) +end +@noinline function isconst(s::Symbol) + depwarn("isconst(symbol) is deprecated, use `isconst(module, symbol)` instead.", :isconst) + return isconst(_current_module(), s) +end +@noinline function include_string(txt::AbstractString, fname::AbstractString) + depwarn("include_string(string, fname) is deprecated, use `include_string(module, string, fname)` instead.", :include_string) + return include_string(_current_module(), txt, fname) +end +@noinline function include_string(txt::AbstractString) + depwarn("include_string(string) is deprecated, use `include_string(module, string)` instead.", :include_string) + return include_string(_current_module(), txt, "string") +end + +""" + current_module() -> Module + +Get the *dynamically* current `Module`, which is the `Module` code is currently being read +from. In general, this is not the same as the module containing the call to this function. + +DEPRECATED: use @__MODULE__ instead +""" +@noinline function current_module() + depwarn("current_module() is deprecated, use `@__MODULE__` instead.", :current_module) + return _current_module() +end +export current_module + # END 0.7 deprecations # BEGIN 1.0 deprecations diff --git a/base/docs/Docs.jl b/base/docs/Docs.jl index 742635d2386b4..4ea4867bda60a 100644 --- a/base/docs/Docs.jl +++ b/base/docs/Docs.jl @@ -72,9 +72,9 @@ export doc const modules = Module[] const META = gensym(:meta) -meta(m::Module = current_module()) = isdefined(m, META) ? getfield(m, META) : ObjectIdDict() +meta(m::Module) = isdefined(m, META) ? getfield(m, META) : ObjectIdDict() -function initmeta(m::Module = current_module()) +function initmeta(m::Module) if !isdefined(m, META) eval(m, :(const $META = $(ObjectIdDict()))) push!(modules, m) @@ -169,10 +169,10 @@ _docstr(doc::DocStr, data) = (doc.data = merge(data, doc.data); doc) macro ref(x) binding = bindingexpr(namify(x)) typesig = signature(x) - esc(docexpr(__source__, binding, typesig)) + esc(docexpr(__source__, __module__, binding, typesig)) end -docexpr(__source__, args...) = Expr(:call, docstr, args...) +docexpr(__source__, __module__, args...) = Expr(:call, docstr, args...) function formatdoc(d::DocStr) buffer = IOBuffer() @@ -225,18 +225,17 @@ end # ======================= """ - Docs.doc!(binding, str, sig) + Docs.doc!(__module__, binding, str, sig) -Adds a new docstring `str` to the docsystem for `binding` and signature `sig`. +Adds a new docstring `str` to the docsystem of `__module__` for `binding` and signature `sig`. """ -function doc!(b::Binding, str::DocStr, sig::ANY = Union{}) - initmeta() - m = get!(meta(), b, MultiDoc()) +function doc!(__module__::Module, b::Binding, str::DocStr, sig::ANY = Union{}) + initmeta(__module__) + m = get!(meta(__module__), b, MultiDoc()) if haskey(m.docs, sig) # We allow for docstrings to be updated, but print a warning since it is possible # that over-writing a docstring *may* have been accidental. - s = "replacing docs for '$b :: $sig' in module '$(current_module())'." - isdefined(Base, :STDERR) ? warn(s) : ccall(:jl_, Void, (Any,), "WARNING: $s") + warn("replacing docs for '$b :: $sig' in module '$(__module__)'.") else # The ordering of docstrings for each Binding is defined by the order in which they # are initially added. Replacing a specific docstring does not change it's ordering. @@ -482,7 +481,7 @@ isfield(x) = isexpr(x, :.) && # ========================= """ - Docs.metadata(source, expr) + Docs.metadata(source, module, expr, ismodule) Build a `Dict` expression containing metadata captured from the expression `expr`. @@ -493,14 +492,18 @@ Fields that may be included in the returned `Dict`: - `:module`: Module where the docstring is defined. - `:fields`: `Dict` of all field docs found in `expr`. Only for concrete types. """ -function metadata(__source__, expr) +function metadata(__source__, __module__, expr, ismodule) args = [] # Filename and linenumber of the docstring. __file__ = isa(__source__.file, Symbol) ? String(__source__.file) : "" push!(args, Pair(:path, __file__)) push!(args, Pair(:linenumber, __source__.line)) # Module in which the docstring is defined. - push!(args, :($(Pair)(:module, $(current_module)()))) + if ismodule # Module docs go inside the module with name `expr` + push!(args, :($Pair(:module, $expr))) + else + push!(args, Pair(:module, __module__)) + end if isexpr(expr, :type) # Field docs for concrete types. fields = [] @@ -519,34 +522,34 @@ function metadata(__source__, expr) :($(Dict)($(args...))) end -function keyworddoc(__source__, str, def) - docstr = esc(docexpr(__source__, lazy_iterpolate(str), metadata(__source__, def))) +function keyworddoc(__source__, __module__, str, def) + docstr = esc(docexpr(__source__, __module__, lazy_iterpolate(str), metadata(__source__, __module__, def, false))) return :($(keywords)[$(esc(quot(def.name)))] = $docstr) end -function objectdoc(__source__, str, def, expr, sig = :(Union{})) +function objectdoc(__source__, __module__, str, def, expr, sig = :(Union{})) binding = esc(bindingexpr(namify(expr))) - docstr = esc(docexpr(__source__, lazy_iterpolate(str), metadata(__source__, expr))) + docstr = esc(docexpr(__source__, __module__, lazy_iterpolate(str), metadata(__source__, __module__, expr, false))) quote $(esc(def)) - $(doc!)($binding, $docstr, $(esc(sig))) + $(doc!)($__module__, $binding, $docstr, $(esc(sig))) end end -function calldoc(__source__, str, def) +function calldoc(__source__, __module__, str, def) args = def.args[2:end] if isempty(args) || all(validcall, args) - objectdoc(__source__, str, nothing, def, signature(def)) + objectdoc(__source__, __module__, str, nothing, def, signature(def)) else docerror(def) end end validcall(x) = isa(x, Symbol) || isexpr(x, (:(::), :..., :kw, :parameters)) -function moduledoc(__source__, meta, def, def′) +function moduledoc(__source__, __module__, meta, def, def′) name = namify(def′) - docex = Expr(:call, doc!, bindingexpr(name), - docexpr(__source__, lazy_iterpolate(meta), metadata(__source__, name))) + docex = Expr(:call, doc!, name, bindingexpr(name), + docexpr(__source__, name, lazy_iterpolate(meta), metadata(__source__, __module__, name, true))) if def === nothing esc(:($eval($name, $(quot(docex))))) else @@ -562,16 +565,16 @@ function moduledoc(__source__, meta, def, def′) end # Shares a single doc, `meta`, between several expressions from the tuple expression `ex`. -function multidoc(__source__, meta, ex, define) +function multidoc(__source__, __module__, meta, ex, define) out = Expr(:toplevel) - str = docexpr(__source__, lazy_iterpolate(meta), metadata(__source__, ex)) + str = docexpr(__source__, __module__, lazy_iterpolate(meta), metadata(__source__, __module__, ex, false)) ref = Ref{DocStr}() for (n, arg) in enumerate(ex.args) # The first `arg` to be documented needs to also create the docstring for the group. # Subsequent `arg`s just need `ref` to be able to find the docstring without having # to create an entirely new one each. docstr = n === 1 ? :($(ref)[] = $str) : :($(ref)[]) - push!(out.args, docm(__source__, docstr, arg, define)) + push!(out.args, docm(__source__, __module__, docstr, arg, define)) end return out end @@ -649,14 +652,14 @@ isquotedmacrocall(x) = isbasicdoc(x) = isexpr(x, :.) || isa(x, Union{QuoteNode, Symbol}) is_signature(x) = isexpr(x, :call) || (isexpr(x, :(::), 2) && isexpr(x.args[1], :call)) || isexpr(x, :where) -function docm(source::LineNumberNode, meta, ex, define = true) +function docm(source::LineNumberNode, mod::Module, meta, ex, define = true) # Some documented expressions may be decorated with macro calls which obscure the actual # expression. Expand the macro calls and remove extra blocks. - x = unblock(macroexpand(ex)) + x = unblock(macroexpand(mod, ex)) # Don't try to redefine expressions. This is only needed for `Base` img gen since # otherwise calling `loaddocs` would redefine all documented functions and types. def = define ? x : nothing - if isa(x, GlobalRef) && (x::GlobalRef).mod == current_module() + if isa(x, GlobalRef) && (x::GlobalRef).mod == mod x = (x::GlobalRef).name end @@ -665,7 +668,7 @@ function docm(source::LineNumberNode, meta, ex, define = true) # "..." # kw"if", kw"else" # - isa(x, Base.BaseDocs.Keyword) ? keyworddoc(source, meta, x) : + isa(x, Base.BaseDocs.Keyword) ? keyworddoc(source, mod, meta, x) : # Method / macro definitions and "call" syntax. # @@ -675,9 +678,9 @@ function docm(source::LineNumberNode, meta, ex, define = true) # function f end # f(...) # - isexpr(x, FUNC_HEADS) && is_signature(x.args[1]) ? objectdoc(source, meta, def, x, signature(x)) : - isexpr(x, :function) && !isexpr(x.args[1], :call) ? objectdoc(source, meta, def, x) : - isexpr(x, :call) ? calldoc(source, meta, x) : + isexpr(x, FUNC_HEADS) && is_signature(x.args[1]) ? objectdoc(source, mod, meta, def, x, signature(x)) : + isexpr(x, :function) && !isexpr(x.args[1], :call) ? objectdoc(source, mod, meta, def, x) : + isexpr(x, :call) ? calldoc(source, mod, meta, x) : # Type definitions. # @@ -685,7 +688,7 @@ function docm(source::LineNumberNode, meta, ex, define = true) # abstract T # bitstype N T # - isexpr(x, [:type, :abstract, :bitstype]) ? objectdoc(source, meta, def, x) : + isexpr(x, [:type, :abstract, :bitstype]) ? objectdoc(source, mod, meta, def, x) : # "Bindings". Names that resolve to objects with different names, ie. # @@ -693,20 +696,20 @@ function docm(source::LineNumberNode, meta, ex, define = true) # T = S # global T = S # - isexpr(x, BINDING_HEADS) && !isexpr(x.args[1], :call) ? objectdoc(source, meta, def, x) : + isexpr(x, BINDING_HEADS) && !isexpr(x.args[1], :call) ? objectdoc(source, mod, meta, def, x) : # Quoted macrocall syntax. `:@time` / `:(Base.@time)`. - isquotedmacrocall(x) ? objectdoc(source, meta, def, x) : + isquotedmacrocall(x) ? objectdoc(source, mod, meta, def, x) : # Modules and baremodules. - isexpr(x, :module) ? moduledoc(source, meta, def, x) : + isexpr(x, :module) ? moduledoc(source, mod, meta, def, x) : # Document several expressions with the same docstring. `a, b, c`. - isexpr(x, :tuple) ? multidoc(source, meta, x, define) : + isexpr(x, :tuple) ? multidoc(source, mod, meta, x, define) : # Errors generated by calling `macroexpand` are passed back to the call site. isexpr(x, :error) ? esc(x) : # When documenting macro-generated code we look for embedded `@__doc__` calls. __doc__!(meta, x, define) ? esc(x) : # Any "basic" expression such as a bare function or module name or numeric literal. - isbasicdoc(x) ? objectdoc(source, meta, nothing, x) : + isbasicdoc(x) ? objectdoc(source, mod, meta, nothing, x) : # All other expressions are undocumentable and should be handled on a case-by-case basis # with `@__doc__`. Unbound string literals are also undocumentable since they cannot be @@ -725,9 +728,9 @@ function docerror(ex) :($(error)($txt, "\n")) end -function docm(source::LineNumberNode, ex) +function docm(source::LineNumberNode, mod::Module, ex) if isexpr(ex, :->) - docm(source, ex.args...) + docm(source, mod, ex.args...) elseif haskey(keywords, ex) parsedoc(keywords[ex]) elseif isa(ex, Union{Expr, Symbol}) @@ -764,7 +767,7 @@ function loaddocs(docs) for (mod, ex, str, file, line) in docs data = Dict(:path => string(file), :linenumber => line) doc = docstr(str, data) - docstring = eval(mod, Expr(:body, Expr(:return, Expr(:call, QuoteNode(docm), QuoteNode(LineNumberNode(line, file)), QuoteNode(doc), QuoteNode(ex), false)))) # expand the real @doc macro now (using a hack because macroexpand takes current-module as an implicit argument) + docstring = docm(LineNumberNode(line, file), mod, doc, ex, false) # expand the real @doc macro now eval(mod, Expr(:macrocall, unescape, nothing, docstring)) end empty!(docs) diff --git a/base/docs/bindings.jl b/base/docs/bindings.jl index ac7fbab7f6bfd..f0c73997c7b63 100644 --- a/base/docs/bindings.jl +++ b/base/docs/bindings.jl @@ -24,7 +24,7 @@ function splitexpr(x::Expr) isexpr(x, :.) ? (x.args[1], x.args[2]) : error("Invalid @var syntax `$x`.") end -splitexpr(s::Symbol) = Expr(:call, current_module), quot(s) +splitexpr(s::Symbol) = Expr(:macrocall, getfield(Base, Symbol("@__MODULE__")), nothing), quot(s) splitexpr(other) = error("Invalid @var syntax `$other`.") macro var(x) diff --git a/base/docs/core.jl b/base/docs/core.jl index 747afab704aa3..b096bf13173aa 100644 --- a/base/docs/core.jl +++ b/base/docs/core.jl @@ -2,10 +2,10 @@ module CoreDocs -import ..esc, ..push!, ..getindex, ..current_module, ..unsafe_load, ..Csize_t +import ..esc, ..push!, ..getindex, ..unsafe_load, ..Csize_t -function doc!(source::LineNumberNode, str, ex) - push!(DOCS, (current_module(), ex, str, source.file, source.line)) +function doc!(source::LineNumberNode, mod::Module, str, ex) + push!(DOCS, (mod, ex, str, source.file, source.line)) end const DOCS = Array{Any, 1}() @@ -14,12 +14,12 @@ isexpr(x, h) = isa(x, Expr) && x.head === h lazy_iterpolate(s::AbstractString) = Expr(:call, Core.svec, s) lazy_iterpolate(x) = isexpr(x, :string) ? Expr(:call, Core.svec, x.args...) : x -function docm(source::LineNumberNode, str, x) - out = esc(Expr(:call, doc!, QuoteNode(source), lazy_iterpolate(str), Expr(:quote, x))) +function docm(source::LineNumberNode, mod::Module, str, x) + out = esc(Expr(:call, doc!, QuoteNode(source), mod, lazy_iterpolate(str), Expr(:quote, x))) isexpr(x, :module) ? Expr(:toplevel, out, esc(x)) : isexpr(x, :call) ? out : Expr(:block, esc(x), out) end -docm(source::LineNumberNode, x) = - isexpr(x, :->) ? docm(source, x.args[1], x.args[2].args[2]) : error("invalid '@doc'.") +docm(source::LineNumberNode, mod::Module, x) = + isexpr(x, :->) ? docm(source, mod, x.args[1], x.args[2].args[2]) : error("invalid '@doc'.") end diff --git a/base/docs/helpdb/Base.jl b/base/docs/helpdb/Base.jl index a3f2530e4fef3..42239e9eb79e5 100644 --- a/base/docs/helpdb/Base.jl +++ b/base/docs/helpdb/Base.jl @@ -1286,13 +1286,12 @@ Run a command object asynchronously, returning the resulting `Process` object. spawn """ - isdefined([m::Module,] s::Symbol) + isdefined(m::Module, s::Symbol) isdefined(object, s::Symbol) isdefined(object, index::Int) Tests whether an assignable location is defined. The arguments can be a module and a symbol -or a composite object and field name (as a symbol) or index. With a single symbol argument, -tests whether a global variable with that name is defined in [`current_module()`](@ref). +or a composite object and field name (as a symbol) or index. """ isdefined diff --git a/base/docs/utils.jl b/base/docs/utils.jl index 895edf349e5be..220f5db5626ab 100644 --- a/base/docs/utils.jl +++ b/base/docs/utils.jl @@ -186,7 +186,9 @@ function repl(io::IO, s::Symbol) quote repl_latex($io, $str) repl_search($io, $str) - ($(isdefined(s) || haskey(keywords, s))) || repl_corrections($io, $str) + $(if !isdefined(Main, s) && !haskey(keywords, s) + :(repl_corrections($io, $str)) + end) $(_repl(s)) end end @@ -336,7 +338,7 @@ end print_joined_cols(args...; cols = displaysize(STDOUT)[2]) = print_joined_cols(STDOUT, args...; cols=cols) function print_correction(io, word) - cors = levsort(word, accessible(current_module())) + cors = levsort(word, accessible(Main)) pre = "Perhaps you meant " print(io, pre) print_joined_cols(io, cors, ", ", " or "; cols = displaysize(io)[2] - length(pre)) @@ -364,7 +366,7 @@ accessible(mod::Module) = map(names, moduleusings(mod))...; builtins] |> unique |> filtervalid -completions(name) = fuzzysort(name, accessible(current_module())) +completions(name) = fuzzysort(name, accessible(Main)) completions(name::Symbol) = completions(string(name)) diff --git a/base/essentials.jl b/base/essentials.jl index 73bccc405f956..d16e1ed107204 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -34,15 +34,6 @@ convert(::Type{Tuple{Vararg{T}}}, x::Tuple) where {T} = cnvt_all(T, x...) cnvt_all(T) = () cnvt_all(T, x, rest...) = tuple(convert(T,x), cnvt_all(T, rest...)...) -macro generated(f) - if isa(f, Expr) && (f.head === :function || is_short_function_def(f)) - f.head = :stagedfunction - return Expr(:escape, f) - else - error("invalid syntax; @generated must be used with a function definition") - end -end - """ @eval [mod,] ex @@ -50,7 +41,7 @@ Evaluate an expression with values interpolated into it using `eval`. If two arguments are provided, the first is the module to evaluate in. """ macro eval(ex) - :(eval($(current_module()), $(Expr(:quote,ex)))) + :(eval($__module__, $(Expr(:quote,ex)))) end macro eval(mod, ex) :(eval($(esc(mod)), $(Expr(:quote,ex)))) diff --git a/base/exports.jl b/base/exports.jl index b9bd9ecebe427..d88133ca324d7 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -1005,7 +1005,6 @@ export # help and reflection apropos, - current_module, edit, code_typed, code_warntype, @@ -1027,6 +1026,7 @@ export which, whos, workspace, + @isdefined, # loading source files __precompile__, @@ -1250,6 +1250,7 @@ export @__FILE__, @__DIR__, @__LINE__, + @__MODULE__, @int128_str, @uint128_str, @big_str, diff --git a/base/expr.jl b/base/expr.jl index 5eb7fa814eaa7..dd41b6b38b363 100644 --- a/base/expr.jl +++ b/base/expr.jl @@ -46,19 +46,21 @@ copy_exprargs(x::Array{Any,1}) = Any[copy_exprs(a) for a in x] ==(x::QuoteNode, y::QuoteNode) = isequal(x.value, y.value) """ - expand(x) + expand(m, x) -Takes the expression `x` and returns an equivalent expression in lowered form. +Takes the expression `x` and returns an equivalent expression in lowered form +for executing in module `m`. See also [`code_lowered`](@ref). """ -expand(x::ANY) = ccall(:jl_expand, Any, (Any,), x) +expand(m::Module, x::ANY) = ccall(:jl_expand, Any, (Any, Any), x, m) """ - macroexpand(x) + macroexpand(m, x) -Takes the expression `x` and returns an equivalent expression with all macros removed (expanded). +Takes the expression `x` and returns an equivalent expression with all macros removed (expanded) +for executing in module `m`. """ -macroexpand(x::ANY) = ccall(:jl_macroexpand, Any, (Any,), x) +macroexpand(m::Module, x::ANY) = ccall(:jl_macroexpand, Any, (Any, Any), x, m) """ @macroexpand @@ -93,8 +95,7 @@ the code was finally called (REPL in the example). Note that when calling `macroexpand` or `@macroexpand` directly from the REPL, both of these contexts coincide, hence there is no difference. """ macro macroexpand(code) - code_expanded = macroexpand(code) - QuoteNode(code_expanded) + return :(macroexpand($__module__, $(QuoteNode(code)))) end ## misc syntax ## @@ -289,3 +290,12 @@ function remove_linenums!(ex::Expr) end return ex end + +macro generated(f) + if isa(f, Expr) && (f.head === :function || is_short_function_def(f)) + f.head = :stagedfunction + return Expr(:escape, f) + else + error("invalid syntax; @generated must be used with a function definition") + end +end diff --git a/base/inference.jl b/base/inference.jl index ee6d044ffb23f..5ef16364df4b5 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -152,7 +152,7 @@ mutable struct InferenceState optimize::Bool, cached::Bool, params::InferenceParams) code = src.code::Array{Any,1} nl = label_counter(code) + 1 - toplevel = !isdefined(linfo, :def) + toplevel = !isa(linfo.def, Method) if !toplevel && isempty(linfo.sparam_vals) && !isempty(linfo.def.sparam_syms) # linfo is unspecialized @@ -250,7 +250,7 @@ mutable struct InferenceState meth = linfo.def inmodule = meth.module else - inmodule = current_module() # toplevel thunks are inferred in the current module + inmodule = linfo.def::Module end if cached && !toplevel @@ -279,7 +279,8 @@ function InferenceState(linfo::MethodInstance, optimize::Bool, cached::Bool, params::InferenceParams) # prepare an InferenceState object for inferring lambda # create copies of the CodeInfo definition, and any fields that type-inference might modify - if linfo.def.isstaged + m = linfo.def::Method + if m.isstaged try # user code might throw errors – ignore them src = get_staged(linfo) @@ -288,10 +289,10 @@ function InferenceState(linfo::MethodInstance, end else # TODO: post-inference see if we can swap back to the original arrays? - if isa(linfo.def.source, Array{UInt8,1}) - src = ccall(:jl_uncompress_ast, Any, (Any, Any), linfo.def, linfo.def.source) + if isa(m.source, Array{UInt8,1}) + src = ccall(:jl_uncompress_ast, Any, (Any, Any), m, m.source) else - src = ccall(:jl_copy_code_info, Ref{CodeInfo}, (Any,), linfo.def.source) + src = ccall(:jl_copy_code_info, Ref{CodeInfo}, (Any,), m.source) src.code = copy_exprargs(src.code) src.slotnames = copy(src.slotnames) src.slotflags = copy(src.slotflags) @@ -1381,7 +1382,7 @@ function abstract_call_method(method::Method, f::ANY, sig::ANY, sparams::SimpleV infstate = sv while infstate !== nothing infstate = infstate::InferenceState - if isdefined(infstate.linfo, :def) && method === infstate.linfo.def + if method === infstate.linfo.def if mightlimitlength && ls > length(unwrap_unionall(infstate.linfo.specTypes).parameters) limitlength = true end @@ -2001,7 +2002,7 @@ function abstract_eval(e::ANY, vtypes::VarTable, sv::InferenceState) t = Any elseif e.head === :foreigncall rt = e.args[2] - if isdefined(sv.linfo, :def) + if isa(sv.linfo.def, Method) spsig = sv.linfo.def.sig if isa(spsig, UnionAll) if !isempty(sv.linfo.sparam_vals) @@ -2391,7 +2392,7 @@ coverage_enabled() = (JLOptions().code_coverage != 0) function update_valid_age!(min_valid::UInt, max_valid::UInt, sv::InferenceState) sv.min_valid = max(sv.min_valid, min_valid) sv.max_valid = min(sv.max_valid, max_valid) - @assert !isdefined(sv.linfo, :def) || !sv.cached || sv.min_valid <= sv.params.world <= sv.max_valid "invalid age range update" + @assert !isa(sv.linfo.def, Method) || !sv.cached || sv.min_valid <= sv.params.world <= sv.max_valid "invalid age range update" nothing end update_valid_age!(edge::InferenceState, sv::InferenceState) = update_valid_age!(edge.min_valid, edge.max_valid, sv) @@ -2399,7 +2400,7 @@ update_valid_age!(li::MethodInstance, sv::InferenceState) = update_valid_age!(mi # temporarily accumulate our edges to later add as backedges in the callee function add_backedge!(li::MethodInstance, caller::InferenceState) - isdefined(caller.linfo, :def) || return # don't add backedges to toplevel exprs + isa(caller.linfo.def, Method) || return # don't add backedges to toplevel exprs if caller.stmt_edges[caller.currpc] === () caller.stmt_edges[caller.currpc] = [] end @@ -2410,7 +2411,7 @@ end # temporarily accumulate our no method errors to later add as backedges in the callee method table function add_mt_backedge(mt::MethodTable, typ::ANY, caller::InferenceState) - isdefined(caller.linfo, :def) || return # don't add backedges to toplevel exprs + isa(caller.linfo.def, Method) || return # don't add backedges to toplevel exprs if caller.stmt_edges[caller.currpc] === () caller.stmt_edges[caller.currpc] = [] end @@ -2421,7 +2422,7 @@ end # add the real backedges now function finalize_backedges(frame::InferenceState) - toplevel = !isdefined(frame.linfo, :def) + toplevel = !isa(frame.linfo.def, Method) if !toplevel && frame.cached && frame.max_valid == typemax(UInt) caller = frame.linfo for edges in frame.stmt_edges @@ -2602,7 +2603,7 @@ function typeinf_code(linfo::MethodInstance, optimize::Bool, cached::Bool, if min_world(linfo) <= params.world <= max_world(linfo) inf = linfo.inferred if linfo.jlcall_api == 2 - method = linfo.def + method = linfo.def::Method tree = ccall(:jl_new_code_info_uninit, Ref{CodeInfo}, ()) tree.code = Any[ Expr(:return, QuoteNode(linfo.inferred_const)) ] tree.slotnames = Any[ compiler_temp_sym for i = 1:method.nargs ] @@ -2660,7 +2661,7 @@ function typeinf_type(method::Method, atypes::ANY, sparams::SimpleVector, end function typeinf_ext(linfo::MethodInstance, world::UInt) - if isdefined(linfo, :def) + if isa(linfo.def, Method) # method lambda - infer this specialization via the method cache return typeinf_code(linfo, true, true, InferenceParams(world)) else @@ -3019,10 +3020,11 @@ function optimize(me::InferenceState) force_noinline = true end end + def = me.linfo.def if force_noinline me.src.inlineable = false - elseif !me.src.inlineable && isdefined(me.linfo, :def) - me.src.inlineable = isinlineable(me.linfo.def, me.src) + elseif !me.src.inlineable && isa(def, Method) + me.src.inlineable = isinlineable(def, me.src) end me.src.inferred = true nothing @@ -3033,7 +3035,7 @@ end function finish(me::InferenceState) me.currpc = 1 # used by add_backedge if me.cached - toplevel = !isdefined(me.linfo, :def) + toplevel = !isa(me.linfo.def, Method) if !toplevel min_valid = me.min_valid max_valid = me.max_valid @@ -3075,13 +3077,14 @@ function finish(me::InferenceState) if !toplevel if !me.const_api + def = me.linfo.def::Method keeptree = me.src.inlineable || ccall(:jl_is_cacheable_sig, Int32, (Any, Any, Any), - me.linfo.specTypes, me.linfo.def.sig, me.linfo.def) != 0 + me.linfo.specTypes, def.sig, def) != 0 if !keeptree inferred_result = nothing else # compress code for non-toplevel thunks - inferred_result = ccall(:jl_compress_ast, Any, (Any, Any), me.linfo.def, inferred_result) + inferred_result = ccall(:jl_compress_ast, Any, (Any, Any), def, inferred_result) end end end diff --git a/base/int.jl b/base/int.jl index 19b65d5ea8f94..a610205e42286 100644 --- a/base/int.jl +++ b/base/int.jl @@ -363,7 +363,7 @@ end # @doc isn't available when running in Core at this point. # Tuple syntax for documention two function signatures at the same time # doesn't work either at this point. -if module_name(current_module()) === :Base +if module_name(@__MODULE__) === :Base for fname in (:mod, :rem) @eval @doc (""" rem(x::Integer, T::Type{<:Integer}) -> T diff --git a/base/interactiveutil.jl b/base/interactiveutil.jl index 144cd02e538ed..32cfb81047023 100644 --- a/base/interactiveutil.jl +++ b/base/interactiveutil.jl @@ -371,8 +371,7 @@ code_warntype(f, t::ANY) = code_warntype(STDOUT, f, t) typesof(args...) = Tuple{Any[ Core.Typeof(a) for a in args ]...} -gen_call_with_extracted_types(fcn, ex0::Symbol) = Expr(:call, fcn, Meta.quot(ex0)) -function gen_call_with_extracted_types(fcn, ex0) +function gen_call_with_extracted_types(__module__, fcn, ex0) if isa(ex0, Expr) if any(a->(Meta.isexpr(a, :kw) || Meta.isexpr(a, :parameters)), ex0.args) # remove keyword args, but call the kwfunc @@ -390,10 +389,10 @@ function gen_call_with_extracted_types(fcn, ex0) end exret = Expr(:none) is_macro = false - ex = expand(ex0) + ex = expand(__module__, ex0) if isa(ex0, Expr) && ex0.head == :macrocall # Make @edit @time 1+2 edit the macro by using the types of the *expressions* is_macro = true - exret = Expr(:call, fcn, esc(ex0.args[1]), Tuple{#=__source__=#LineNumberNode, Any[ Core.Typeof(a) for a in ex0.args[3:end] ]...}) + exret = Expr(:call, fcn, esc(ex0.args[1]), Tuple{#=__source__=#LineNumberNode, #=__module__=#Module, Any[ Core.Typeof(a) for a in ex0.args[3:end] ]...}) elseif !isa(ex, Expr) exret = Expr(:call, :error, "expression is not a function call or symbol") elseif ex.head == :call @@ -430,15 +429,19 @@ for fname in [:which, :less, :edit, :functionloc, :code_warntype, :code_llvm, :code_llvm_raw, :code_native] @eval begin macro ($fname)(ex0) - gen_call_with_extracted_types($(Expr(:quote,fname)), ex0) + gen_call_with_extracted_types(__module__, $(Expr(:quote, fname)), ex0) end end end +macro which(ex0::Symbol) + ex0 = QuoteNode(ex0) + return :(which_module($__module__, $ex0)) +end for fname in [:code_typed, :code_lowered] @eval begin macro ($fname)(ex0) - thecall = gen_call_with_extracted_types($(Expr(:quote,fname)), ex0) + thecall = gen_call_with_extracted_types(__module__, $(Expr(:quote, fname)), ex0) quote results = $thecall length(results) == 1 ? results[1] : results @@ -654,15 +657,15 @@ accessed using a statement such as `using LastMain.Package`. This function should only be used interactively. """ function workspace() - last = Core.Main - b = last.Base - ccall(:jl_new_main_module, Any, ()) - m = Core.Main + last = Core.Main # ensure to reference the current Main module + b = Base # this module + ccall(:jl_new_main_module, Any, ()) # make Core.Main a new baremodule + m = Core.Main # now grab a handle to the new Main module ccall(:jl_add_standard_imports, Void, (Any,), m) - eval(m, - Expr(:toplevel, - :(const Base = $(Expr(:quote, b))), - :(const LastMain = $(Expr(:quote, last))))) + eval(m, Expr(:toplevel, + :(const Base = $b), + :(const LastMain = $last), + :(include(x) = $include($m, x)))) empty!(package_locks) nothing end @@ -696,13 +699,13 @@ end """ - whos(io::IO=STDOUT, m::Module=current_module(), pattern::Regex=r"") + whos(io::IO=STDOUT, m::Module=Main, pattern::Regex=r"") Print information about exported global variables in a module, optionally restricted to those matching `pattern`. The memory consumption estimate is an approximate lower bound on the size of the internal structure of the object. """ -function whos(io::IO=STDOUT, m::Module=current_module(), pattern::Regex=r"") +function whos(io::IO=STDOUT, m::Module=Main, pattern::Regex=r"") maxline = displaysize(io)[2] line = zeros(UInt8, maxline) head = PipeBuffer(maxline + 1) @@ -746,4 +749,4 @@ function whos(io::IO=STDOUT, m::Module=current_module(), pattern::Regex=r"") end end whos(m::Module, pat::Regex=r"") = whos(STDOUT, m, pat) -whos(pat::Regex) = whos(STDOUT, current_module(), pat) +whos(pat::Regex) = whos(STDOUT, Main, pat) diff --git a/base/loading.jl b/base/loading.jl index b0a432d8e0df0..67d4b08b80557 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -466,20 +466,19 @@ function _require(mod::Symbol) # just load the file normally via include # for unknown dependencies try - if last && myid() == 1 && nprocs() > 1 - # include on node 1 first to check for PrecompilableErrors - eval(Main, :(Base.include_from_node1($path))) + # include on node 1 first to check for PrecompilableErrors + Base.include_from_node1(Main, path) + if last && myid() == 1 && nprocs() > 1 # broadcast top-level import/using from node 1 (only) @sync begin for p in filter(x -> x != 1, procs()) @async remotecall_fetch(p) do - eval(Main, :(Base.include_from_node1($path); nothing)) + Base.include_from_node1(Main, path) + nothing end end end - else - eval(Main, :(Base.include_from_node1($path))) end catch ex if doneprecompile === true || JLOptions().use_compilecache == 0 || !precompilableerror(ex, true) @@ -506,17 +505,17 @@ end # remote/parallel load """ - include_string(code::AbstractString, filename::AbstractString="string") + include_string(m::Module, code::AbstractString, filename::AbstractString="string") Like `include`, except reads code from the given string rather than from a file. Since there is no file path involved, no path processing or fetching from node 1 is done. """ -include_string(txt::String, fname::String) = - ccall(:jl_load_file_string, Any, (Ptr{UInt8},Csize_t,Cstring), - txt, sizeof(txt), fname) +include_string(m::Module, txt::String, fname::String) = + ccall(:jl_load_file_string, Any, (Ptr{UInt8}, Csize_t, Cstring, Any), + txt, sizeof(txt), fname, m) -include_string(txt::AbstractString, fname::AbstractString="string") = - include_string(String(txt), String(fname)) +include_string(m::Module, txt::AbstractString, fname::AbstractString="string") = + include_string(m, String(txt), String(fname)) function source_path(default::Union{AbstractString,Void}="") t = current_task() @@ -537,8 +536,8 @@ function source_dir() p === nothing ? pwd() : dirname(p) end -include_from_node1(path::AbstractString) = include_from_node1(String(path)) -function include_from_node1(_path::String) +include_from_node1(mod::Module, path::AbstractString) = include_from_node1(mod, String(path)) +function include_from_node1(mod::Module, _path::String) path, prev = _include_dependency(_path) tls = task_local_storage() tls[:SOURCE_PATH] = path @@ -547,10 +546,10 @@ function include_from_node1(_path::String) if myid()==1 # sleep a bit to process file requests from other nodes nprocs()>1 && sleep(0.005) - result = Core.include(path) + result = Core.include(mod, path) nprocs()>1 && sleep(0.005) else - result = include_string(remotecall_fetch(readstring, 1, path), path) + result = include_string(mod, remotecall_fetch(readstring, 1, path), path) end finally if prev === nothing @@ -563,9 +562,9 @@ function include_from_node1(_path::String) end """ - include(path::AbstractString) + include(m::Module, path::AbstractString) -Evaluate the contents of the input source file in the current context. Returns the result +Evaluate the contents of the input source file into module `m`. Returns the result of the last evaluated expression of the input file. During including, a task-local include path is set to the directory containing the file. Nested calls to `include` will search relative to that path. All paths refer to files on node 1 when running in parallel, and @@ -584,9 +583,10 @@ function evalfile(path::AbstractString, args::Vector{String}=String[]) return eval(Module(:__anon__), Expr(:toplevel, :(const ARGS = $args), - :(eval(x) = Main.Core.eval(__anon__,x)), - :(eval(m,x) = Main.Core.eval(m,x)), - :(Main.Base.include($path)))) + :(eval(x) = $(Expr(:core, :eval))(__anon__, x)), + :(eval(m, x) = $(Expr(:core, :eval))(m, x)), + :(include(x) = $(Expr(:top, :include))(__anon__, x)), + :(include($path)))) end evalfile(path::AbstractString, args::Vector) = evalfile(path, String[args...]) @@ -622,7 +622,7 @@ function create_expr_cache(input::String, output::String, concrete_deps::Vector{ task_local_storage()[:SOURCE_PATH] = $(source) end) end - serialize(in, :(Base.include($(abspath(input))))) + serialize(in, :(Base.include(Main, $(abspath(input))))) if source !== nothing serialize(in, :(delete!(task_local_storage(), :SOURCE_PATH))) end diff --git a/base/markdown/Markdown.jl b/base/markdown/Markdown.jl index fff30da7fec3c..93fb7a045f04c 100644 --- a/base/markdown/Markdown.jl +++ b/base/markdown/Markdown.jl @@ -37,23 +37,23 @@ function mdexpr(s, flavor = :julia) esc(toexpr(md)) end -function docexpr(source::LineNumberNode, s, flavor = :julia) - :($doc_str($(mdexpr(s, flavor)), $(QuoteNode(source)))) +function docexpr(source::LineNumberNode, mod::Module, s, flavor = :julia) + :($doc_str($(mdexpr(s, flavor)), $(QuoteNode(source)), $mod)) end macro md_str(s, t...) mdexpr(s, t...) end -function doc_str(md, source::LineNumberNode) +function doc_str(md, source::LineNumberNode, mod::Module) md.meta[:path] = isa(source.file, Symbol) ? String(source.file) : "" - md.meta[:module] = current_module() + md.meta[:module] = mod md end -doc_str(md::AbstractString, source::LineNumberNode) = doc_str(parse(md), source) +doc_str(md::AbstractString, source::LineNumberNode, mod::Module) = doc_str(parse(md), source, mod) macro doc_str(s::AbstractString, t...) - docexpr(__source__, s, t...) + docexpr(__source__, __module__, s, t...) end function Base.display(d::Base.REPL.REPLDisplay, md::Vector{MD}) diff --git a/base/operators.jl b/base/operators.jl index 8785134cf8571..fbb99958f67e9 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -906,7 +906,7 @@ julia> filter(!isalpha, str) # some operators not defined yet global //, >:, <|, hcat, hvcat, ⋅, ×, ∈, ∉, ∋, ∌, ⊆, ⊈, ⊊, ∩, ∪, √, ∛ -this_module = current_module() +this_module = @__MODULE__ baremodule Operators export diff --git a/base/osutils.jl b/base/osutils.jl index 4a133a4bd9a7f..a37f51c5f0db2 100644 --- a/base/osutils.jl +++ b/base/osutils.jl @@ -61,7 +61,7 @@ such as a `ccall` to a non-existent function. macro static(ex) if isa(ex, Expr) if ex.head === :if || ex.head === :&& || ex.head === :|| - cond = eval(current_module(), ex.args[1]) + cond = eval(__module__, ex.args[1]) if xor(cond, ex.head === :||) return esc(ex.args[2]) elseif length(ex.args) == 3 @@ -76,11 +76,12 @@ macro static(ex) throw(ArgumentError("invalid @static macro")) end -let KERNEL = ccall(:jl_get_UNAME, Any, ()) +let KERNEL = ccall(:jl_get_UNAME, Any, ()), + __module__ = @__MODULE__ # evaluate the zero-argument form of each of these functions # as a function returning a static constant based on the build-time # operating-system kernel for f in (:is_unix, :is_linux, :is_bsd, :is_apple, :is_windows) - @eval $f() = $(getfield(current_module(),f)(KERNEL)) + @eval $f() = $(getfield(__module__, f)(KERNEL)) end end diff --git a/base/precompile.jl b/base/precompile.jl index 5149aed65b332..2587bec08e738 100644 --- a/base/precompile.jl +++ b/base/precompile.jl @@ -743,7 +743,7 @@ precompile(Tuple{getfield(Base.Docs, Symbol("#@repl")), Base.TTY, Symbol}) precompile(Tuple{typeof(Base.Docs.repl), Base.TTY, Symbol}) precompile(Tuple{typeof(Base.Docs._repl), Symbol}) precompile(Tuple{getfield(Core, Symbol("#@doc")), Symbol}) -precompile(Tuple{typeof(Base.Docs.docm), LineNumberNode, Symbol}) +precompile(Tuple{typeof(Base.Docs.docm), LineNumberNode, Module, Symbol}) precompile(Tuple{typeof(Base._setindex!), Base.Dict{Any, Any}, Base.Markdown.Config, Symbol, Int64}) precompile(Tuple{Type{Base.Markdown.MD}}) precompile(Tuple{typeof(Base.setindex!), Base.Dict{Any, Any}, Base.Markdown.Config, Symbol}) @@ -1720,8 +1720,8 @@ precompile(Tuple{typeof(Base.Distributed.send_msg), Base.Distributed.Worker, Bas precompile(Tuple{typeof(Base.Distributed.send_msg_), Base.Distributed.Worker, Base.Distributed.MsgHeader, Base.Distributed.RemoteDoMsg, Bool}) precompile(Tuple{typeof(Base.Distributed.terminate_all_workers)}) precompile(Tuple{typeof(Base.Distributed.test_existing_ref), Base.Distributed.Future}) -precompile(Tuple{typeof(Base.Docs.docm), LineNumberNode, String, Expr}) -precompile(Tuple{typeof(Base.Docs.docm), LineNumberNode, String, Expr, Bool}) +precompile(Tuple{typeof(Base.Docs.docm), LineNumberNode, Module, String, Expr}) +precompile(Tuple{typeof(Base.Docs.docm), LineNumberNode, Module, String, Expr, Bool}) precompile(Tuple{typeof(Base.Docs.keyworddoc), String, Base.BaseDocs.Keyword}) precompile(Tuple{typeof(Base.Docs.objectdoc), String, Expr, Expr, Expr}) precompile(Tuple{typeof(Base.FastMath.make_fastmath), Expr}) diff --git a/base/reflection.jl b/base/reflection.jl index e5db516ec27df..63eb16d12ecf0 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -30,12 +30,14 @@ Base.LinAlg module_parent(m::Module) = ccall(:jl_module_parent, Ref{Module}, (Any,), m) """ - current_module() -> Module + @__MODULE__ -> Module -Get the *dynamically* current `Module`, which is the `Module` code is currently being read -from. In general, this is not the same as the module containing the call to this function. +Get the `Module` of the toplevel eval, +which is the `Module` code is currently being read from. """ -current_module() = ccall(:jl_get_current_module, Ref{Module}, ()) +macro __MODULE__() + return __module__ +end """ fullname(m::Module) @@ -90,7 +92,6 @@ isexported(m::Module, s::Symbol) = ccall(:jl_module_exports_p, Cint, (Any, Any), isdeprecated(m::Module, s::Symbol) = ccall(:jl_is_binding_deprecated, Cint, (Any, Any), m, s) != 0 isbindingresolved(m::Module, var::Symbol) = ccall(:jl_binding_resolved_p, Cint, (Any, Any), m, var) != 0 -binding_module(s::Symbol) = binding_module(current_module(), s) function binding_module(m::Module, s::Symbol) p = ccall(:jl_get_module_of_binding, Ptr{Void}, (Any, Any), m, s) p == C_NULL && return m @@ -159,17 +160,23 @@ Determine the module containing the definition of a `DataType`. """ datatype_module(t::DataType) = t.name.module -isconst(s::Symbol) = ccall(:jl_is_const, Cint, (Ptr{Void}, Any), C_NULL, s) != 0 - """ - isconst([m::Module], s::Symbol) -> Bool + isconst(m::Module, s::Symbol) -> Bool -Determine whether a global is declared `const` in a given `Module`. The default `Module` -argument is [`current_module()`](@ref). +Determine whether a global is declared `const` in a given `Module`. """ isconst(m::Module, s::Symbol) = ccall(:jl_is_const, Cint, (Any, Any), m, s) != 0 +""" + @isdefined s -> Bool + +Tests whether symbol `s` is defined in the current scope. +""" +macro isdefined(s::Symbol) + return :(isdefined($__module__, $(QuoteNode(s)))) +end + # return an integer such that object_id(x)==object_id(y) if x===y object_id(x::ANY) = ccall(:jl_object_id, UInt, (Any,), x) @@ -804,9 +811,9 @@ end """ which(symbol) -Return the module in which the binding for the variable referenced by `symbol` was created. +Return the module in which the binding for the variable referenced by `symbol` in module `Main` was created. """ -which(s::Symbol) = which_module(current_module(), s) +which(s::Symbol) = which_module(Main, s) # TODO: making this a method of which() causes a strange error function which_module(m::Module, s::Symbol) if !isdefined(m, s) diff --git a/base/serialize.jl b/base/serialize.jl index d453e9e0a33f9..b8e2387e98d00 100644 --- a/base/serialize.jl +++ b/base/serialize.jl @@ -404,7 +404,7 @@ end function serialize(s::AbstractSerializer, linfo::Core.MethodInstance) serialize_cycle(s, linfo) && return - isdefined(linfo, :def) && error("can only serialize toplevel MethodInstance objects") + isa(linfo.def, Module) || error("can only serialize toplevel MethodInstance objects") writetag(s.io, METHODINSTANCE_TAG) serialize(s, linfo.inferred) if isdefined(linfo, :inferred_const) @@ -415,6 +415,8 @@ function serialize(s::AbstractSerializer, linfo::Core.MethodInstance) serialize(s, linfo.sparam_vals) serialize(s, linfo.rettype) serialize(s, linfo.specTypes) + serialize(s, linfo.def) + nothing end function serialize(s::AbstractSerializer, t::Task) @@ -765,7 +767,7 @@ function deserialize(s::AbstractSerializer, ::Type{Method}) meth = meth::Method makenew = false else - meth = ccall(:jl_new_method_uninit, Ref{Method}, ()) + meth = ccall(:jl_new_method_uninit, Ref{Method}, (Any,), Main) makenew = true end deserialize_cycle(s, meth) @@ -798,6 +800,7 @@ function deserialize(s::AbstractSerializer, ::Type{Method}) linfo = ccall(:jl_new_method_instance_uninit, Ref{Core.MethodInstance}, ()) linfo.specTypes = Tuple linfo.inferred = template + linfo.def = meth meth.generator = linfo end ftype = ccall(:jl_first_argument_datatype, Any, (Any,), sig)::DataType @@ -820,6 +823,7 @@ function deserialize(s::AbstractSerializer, ::Type{Core.MethodInstance}) linfo.sparam_vals = deserialize(s)::SimpleVector linfo.rettype = deserialize(s) linfo.specTypes = deserialize(s) + linfo.def = deserialize(s)::Module return linfo end @@ -920,8 +924,8 @@ function deserialize_typename(s::AbstractSerializer, number) # TODO: there's an unhanded cycle in the dependency graph at this point: # while deserializing super and/or types, we may have encountered # tn.wrapper and throw UndefRefException before we get to this point - ndt = ccall(:jl_new_datatype, Any, (Any, Any, Any, Any, Any, Cint, Cint, Cint), - tn, super, parameters, names, types, + ndt = ccall(:jl_new_datatype, Any, (Any, Any, Any, Any, Any, Any, Cint, Cint, Cint), + tn, tn.module, super, parameters, names, types, abstr, mutabl, ninitialized) tn.wrapper = ndt.name.wrapper ccall(:jl_set_const, Void, (Any, Any, Any), tn.module, tn.name, tn.wrapper) diff --git a/base/show.jl b/base/show.jl index 5cfa8acdd032d..cd58087312bbc 100644 --- a/base/show.jl +++ b/base/show.jl @@ -317,13 +317,14 @@ function sourceinfo_slotnames(src::CodeInfo) end function show(io::IO, l::Core.MethodInstance) - if isdefined(l, :def) - if l.def.isstaged && l === l.def.generator + def = l.def + if isa(def, Method) + if def.isstaged && l === def.generator print(io, "MethodInstance generator for ") - show(io, l.def) + show(io, def) else print(io, "MethodInstance for ") - show_tuple_as_call(io, l.def.name, l.specTypes) + show_tuple_as_call(io, def.name, l.specTypes) end else print(io, "Toplevel MethodInstance thunk") @@ -1097,12 +1098,30 @@ function show_tuple_as_call(io::IO, name::Symbol, sig::Type) nothing end +resolvebinding(ex::ANY) = ex +resolvebinding(ex::QuoteNode) = ex.value +resolvebinding(ex::Symbol) = resolvebinding(GlobalRef(Main, ex)) +function resolvebinding(ex::Expr) + if ex.head == :. && isa(ex.args[2], Symbol) + parent = resolvebinding(ex.args[1]) + if isa(parent, Module) + return resolvebinding(GlobalRef(parent, ex.args[2])) + end + end + return nothing +end +function resolvebinding(ex::GlobalRef) + isdefined(ex.mod, ex.name) || return nothing + isconst(ex.mod, ex.name) || return nothing + m = getfield(ex.mod, ex.name) + isa(m, Module) || return nothing + return m +end + function ismodulecall(ex::Expr) return ex.head == :call && (ex.args[1] === GlobalRef(Base,:getfield) || ex.args[1] === GlobalRef(Core,:getfield)) && - isa(ex.args[2], Symbol) && - isdefined(current_module(), ex.args[2]) && - isa(getfield(current_module(), ex.args[2]), Module) + isa(resolvebinding(ex.args[2]), Module) end function show(io::IO, tv::TypeVar) diff --git a/base/stacktraces.jl b/base/stacktraces.jl index 82a30cbf12f0c..8fbe116a6270c 100644 --- a/base/stacktraces.jl +++ b/base/stacktraces.jl @@ -213,7 +213,7 @@ function show_spec_linfo(io::IO, frame::StackFrame) end else linfo = get(frame.linfo) - if isdefined(linfo, :def) + if isa(linfo.def, Method) Base.show_tuple_as_call(io, linfo.def.name, linfo.specTypes) else Base.show(io, linfo) @@ -250,7 +250,8 @@ function from(frame::StackFrame, m::Module) result = false if !isnull(finfo) - frame_m = get(finfo).def.module + frame_m = get(finfo).def + isa(frame_m, Method) && (frame_m = frame_m.module) result = module_name(frame_m) === module_name(m) end diff --git a/base/sysimg.jl b/base/sysimg.jl index efaa3570fad1c..5431dd9706392 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -3,18 +3,43 @@ baremodule Base using Core.Intrinsics -ccall(:jl_set_istopmod, Void, (Bool,), true) -function include(path::AbstractString) +ccall(:jl_set_istopmod, Void, (Any, Bool), Base, true) +function include(mod::Module, path::AbstractString) local result if INCLUDE_STATE === 1 - result = Core.include(path) + result = Core.include(mod, path) elseif INCLUDE_STATE === 2 - result = _include(path) + result = _include(mod, path) elseif INCLUDE_STATE === 3 - result = include_from_node1(path) + result = include_from_node1(mod, path) + end + result +end +function include(path::AbstractString) + local result + if INCLUDE_STATE === 1 + result = Core.include(Base, path) + elseif INCLUDE_STATE === 2 + result = _include(Base, path) + else + # to help users avoid error (accidentally evaluating into Base), this is deprecated + depwarn("Base.include(string) is deprecated, use `include(fname)` or `Base.include(@__MODULE__, fname)` instead.", :include) + result = include_from_node1(_current_module(), path) end result end +let SOURCE_PATH = "" + # simple, race-y TLS, relative include + global _include + function _include(mod::Module, path) + prev = SOURCE_PATH + path = joinpath(dirname(prev), path) + SOURCE_PATH = path + result = Core.include(mod, path) + SOURCE_PATH = prev + result + end +end INCLUDE_STATE = 1 # include = Core.include include("coreio.jl") @@ -255,15 +280,6 @@ importall .Math const (√)=sqrt const (∛)=cbrt -let SOURCE_PATH = "" - global function _include(path) - prev = SOURCE_PATH - path = joinpath(dirname(prev),path) - SOURCE_PATH = path - Core.include(path) - SOURCE_PATH = prev - end -end INCLUDE_STATE = 2 # include = _include (from lines above) # reduction along dims @@ -426,11 +442,11 @@ function __init__() end INCLUDE_STATE = 3 # include = include_from_node1 -include("precompile.jl") +include(Base, "precompile.jl") end # baremodule Base using Base importall Base.Operators -Base.isfile("userimg.jl") && Base.include("userimg.jl") +Base.isfile("userimg.jl") && Base.include(Main, "userimg.jl") diff --git a/base/test.jl b/base/test.jl index 9d7dc05bd553e..9180f27061f01 100644 --- a/base/test.jl +++ b/base/test.jl @@ -1073,7 +1073,7 @@ macro inferred(ex) kwargs = gensym() quote $(esc(args)), $(esc(kwargs)), result = $(esc(Expr(:call, _args_and_call, ex.args[2:end]..., ex.args[1]))) - inftypes = $(Base.gen_call_with_extracted_types(Base.return_types, :($(ex.args[1])($(args)...; $(kwargs)...)))) + inftypes = $(Base.gen_call_with_extracted_types(__module__, Base.return_types, :($(ex.args[1])($(args)...; $(kwargs)...)))) end else # No keywords diff --git a/base/util.jl b/base/util.jl index 187bc416c4ba3..ec2cdc660ed01 100644 --- a/base/util.jl +++ b/base/util.jl @@ -431,7 +431,8 @@ const log_error_to = Dict{Tuple{Union{Module,Void},Union{Symbol,Void}},IO}() function _redirect(io::IO, log_to::Dict, sf::StackTraces.StackFrame) isnull(sf.linfo) && return io - mod = get(sf.linfo).def.module + mod = get(sf.linfo).def + isa(mod, Method) && (mod = mod.module) fun = sf.func if haskey(log_to, (mod,fun)) return log_to[(mod,fun)] @@ -456,7 +457,9 @@ function _redirect(io::IO, log_to::Dict, fun::Symbol) isnull(frame.linfo) && continue sf = frame break_next_frame && (@goto skip) - get(frame.linfo).def.module == Base || continue + mod = get(frame.linfo).def + isa(mod, Method) && (mod = mod.module) + mod === Base || continue sff = string(frame.func) if frame.func == fun || startswith(sff, clos) || startswith(sff, kw) break_next_frame = true @@ -792,7 +795,7 @@ end ``` """ macro kwdef(expr) - expr = macroexpand(expr) # to expand @static + expr = macroexpand(__module__, expr) # to expand @static T = expr.args[2] params_ex = Expr(:parameters) call_ex = Expr(:call, T) diff --git a/doc/src/devdocs/ast.md b/doc/src/devdocs/ast.md index 157dd60a624c0..bcde2617b7b1d 100644 --- a/doc/src/devdocs/ast.md +++ b/doc/src/devdocs/ast.md @@ -242,8 +242,8 @@ for important details on how to modify these fields safely. * `def` - The `Method` that this function describes a specialization of. Or `#undef`, if this is - a top-level Lambda that is not part of a Method. + The `Method` that this function describes a specialization of. Or a `Module`, + if this is a top-level Lambda expanded in Module, and which is not part of a Method. * `sparam_vals` diff --git a/doc/src/manual/calling-c-and-fortran-code.md b/doc/src/manual/calling-c-and-fortran-code.md index 30da54ac330ad..5a98756ca8e15 100644 --- a/doc/src/manual/calling-c-and-fortran-code.md +++ b/doc/src/manual/calling-c-and-fortran-code.md @@ -847,21 +847,19 @@ case, the expression must evaluate to a `Ptr`, which will be used as the address function to call. This behavior occurs when the first [`ccall`](@ref) argument contains references to non-constants, such as local variables, function arguments, or non-constant globals. -For example, you might look up the function via `dlsym`, then cache it in a global -variable for that session. For example: +For example, you might look up the function via `dlsym`, +then cache it in a shared reference for that session. For example: ```julia macro dlsym(func, lib) - z, zlocal = gensym(string(func)), gensym() - eval(current_module(), :(global $z = C_NULL)) - z = esc(z) + z = Ref{Ptr{Void}}(C_NULL) quote - let $zlocal::Ptr{Void} = $z::Ptr{Void} - if $zlocal == C_NULL - $zlocal = dlsym($(esc(lib))::Ptr{Void}, $(esc(func))) - global $z = $zlocal + let zlocal = $z[] + if zlocal == C_NULL + zlocal = dlsym($(esc(lib))::Ptr{Void}, $(esc(func)))::Ptr{Void} + $z[] = $zlocal end - $zlocal + zlocal end end end diff --git a/doc/src/manual/metaprogramming.md b/doc/src/manual/metaprogramming.md index a6d3fa57840e5..031f93fdacf52 100644 --- a/doc/src/manual/metaprogramming.md +++ b/doc/src/manual/metaprogramming.md @@ -512,10 +512,10 @@ julia> @showarg(println("Yo!")) :(println("Yo!")) ``` -In addition to the given argument list, every macro is passed an extra argument named `__source__` -providing information (in the form of a `LineNumberNode` object) about the parser location -of the `@` sign from the macro invocation. +In addition to the given argument list, every macro is passed extra arguments named `__source__` and `__module__`. +The argument `__source__` provides information (in the form of a `LineNumberNode` object) about the parser location +of the `@` sign from the macro invocation. This allows macros to include better error diagnostic information, and is commonly used by logging, string-parser macros, and docs, for example, as well as to implement the `@__LINE__`, `@__FILE__`, and `@__DIR__` macros. @@ -534,6 +534,13 @@ LineNumberNode file: Symbol none ``` +The argument `__module__` provides information (in the form of a `Module` object) +about the expansion context of the macro invocation. +This allows macros to look up contextual information, such as existing bindings, +or to insert the value as an extra argument to a runtime function call doing self-reflection +in the current module. + + ### Building an advanced macro Here is a simplified definition of Julia's `@assert` macro: diff --git a/doc/src/manual/modules.md b/doc/src/manual/modules.md index bbd6b4248b1f6..3063b1d45c41c 100644 --- a/doc/src/manual/modules.md +++ b/doc/src/manual/modules.md @@ -336,8 +336,8 @@ Other known potential failure scenarios include: Note that `object_id` (which works by hashing the memory pointer) has similar issues (see notes on `Dict` usage below). - One alternative is to store both [`current_module()`](@ref) and the current `counter` value, however, - it may be better to redesign the code to not depend on this global state. + One alternative is to use a macro to capture [`@__MODULE__`](@ref) and store it alone with the current `counter` value, + however, it may be better to redesign the code to not depend on this global state. 2. Associative collections (such as `Dict` and `Set`) need to be re-hashed in `__init__`. (In the future, a mechanism may be provided to register an initializer function.) 3. Depending on compile-time side-effects persisting through load-time. Example include: modifying diff --git a/doc/src/manual/parallel-computing.md b/doc/src/manual/parallel-computing.md index 0108eb0097060..b29445132d2b7 100644 --- a/doc/src/manual/parallel-computing.md +++ b/doc/src/manual/parallel-computing.md @@ -152,8 +152,8 @@ end Starting Julia with `julia -p 2`, you can use this to verify the following: - * [`include("DummyModule.jl")`](@ref) loads the file on just a single process (whichever one executes - the statement). + * `include("DummyModule.jl")` loads the file on just a single process + (whichever one executes the statement). * `using DummyModule` causes the module to be loaded on all processes; however, the module is brought into scope only on the one executing the statement. * As long as `DummyModule` is loaded on process 2, commands like diff --git a/doc/src/stdlib/base.md b/doc/src/stdlib/base.md index 9af89439bcc8f..d17eb625344be 100644 --- a/doc/src/stdlib/base.md +++ b/doc/src/stdlib/base.md @@ -76,6 +76,7 @@ Base.finalize Base.copy Base.deepcopy Core.isdefined +Base.@isdefined Base.convert Base.promote Base.oftype @@ -250,7 +251,7 @@ Base.AsyncCondition(::Function) ```@docs Base.module_name Base.module_parent -Base.current_module +Base.@__MODULE__ Base.fullname Base.names Core.nfields diff --git a/src/ast.c b/src/ast.c index ed44ab1509d09..0b286de277d5b 100644 --- a/src/ast.c +++ b/src/ast.c @@ -97,6 +97,7 @@ typedef struct _jl_ast_context_t { jl_ast_context_list_t list; int ref; jl_task_t *task; + jl_module_t *module; // use a pointer to a stack slot so that we can detect if // `jl_ast_preserve` is called in the wrong context. // If `roots` is not NULL, it always points to a rooted stack slot. @@ -109,14 +110,19 @@ static jl_ast_context_t jl_ast_main_ctx; #define jl_ast_context_list_item(node) \ container_of(node, jl_ast_context_t, list) -#define JL_AST_PRESERVE_PUSH(ctx, _roots, old_roots) \ - jl_array_t *_roots = NULL; \ - jl_array_t **old_roots = ctx->roots; \ - ctx->roots = &_roots; \ - JL_GC_PUSH1(&_roots) -#define JL_AST_PRESERVE_POP(ctx, old_roots) \ +#define JL_AST_PRESERVE_PUSH(ctx, _roots, old, inmodule) \ + jl_array_t *(_roots) = NULL; \ + struct { jl_array_t **roots; \ + jl_module_t *module; } (old); \ + old.roots = ctx->roots; \ + old.module = ctx->module; \ + ctx->roots = &(_roots); \ + ctx->module = (inmodule); \ + JL_GC_PUSH2(&(_roots), &(inmodule)) +#define JL_AST_PRESERVE_POP(ctx, old) \ JL_GC_POP(); \ - ctx->roots = old_roots + ctx->roots = (old).roots; \ + ctx->module = (old).module static void jl_ast_preserve(fl_context_t *fl_ctx, jl_value_t *obj) { @@ -137,10 +143,10 @@ static value_t julia_to_scm(fl_context_t *fl_ctx, jl_value_t *v); value_t fl_defined_julia_global(fl_context_t *fl_ctx, value_t *args, uint32_t nargs) { - jl_ptls_t ptls = jl_get_ptls_states(); + jl_ast_context_t *ctx = jl_ast_ctx(fl_ctx); // tells whether a var is defined in and *by* the current module argcount(fl_ctx, "defined-julia-global", nargs, 1); - jl_module_t *mod = ptls->current_module; + jl_module_t *mod = ctx->module; jl_sym_t *sym = (jl_sym_t*)scm_to_julia(fl_ctx, args[0], 0); if (jl_is_globalref(sym)) { mod = jl_globalref_mod(sym); @@ -154,30 +160,21 @@ value_t fl_defined_julia_global(fl_context_t *fl_ctx, value_t *args, uint32_t na return (b != HT_NOTFOUND && b->owner == mod) ? fl_ctx->T : fl_ctx->F; } -value_t fl_current_julia_module(fl_context_t *fl_ctx, value_t *args, uint32_t nargs) -{ - jl_ptls_t ptls = jl_get_ptls_states(); - value_t opaque = cvalue(fl_ctx, jl_ast_ctx(fl_ctx)->jvtype, sizeof(void*)); - *(jl_value_t**)cv_data((cvalue_t*)ptr(opaque)) = (jl_value_t*)ptls->current_module; - return opaque; -} - value_t fl_current_module_counter(fl_context_t *fl_ctx, value_t *args, uint32_t nargs) { - jl_ptls_t ptls = jl_get_ptls_states(); - static uint32_t fallback_counter = 0; - if (ptls->current_module == NULL) - return fixnum(++fallback_counter); - else - return fixnum(jl_module_next_counter(ptls->current_module)); + jl_ast_context_t *ctx = jl_ast_ctx(fl_ctx); + assert(ctx->module); + return fixnum(jl_module_next_counter(ctx->module)); } value_t fl_invoke_julia_macro(fl_context_t *fl_ctx, value_t *args, uint32_t nargs) { JL_TIMING(MACRO_INVOCATION); jl_ptls_t ptls = jl_get_ptls_states(); + jl_ast_context_t *ctx = jl_ast_ctx(fl_ctx); if (nargs < 2) // macro name and location argcount(fl_ctx, "invoke-julia-macro", nargs, 2); + nargs++; // add __module__ argument jl_method_instance_t *mfunc = NULL; jl_value_t **margs; // Reserve one more slot for the result @@ -206,13 +203,14 @@ value_t fl_invoke_julia_macro(fl_context_t *fl_ctx, value_t *args, uint32_t narg else if (!jl_typeis(lno, jl_linenumbernode_type)) { margs[1] = jl_new_struct(jl_linenumbernode_type, jl_box_long(0), jl_nothing); } - for (i = 2; i < nargs; i++) - margs[i] = scm_to_julia(fl_ctx, args[i], 1); + margs[2] = (jl_value_t*)ctx->module; + for (i = 3; i < nargs; i++) + margs[i] = scm_to_julia(fl_ctx, args[i - 1], 1); jl_value_t *result = NULL; size_t world = jl_get_ptls_states()->world_age; JL_TRY { - margs[0] = jl_toplevel_eval(margs[0]); + margs[0] = jl_toplevel_eval(ctx->module, margs[0]); mfunc = jl_method_lookup(jl_gf_mtable(margs[0]), margs, nargs, 1, world); if (mfunc == NULL) { jl_method_error((jl_function_t*)margs[0], margs, nargs, world); @@ -236,15 +234,10 @@ value_t fl_invoke_julia_macro(fl_context_t *fl_ctx, value_t *args, uint32_t narg value_t scm = julia_to_scm(fl_ctx, result); fl_gc_handle(fl_ctx, &scm); value_t scmresult; - jl_module_t *defmod = mfunc->def->module; - /* if (defmod == NULL || defmod == ptls->current_module) { */ - /* scmresult = fl_cons(fl_ctx, scm, fl_ctx->F); */ - /* } */ - /* else { */ + jl_module_t *defmod = mfunc->def.method->module; value_t opaque = cvalue(fl_ctx, jl_ast_ctx(fl_ctx)->jvtype, sizeof(void*)); *(jl_value_t**)cv_data((cvalue_t*)ptr(opaque)) = (jl_value_t*)defmod; scmresult = fl_cons(fl_ctx, scm, opaque); - /* } */ fl_free_gc_handles(fl_ctx, 1); JL_GC_POP(); @@ -270,7 +263,6 @@ value_t fl_julia_scalar(fl_context_t *fl_ctx, value_t *args, uint32_t nargs) static const builtinspec_t julia_flisp_ast_ext[] = { { "defined-julia-global", fl_defined_julia_global }, { "invoke-julia-macro", fl_invoke_julia_macro }, - { "current-julia-module", fl_current_julia_module }, { "current-julia-module-counter", fl_current_module_counter }, { "julia-scalar?", fl_julia_scalar }, { NULL, NULL } @@ -291,14 +283,17 @@ static void jl_init_ast_ctx(jl_ast_context_t *ast_ctx) fl_applyn(fl_ctx, 0, symbol_value(symbol(fl_ctx, "__init_globals"))); - jl_ast_ctx(fl_ctx)->jvtype = define_opaque_type(fl_ctx->jl_sym, sizeof(void*), NULL, NULL); + jl_ast_context_t *ctx = jl_ast_ctx(fl_ctx); + ctx->jvtype = define_opaque_type(fl_ctx->jl_sym, sizeof(void*), NULL, NULL); assign_global_builtins(fl_ctx, julia_flisp_ast_ext); - jl_ast_ctx(fl_ctx)->true_sym = symbol(fl_ctx, "true"); - jl_ast_ctx(fl_ctx)->false_sym = symbol(fl_ctx, "false"); - jl_ast_ctx(fl_ctx)->error_sym = symbol(fl_ctx, "error"); - jl_ast_ctx(fl_ctx)->null_sym = symbol(fl_ctx, "null"); - jl_ast_ctx(fl_ctx)->ssavalue_sym = symbol(fl_ctx, "ssavalue"); - jl_ast_ctx(fl_ctx)->slot_sym = symbol(fl_ctx, "slot"); + ctx->true_sym = symbol(fl_ctx, "true"); + ctx->false_sym = symbol(fl_ctx, "false"); + ctx->error_sym = symbol(fl_ctx, "error"); + ctx->null_sym = symbol(fl_ctx, "null"); + ctx->ssavalue_sym = symbol(fl_ctx, "ssavalue"); + ctx->slot_sym = symbol(fl_ctx, "slot"); + ctx->task = NULL; + ctx->module = NULL; // Enable / disable syntax deprecation warnings if (jl_options.depwarn == JL_OPTIONS_DEPWARN_ERROR) @@ -336,6 +331,7 @@ static jl_ast_context_t *jl_ast_ctx_enter(void) ctx->ref = 1; ctx->task = ptls->current_task; ctx->roots = NULL; + ctx->module = NULL; JL_UNLOCK_NOGC(&flisp_lock); return ctx; } @@ -444,7 +440,7 @@ JL_DLLEXPORT void jl_lisp_prompt(void) JL_SIGATOMIC_BEGIN(); jl_init_frontend(); jl_ast_context_t *ctx = jl_ast_ctx_enter(); - JL_AST_PRESERVE_PUSH(ctx, roots, old_roots); + JL_AST_PRESERVE_PUSH(ctx, roots, old_roots, jl_main_module); fl_context_t *fl_ctx = &ctx->fl; fl_applyn(fl_ctx, 1, symbol_value(symbol(fl_ctx, "__start")), fl_cons(fl_ctx, fl_ctx->NIL,fl_ctx->NIL)); JL_AST_PRESERVE_POP(ctx, old_roots); @@ -512,7 +508,7 @@ extern int64_t conv_to_int64(void *data, numerictype_t tag); static jl_value_t *scm_to_julia_(fl_context_t *fl_ctx, value_t e, int eo) { - jl_ptls_t ptls = jl_get_ptls_states(); + jl_ast_context_t *ctx = jl_ast_ctx(fl_ctx); if (fl_isnumber(fl_ctx, e)) { int64_t i64; if (isfixnum(e)) { @@ -616,7 +612,7 @@ static jl_value_t *scm_to_julia_(fl_context_t *fl_ctx, value_t e, int eo) if (sym == top_sym) { scmv = scm_to_julia_(fl_ctx,car_(e),0); assert(jl_is_symbol(scmv)); - temp = jl_module_globalref(jl_base_relative_to(ptls->current_module), (jl_sym_t*)scmv); + temp = jl_module_globalref(jl_base_relative_to(ctx->module), (jl_sym_t*)scmv); JL_GC_POP(); return temp; } @@ -839,7 +835,8 @@ JL_DLLEXPORT jl_value_t *jl_parse_string(const char *str, size_t len, // parse and eval a whole file, possibly reading from a string (`content`) jl_value_t *jl_parse_eval_all(const char *fname, - const char *content, size_t contentlen) + const char *content, size_t contentlen, + jl_module_t *inmodule) { jl_ptls_t ptls = jl_get_ptls_states(); if (ptls->in_pure_callback) @@ -876,10 +873,12 @@ jl_value_t *jl_parse_eval_all(const char *fname, jl_filename = fname; jl_array_t *roots = NULL; jl_array_t **old_roots = ctx->roots; + jl_module_t *old_module = ctx->module; ctx->roots = &roots; + ctx->module = inmodule; jl_value_t *form=NULL, *result=jl_nothing; int err = 0; - JL_GC_PUSH3(&roots, &form, &result); + JL_GC_PUSH4(&roots, &form, &result, &inmodule); JL_TRY { assert(iscons(ast) && car_(ast) == symbol(fl_ctx,"toplevel")); ast = cdr_(ast); @@ -896,15 +895,15 @@ jl_value_t *jl_parse_eval_all(const char *fname, JL_SIGATOMIC_END(); jl_get_ptls_states()->world_age = jl_world_counter; if (head == jl_incomplete_sym) - jl_errorf("syntax: %s", jl_string_data(jl_exprarg(form,0))); + jl_errorf("syntax: %s", jl_string_data(jl_exprarg(form, 0))); else if (head == error_sym) - jl_interpret_toplevel_expr(form); + jl_interpret_toplevel_expr_in(inmodule, form, NULL, NULL); else if (head == line_sym) - jl_lineno = jl_unbox_long(jl_exprarg(form,0)); + jl_lineno = jl_unbox_long(jl_exprarg(form, 0)); else if (jl_is_linenode(form)) jl_lineno = jl_linenode_line(form); else - result = jl_toplevel_eval_flex(form, 1, 1); + result = jl_toplevel_eval_flex(inmodule, form, 1, 1); JL_SIGATOMIC_BEGIN(); ast = cdr_(ast); } @@ -919,6 +918,7 @@ jl_value_t *jl_parse_eval_all(const char *fname, jl_filename = last_filename; fl_free_gc_handles(fl_ctx, 1); ctx->roots = old_roots; + ctx->module = old_module; jl_ast_ctx_leave(ctx); if (err) { if (jl_loaderror_type == NULL) @@ -932,9 +932,9 @@ jl_value_t *jl_parse_eval_all(const char *fname, } JL_DLLEXPORT jl_value_t *jl_load_file_string(const char *text, size_t len, - char *filename) + char *filename, jl_module_t *inmodule) { - return jl_parse_eval_all(filename, text, len); + return jl_parse_eval_all(filename, text, len, inmodule); } JL_DLLEXPORT int jl_parse_depwarn(int warn) @@ -960,11 +960,11 @@ static int jl_parse_deperror(fl_context_t *fl_ctx, int err) } // returns either an expression or a thunk -jl_value_t *jl_call_scm_on_ast(const char *funcname, jl_value_t *expr) +jl_value_t *jl_call_scm_on_ast(const char *funcname, jl_value_t *expr, jl_module_t *inmodule) { jl_ast_context_t *ctx = jl_ast_ctx_enter(); fl_context_t *fl_ctx = &ctx->fl; - JL_AST_PRESERVE_PUSH(ctx, roots, old_roots); + JL_AST_PRESERVE_PUSH(ctx, roots, old_roots, inmodule); value_t arg = julia_to_scm(fl_ctx, expr); value_t e = fl_applyn(fl_ctx, 1, symbol_value(symbol(fl_ctx, funcname)), arg); jl_value_t *result = scm_to_julia(fl_ctx, e, 0); @@ -973,16 +973,16 @@ jl_value_t *jl_call_scm_on_ast(const char *funcname, jl_value_t *expr) return result; } -JL_DLLEXPORT jl_value_t *jl_expand(jl_value_t *expr) +JL_DLLEXPORT jl_value_t *jl_expand(jl_value_t *expr, jl_module_t *inmodule) { JL_TIMING(LOWERING); - return jl_call_scm_on_ast("jl-expand-to-thunk", expr); + return jl_call_scm_on_ast("jl-expand-to-thunk", expr, inmodule); } -JL_DLLEXPORT jl_value_t *jl_macroexpand(jl_value_t *expr) +JL_DLLEXPORT jl_value_t *jl_macroexpand(jl_value_t *expr, jl_module_t *inmodule) { JL_TIMING(LOWERING); - return jl_call_scm_on_ast("jl-macroexpand", expr); + return jl_call_scm_on_ast("jl-macroexpand", expr, inmodule); } // wrap expr in a thunk AST diff --git a/src/builtins.c b/src/builtins.c index e7f29e0051e73..70ca4262d1ba2 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -493,7 +493,7 @@ JL_DLLEXPORT jl_value_t *jl_toplevel_eval_in(jl_module_t *m, jl_value_t *ex) JL_TRY { ptls->current_task->current_module = ptls->current_module = m; ptls->world_age = jl_world_counter; - v = jl_toplevel_eval(ex); + v = jl_toplevel_eval(m, ex); } JL_CATCH { jl_lineno = last_lineno; @@ -511,9 +511,8 @@ JL_DLLEXPORT jl_value_t *jl_toplevel_eval_in(jl_module_t *m, jl_value_t *ex) JL_CALLABLE(jl_f_isdefined) { - jl_ptls_t ptls = jl_get_ptls_states(); - jl_module_t *m = ptls->current_module; - jl_sym_t *s=NULL; + jl_module_t *m = NULL; + jl_sym_t *s = NULL; JL_NARGSV(isdefined, 1); if (jl_is_array(args[0])) { return jl_array_isdefined(args, nargs) ? jl_true : jl_false; @@ -524,6 +523,11 @@ JL_CALLABLE(jl_f_isdefined) } if (nargs != 2) { JL_NARGS(isdefined, 1, 1); + jl_depwarn("`isdefined(:symbol)` is deprecated, " + "use `@isdefined symbol` instead", + (jl_value_t*)jl_symbol("isdefined")); + jl_ptls_t ptls = jl_get_ptls_states(); + m = ptls->current_module; } else { if (!jl_is_module(args[0])) { diff --git a/src/ccall.cpp b/src/ccall.cpp index eeb2bb2d833df..32058d0a47731 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -483,7 +483,7 @@ static Value *runtime_apply_type(jl_value_t *ty, jl_unionall_t *unionall, jl_cod // box if concrete type was not statically known Value *args[3]; args[0] = literal_pointer_val(ty); - args[1] = literal_pointer_val((jl_value_t*)ctx->linfo->def->sig); + args[1] = literal_pointer_val((jl_value_t*)ctx->linfo->def.method->sig); args[2] = builder.CreateInBoundsGEP( LLVM37_param(T_pjlvalue) emit_bitcast(ctx->spvals_ptr, T_ppjlvalue), @@ -1522,8 +1522,8 @@ static jl_cgval_t emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) return jl_cgval_t(); } - jl_unionall_t *unionall = (ctx->linfo->def && jl_is_unionall(ctx->linfo->def->sig)) - ? (jl_unionall_t*)ctx->linfo->def->sig + jl_unionall_t *unionall = (jl_is_method(ctx->linfo->def.method) && jl_is_unionall(ctx->linfo->def.method->sig)) + ? (jl_unionall_t*)ctx->linfo->def.method->sig : NULL; if (jl_is_abstract_ref_type(rt)) { diff --git a/src/cgutils.cpp b/src/cgutils.cpp index e9554702765fb..a14dff0ecfe91 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -299,8 +299,8 @@ static Value *literal_pointer_val_slot(jl_value_t *p) if (jl_is_method_instance(p)) { jl_method_instance_t *linfo = (jl_method_instance_t*)p; // Type-inferred functions are also prefixed with a - - if (linfo->def) - return julia_pgv("-", linfo->def->name, linfo->def->module, p); + if (jl_is_method(linfo->def.method)) + return julia_pgv("-", linfo->def.method->name, linfo->def.method->module, p); } if (jl_is_symbol(p)) { jl_sym_t *addr = (jl_sym_t*)p; @@ -1896,7 +1896,7 @@ static Value *_boxed_special(const jl_cgval_t &vinfo, Type *t, jl_codectx_t *ctx if (t == T_int1) return julia_bool(as_value(t, vinfo)); - if (ctx->linfo && ctx->linfo->def && !vinfo.ispointer()) { // don't bother codegen pre-boxing for toplevel + if (ctx->linfo && jl_is_method(ctx->linfo->def.method) && !vinfo.ispointer()) { // don't bother codegen pre-boxing for toplevel if (Constant *c = dyn_cast(vinfo.V)) { jl_value_t *s = static_constant_instance(c, jt); if (s) { diff --git a/src/codegen.cpp b/src/codegen.cpp index 82685cd2f57a9..d701a6181a66c 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1169,7 +1169,7 @@ jl_llvm_functions_t jl_compile_linfo(jl_method_instance_t **pli, jl_code_info_t jl_error("functions compiled with custom codegen params mustn't be cached"); // Fast path for the already-compiled case - if (li->def != NULL) { + if (jl_is_method(li->def.method)) { decls = li->functionObjectsDecls; bool already_compiled = params->cached && decls.functionObject != NULL; if (!src) { @@ -1190,10 +1190,8 @@ jl_llvm_functions_t jl_compile_linfo(jl_method_instance_t **pli, jl_code_info_t { // Step 1: Re-check if this was already compiled (it may have been while // we waited at the lock). - if (li->def == NULL) { + if (!jl_is_method(li->def.method)) { src = (jl_code_info_t*)li->inferred; - if (src && (jl_value_t*)src != jl_nothing) - src = jl_uncompress_ast(li->def, (jl_array_t*)src); if (decls.functionObject != NULL || !src || !jl_is_code_info(src) || li->jlcall_api == 2) { goto locked_out; } @@ -1209,7 +1207,7 @@ jl_llvm_functions_t jl_compile_linfo(jl_method_instance_t **pli, jl_code_info_t src = (jl_code_info_t*)li->inferred; if (src) { if ((jl_value_t*)src != jl_nothing) - src = jl_uncompress_ast(li->def, (jl_array_t*)src); + src = jl_uncompress_ast(li->def.method, (jl_array_t*)src); if (!jl_is_code_info(src)) { src = jl_type_infer(pli, world, 0); li = *pli; @@ -1229,7 +1227,7 @@ jl_llvm_functions_t jl_compile_linfo(jl_method_instance_t **pli, jl_code_info_t } else { if ((jl_value_t*)src != jl_nothing) - src = jl_uncompress_ast(li->def, (jl_array_t*)src); + src = jl_uncompress_ast(li->def.method, (jl_array_t*)src); } assert(jl_is_code_info(src)); @@ -1249,7 +1247,7 @@ jl_llvm_functions_t jl_compile_linfo(jl_method_instance_t **pli, jl_code_info_t pdecls = &decls; else if (li->min_world <= world && li->max_world >= world) pdecls = &li->functionObjectsDecls; - else if (li->def == NULL) + else if (!jl_is_method(li->def.method)) // toplevel thunk pdecls = &li->functionObjectsDecls; else pdecls = &decls; @@ -1267,7 +1265,8 @@ jl_llvm_functions_t jl_compile_linfo(jl_method_instance_t **pli, jl_code_info_t builder.restoreIP(old); builder.SetCurrentDebugLocation(olddl); JL_UNLOCK(&codegen_lock); // Might GC - jl_rethrow_with_add("error compiling %s", jl_symbol_name(li->def ? li->def->name : anonymous_sym)); + const char *mname = jl_symbol_name(jl_is_method(li->def.method) ? li->def.method->name : anonymous_sym); + jl_rethrow_with_add("error compiling %s", mname); } Function *f = (Function*)decls.functionObject; Function *specf = (Function*)decls.specFunctionObject; @@ -1278,7 +1277,7 @@ jl_llvm_functions_t jl_compile_linfo(jl_method_instance_t **pli, jl_code_info_t // Step 4. Prepare debug info to receive this function // record that this function name came from this linfo, // so we can build a reverse mapping for debug-info. - bool toplevel = li->def == NULL; + bool toplevel = !jl_is_method(li->def.method); if (!toplevel) { const DataLayout &DL = #if JL_LLVM_VERSION >= 30500 @@ -1301,13 +1300,13 @@ jl_llvm_functions_t jl_compile_linfo(jl_method_instance_t **pli, jl_code_info_t // don't delete code when debugging level >= 2 jl_options.debug_level <= 1 && // don't delete toplevel code - li->def && + jl_is_method(li->def.method) && // don't change inferred state li->inferred && // and there is something to delete (test this before calling jl_ast_flag_inlineable) li->inferred != jl_nothing && // don't delete the code for the generator - li != li->def->generator && + li != li->def.method->generator && // don't delete inlineable code, unless it is constant (li->jlcall_api == 2 || !jl_ast_flag_inlineable((jl_array_t*)li->inferred)) && // don't delete code when generating a precompile file @@ -1430,7 +1429,7 @@ uint64_t jl_get_llvm_fptr(llvm::Function *llvmf) static jl_method_instance_t *jl_get_unspecialized(jl_method_instance_t *method) { // one unspecialized version of a function can be shared among all cached specializations - jl_method_t *def = method->def; + jl_method_t *def = method->def.method; if (def->isstaged) { return method; } @@ -1469,9 +1468,9 @@ jl_generic_fptr_t jl_generate_fptr(jl_method_instance_t *li, void *_F, size_t wo return fptr; } jl_method_instance_t *unspec = NULL; - if (li->def) { - if (!li->def->isstaged && li->def->unspecialized) { - unspec = li->def->unspecialized; + if (jl_is_method(li->def.method)) { + if (!li->def.method->isstaged && li->def.method->unspecialized) { + unspec = li->def.method->unspecialized; } if (!F || !jl_can_finalize_function(F)) { // can't compile F in the JIT right now, @@ -1479,7 +1478,7 @@ jl_generic_fptr_t jl_generate_fptr(jl_method_instance_t *li, void *_F, size_t wo // and return its fptr instead if (!unspec) unspec = jl_get_unspecialized(li); // get-or-create the unspecialized version to cache the result - jl_code_info_t *src = unspec->def->isstaged ? jl_code_for_staged(unspec) : (jl_code_info_t*)unspec->def->source; + jl_code_info_t *src = unspec->def.method->isstaged ? jl_code_for_staged(unspec) : (jl_code_info_t*)unspec->def.method->source; fptr.fptr = unspec->fptr; fptr.jlcall_api = unspec->jlcall_api; if (fptr.fptr && fptr.jlcall_api) { @@ -1611,7 +1610,7 @@ void jl_extern_c(jl_function_t *f, jl_value_t *rt, jl_value_t *argt, char *name) extern "C" JL_DLLEXPORT void *jl_get_llvmf_defn(jl_method_instance_t *linfo, size_t world, bool getwrapper, bool optimize, const jl_cgparams_t params) { - if (linfo->def && linfo->def->source == NULL) { + if (jl_is_method(linfo->def.method) && linfo->def.method->source == NULL) { // not a generic function return NULL; } @@ -1620,12 +1619,17 @@ void *jl_get_llvmf_defn(jl_method_instance_t *linfo, size_t world, bool getwrapp JL_GC_PUSH1(&src); if (!src || (jl_value_t*)src == jl_nothing) { src = jl_type_infer(&linfo, world, 0); - if (!src) - src = linfo->def->isstaged ? jl_code_for_staged(linfo) : (jl_code_info_t*)linfo->def->source; - } - if (!src || (jl_value_t*)src == jl_nothing) + if (!src && jl_is_method(linfo->def.method)) + src = linfo->def.method->isstaged ? jl_code_for_staged(linfo) : (jl_code_info_t*)linfo->def.method->source; + } + if ((jl_value_t*)src == jl_nothing) + src = NULL; + if (src && !jl_is_code_info(src) && jl_is_method(linfo->def.method)) + src = jl_uncompress_ast(linfo->def.method, (jl_array_t*)src); + if (src && !jl_is_code_info(src)) + src = NULL; + if (!src) jl_error("source not found for function"); - src = jl_uncompress_ast(linfo->def, (jl_array_t*)src); // Backup the info for the nested compile JL_LOCK(&codegen_lock); @@ -1646,7 +1650,8 @@ void *jl_get_llvmf_defn(jl_method_instance_t *linfo, size_t world, bool getwrapp builder.restoreIP(old); builder.SetCurrentDebugLocation(olddl); JL_UNLOCK(&codegen_lock); // Might GC - jl_rethrow_with_add("error compiling %s", jl_symbol_name(linfo->def ? linfo->def->name : anonymous_sym)); + const char *mname = jl_symbol_name(jl_is_method(linfo->def.method) ? linfo->def.method->name : anonymous_sym); + jl_rethrow_with_add("error compiling %s", mname); } // Restore the previous compile context builder.restoreIP(old); @@ -1691,7 +1696,7 @@ void *jl_get_llvmf_defn(jl_method_instance_t *linfo, size_t world, bool getwrapp extern "C" JL_DLLEXPORT void *jl_get_llvmf_decl(jl_method_instance_t *linfo, size_t world, bool getwrapper, const jl_cgparams_t params) { - if (linfo->def && linfo->def->source == NULL) { + if (jl_is_method(linfo->def.method) && linfo->def.method->source == NULL) { // not a generic function return NULL; } @@ -1699,7 +1704,7 @@ void *jl_get_llvmf_decl(jl_method_instance_t *linfo, size_t world, bool getwrapp // compile this normally jl_llvm_functions_t decls = jl_compile_for_dispatch(&linfo, world); - if (decls.functionObject == NULL && linfo->jlcall_api == 2 && linfo->def) { + if (decls.functionObject == NULL && linfo->jlcall_api == 2 && jl_is_method(linfo->def.method)) { // normally we don't generate native code for these functions, so need an exception here // This leaks a bit of memory to cache native code that we'll never actually need JL_LOCK(&codegen_lock); @@ -1708,7 +1713,7 @@ void *jl_get_llvmf_decl(jl_method_instance_t *linfo, size_t world, bool getwrapp jl_code_info_t *src = NULL; src = jl_type_infer(&linfo, world, 0); if (!src) { - src = linfo->def->isstaged ? jl_code_for_staged(linfo) : (jl_code_info_t*)linfo->def->source; + src = linfo->def.method->isstaged ? jl_code_for_staged(linfo) : (jl_code_info_t*)linfo->def.method->source; } decls = jl_compile_linfo(&linfo, src, world, ¶ms); linfo->functionObjectsDecls = decls; @@ -3159,7 +3164,7 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, else if (f==jl_builtin_apply_type && nargs > 0) { size_t i; - if (ctx->linfo->def == NULL) { + if (jl_is_method(ctx->linfo->def.method)) { // don't bother codegen constant-folding for toplevel JL_GC_POP(); return false; @@ -4051,7 +4056,8 @@ static void emit_stmtpos(jl_value_t *expr, jl_codectx_t *ctx) ConstantInt::get(T_int32, jl_unbox_long(args[0]))); } else { - if (ctx->linfo->def == NULL) { + if (!jl_is_method(ctx->linfo->def.method)) { + // TODO: inference is invalid if this has an effect Value *world = builder.CreateLoad(prepare_global(jlgetworld_global)); builder.CreateStore(world, ctx->world_age_field); } @@ -4113,7 +4119,7 @@ static jl_cgval_t emit_expr(jl_value_t *expr, jl_codectx_t *ctx) expr = jl_box_int64(val); } } - if (needroot && ctx->linfo->def) { // toplevel exprs and some integers are already rooted + if (needroot && jl_is_method(ctx->linfo->def.method)) { // toplevel exprs and some integers are already rooted jl_add_method_root(ctx, expr); } return mark_julia_const(expr); @@ -4129,7 +4135,7 @@ static jl_cgval_t emit_expr(jl_value_t *expr, jl_codectx_t *ctx) return emit_invoke(ex, ctx); } else if (head == call_sym) { - if (ctx->linfo->def) { // don't bother codegen constant-folding for toplevel + if (jl_is_method(ctx->linfo->def.method)) { // don't bother codegen constant-folding for toplevel jl_value_t *c = static_eval(expr, ctx, true, true); if (c) { jl_add_method_root(ctx, c); @@ -4165,8 +4171,8 @@ static jl_cgval_t emit_expr(jl_value_t *expr, jl_codectx_t *ctx) jl_binding_t *bnd = NULL; bool issym = jl_is_symbol(mn); bool isglobalref = !issym && jl_is_globalref(mn); + jl_module_t *mod = ctx->module; if (issym || isglobalref) { - jl_module_t *mod = ctx->module; if (isglobalref) { mod = jl_globalref_mod(mn); mn = (jl_value_t*)jl_globalref_name(mn); @@ -4185,17 +4191,22 @@ static jl_cgval_t emit_expr(jl_value_t *expr, jl_codectx_t *ctx) name = literal_pointer_val((jl_value_t*)slot_symbol(sl, ctx)); } if (bp) { - Value *mdargs[4] = { name, bp, bp_owner, literal_pointer_val(bnd) }; + Value *mdargs[5] = { name, literal_pointer_val((jl_value_t*)mod), bp, bp_owner, literal_pointer_val(bnd) }; jl_cgval_t gf = mark_julia_type( - builder.CreateCall(prepare_call(jlgenericfunction_func), ArrayRef(&mdargs[0], 4)), + builder.CreateCall(prepare_call(jlgenericfunction_func), makeArrayRef(mdargs)), true, jl_function_type, ctx); if (jl_expr_nargs(ex) == 1) return gf; } Value *a1 = boxed(emit_expr(args[1], ctx), ctx); Value *a2 = boxed(emit_expr(args[2], ctx), ctx); - Value *mdargs[3] = { a1, a2, literal_pointer_val(args[3]) }; - builder.CreateCall(prepare_call(jlmethod_func), ArrayRef(&mdargs[0], 3)); + Value *mdargs[4] = { + /*argdata*/a1, + /*code*/a2, + /*module*/literal_pointer_val((jl_value_t*)ctx->module), + /*isstaged*/literal_pointer_val(args[3]) + }; + builder.CreateCall(prepare_call(jlmethod_func), makeArrayRef(mdargs)); return ghostValue(jl_void_type); } else if (head == const_sym) { @@ -4267,11 +4278,15 @@ static jl_cgval_t emit_expr(jl_value_t *expr, jl_codectx_t *ctx) if (!strcmp(jl_symbol_name(head), "$")) jl_error("syntax: prefix \"$\" in non-quoted expression"); if (jl_is_toplevel_only_expr(expr) && - ctx->linfo->def == NULL) { + !jl_is_method(ctx->linfo->def.method)) { JL_FEAT_REQUIRE(ctx, runtime); // call interpreter to run a toplevel expr from inside a // compiled toplevel thunk. - builder.CreateCall(prepare_call(jltopeval_func), literal_pointer_val(expr)); + Value *args[2] = { + literal_pointer_val((jl_value_t*)ctx->module), + literal_pointer_val(expr) + }; + builder.CreateCall(prepare_call(jltopeval_func), args); return ghostValue(jl_void_type); } if (head == abstracttype_sym || head == compositetype_sym || @@ -4330,7 +4345,7 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t jl_value_t *astrt = (jl_value_t*)jl_any_type; // infer it first, if necessary if (lam) { - name = jl_symbol_name(lam->def->name); + name = jl_symbol_name(lam->def.method->name); jl_code_info_t *src = NULL; if (!lam->inferred) // TODO: this isn't ideal to be unconditionally calling type inference from here src = jl_type_infer(&lam, world, 0); @@ -4946,7 +4961,7 @@ static Function *gen_jlcall_wrapper(jl_method_instance_t *lam, const jl_returnin allocate_gc_frame(b0, &ctx); FunctionType *ftype = f.decl->getFunctionType(); - size_t nargs = lam->def->nargs; + size_t nargs = lam->def.method->nargs; size_t nfargs = ftype->getNumParams(); Value **args = (Value**) alloca(nfargs*sizeof(Value*)); unsigned idx = 0; @@ -5143,7 +5158,6 @@ static std::unique_ptr emit_function( jl_llvm_functions_t *declarations, const jl_cgparams_t *params) { - jl_ptls_t ptls = jl_get_ptls_states(); assert(declarations && "Capturing declarations is always required"); // step 1. unpack AST and allocate codegen context for this function @@ -5156,18 +5170,18 @@ static std::unique_ptr emit_function( std::map arrayvars; std::map labels; ctx.arrayvars = &arrayvars; - ctx.module = lam->def ? lam->def->module : ptls->current_module; + ctx.module = jl_is_method(lam->def.method) ? lam->def.method->module : lam->def.module; ctx.linfo = lam; ctx.source = src; ctx.world = world; - ctx.name = jl_symbol_name(lam->def ? lam->def->name : anonymous_sym); + ctx.name = jl_symbol_name(jl_is_method(lam->def.method) ? lam->def.method->name : anonymous_sym); ctx.funcName = ctx.name; ctx.vaSlot = -1; ctx.vaStack = false; ctx.params = params; ctx.spvals_ptr = NULL; - ctx.nargs = lam->def ? lam->def->nargs : 0; - bool toplevel = lam->def == NULL; + ctx.nargs = jl_is_method(lam->def.method) ? lam->def.method->nargs : 0; + bool toplevel = !jl_is_method(lam->def.method); // step 1b. unpack debug information int coverage_mode = jl_options.code_coverage; @@ -5175,10 +5189,10 @@ static std::unique_ptr emit_function( StringRef filename = ""; StringRef dbgFuncName = ctx.name; int toplineno = -1; - if (lam->def) { - toplineno = lam->def->line; - if (lam->def->file != empty_sym) - filename = jl_symbol_name(lam->def->file); + if (jl_is_method(lam->def.method)) { + toplineno = lam->def.method->line; + if (lam->def.method->file != empty_sym) + filename = jl_symbol_name(lam->def.method->file); } ctx.file = filename; // jl_printf(JL_STDERR, "\n*** compiling %s at %s:%d\n\n", @@ -5204,7 +5218,7 @@ static std::unique_ptr emit_function( assert(lam->specTypes); // the specTypes field should always be assigned - if (nreq > 0 && lam->def->isva) { + if (nreq > 0 && lam->def.method->isva) { nreq--; va = 1; jl_sym_t *vn = (jl_sym_t*)jl_array_ptr_ref(src->slotnames, ctx.nargs - 1); @@ -5262,7 +5276,9 @@ static std::unique_ptr emit_function( jl_value_t *jlrettype = lam->rettype; bool specsig = false; - bool needsparams = lam->def ? jl_svec_len(lam->def->sparam_syms) != jl_svec_len(lam->sparam_vals) : false; + bool needsparams = jl_is_method(lam->def.method) + ? jl_svec_len(lam->def.method->sparam_syms) != jl_svec_len(lam->sparam_vals) + : false; for (i = 0; !needsparams && i < jl_svec_len(lam->sparam_vals); i++) { jl_value_t *e = jl_svecref(lam->sparam_vals, i); if (jl_is_typevar(e)) @@ -6257,7 +6273,7 @@ static std::unique_ptr emit_function( // copy ctx.roots into m->roots // if we created any new roots during codegen if (ctx.roots) { - jl_method_t *m = lam->def; + jl_method_t *m = lam->def.method; JL_LOCK(&m->writelock); if (m->roots == NULL) { m->roots = ctx.roots; @@ -6357,7 +6373,7 @@ extern "C" void jl_fptr_to_llvm(jl_fptr_t fptr, jl_method_instance_t *lam, int s funcName << "jlsysw_"; // it's a specsig wrapper else if (lam->jlcall_api == 1) funcName << "jsys1_"; // it's a jlcall without a specsig - const char* unadorned_name = jl_symbol_name(lam->def->name); + const char* unadorned_name = jl_symbol_name(lam->def.method->name); #if (defined(_OS_LINUX_) && JL_LLVM_VERSION < 30400) if (unadorned_name[0] == '@') unadorned_name++; @@ -6826,16 +6842,19 @@ static void init_julia_llvm_env(Module *m) exp_args.push_back(T_int1); expect_func = Intrinsic::getDeclaration(m, Intrinsic::expect, exp_args); - std::vector args3(0); - args3.push_back(T_pjlvalue); + std::vector args_topeval(0); + args_topeval.push_back(T_pjlvalue); + args_topeval.push_back(T_pjlvalue); jltopeval_func = - Function::Create(FunctionType::get(T_pjlvalue, args3, false), + Function::Create(FunctionType::get(T_pjlvalue, args_topeval, false), Function::ExternalLinkage, "jl_toplevel_eval", m); add_named_global(jltopeval_func, &jl_toplevel_eval); + std::vector args_copyast(0); + args_copyast.push_back(T_pjlvalue); jlcopyast_func = - Function::Create(FunctionType::get(T_pjlvalue, args3, false), + Function::Create(FunctionType::get(T_pjlvalue, args_copyast, false), Function::ExternalLinkage, "jl_copy_ast", m); add_named_global(jlcopyast_func, &jl_copy_ast); @@ -6852,6 +6871,7 @@ static void init_julia_llvm_env(Module *m) mdargs.push_back(T_pjlvalue); mdargs.push_back(T_pjlvalue); mdargs.push_back(T_pjlvalue); + mdargs.push_back(T_pjlvalue); jlmethod_func = Function::Create(FunctionType::get(T_void, mdargs, false), Function::ExternalLinkage, @@ -6860,6 +6880,7 @@ static void init_julia_llvm_env(Module *m) std::vector funcdefargs(0); funcdefargs.push_back(T_pjlvalue); + funcdefargs.push_back(T_pjlvalue); funcdefargs.push_back(T_ppjlvalue); funcdefargs.push_back(T_pjlvalue); funcdefargs.push_back(T_pjlvalue); diff --git a/src/datatype.c b/src/datatype.c index 746d3a1b762a2..1c2486414b840 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -66,17 +66,11 @@ JL_DLLEXPORT jl_typename_t *jl_new_typename_in(jl_sym_t *name, jl_module_t *modu return tn; } -JL_DLLEXPORT jl_typename_t *jl_new_typename(jl_sym_t *name) -{ - jl_ptls_t ptls = jl_get_ptls_states(); - return jl_new_typename_in(name, ptls->current_module); -} - // allocating DataTypes ----------------------------------------------------------- -jl_datatype_t *jl_new_abstracttype(jl_value_t *name, jl_datatype_t *super, jl_svec_t *parameters) +jl_datatype_t *jl_new_abstracttype(jl_value_t *name, jl_module_t *module, jl_datatype_t *super, jl_svec_t *parameters) { - return jl_new_datatype((jl_sym_t*)name, super, parameters, jl_emptysvec, jl_emptysvec, 1, 0, 0); + return jl_new_datatype((jl_sym_t*)name, module, super, parameters, jl_emptysvec, jl_emptysvec, 1, 0, 0); } jl_datatype_t *jl_new_uninitialized_datatype(void) @@ -330,15 +324,18 @@ void jl_compute_field_offsets(jl_datatype_t *st) extern int jl_boot_file_loaded; -JL_DLLEXPORT jl_datatype_t *jl_new_datatype(jl_sym_t *name, jl_datatype_t *super, - jl_svec_t *parameters, - jl_svec_t *fnames, jl_svec_t *ftypes, - int abstract, int mutabl, - int ninitialized) +JL_DLLEXPORT jl_datatype_t *jl_new_datatype( + jl_sym_t *name, + jl_module_t *module, + jl_datatype_t *super, + jl_svec_t *parameters, + jl_svec_t *fnames, + jl_svec_t *ftypes, + int abstract, int mutabl, + int ninitialized) { - jl_ptls_t ptls = jl_get_ptls_states(); - jl_datatype_t *t=NULL; - jl_typename_t *tn=NULL; + jl_datatype_t *t = NULL; + jl_typename_t *tn = NULL; JL_GC_PUSH2(&t, &tn); if (!jl_boot_file_loaded && jl_is_symbol(name)) { @@ -357,7 +354,7 @@ JL_DLLEXPORT jl_datatype_t *jl_new_datatype(jl_sym_t *name, jl_datatype_t *super t = jl_new_uninitialized_datatype(); else tn = t->name; - // init before possibly calling jl_new_typename + // init before possibly calling jl_new_typename_in t->super = super; if (super != NULL) jl_gc_wb(t, t->super); t->parameters = parameters; @@ -378,9 +375,9 @@ JL_DLLEXPORT jl_datatype_t *jl_new_datatype(jl_sym_t *name, jl_datatype_t *super tn = (jl_typename_t*)name; } else { - tn = jl_new_typename((jl_sym_t*)name); + tn = jl_new_typename_in((jl_sym_t*)name, module); if (!abstract) { - tn->mt = jl_new_method_table(name, ptls->current_module); + tn->mt = jl_new_method_table(name, module); jl_gc_wb(tn, tn->mt); } } @@ -412,10 +409,11 @@ JL_DLLEXPORT jl_datatype_t *jl_new_datatype(jl_sym_t *name, jl_datatype_t *super return t; } -JL_DLLEXPORT jl_datatype_t *jl_new_primitivetype(jl_value_t *name, jl_datatype_t *super, +JL_DLLEXPORT jl_datatype_t *jl_new_primitivetype(jl_value_t *name, jl_module_t *module, + jl_datatype_t *super, jl_svec_t *parameters, size_t nbits) { - jl_datatype_t *bt = jl_new_datatype((jl_sym_t*)name, super, parameters, + jl_datatype_t *bt = jl_new_datatype((jl_sym_t*)name, module, super, parameters, jl_emptysvec, jl_emptysvec, 0, 0, 0); uint32_t nbytes = (nbits + 7) / 8; uint32_t alignm = next_power_of_two(nbytes); diff --git a/src/dump.c b/src/dump.c index 601d73ec1d0f5..c020c554b29e6 100644 --- a/src/dump.c +++ b/src/dump.c @@ -442,7 +442,7 @@ static void jl_update_all_fptrs(void) jl_method_instance_t **linfos = (jl_method_instance_t**)malloc(sizeof(jl_method_instance_t*) * sysimg_fvars_max); for (i = 0; i < delayed_fptrs_n; i++) { jl_method_instance_t *li = delayed_fptrs[i].li; - assert(li->def && li->jlcall_api && li->jlcall_api != 2); + assert(jl_is_method(li->def.method) && li->jlcall_api && li->jlcall_api != 2); int32_t cfunc = delayed_fptrs[i].cfunc - 1; if (cfunc >= 0) { jl_fptr_to_llvm((jl_fptr_t)(uintptr_t)fvars[cfunc], li, 1); @@ -961,7 +961,7 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li if (li->max_world == 0 && li->min_world == 0) { internal = 1; // not world-tracked } - else if (!li->def || module_in_worklist(li->def->module)) { + else if (!jl_is_method(li->def.method) || module_in_worklist(li->def.method->module)) { if (li->max_world == ~(size_t)0) { internal = 2; // update world on deserialization } @@ -978,9 +978,9 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li } jl_serialize_value(s, (jl_value_t*)li->specTypes); if (s->mode == MODE_MODULE && !internal) - jl_serialize_value(s, (jl_value_t*)li->def->sig); + jl_serialize_value(s, (jl_value_t*)li->def.method->sig); else - jl_serialize_value(s, (jl_value_t*)li->def); + jl_serialize_value(s, li->def.value); if (s->mode == MODE_MODULE) { write_uint8(s->s, internal); if (!internal) @@ -995,7 +995,7 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li write_int32(s->s, li->min_world); write_int32(s->s, li->max_world); } - if (li->def) { + if (jl_is_method(li->def.method)) { uint16_t id = jl_fptr_id((void*)(uintptr_t)li->fptr); if (li->jlcall_api == 2) { write_int8(s->s, 2); @@ -1266,7 +1266,7 @@ static void jl_serialize_backedges(jl_serializer_state *s) for (i = 0; i < edges_map.size; i += 2) { jl_method_instance_t *caller = (jl_method_instance_t*)table[i]; jl_array_t *callee = (jl_array_t*)table[i + 1]; - if (callee != HT_NOTFOUND && module_in_worklist(caller->def->module)) { + if (callee != HT_NOTFOUND && module_in_worklist(caller->def.method->module)) { arraylist_push(&worklist, (void*)caller); } } @@ -1776,9 +1776,9 @@ static jl_value_t *jl_deserialize_value_method_instance(jl_serializer_state *s, li->specTypes = (jl_value_t*)jl_deserialize_value(s, (jl_value_t**)&li->specTypes); if (li->specTypes) jl_gc_wb(li, li->specTypes); - li->def = (jl_method_t*)jl_deserialize_value(s, (jl_value_t**)&li->def); - if (li->def) - jl_gc_wb(li, li->def); + li->def.value = jl_deserialize_value(s, &li->def.value); + if (li->def.value) + jl_gc_wb(li, li->def.value); int internal = 0; if (s->mode == MODE_MODULE) { @@ -1828,7 +1828,7 @@ static jl_value_t *jl_deserialize_value_method_instance(jl_serializer_state *s, li->functionObjectsDecls.specFunctionObject = NULL; li->inInference = 0; int8_t jlcall_api = read_int8(s->s); - if (jlcall_api == 2 || jlcall_api == 0 || li->def == NULL) { + if (jlcall_api == 2 || jlcall_api == 0 || !jl_is_method(li->def.method)) { li->fptr = NULL; li->jlcall_api = jlcall_api; } @@ -2204,12 +2204,12 @@ static void jl_insert_backedges(linkedlist_t *list) assert(jl_is_method_instance(caller)); jl_array_t *callees = list->def[i].callee; assert(jl_is_array(callees)); - if (!caller->inferred || module_in_worklist(caller->def->module)) { + if (!caller->inferred || module_in_worklist(caller->def.method->module)) { for (j = 0; j < jl_array_len(callees); j++) { jl_value_t *callee = jl_array_ptr_ref(callees, j); if (jl_is_method_instance(callee)) { jl_method_instance_t *callee_mi = (jl_method_instance_t*)callee; - if (!module_in_worklist(callee_mi->def->module)) { + if (!module_in_worklist(callee_mi->def.method->module)) { // verify that this MethodInstance is still the correct lookup for this callee sig jl_value_t *sig = callee_mi->specTypes; jl_method_t *m = NULL; @@ -2222,7 +2222,7 @@ static void jl_insert_backedges(linkedlist_t *list) if (entry != NULL) m = entry->func.method; } - if (m != callee_mi->def) { + if (m != callee_mi->def.method) { // probably no good, just invalidate everything now jl_method_instance_delete(caller); break; @@ -3169,7 +3169,7 @@ static jl_method_t *jl_recache_method(jl_method_t *m, size_t start, arraylist_t static jl_method_instance_t *jl_recache_method_instance(jl_method_instance_t *li, size_t start, arraylist_t *dependent_worlds) { - jl_datatype_t *sig = (jl_datatype_t*)li->def; + jl_datatype_t *sig = (jl_datatype_t*)li->def.value; assert(jl_is_datatype(sig) || jl_is_unionall(sig)); jl_datatype_t *ftype = jl_first_argument_datatype((jl_value_t*)sig); jl_methtable_t *mt = ftype->name->mt; diff --git a/src/gf.c b/src/gf.c index 683b11bc1d24c..3be37fce6fc59 100644 --- a/src/gf.c +++ b/src/gf.c @@ -214,14 +214,15 @@ void jl_mk_builtin_func(jl_datatype_t *dt, const char *name, jl_fptr_t fptr) li->max_world = ~(size_t)0; JL_GC_PUSH1(&li); - li->def = jl_new_method_uninit(); - jl_gc_wb(li, li->def); - li->def->name = sname; - li->def->module = jl_core_module; - li->def->isva = 1; - li->def->nargs = 2; - li->def->sig = (jl_value_t*)jl_anytuple_type; - li->def->sparam_syms = jl_emptysvec; + jl_method_t *m = jl_new_method_uninit(); + li->def.method = m; + jl_gc_wb(li, m); + m->name = sname; + m->module = jl_core_module; + m->isva = 1; + m->nargs = 2; + m->sig = (jl_value_t*)jl_anytuple_type; + m->sparam_syms = jl_emptysvec; jl_methtable_t *mt = dt->name->mt; jl_typemap_insert(&mt->cache, (jl_value_t*)mt, jl_anytuple_type, @@ -261,7 +262,7 @@ jl_code_info_t *jl_type_infer(jl_method_instance_t **pli, size_t world, int forc li->inInference = 1; jl_svec_t *linfo_src_rettype = (jl_svec_t*)jl_apply_with_saved_exception_state(fargs, 3, 0); ptls->world_age = last_age; - assert((li->def || li->inInference == 0) && "inference failed on a toplevel expr"); + assert((jl_is_method(li->def.method) || li->inInference == 0) && "inference failed on a toplevel expr"); jl_code_info_t *src = NULL; if (jl_is_svec(linfo_src_rettype) && jl_svec_len(linfo_src_rettype) == 3 && @@ -315,7 +316,7 @@ static void update_world_bound(jl_method_instance_t *replaced, jl_typemap_visito update.replaced = replaced; update.world = world; - jl_method_t *m = replaced->def; + jl_method_t *m = replaced->def.method; // update the world-valid in the specializations caches jl_typemap_visitor(m->specializations, fptr, (void*)&update); // update the world-valid in the invoke cache @@ -336,14 +337,14 @@ JL_DLLEXPORT jl_method_instance_t* jl_set_method_inferred( assert(min_world <= max_world && "attempting to set invalid world constraints"); assert(li->inInference && "shouldn't be caching an inference result for a MethodInstance that wasn't being inferred"); if (min_world != li->min_world || max_world != li->max_world) { - if (li->def == NULL) { + if (!jl_is_method(li->def.method)) { // thunks don't have multiple references, so just update in-place li->min_world = min_world; li->max_world = max_world; } else { - JL_LOCK(&li->def->writelock); - assert(min_world >= li->def->min_world); + JL_LOCK(&li->def.method->writelock); + assert(min_world >= li->def.method->min_world); int isinferred = jl_is_rettype_inferred(li); if (!isinferred && li->min_world >= min_world && li->max_world <= max_world) { // expand the current (uninferred) entry to cover the full inferred range @@ -354,12 +355,12 @@ JL_DLLEXPORT jl_method_instance_t* jl_set_method_inferred( if (li->min_world != min_world) { li->min_world = min_world; update.world = min_world; - jl_typemap_visitor(li->def->specializations, set_min_world2, (void*)&update); + jl_typemap_visitor(li->def.method->specializations, set_min_world2, (void*)&update); } if (li->max_world != max_world) { li->max_world = max_world; update.world = max_world; - jl_typemap_visitor(li->def->specializations, set_max_world2, (void*)&update); + jl_typemap_visitor(li->def.method->specializations, set_max_world2, (void*)&update); } } else { @@ -370,7 +371,7 @@ JL_DLLEXPORT jl_method_instance_t* jl_set_method_inferred( if (li->max_world >= min_world && li->min_world <= max_world) { // there is a non-zero overlap between [li->min, li->max] and [min, max] // there are now 4 regions left to consider - // TODO: also take into account li->def->world range when computing preferred division + // TODO: also take into account li->def.method->world range when computing preferred division if (li->max_world > max_world) { // prefer making it applicable to future ages, // as those are more likely to be useful @@ -388,15 +389,15 @@ JL_DLLEXPORT jl_method_instance_t* jl_set_method_inferred( } // build a new entry to describe the new (inferred) applicability - li = jl_get_specialized(li->def, li->specTypes, li->sparam_vals); + li = jl_get_specialized(li->def.method, li->specTypes, li->sparam_vals); li->min_world = min_world; li->max_world = max_world; - jl_typemap_insert(&li->def->specializations, (jl_value_t*)li->def, + jl_typemap_insert(&li->def.method->specializations, li->def.value, (jl_tupletype_t*)li->specTypes, NULL, jl_emptysvec, (jl_value_t*)li, 0, &tfunc_cache, li->min_world, li->max_world, NULL); } - JL_UNLOCK(&li->def->writelock); + JL_UNLOCK(&li->def.method->writelock); } } @@ -1247,7 +1248,7 @@ static int JL_DEBUG_METHOD_INVALIDATION = 0; // invalidate cached methods that had an edge to a replaced method static void invalidate_method_instance(jl_method_instance_t *replaced, size_t max_world, int depth) { - JL_LOCK_NOGC(&replaced->def->writelock); + JL_LOCK_NOGC(&replaced->def.method->writelock); jl_array_t *backedges = replaced->backedges; if (replaced->max_world > max_world) { // recurse to all backedges to update their valid range also @@ -1270,7 +1271,7 @@ static void invalidate_method_instance(jl_method_instance_t *replaced, size_t ma } } replaced->backedges = NULL; - JL_UNLOCK_NOGC(&replaced->def->writelock); + JL_UNLOCK_NOGC(&replaced->def.method->writelock); } // invalidate cached methods that overlap this definition @@ -1286,7 +1287,7 @@ static int invalidate_backedges(jl_typemap_entry_t *oldentry, struct typemap_int struct set_world def; def.replaced = oldentry->func.linfo; def.world = closure->max_world; - jl_method_t *m = def.replaced->def; + jl_method_t *m = def.replaced->def.method; // truncate the max-valid in the invoke cache if (m->invokes.unknown != NULL) @@ -1297,7 +1298,7 @@ static int invalidate_backedges(jl_typemap_entry_t *oldentry, struct typemap_int jl_typemap_visitor(gf->name->mt->cache, set_max_world2, (void*)&def); // invalidate backedges - JL_LOCK_NOGC(&def.replaced->def->writelock); + JL_LOCK_NOGC(&def.replaced->def.method->writelock); jl_array_t *backedges = def.replaced->backedges; if (backedges) { size_t i, l = jl_array_len(backedges); @@ -1308,7 +1309,7 @@ static int invalidate_backedges(jl_typemap_entry_t *oldentry, struct typemap_int } closure->invalidated = 1; def.replaced->backedges = NULL; - JL_UNLOCK_NOGC(&def.replaced->def->writelock); + JL_UNLOCK_NOGC(&def.replaced->def.method->writelock); } return 1; } @@ -1317,7 +1318,7 @@ static int invalidate_backedges(jl_typemap_entry_t *oldentry, struct typemap_int JL_DLLEXPORT void jl_method_instance_add_backedge(jl_method_instance_t *callee, jl_method_instance_t *caller) { assert(callee->min_world <= caller->min_world && callee->max_world >= caller->max_world); - JL_LOCK(&callee->def->writelock); + JL_LOCK(&callee->def.method->writelock); if (!callee->backedges) { // lazy-init the backedges array callee->backedges = jl_alloc_vec_any(1); @@ -1334,7 +1335,7 @@ JL_DLLEXPORT void jl_method_instance_add_backedge(jl_method_instance_t *callee, jl_array_ptr_1d_push(callee->backedges, (jl_value_t*)caller); } } - JL_UNLOCK(&callee->def->writelock); + JL_UNLOCK(&callee->def.method->writelock); } // add a backedge from a non-existent signature to caller @@ -1619,8 +1620,8 @@ jl_llvm_functions_t jl_compile_for_dispatch(jl_method_instance_t **pli, size_t w if (jl_options.compile_enabled == JL_OPTIONS_COMPILE_OFF || jl_options.compile_enabled == JL_OPTIONS_COMPILE_MIN) { // copy fptr from the template method definition - jl_method_t *def = li->def; - if (def && !def->isstaged && def->unspecialized) { + jl_method_t *def = li->def.method; + if (jl_is_method(def) && !def->isstaged && def->unspecialized) { if (def->unspecialized->jlcall_api == 2) { li->functionObjectsDecls.functionObject = NULL; li->functionObjectsDecls.specFunctionObject = NULL; @@ -1651,8 +1652,8 @@ jl_llvm_functions_t jl_compile_for_dispatch(jl_method_instance_t **pli, size_t w return decls; jl_code_info_t *src = NULL; - if (li->def && !jl_is_rettype_inferred(li) && - jl_symbol_name(li->def->name)[0] != '@') { + if (jl_is_method(li->def.method) && !jl_is_rettype_inferred(li) && + jl_symbol_name(li->def.method->name)[0] != '@') { // don't bother with typeinf on macros or toplevel thunks // but try to infer everything else src = jl_type_infer(pli, world, 0); @@ -1701,7 +1702,7 @@ jl_method_instance_t *jl_get_specialization1(jl_tupletype_t *types, size_t world jl_method_instance_t *sf = jl_method_lookup_by_type(mt, types, 1, 1, 1, world); assert(sf == NULL || (sf->min_world <= world && sf->max_world >= world)); JL_GC_PUSH1(&sf); - if (sf != NULL && jl_has_call_ambiguities(types, sf->def)) { + if (sf != NULL && jl_has_call_ambiguities(types, sf->def.method)) { sf = NULL; } JL_GC_POP(); @@ -1904,7 +1905,7 @@ STATIC_INLINE jl_method_instance_t *jl_lookup_generic_(jl_value_t **args, uint32 #ifdef JL_TRACE if (traceen) - jl_printf(JL_STDOUT, " at %s:%d\n", jl_symbol_name(mfunc->def->file), mfunc->def->line); + jl_printf(JL_STDOUT, " at %s:%d\n", jl_symbol_name(mfunc->def.method->file), mfunc->def.method->line); #endif return mfunc; } @@ -2100,12 +2101,12 @@ jl_function_t *jl_new_generic_function_with_supertype(jl_sym_t *name, jl_module_ } jl_sym_t *tname = jl_symbol(prefixed); free(prefixed); - jl_datatype_t *ftype = (jl_datatype_t*)jl_new_datatype(tname, st, jl_emptysvec, jl_emptysvec, jl_emptysvec, 0, 0, 0); + jl_datatype_t *ftype = (jl_datatype_t*)jl_new_datatype( + tname, module, st, jl_emptysvec, jl_emptysvec, jl_emptysvec, 0, 0, 0); assert(jl_is_datatype(ftype)); JL_GC_PUSH1(&ftype); - ftype->name->mt->name = name; jl_gc_wb(ftype->name->mt, name); - ftype->name->module = module; jl_gc_wb(ftype->name, module); - ftype->name->mt->module = module; jl_gc_wb(ftype->name->mt, module); + ftype->name->mt->name = name; + jl_gc_wb(ftype->name->mt, name); jl_set_const(module, tname, (jl_value_t*)ftype); jl_value_t *f = jl_new_struct(ftype); ftype->instance = f; jl_gc_wb(ftype, f); diff --git a/src/init.c b/src/init.c index 612f6b1e3c54f..1cdc0db222640 100644 --- a/src/init.c +++ b/src/init.c @@ -664,11 +664,11 @@ void _julia_init(JL_IMAGE_SEARCH rel) jl_internal_main_module = jl_main_module; ptls->current_module = jl_core_module; - for (int t = 0;t < jl_n_threads;t++) { - jl_all_tls_states[t]->root_task->current_module = ptls->current_module; + for (int t = 0; t < jl_n_threads; t++) { + jl_all_tls_states[t]->root_task->current_module = jl_core_module; } - jl_load("boot.jl"); + jl_load(jl_core_module, "boot.jl"); jl_get_builtin_hooks(); jl_boot_file_loaded = 1; jl_init_box_caches(); @@ -713,8 +713,8 @@ void _julia_init(JL_IMAGE_SEARCH rel) jl_add_standard_imports(jl_main_module); } ptls->current_module = jl_main_module; - for (int t = 0;t < jl_n_threads;t++) { - jl_all_tls_states[t]->root_task->current_module = ptls->current_module; + for (int t = 0; t < jl_n_threads; t++) { + jl_all_tls_states[t]->root_task->current_module = jl_main_module; } // This needs to be after jl_start_threads diff --git a/src/interpreter.c b/src/interpreter.c index 99fc01c7c7bb0..b78fd15686fd3 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -24,18 +24,9 @@ typedef struct { static jl_value_t *eval(jl_value_t *e, interpreter_state *s); static jl_value_t *eval_body(jl_array_t *stmts, interpreter_state *s, int start, int toplevel); -jl_value_t *jl_eval_module_expr(jl_expr_t *ex); +jl_value_t *jl_eval_module_expr(jl_module_t *m, jl_expr_t *ex); int jl_is_toplevel_only_expr(jl_value_t *e); -jl_value_t *jl_interpret_toplevel_expr(jl_value_t *e) -{ - size_t last_age = jl_get_ptls_states()->world_age; - jl_get_ptls_states()->world_age = jl_world_counter; - jl_value_t *ret = eval(e, NULL); - jl_get_ptls_states()->world_age = last_age; - return ret; -} - jl_value_t *jl_interpret_toplevel_expr_in(jl_module_t *m, jl_value_t *e, jl_code_info_t *src, jl_svec_t *sparam_vals) @@ -200,7 +191,7 @@ static int jl_source_nssavalues(jl_code_info_t *src) static jl_value_t *eval(jl_value_t *e, interpreter_state *s) { jl_ptls_t ptls = jl_get_ptls_states(); - jl_code_info_t *src = s==NULL ? NULL : s->src; + jl_code_info_t *src = s->src; if (jl_is_ssavalue(e)) { ssize_t id = ((jl_ssavalue_t*)e)->id; if (src == NULL || id >= jl_source_nssavalues(src) || id < 0 || s->locals == NULL) @@ -226,7 +217,7 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s) } if (jl_is_quotenode(e)) return jl_fieldref(e,0); - jl_module_t *modu = (s == NULL ? ptls->current_module : s->module); + jl_module_t *modu = s->module; if (jl_is_symbol(e)) { // bare symbols appear in toplevel exprs not wrapped in `thunk` jl_value_t *v = jl_get_global(modu, (jl_sym_t*)e); if (v == NULL) @@ -291,7 +282,7 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s) bp = &b->value; bp_owner = (jl_value_t*)modu; } - jl_value_t *gf = jl_generic_function_def(fname, bp, bp_owner, b); + jl_value_t *gf = jl_generic_function_def(fname, modu, bp, bp_owner, b); if (jl_expr_nargs(ex) == 1) return gf; } @@ -300,7 +291,7 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s) JL_GC_PUSH2(&atypes, &meth); atypes = eval(args[1], s); meth = eval(args[2], s); - jl_method_def((jl_svec_t*)atypes, (jl_code_info_t*)meth, args[3]); + jl_method_def((jl_svec_t*)atypes, (jl_code_info_t*)meth, s->module, args[3]); JL_GC_POP(); return jl_nothing; } @@ -347,7 +338,7 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s) name = (jl_value_t*)jl_globalref_name(name); } assert(jl_is_symbol(name)); - dt = jl_new_abstracttype(name, NULL, (jl_svec_t*)para); + dt = jl_new_abstracttype(name, modu, NULL, (jl_svec_t*)para); w = dt->name->wrapper; jl_binding_t *b = jl_get_binding_wr(modu, (jl_sym_t*)name); temp = b->value; @@ -395,7 +386,7 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s) if (nb < 1 || nb>=(1<<23) || (nb&7) != 0) jl_errorf("invalid number of bits in type %s", jl_symbol_name((jl_sym_t*)name)); - dt = jl_new_primitivetype(name, NULL, (jl_svec_t*)para, nb); + dt = jl_new_primitivetype(name, modu, NULL, (jl_svec_t*)para, nb); w = dt->name->wrapper; jl_binding_t *b = jl_get_binding_wr(modu, (jl_sym_t*)name); temp = b->value; @@ -437,7 +428,7 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s) assert(jl_is_symbol(name)); assert(jl_is_svec(para)); temp = eval(args[2], s); // field names - dt = jl_new_datatype((jl_sym_t*)name, NULL, (jl_svec_t*)para, + dt = jl_new_datatype((jl_sym_t*)name, modu, NULL, (jl_svec_t*)para, (jl_svec_t*)temp, NULL, 0, args[5]==jl_true ? 1 : 0, jl_unbox_long(args[6])); w = dt->name->wrapper; @@ -485,10 +476,10 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s) return (jl_value_t*)jl_nothing; } else if (ex->head == module_sym) { - return jl_eval_module_expr(ex); + return jl_eval_module_expr(s->module, ex); } else if (ex->head == thunk_sym) { - return jl_toplevel_eval((jl_value_t*)ex); + return jl_toplevel_eval(s->module, (jl_value_t*)ex); } else if (ex->head == error_sym || ex->head == jl_incomplete_sym) { if (nargs == 0) @@ -505,19 +496,24 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s) return (jl_value_t*)jl_nothing; } -jl_value_t *jl_toplevel_eval_body(jl_array_t *stmts) +jl_value_t *jl_toplevel_eval_body(jl_module_t *m, jl_array_t *stmts) { size_t last_age = jl_get_ptls_states()->world_age; - jl_value_t *ret = eval_body(stmts, NULL, 0, 1); + interpreter_state s; + s.src = NULL; + s.module = m; + s.locals = NULL; + s.sparam_vals = NULL; + jl_value_t *ret = eval_body(stmts, &s, 0, 1); jl_get_ptls_states()->world_age = last_age; return ret; } static jl_value_t *eval_body(jl_array_t *stmts, interpreter_state *s, int start, int toplevel) { - jl_ptls_t ptls = jl_get_ptls_states(); jl_handler_t __eh; - size_t i=start, ns = jl_array_len(stmts); + size_t i = start; + size_t ns = jl_array_len(stmts); while (1) { if (i >= ns) @@ -534,7 +530,7 @@ static jl_value_t *eval_body(jl_array_t *stmts, interpreter_state *s, int start, if (head == return_sym) { jl_value_t *ex = jl_exprarg(stmt, 0); if (toplevel && jl_is_toplevel_only_expr(ex)) - return jl_toplevel_eval(ex); + return jl_toplevel_eval(s->module, ex); else return eval(ex, s); } @@ -559,7 +555,7 @@ static jl_value_t *eval_body(jl_array_t *stmts, interpreter_state *s, int start, sym = (jl_value_t*)jl_globalref_name(sym); } else { - m = (s == NULL ? ptls->current_module : s->module); + m = s->module; } assert(jl_is_symbol(sym)); JL_GC_PUSH1(&rhs); @@ -590,7 +586,7 @@ static jl_value_t *eval_body(jl_array_t *stmts, interpreter_state *s, int start, } else { #ifdef _OS_WINDOWS_ - if (ptls->exception_in_transit == jl_stackovf_exception) + if (jl_get_ptls_states()->exception_in_transit == jl_stackovf_exception) _resetstkoflw(); #endif i = jl_unbox_long(jl_exprarg(stmt, 0)) - 1; @@ -602,7 +598,7 @@ static jl_value_t *eval_body(jl_array_t *stmts, interpreter_state *s, int start, jl_pop_handler(hand_n_leave); } else if (toplevel && jl_is_toplevel_only_expr(stmt)) { - jl_toplevel_eval(stmt); + jl_toplevel_eval(s->module, stmt); } else { eval(stmt, s); @@ -635,17 +631,17 @@ jl_value_t *jl_interpret_call(jl_method_instance_t *lam, jl_value_t **args, uint return lam->inferred_const; jl_code_info_t *src = (jl_code_info_t*)lam->inferred; if (!src || (jl_value_t*)src == jl_nothing) { - if (lam->def->isstaged) { + if (lam->def.method->isstaged) { src = jl_code_for_staged(lam); lam->inferred = (jl_value_t*)src; jl_gc_wb(lam, src); } else { - src = (jl_code_info_t*)lam->def->source; + src = (jl_code_info_t*)lam->def.method->source; } } if (src && (jl_value_t*)src != jl_nothing) { - src = jl_uncompress_ast(lam->def, (jl_array_t*)src); + src = jl_uncompress_ast(lam->def.method, (jl_array_t*)src); lam->inferred = (jl_value_t*)src; jl_gc_wb(lam, src); } @@ -661,12 +657,12 @@ jl_value_t *jl_interpret_call(jl_method_instance_t *lam, jl_value_t **args, uint locals[1] = (jl_value_t*)stmts; interpreter_state s; s.src = src; - s.module = lam->def->module; + s.module = lam->def.method->module; s.locals = locals + 2; s.sparam_vals = lam->sparam_vals; size_t i; - for (i = 0; i < lam->def->nargs; i++) { - if (lam->def->isva && i == lam->def->nargs - 1) + for (i = 0; i < lam->def.method->nargs; i++) { + if (lam->def.method->isva && i == lam->def.method->nargs - 1) s.locals[i] = jl_f_tuple(NULL, &args[i], nargs - i); else s.locals[i] = args[i]; @@ -676,9 +672,8 @@ jl_value_t *jl_interpret_call(jl_method_instance_t *lam, jl_value_t **args, uint return r; } -jl_value_t *jl_interpret_toplevel_thunk(jl_code_info_t *src) +jl_value_t *jl_interpret_toplevel_thunk(jl_module_t *m, jl_code_info_t *src) { - jl_ptls_t ptls = jl_get_ptls_states(); jl_array_t *stmts = src->code; assert(jl_typeis(stmts, jl_array_any_type)); jl_value_t **locals; @@ -686,7 +681,7 @@ jl_value_t *jl_interpret_toplevel_thunk(jl_code_info_t *src) interpreter_state s; s.src = src; s.locals = locals; - s.module = ptls->current_module; + s.module = m; s.sparam_vals = jl_emptysvec; size_t last_age = jl_get_ptls_states()->world_age; jl_value_t *r = eval_body(stmts, &s, 0, 1); diff --git a/src/jlapi.c b/src/jlapi.c index 703ec688aad8c..be3e74be8b578 100644 --- a/src/jlapi.c +++ b/src/jlapi.c @@ -74,7 +74,7 @@ JL_DLLEXPORT jl_value_t *jl_eval_string(const char *str) JL_GC_PUSH1(&ast); size_t last_age = jl_get_ptls_states()->world_age; jl_get_ptls_states()->world_age = jl_get_world_counter(); - r = jl_toplevel_eval(ast); + r = jl_toplevel_eval_in(jl_main_module, ast); jl_get_ptls_states()->world_age = last_age; JL_GC_POP(); jl_exception_clear(); diff --git a/src/jlfrontend.scm b/src/jlfrontend.scm index 28f62d2525fb0..59828a423173e 100644 --- a/src/jlfrontend.scm +++ b/src/jlfrontend.scm @@ -119,19 +119,23 @@ ;; called by jl_eval_module_expr (define (module-default-defs e) (jl-expand-to-thunk - (let ((name (caddr e)) - (body (cadddr e))) - (let ((loc (cadr body))) - `(block - ,(let ((x (if (eq? name 'x) 'y 'x))) - `(= (call eval ,x) - (block - ,loc - (call (core eval) ,name ,x)))) - (= (call eval m x) - (block - ,loc - (call (core eval) m x)))))))) + (let* ((name (caddr e)) + (body (cadddr e)) + (loc (cadr body)) + (x (if (eq? name 'x) 'y 'x))) + `(block + (= (call eval ,x) + (block + ,loc + (call (core eval) ,name ,x))) + (= (call eval m ,x) + (block + ,loc + (call (core eval) m ,x))) + (= (call include ,x) + (block + ,loc + (call (top include) ,name ,x))))))) ;; parse only, returning end position, no expansion. (define (jl-parse-one-string s pos0 greedy) diff --git a/src/jltypes.c b/src/jltypes.c index 91a579b36ae50..c292cae8e523e 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -1534,7 +1534,8 @@ extern void jl_init_int32_int64_cache(void); void jl_init_types(void) { - jl_ptls_t ptls = jl_get_ptls_states(); + jl_module_t *core = NULL; // will need to be assigned later + arraylist_new(&partial_inst, 0); // create base objects jl_datatype_type = jl_new_uninitialized_datatype(); @@ -1553,15 +1554,15 @@ void jl_init_types(void) jl_emptysvec = (jl_svec_t*)jl_gc_permobj(sizeof(void*), jl_simplevector_type); jl_svec_set_len_unsafe(jl_emptysvec, 0); - jl_any_type = (jl_datatype_t*)jl_new_abstracttype((jl_value_t*)jl_symbol("Any"), NULL, jl_emptysvec); + jl_any_type = (jl_datatype_t*)jl_new_abstracttype((jl_value_t*)jl_symbol("Any"), core, NULL, jl_emptysvec); jl_any_type->super = jl_any_type; - jl_type_type = (jl_unionall_t*)jl_new_abstracttype((jl_value_t*)jl_symbol("Type"), jl_any_type, jl_emptysvec); + jl_type_type = (jl_unionall_t*)jl_new_abstracttype((jl_value_t*)jl_symbol("Type"), core, jl_any_type, jl_emptysvec); jl_type_typename = ((jl_datatype_t*)jl_type_type)->name; - jl_type_type_mt = jl_new_method_table(jl_type_typename->name, ptls->current_module); + jl_type_type_mt = jl_new_method_table(jl_type_typename->name, core); jl_type_typename->mt = jl_type_type_mt; // initialize them. lots of cycles. - jl_datatype_type->name = jl_new_typename(jl_symbol("DataType")); + jl_datatype_type->name = jl_new_typename_in(jl_symbol("DataType"), core); jl_datatype_type->name->wrapper = (jl_value_t*)jl_datatype_type; jl_datatype_type->super = (jl_datatype_t*)jl_type_type; jl_datatype_type->parameters = jl_emptysvec; @@ -1601,9 +1602,9 @@ void jl_init_types(void) jl_datatype_type->mutabl = 1; jl_datatype_type->ninitialized = 4; - jl_typename_type->name = jl_new_typename(jl_symbol("TypeName")); + jl_typename_type->name = jl_new_typename_in(jl_symbol("TypeName"), core); jl_typename_type->name->wrapper = (jl_value_t*)jl_typename_type; - jl_typename_type->name->mt = jl_new_method_table(jl_typename_type->name->name, ptls->current_module); + jl_typename_type->name->mt = jl_new_method_table(jl_typename_type->name->name, core); jl_typename_type->super = jl_any_type; jl_typename_type->parameters = jl_emptysvec; jl_typename_type->name->names = jl_perm_symsvec(8, "name", "module", @@ -1621,9 +1622,9 @@ void jl_init_types(void) jl_typename_type->mutabl = 1; jl_typename_type->ninitialized = 2; - jl_methtable_type->name = jl_new_typename(jl_symbol("MethodTable")); + jl_methtable_type->name = jl_new_typename_in(jl_symbol("MethodTable"), core); jl_methtable_type->name->wrapper = (jl_value_t*)jl_methtable_type; - jl_methtable_type->name->mt = jl_new_method_table(jl_methtable_type->name->name, ptls->current_module); + jl_methtable_type->name->mt = jl_new_method_table(jl_methtable_type->name->name, core); jl_methtable_type->super = jl_any_type; jl_methtable_type->parameters = jl_emptysvec; jl_methtable_type->name->names = jl_perm_symsvec(9, "name", "defs", @@ -1641,9 +1642,9 @@ void jl_init_types(void) jl_methtable_type->mutabl = 1; jl_methtable_type->ninitialized = 4; - jl_sym_type->name = jl_new_typename(jl_symbol("Symbol")); + jl_sym_type->name = jl_new_typename_in(jl_symbol("Symbol"), core); jl_sym_type->name->wrapper = (jl_value_t*)jl_sym_type; - jl_sym_type->name->mt = jl_new_method_table(jl_sym_type->name->name, ptls->current_module); + jl_sym_type->name->mt = jl_new_method_table(jl_sym_type->name->name, core); jl_sym_type->super = jl_any_type; jl_sym_type->parameters = jl_emptysvec; jl_sym_type->name->names = jl_emptysvec; @@ -1657,9 +1658,9 @@ void jl_init_types(void) jl_sym_type->mutabl = 1; jl_sym_type->ninitialized = 0; - jl_simplevector_type->name = jl_new_typename(jl_symbol("SimpleVector")); + jl_simplevector_type->name = jl_new_typename_in(jl_symbol("SimpleVector"), core); jl_simplevector_type->name->wrapper = (jl_value_t*)jl_simplevector_type; - jl_simplevector_type->name->mt = jl_new_method_table(jl_simplevector_type->name->name, ptls->current_module); + jl_simplevector_type->name->mt = jl_new_method_table(jl_simplevector_type->name->name, core); jl_simplevector_type->super = jl_any_type; jl_simplevector_type->parameters = jl_emptysvec; jl_simplevector_type->name->names = jl_perm_symsvec(1, "length"); @@ -1673,29 +1674,28 @@ void jl_init_types(void) jl_simplevector_type->ninitialized = 1; // now they can be used to create the remaining base kinds and types - jl_void_type = jl_new_datatype(jl_symbol("Void"), jl_any_type, jl_emptysvec, + jl_void_type = jl_new_datatype(jl_symbol("Void"), core, jl_any_type, jl_emptysvec, jl_emptysvec, jl_emptysvec, 0, 0, 0); jl_astaggedvalue(jl_nothing)->header = ((uintptr_t)jl_void_type) | GC_OLD_MARKED; jl_void_type->instance = jl_nothing; jl_datatype_t *type_type = (jl_datatype_t*)jl_type_type; - jl_typeofbottom_type = jl_new_datatype(jl_symbol("TypeofBottom"), type_type, jl_emptysvec, + jl_typeofbottom_type = jl_new_datatype(jl_symbol("TypeofBottom"), core, type_type, jl_emptysvec, jl_emptysvec, jl_emptysvec, 0, 0, 0); jl_bottom_type = jl_new_struct(jl_typeofbottom_type); jl_typeofbottom_type->instance = jl_bottom_type; - jl_uniontype_type = jl_new_datatype(jl_symbol("Union"), type_type, jl_emptysvec, + jl_uniontype_type = jl_new_datatype(jl_symbol("Union"), core, type_type, jl_emptysvec, jl_perm_symsvec(2, "a", "b"), jl_svec(2, jl_any_type, jl_any_type), 0, 0, 2); - jl_tvar_type = jl_new_datatype(jl_symbol("TypeVar"), jl_any_type, jl_emptysvec, + jl_tvar_type = jl_new_datatype(jl_symbol("TypeVar"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(3, "name", "lb", "ub"), - jl_svec(3, jl_sym_type, - jl_any_type, jl_any_type), + jl_svec(3, jl_sym_type, jl_any_type, jl_any_type), 0, 1, 3); - jl_unionall_type = jl_new_datatype(jl_symbol("UnionAll"), type_type, jl_emptysvec, + jl_unionall_type = jl_new_datatype(jl_symbol("UnionAll"), core, type_type, jl_emptysvec, jl_perm_symsvec(2, "var", "body"), jl_svec(2, jl_tvar_type, jl_any_type), 0, 0, 2); @@ -1703,10 +1703,10 @@ void jl_init_types(void) vararg_sym = jl_symbol("Vararg"); jl_svec_t *tv; tv = jl_svec2(tvar("T"),tvar("N")); - jl_vararg_type = (jl_unionall_t*)jl_new_abstracttype((jl_value_t*)vararg_sym, jl_any_type, tv)->name->wrapper; + jl_vararg_type = (jl_unionall_t*)jl_new_abstracttype((jl_value_t*)vararg_sym, core, jl_any_type, tv)->name->wrapper; jl_vararg_typename = ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_vararg_type))->name; - jl_anytuple_type = jl_new_datatype(jl_symbol("Tuple"), jl_any_type, jl_emptysvec, + jl_anytuple_type = jl_new_datatype(jl_symbol("Tuple"), core, jl_any_type, jl_emptysvec, jl_emptysvec, jl_emptysvec, 0, 0, 0); jl_tuple_typename = jl_anytuple_type->name; jl_anytuple_type->uid = 0; @@ -1731,48 +1731,49 @@ void jl_init_types(void) // non-primitive definitions follow jl_int32_type = NULL; - jl_int32_type = jl_new_primitivetype((jl_value_t*)jl_symbol("Int32"), + jl_int32_type = jl_new_primitivetype((jl_value_t*)jl_symbol("Int32"), core, jl_any_type, jl_emptysvec, 32); jl_int64_type = NULL; - jl_int64_type = jl_new_primitivetype((jl_value_t*)jl_symbol("Int64"), + jl_int64_type = jl_new_primitivetype((jl_value_t*)jl_symbol("Int64"), core, jl_any_type, jl_emptysvec, 64); jl_uint8_type = NULL; - jl_uint8_type = jl_new_primitivetype((jl_value_t*)jl_symbol("UInt8"), + jl_uint8_type = jl_new_primitivetype((jl_value_t*)jl_symbol("UInt8"), core, jl_any_type, jl_emptysvec, 8); - jl_ssavalue_type = jl_new_datatype(jl_symbol("SSAValue"), jl_any_type, jl_emptysvec, + jl_ssavalue_type = jl_new_datatype(jl_symbol("SSAValue"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(1, "id"), jl_svec1(jl_long_type), 0, 0, 1); - jl_abstractslot_type = jl_new_abstracttype((jl_value_t*)jl_symbol("Slot"), jl_any_type, + jl_abstractslot_type = jl_new_abstracttype((jl_value_t*)jl_symbol("Slot"), core, jl_any_type, jl_emptysvec); - jl_slotnumber_type = jl_new_datatype(jl_symbol("SlotNumber"), jl_abstractslot_type, jl_emptysvec, + jl_slotnumber_type = jl_new_datatype(jl_symbol("SlotNumber"), core, jl_abstractslot_type, jl_emptysvec, jl_perm_symsvec(1, "id"), jl_svec1(jl_long_type), 0, 0, 1); - jl_typedslot_type = jl_new_datatype(jl_symbol("TypedSlot"), jl_abstractslot_type, jl_emptysvec, + jl_typedslot_type = jl_new_datatype(jl_symbol("TypedSlot"), core, jl_abstractslot_type, jl_emptysvec, jl_perm_symsvec(2, "id", "typ"), jl_svec(2, jl_long_type, jl_any_type), 0, 0, 2); jl_init_int32_int64_cache(); jl_bool_type = NULL; - jl_bool_type = jl_new_primitivetype((jl_value_t*)jl_symbol("Bool"), + jl_bool_type = jl_new_primitivetype((jl_value_t*)jl_symbol("Bool"), core, jl_any_type, jl_emptysvec, 8); jl_false = jl_permbox8(jl_bool_type, 0); jl_true = jl_permbox8(jl_bool_type, 1); jl_typemap_level_type = - jl_new_datatype(jl_symbol("TypeMapLevel"), jl_any_type, jl_emptysvec, - jl_perm_symsvec(7, "index_arg1", - "arg1", - "index_targ", - "targ", - "list", - "any", - "key"), + jl_new_datatype(jl_symbol("TypeMapLevel"), core, jl_any_type, jl_emptysvec, + jl_perm_symsvec(7, + "index_arg1", + "arg1", + "index_targ", + "targ", + "list", + "any", + "key"), jl_svec(7, jl_any_type, jl_any_type, @@ -1784,18 +1785,18 @@ void jl_init_types(void) 0, 1, 6); jl_typemap_entry_type = - jl_new_datatype(jl_symbol("TypeMapEntry"), jl_any_type, jl_emptysvec, + jl_new_datatype(jl_symbol("TypeMapEntry"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(10, - "next", - "sig", - "simplesig", - "guardsigs", - "min_world", - "max_world", - "func", - "isleafsig", - "issimplesig", - "va"), + "next", + "sig", + "simplesig", + "guardsigs", + "min_world", + "max_world", + "func", + "isleafsig", + "issimplesig", + "va"), jl_svec(10, jl_any_type, // Union{TypeMapEntry, Void} jl_type_type, // TupleType @@ -1809,23 +1810,23 @@ void jl_init_types(void) jl_bool_type), 0, 1, 4); - jl_function_type = jl_new_abstracttype((jl_value_t*)jl_symbol("Function"), jl_any_type, jl_emptysvec); - jl_builtin_type = jl_new_abstracttype((jl_value_t*)jl_symbol("Builtin"), jl_function_type, jl_emptysvec); + jl_function_type = jl_new_abstracttype((jl_value_t*)jl_symbol("Function"), core, jl_any_type, jl_emptysvec); + jl_builtin_type = jl_new_abstracttype((jl_value_t*)jl_symbol("Builtin"), core, jl_function_type, jl_emptysvec); tv = jl_svec2(tvar("T"), tvar("N")); jl_abstractarray_type = (jl_unionall_t*) - jl_new_abstracttype((jl_value_t*)jl_symbol("AbstractArray"), + jl_new_abstracttype((jl_value_t*)jl_symbol("AbstractArray"), core, jl_any_type, tv)->name->wrapper; tv = jl_svec2(tvar("T"), tvar("N")); jl_densearray_type = (jl_unionall_t*) - jl_new_abstracttype((jl_value_t*)jl_symbol("DenseArray"), + jl_new_abstracttype((jl_value_t*)jl_symbol("DenseArray"), core, (jl_datatype_t*)jl_apply_type((jl_value_t*)jl_abstractarray_type, jl_svec_data(tv), 2), tv)->name->wrapper; tv = jl_svec2(tvar("T"), tvar("N")); jl_array_type = (jl_unionall_t*) - jl_new_datatype(jl_symbol("Array"), + jl_new_datatype(jl_symbol("Array"), core, (jl_datatype_t*) jl_apply_type((jl_value_t*)jl_densearray_type, jl_svec_data(tv), 2), tv, @@ -1841,7 +1842,7 @@ void jl_init_types(void) jl_array_uint8_type = jl_apply_type2((jl_value_t*)jl_array_type, (jl_value_t*)jl_uint8_type, jl_box_long(1)); jl_expr_type = - jl_new_datatype(jl_symbol("Expr"), + jl_new_datatype(jl_symbol("Expr"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(3, "head", "args", "typ"), jl_svec(3, jl_sym_type, jl_array_any_type, @@ -1849,161 +1850,161 @@ void jl_init_types(void) 0, 1, 3); jl_linenumbernode_type = - jl_new_datatype(jl_symbol("LineNumberNode"), jl_any_type, jl_emptysvec, + jl_new_datatype(jl_symbol("LineNumberNode"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(2, "line", "file"), jl_svec(2, jl_long_type, jl_any_type), 0, 0, 2); jl_labelnode_type = - jl_new_datatype(jl_symbol("LabelNode"), jl_any_type, jl_emptysvec, + jl_new_datatype(jl_symbol("LabelNode"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(1, "label"), jl_svec(1, jl_long_type), 0, 0, 1); jl_gotonode_type = - jl_new_datatype(jl_symbol("GotoNode"), jl_any_type, jl_emptysvec, + jl_new_datatype(jl_symbol("GotoNode"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(1, "label"), jl_svec(1, jl_long_type), 0, 0, 1); jl_quotenode_type = - jl_new_datatype(jl_symbol("QuoteNode"), jl_any_type, jl_emptysvec, + jl_new_datatype(jl_symbol("QuoteNode"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(1, "value"), jl_svec(1, jl_any_type), 0, 0, 1); jl_newvarnode_type = - jl_new_datatype(jl_symbol("NewvarNode"), jl_any_type, jl_emptysvec, + jl_new_datatype(jl_symbol("NewvarNode"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(1, "slot"), jl_svec(1, jl_slotnumber_type), 0, 0, 1); jl_module_type = - jl_new_datatype(jl_symbol("Module"), jl_any_type, jl_emptysvec, + jl_new_datatype(jl_symbol("Module"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(2, "name", "parent"), jl_svec(2, jl_sym_type, jl_any_type), 0, 1, 2); jl_globalref_type = - jl_new_datatype(jl_symbol("GlobalRef"), jl_any_type, jl_emptysvec, + jl_new_datatype(jl_symbol("GlobalRef"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(2, "mod", "name"), jl_svec(2, jl_module_type, jl_sym_type), 0, 0, 2); jl_code_info_type = - jl_new_datatype(jl_symbol("CodeInfo"), + jl_new_datatype(jl_symbol("CodeInfo"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(9, - "code", - "slottypes", - "ssavaluetypes", - "slotflags", - "slotnames", - "inferred", - "inlineable", - "propagate_inbounds", - "pure"), + "code", + "slottypes", + "ssavaluetypes", + "slotflags", + "slotnames", + "inferred", + "inlineable", + "propagate_inbounds", + "pure"), jl_svec(9, - jl_array_any_type, - jl_any_type, - jl_any_type, - jl_array_uint8_type, - jl_array_any_type, - jl_bool_type, - jl_bool_type, - jl_bool_type, - jl_bool_type), + jl_array_any_type, + jl_any_type, + jl_any_type, + jl_array_uint8_type, + jl_array_any_type, + jl_bool_type, + jl_bool_type, + jl_bool_type, + jl_bool_type), 0, 1, 9); jl_method_type = - jl_new_datatype(jl_symbol("Method"), + jl_new_datatype(jl_symbol("Method"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(19, - "name", - "module", - "file", - "line", - "sig", - "min_world", - "ambig", - "specializations", - "sparam_syms", - "source", - "unspecialized", - "generator", - "roots", - "invokes", - "nargs", - "called", - "isva", - "isstaged", - "pure"), + "name", + "module", + "file", + "line", + "sig", + "min_world", + "ambig", + "specializations", + "sparam_syms", + "source", + "unspecialized", + "generator", + "roots", + "invokes", + "nargs", + "called", + "isva", + "isstaged", + "pure"), jl_svec(19, - jl_sym_type, - jl_module_type, - jl_sym_type, - jl_int32_type, - jl_type_type, - jl_long_type, - jl_any_type, // Union{Array, Void} - jl_any_type, // TypeMap - jl_simplevector_type, - jl_any_type, - jl_any_type, // jl_method_instance_type - jl_any_type, // jl_method_instance_type - jl_array_any_type, - jl_any_type, - jl_int32_type, - jl_int32_type, - jl_bool_type, - jl_bool_type, - jl_bool_type), + jl_sym_type, + jl_module_type, + jl_sym_type, + jl_int32_type, + jl_type_type, + jl_long_type, + jl_any_type, // Union{Array, Void} + jl_any_type, // TypeMap + jl_simplevector_type, + jl_any_type, + jl_any_type, // jl_method_instance_type + jl_any_type, // jl_method_instance_type + jl_array_any_type, + jl_any_type, + jl_int32_type, + jl_int32_type, + jl_bool_type, + jl_bool_type, + jl_bool_type), 0, 1, 9); jl_method_instance_type = - jl_new_datatype(jl_symbol("MethodInstance"), + jl_new_datatype(jl_symbol("MethodInstance"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(16, - "specTypes", - "rettype", - "sparam_vals", - "backedges", - "inferred", - "inferred_const", - "def", - "min_world", - "max_world", - "inInference", - "jlcall_api", - "", - "fptr", - "unspecialized_ducttape", - "", ""), + "def", + "specTypes", + "rettype", + "sparam_vals", + "backedges", + "inferred", + "inferred_const", + "min_world", + "max_world", + "inInference", + "jlcall_api", + "", + "fptr", + "unspecialized_ducttape", + "", ""), jl_svec(16, - jl_any_type, - jl_any_type, - jl_simplevector_type, - jl_any_type, - jl_any_type, - jl_any_type, - jl_method_type, - jl_long_type, - jl_long_type, - jl_bool_type, - jl_uint8_type, - jl_bool_type, - jl_any_type, // void* - jl_any_type, // void* - jl_any_type, jl_any_type), // void*, void* - 0, 1, 3); + jl_new_struct(jl_uniontype_type, jl_method_type, jl_module_type), + jl_any_type, + jl_any_type, + jl_simplevector_type, + jl_any_type, + jl_any_type, + jl_any_type, + jl_long_type, + jl_long_type, + jl_bool_type, + jl_uint8_type, + jl_bool_type, + jl_any_type, // void* + jl_any_type, // void* + jl_any_type, jl_any_type), // void*, void* + 0, 1, 4); // all kinds of types share a method table jl_unionall_type->name->mt = jl_uniontype_type->name->mt = jl_datatype_type->name->mt = jl_type_typename->mt; - jl_intrinsic_type = jl_new_primitivetype((jl_value_t*)jl_symbol("IntrinsicFunction"), + jl_intrinsic_type = jl_new_primitivetype((jl_value_t*)jl_symbol("IntrinsicFunction"), core, jl_builtin_type, jl_emptysvec, 32); tv = jl_svec1(tvar("T")); jl_ref_type = (jl_unionall_t*) - jl_new_abstracttype((jl_value_t*)jl_symbol("Ref"), jl_any_type, tv)->name->wrapper; + jl_new_abstracttype((jl_value_t*)jl_symbol("Ref"), core, jl_any_type, tv)->name->wrapper; tv = jl_svec1(tvar("T")); jl_pointer_type = (jl_unionall_t*) - jl_new_primitivetype((jl_value_t*)jl_symbol("Ptr"), + jl_new_primitivetype((jl_value_t*)jl_symbol("Ptr"), core, (jl_datatype_t*)jl_apply_type((jl_value_t*)jl_ref_type, jl_svec_data(tv), 1), tv, sizeof(void*)*8)->name->wrapper; jl_pointer_typename = ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_pointer_type))->name; @@ -2023,8 +2024,8 @@ void jl_init_types(void) jl_ANY_flag = (jl_value_t*)tvar("ANY"); - jl_abstractstring_type = jl_new_abstracttype((jl_value_t*)jl_symbol("AbstractString"), jl_any_type, jl_emptysvec); - jl_string_type = jl_new_datatype(jl_symbol("String"), jl_abstractstring_type, jl_emptysvec, + jl_abstractstring_type = jl_new_abstracttype((jl_value_t*)jl_symbol("AbstractString"), core, jl_any_type, jl_emptysvec); + jl_string_type = jl_new_datatype(jl_symbol("String"), core, jl_abstractstring_type, jl_emptysvec, jl_perm_symsvec(1, "len"), jl_svec1(jl_long_type), 0, 1, 1); diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index faee84d7c940b..123e44621140a 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -1163,6 +1163,7 @@ (expand-forms `(function (call ,(symbol (string #\@ (cadr (cadr e)))) (|::| __source__ (core LineNumberNode)) + (|::| __module__ (core Module)) ,@(map (lambda (v) (if (symbol? v) `(|::| ,v (core ANY)) diff --git a/src/julia.h b/src/julia.h index d25c67a3a2d2d..314feafc4dc1a 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1,5 +1,8 @@ // This file is a part of Julia. License is MIT: https://julialang.org/license +// TODO: add `@isdefined` +// + #ifndef JULIA_H #define JULIA_H @@ -264,13 +267,17 @@ typedef struct _jl_method_t { // This type caches the data for a specType signature specialization of a Method typedef struct _jl_method_instance_t { JL_DATA_TYPE + union { + jl_value_t *value; // generic accessor + struct _jl_module_t *module; // this is a toplevel thunk + jl_method_t *method; // method this is specialized from + } def; // context for this lambda definition jl_value_t *specTypes; // argument types this was specialized for jl_value_t *rettype; // return type for fptr - jl_svec_t *sparam_vals; // static parameter values, indexed by def->sparam_syms + jl_svec_t *sparam_vals; // static parameter values, indexed by def.method->sparam_syms jl_array_t *backedges; jl_value_t *inferred; // inferred jl_code_info_t, or value of the function if jlcall_api == 2, or null jl_value_t *inferred_const; // inferred constant return value, or null - jl_method_t *def; // method this is specialized from, null if this is a toplevel thunk size_t min_world; size_t max_world; uint8_t inInference; // flags to tell if inference is running on this function @@ -419,7 +426,7 @@ typedef struct _jl_typemap_entry_t { size_t min_world; size_t max_world; union { - jl_value_t *value; + jl_value_t *value; // generic accessor jl_method_instance_t *linfo; // [nullable] for guard entries jl_method_t *method; } func; @@ -997,7 +1004,7 @@ STATIC_INLINE int jl_is_leaf_type_(jl_value_t *v) #endif // type constructors -JL_DLLEXPORT jl_typename_t *jl_new_typename(jl_sym_t *name); +JL_DLLEXPORT jl_typename_t *jl_new_typename_in(jl_sym_t *name, jl_module_t *inmodule); JL_DLLEXPORT jl_tvar_t *jl_new_typevar(jl_sym_t *name, jl_value_t *lb, jl_value_t *ub); JL_DLLEXPORT jl_value_t *jl_instantiate_unionall(jl_unionall_t *u, jl_value_t *p); JL_DLLEXPORT jl_value_t *jl_apply_type(jl_value_t *tc, jl_value_t **params, size_t n); @@ -1005,14 +1012,19 @@ JL_DLLEXPORT jl_value_t *jl_apply_type1(jl_value_t *tc, jl_value_t *p1); JL_DLLEXPORT jl_value_t *jl_apply_type2(jl_value_t *tc, jl_value_t *p1, jl_value_t *p2); JL_DLLEXPORT jl_tupletype_t *jl_apply_tuple_type(jl_svec_t *params); JL_DLLEXPORT jl_tupletype_t *jl_apply_tuple_type_v(jl_value_t **p, size_t np); -JL_DLLEXPORT jl_datatype_t *jl_new_datatype(jl_sym_t *name, jl_datatype_t *super, +JL_DLLEXPORT jl_datatype_t *jl_new_datatype(jl_sym_t *name, + jl_module_t *module, + jl_datatype_t *super, jl_svec_t *parameters, jl_svec_t *fnames, jl_svec_t *ftypes, int abstract, int mutabl, int ninitialized); JL_DLLEXPORT jl_datatype_t *jl_new_primitivetype(jl_value_t *name, + jl_module_t *module, jl_datatype_t *super, jl_svec_t *parameters, size_t nbits); +jl_datatype_t *jl_new_abstracttype(jl_value_t *name, jl_module_t *module, + jl_datatype_t *super, jl_svec_t *parameters); // constructors JL_DLLEXPORT jl_value_t *jl_new_bits(jl_value_t *bt, void *data); @@ -1035,10 +1047,11 @@ JL_DLLEXPORT jl_sym_t *jl_symbol_n(const char *str, size_t len); JL_DLLEXPORT jl_sym_t *jl_gensym(void); JL_DLLEXPORT jl_sym_t *jl_tagged_gensym(const char *str, int32_t len); JL_DLLEXPORT jl_sym_t *jl_get_root_symbol(void); -JL_DLLEXPORT jl_value_t *jl_generic_function_def(jl_sym_t *name, jl_value_t **bp, - jl_value_t *bp_owner, +JL_DLLEXPORT jl_value_t *jl_generic_function_def(jl_sym_t *name, + jl_module_t *module, + jl_value_t **bp, jl_value_t *bp_owner, jl_binding_t *bnd); -JL_DLLEXPORT void jl_method_def(jl_svec_t *argdata, jl_code_info_t *f, jl_value_t *isstaged); +JL_DLLEXPORT void jl_method_def(jl_svec_t *argdata, jl_code_info_t *f, jl_module_t *module, jl_value_t *isstaged); JL_DLLEXPORT jl_code_info_t *jl_code_for_staged(jl_method_instance_t *linfo); JL_DLLEXPORT jl_code_info_t *jl_copy_code_info(jl_code_info_t *src); JL_DLLEXPORT size_t jl_get_world_counter(void); @@ -1343,8 +1356,8 @@ JL_DLLEXPORT jl_value_t *jl_parse_string(const char *str, size_t len, int pos0, int greedy); JL_DLLEXPORT int jl_parse_depwarn(int warn); JL_DLLEXPORT jl_value_t *jl_load_file_string(const char *text, size_t len, - char *filename); -JL_DLLEXPORT jl_value_t *jl_expand(jl_value_t *expr); + char *filename, jl_module_t *inmodule); +JL_DLLEXPORT jl_value_t *jl_expand(jl_value_t *expr, jl_module_t *inmodule); JL_DLLEXPORT jl_value_t *jl_eval_string(const char *str); // external libraries @@ -1376,9 +1389,9 @@ JL_DLLEXPORT const char *jl_lookup_soname(const char *pfx, size_t n); #endif // compiler -JL_DLLEXPORT jl_value_t *jl_toplevel_eval(jl_value_t *v); +JL_DLLEXPORT jl_value_t *jl_toplevel_eval(jl_module_t *m, jl_value_t *v); JL_DLLEXPORT jl_value_t *jl_toplevel_eval_in(jl_module_t *m, jl_value_t *ex); -JL_DLLEXPORT jl_value_t *jl_load(const char *fname); +JL_DLLEXPORT jl_value_t *jl_load(jl_module_t *module, const char *fname); JL_DLLEXPORT jl_module_t *jl_base_relative_to(jl_module_t *m); // tracing diff --git a/src/julia_internal.h b/src/julia_internal.h index 47b2b1365dd83..9337c784fcff6 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -294,17 +294,14 @@ jl_value_t *jl_gc_realloc_string(jl_value_t *s, size_t sz); jl_code_info_t *jl_type_infer(jl_method_instance_t **li, size_t world, int force); jl_generic_fptr_t jl_generate_fptr(jl_method_instance_t *li, void *F, size_t world); -jl_llvm_functions_t jl_compile_linfo(jl_method_instance_t **pli, jl_code_info_t *src, size_t world, const jl_cgparams_t *params); +jl_llvm_functions_t jl_compile_linfo( + jl_method_instance_t **pli, + jl_code_info_t *src, + size_t world, + const jl_cgparams_t *params); jl_llvm_functions_t jl_compile_for_dispatch(jl_method_instance_t **li, size_t world); JL_DLLEXPORT int jl_compile_hint(jl_tupletype_t *types); jl_code_info_t *jl_new_code_info_from_ast(jl_expr_t *ast); -jl_method_t *jl_new_method(jl_code_info_t *definition, - jl_sym_t *name, - jl_tupletype_t *sig, - size_t nargs, - int isva, - jl_svec_t *tvars, - int isstaged); STATIC_INLINE jl_value_t *jl_compile_method_internal(jl_generic_fptr_t *fptr, jl_method_instance_t *meth) @@ -326,11 +323,11 @@ STATIC_INLINE jl_value_t *jl_compile_method_internal(jl_generic_fptr_t *fptr, fptr->fptr = meth->unspecialized_ducttape; fptr->jlcall_api = 1; if (!fptr->fptr) { - if (meth->def && !meth->def->isstaged && meth->def->unspecialized) { - fptr->fptr = meth->def->unspecialized->fptr; - fptr->jlcall_api = meth->def->unspecialized->jlcall_api; + if (jl_is_method(meth->def.method) && !meth->def.method->isstaged && meth->def.method->unspecialized) { + fptr->fptr = meth->def.method->unspecialized->fptr; + fptr->jlcall_api = meth->def.method->unspecialized->jlcall_api; if (fptr->jlcall_api == 2) { - return jl_assume(meth->def->unspecialized->inferred_const); + return jl_assume(meth->def.method->unspecialized->inferred_const); } } } @@ -461,8 +458,6 @@ jl_svec_t *jl_outer_unionall_vars(jl_value_t *u); int jl_count_union_components(jl_value_t *v); jl_value_t *jl_nth_union_component(jl_value_t *v, int i); jl_datatype_t *jl_new_uninitialized_datatype(void); -jl_datatype_t *jl_new_abstracttype(jl_value_t *name, jl_datatype_t *super, - jl_svec_t *parameters); void jl_precompute_memoized_dt(jl_datatype_t *dt); jl_datatype_t *jl_wrap_Type(jl_value_t *t); // x -> Type{x} jl_value_t *jl_wrap_vararg(jl_value_t *t, jl_value_t *n); @@ -473,19 +468,19 @@ jl_function_t *jl_new_generic_function_with_supertype(jl_sym_t *name, jl_module_ jl_function_t *jl_module_call_func(jl_module_t *m); int jl_is_submodule(jl_module_t *child, jl_module_t *parent); -jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast, int expanded); +jl_value_t *jl_toplevel_eval_flex(jl_module_t *m, jl_value_t *e, int fast, int expanded); jl_code_info_t *jl_wrap_expr(jl_value_t *expr); jl_value_t *jl_eval_global_var(jl_module_t *m, jl_sym_t *e); jl_value_t *jl_parse_eval_all(const char *fname, - const char *content, size_t contentlen); -jl_value_t *jl_interpret_toplevel_thunk(jl_code_info_t *src); -jl_value_t *jl_interpret_toplevel_expr(jl_value_t *e); + const char *content, size_t contentlen, + jl_module_t *inmodule); +jl_value_t *jl_interpret_toplevel_thunk(jl_module_t *m, jl_code_info_t *src); jl_value_t *jl_interpret_toplevel_expr_in(jl_module_t *m, jl_value_t *e, jl_code_info_t *src, jl_svec_t *sparam_vals); int jl_is_toplevel_only_expr(jl_value_t *e); -jl_value_t *jl_call_scm_on_ast(const char *funcname, jl_value_t *expr); +jl_value_t *jl_call_scm_on_ast(const char *funcname, jl_value_t *expr, jl_module_t *inmodule); jl_method_instance_t *jl_method_lookup_by_type(jl_methtable_t *mt, jl_tupletype_t *types, int cache, int inexact, int allow_exec, size_t world); diff --git a/src/method.c b/src/method.c index 4cd52b82776e9..123ccd0007b14 100644 --- a/src/method.c +++ b/src/method.c @@ -210,7 +210,7 @@ JL_DLLEXPORT jl_method_instance_t *jl_new_method_instance_uninit(void) li->functionObjectsDecls.specFunctionObject = NULL; li->specTypes = NULL; li->inInference = 0; - li->def = NULL; + li->def.value = NULL; li->min_world = 0; li->max_world = 0; return li; @@ -252,11 +252,11 @@ STATIC_INLINE jl_value_t *jl_call_staged(jl_svec_t *sparam_vals, jl_method_insta fptr.fptr = generator->fptr; fptr.jlcall_api = generator->jlcall_api; if (__unlikely(fptr.fptr == NULL || fptr.jlcall_api == 0)) { - size_t world = generator->def->min_world; + size_t world = generator->def.method->min_world; void *F = jl_compile_linfo(&generator, (jl_code_info_t*)generator->inferred, world, &jl_default_cgparams).functionObject; fptr = jl_generate_fptr(generator, F, world); } - assert(jl_svec_len(generator->def->sparam_syms) == jl_svec_len(sparam_vals)); + assert(jl_svec_len(generator->def.method->sparam_syms) == jl_svec_len(sparam_vals)); if (fptr.jlcall_api == 1) return fptr.fptr1(args[0], &args[1], nargs-1); else if (fptr.jlcall_api == 3) @@ -275,9 +275,9 @@ JL_DLLEXPORT jl_code_info_t *jl_code_for_staged(jl_method_instance_t *linfo) jl_expr_t *ex = NULL; jl_value_t *linenum = NULL; jl_svec_t *sparam_vals = env; - jl_method_instance_t *generator = linfo->def->generator; + jl_method_instance_t *generator = linfo->def.method->generator; assert(linfo != generator); - assert(linfo->def->isstaged); + assert(linfo->def.method->isstaged); jl_code_info_t *func = NULL; JL_GC_PUSH4(&ex, &linenum, &sparam_vals, &func); jl_ptls_t ptls = jl_get_ptls_states(); @@ -286,19 +286,19 @@ JL_DLLEXPORT jl_code_info_t *jl_code_for_staged(jl_method_instance_t *linfo) jl_module_t *last_m = ptls->current_module; jl_module_t *task_last_m = ptls->current_task->current_module; size_t last_age = jl_get_ptls_states()->world_age; - assert(jl_svec_len(linfo->def->sparam_syms) == jl_svec_len(sparam_vals)); + assert(jl_svec_len(linfo->def.method->sparam_syms) == jl_svec_len(sparam_vals)); JL_TRY { ptls->in_pure_callback = 1; // need to eval macros in the right module - ptls->current_task->current_module = ptls->current_module = linfo->def->module; + ptls->current_task->current_module = ptls->current_module = linfo->def.method->module; // and the right world - ptls->world_age = generator->def->min_world; + ptls->world_age = generator->def.method->min_world; ex = jl_exprn(lambda_sym, 2); - jl_array_t *argnames = jl_alloc_vec_any(linfo->def->nargs); + jl_array_t *argnames = jl_alloc_vec_any(linfo->def.method->nargs); jl_array_ptr_set(ex->args, 0, argnames); - jl_fill_argnames((jl_array_t*)linfo->def->source, argnames); + jl_fill_argnames((jl_array_t*)linfo->def.method->source, argnames); // build the rest of the body to pass to expand jl_expr_t *scopeblock = jl_exprn(jl_symbol("scope-block"), 1); @@ -307,36 +307,36 @@ JL_DLLEXPORT jl_code_info_t *jl_code_for_staged(jl_method_instance_t *linfo) jl_array_ptr_set(((jl_expr_t*)jl_exprarg(ex, 1))->args, 0, body); // add location meta - linenum = jl_box_long(linfo->def->line); - jl_value_t *linenode = jl_new_struct(jl_linenumbernode_type, linenum, linfo->def->file); + linenum = jl_box_long(linfo->def.method->line); + jl_value_t *linenode = jl_new_struct(jl_linenumbernode_type, linenum, linfo->def.method->file); jl_array_ptr_set(body->args, 0, linenode); jl_expr_t *pushloc = jl_exprn(meta_sym, 3); jl_array_ptr_set(body->args, 1, pushloc); jl_array_ptr_set(pushloc->args, 0, jl_symbol("push_loc")); - jl_array_ptr_set(pushloc->args, 1, linfo->def->file); // file + jl_array_ptr_set(pushloc->args, 1, linfo->def.method->file); // file jl_array_ptr_set(pushloc->args, 2, jl_symbol("@generated body")); // function // invoke code generator assert(jl_nparams(tt) == jl_array_len(argnames) || - (linfo->def->isva && (jl_nparams(tt) >= jl_array_len(argnames) - 1))); + (linfo->def.method->isva && (jl_nparams(tt) >= jl_array_len(argnames) - 1))); jl_value_t *generated_body = jl_call_staged(sparam_vals, generator, jl_svec_data(tt->parameters), jl_nparams(tt)); jl_array_ptr_set(body->args, 2, generated_body); - if (linfo->def->sparam_syms != jl_emptysvec) { + if (linfo->def.method->sparam_syms != jl_emptysvec) { // mark this function as having the same static parameters as the generator - size_t i, nsp = jl_svec_len(linfo->def->sparam_syms); + size_t i, nsp = jl_svec_len(linfo->def.method->sparam_syms); jl_expr_t *newast = jl_exprn(jl_symbol("with-static-parameters"), nsp + 1); jl_exprarg(newast, 0) = (jl_value_t*)ex; // (with-static-parameters func_expr sp_1 sp_2 ...) for (i = 0; i < nsp; i++) - jl_exprarg(newast, i+1) = jl_svecref(linfo->def->sparam_syms, i); + jl_exprarg(newast, i+1) = jl_svecref(linfo->def.method->sparam_syms, i); ex = newast; } - func = (jl_code_info_t*)jl_expand((jl_value_t*)ex); + func = (jl_code_info_t*)jl_expand((jl_value_t*)ex, linfo->def.method->module); if (!jl_is_code_info(func)) { if (jl_is_expr(func) && ((jl_expr_t*)func)->head == error_sym) - jl_interpret_toplevel_expr((jl_value_t*)func); + jl_interpret_toplevel_expr_in(linfo->def.method->module, (jl_value_t*)func, NULL, NULL); jl_error("generated function body is not pure. this likely means it contains a closure or comprehension."); } @@ -344,7 +344,7 @@ JL_DLLEXPORT jl_code_info_t *jl_code_for_staged(jl_method_instance_t *linfo) size_t i, l; for (i = 0, l = jl_array_len(stmts); i < l; i++) { jl_value_t *stmt = jl_array_ptr_ref(stmts, i); - stmt = jl_resolve_globals(stmt, linfo->def->module, env); + stmt = jl_resolve_globals(stmt, linfo->def.method->module, env); jl_array_ptr_set(stmts, i, stmt); } @@ -386,7 +386,7 @@ jl_method_instance_t *jl_get_specialized(jl_method_t *m, jl_value_t *types, jl_s { assert(jl_svec_len(m->sparam_syms) == jl_svec_len(sp) || sp == jl_emptysvec); jl_method_instance_t *new_linfo = jl_new_method_instance_uninit(); - new_linfo->def = m; + new_linfo->def.method = m; new_linfo->specTypes = types; new_linfo->sparam_vals = sp; new_linfo->min_world = m->min_world; @@ -456,7 +456,7 @@ static void jl_method_set_source(jl_method_t *m, jl_code_info_t *src) JL_GC_POP(); } -JL_DLLEXPORT jl_method_t *jl_new_method_uninit(void) +JL_DLLEXPORT jl_method_t *jl_new_method_uninit(jl_module_t *module) { jl_ptls_t ptls = jl_get_ptls_states(); jl_method_t *m = @@ -466,7 +466,7 @@ JL_DLLEXPORT jl_method_t *jl_new_method_uninit(void) m->sparam_syms = NULL; m->ambig = jl_nothing; m->roots = NULL; - m->module = ptls->current_module; + m->module = module; m->source = NULL; m->unspecialized = NULL; m->generator = NULL; @@ -485,13 +485,15 @@ JL_DLLEXPORT jl_method_t *jl_new_method_uninit(void) } jl_array_t *jl_all_methods; -jl_method_t *jl_new_method(jl_code_info_t *definition, - jl_sym_t *name, - jl_tupletype_t *sig, - size_t nargs, - int isva, - jl_svec_t *tvars, - int isstaged) +static jl_method_t *jl_new_method( + jl_code_info_t *definition, + jl_sym_t *name, + jl_module_t *inmodule, + jl_tupletype_t *sig, + size_t nargs, + int isva, + jl_svec_t *tvars, + int isstaged) { size_t i, l = jl_svec_len(tvars); jl_svec_t *sparam_syms = jl_alloc_svec_uninit(l); @@ -502,7 +504,7 @@ jl_method_t *jl_new_method(jl_code_info_t *definition, jl_method_t *m = NULL; JL_GC_PUSH1(&root); - m = jl_new_method_uninit(); + m = jl_new_method_uninit(inmodule); m->sparam_syms = sparam_syms; root = (jl_value_t*)m; m->min_world = ++jl_world_counter; @@ -563,11 +565,12 @@ static void jl_check_static_parameter_conflicts(jl_method_t *m, jl_code_info_t * } // empty generic function def -JL_DLLEXPORT jl_value_t *jl_generic_function_def(jl_sym_t *name, jl_value_t **bp, jl_value_t *bp_owner, +JL_DLLEXPORT jl_value_t *jl_generic_function_def(jl_sym_t *name, + jl_module_t *module, + jl_value_t **bp, jl_value_t *bp_owner, jl_binding_t *bnd) { - jl_ptls_t ptls = jl_get_ptls_states(); - jl_value_t *gf=NULL; + jl_value_t *gf = NULL; assert(name && bp); if (bnd && bnd->value != NULL && !bnd->constp) @@ -580,7 +583,6 @@ JL_DLLEXPORT jl_value_t *jl_generic_function_def(jl_sym_t *name, jl_value_t **bp if (bnd) bnd->constp = 1; if (*bp == NULL) { - jl_module_t *module = (bnd ? bnd->owner : ptls->current_module); gf = (jl_value_t*)jl_new_generic_function(name, module); *bp = gf; if (bp_owner) jl_gc_wb(bp_owner, gf); @@ -633,6 +635,7 @@ jl_datatype_t *jl_argument_datatype(jl_value_t *argt) extern tracer_cb jl_newmeth_tracer; JL_DLLEXPORT void jl_method_def(jl_svec_t *argdata, jl_code_info_t *f, + jl_module_t *module, jl_value_t *isstaged) { // argdata is svec(svec(types...), svec(typevars...)) @@ -673,14 +676,14 @@ JL_DLLEXPORT void jl_method_def(jl_svec_t *argdata, jl_error("cannot add methods to a builtin function"); int j; - for(j=(int)jl_svec_len(tvars)-1; j >= 0 ; j--) { + for (j = (int)jl_svec_len(tvars) - 1; j >= 0 ; j--) { jl_value_t *tv = jl_svecref(tvars,j); if (!jl_is_typevar(tv)) jl_type_error_rt(jl_symbol_name(name), "method definition", (jl_value_t*)jl_tvar_type, tv); argtype = jl_new_struct(jl_unionall_type, tv, argtype); } - m = jl_new_method(f, name, (jl_tupletype_t*)argtype, nargs, isva, tvars, isstaged == jl_true); + m = jl_new_method(f, name, module, (jl_tupletype_t*)argtype, nargs, isva, tvars, isstaged == jl_true); if (jl_has_free_typevars(argtype)) { jl_exceptionf(jl_argumenterror_type, diff --git a/src/module.c b/src/module.c index dc9d7b8f1f601..9b518fb2637a8 100644 --- a/src/module.c +++ b/src/module.c @@ -61,12 +61,11 @@ JL_DLLEXPORT jl_value_t *jl_f_new_module(jl_sym_t *name, uint8_t std_imports) return (jl_value_t*)m; } -JL_DLLEXPORT void jl_set_istopmod(uint8_t isprimary) +JL_DLLEXPORT void jl_set_istopmod(jl_module_t *self, uint8_t isprimary) { - jl_ptls_t ptls = jl_get_ptls_states(); - ptls->current_module->istopmod = 1; + self->istopmod = 1; if (isprimary) { - jl_top_module = ptls->current_module; + jl_top_module = self; jl_append_any_func = NULL; } } @@ -457,8 +456,6 @@ JL_DLLEXPORT void jl_set_const(jl_module_t *m, jl_sym_t *var, jl_value_t *val) JL_DLLEXPORT int jl_is_const(jl_module_t *m, jl_sym_t *var) { - jl_ptls_t ptls = jl_get_ptls_states(); - if (m == NULL) m = ptls->current_module; jl_binding_t *b = jl_get_binding(m, var); return b && b->constp; } diff --git a/src/rtutils.c b/src/rtutils.c index 963485a926899..611a2df890664 100644 --- a/src/rtutils.c +++ b/src/rtutils.c @@ -532,19 +532,21 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt } else if (vt == jl_method_instance_type) { jl_method_instance_t *li = (jl_method_instance_t*)v; - if (li->def) { - n += jl_static_show_x(out, (jl_value_t*)li->def->module, depth); + if (jl_is_method(li->def.method)) { + jl_method_t *m = li->def.method; + n += jl_static_show_x(out, (jl_value_t*)m->module, depth); if (li->specTypes) { n += jl_printf(out, "."); n += jl_show_svec(out, ((jl_datatype_t*)jl_unwrap_unionall(li->specTypes))->parameters, - jl_symbol_name(li->def->name), "(", ")"); + jl_symbol_name(m->name), "(", ")"); } else { - n += jl_printf(out, ".%s(?)", jl_symbol_name(li->def->name)); + n += jl_printf(out, ".%s(?)", jl_symbol_name(m->name)); } } else { - n += jl_printf(out, " -> "); + n += jl_static_show_x(out, (jl_value_t*)li->def.module, depth); + n += jl_printf(out, ". -> "); n += jl_static_show_x(out, li->inferred, depth); } } diff --git a/src/task.c b/src/task.c index 37fedf3838eae..dd10b3f2129a9 100644 --- a/src/task.c +++ b/src/task.c @@ -658,6 +658,7 @@ void jl_init_tasks(void) _probe_arch(); jl_task_type = (jl_datatype_t*) jl_new_datatype(jl_symbol("Task"), + NULL, jl_any_type, jl_emptysvec, jl_perm_symsvec(9, diff --git a/src/toplevel.c b/src/toplevel.c index 50f3673d243be..c90f335ea8b11 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -121,7 +121,7 @@ static void jl_module_load_time_initialize(jl_module_t *m) } extern void jl_get_system_hooks(void); -jl_value_t *jl_eval_module_expr(jl_expr_t *ex) +jl_value_t *jl_eval_module_expr(jl_module_t *parent_module, jl_expr_t *ex) { jl_ptls_t ptls = jl_get_ptls_states(); static arraylist_t module_stack; @@ -141,7 +141,6 @@ jl_value_t *jl_eval_module_expr(jl_expr_t *ex) if (!jl_is_symbol(name)) { jl_type_error("module", (jl_value_t*)jl_sym_type, (jl_value_t*)name); } - jl_module_t *parent_module = ptls->current_module; jl_binding_t *b = jl_get_binding_wr(parent_module, name); jl_declare_constant(b); if (b->value != NULL) { @@ -191,18 +190,18 @@ jl_value_t *jl_eval_module_expr(jl_expr_t *ex) JL_TRY { if (std_imports) { // add `eval` function - defaultdefs = jl_call_scm_on_ast("module-default-defs", (jl_value_t*)ex); + defaultdefs = jl_call_scm_on_ast("module-default-defs", (jl_value_t*)ex, newm); ptls->world_age = jl_world_counter; - jl_toplevel_eval_flex(defaultdefs, 0, 1); + jl_toplevel_eval_flex(newm, defaultdefs, 0, 1); defaultdefs = NULL; } for (int i = 0; i < jl_array_len(exprs); i++) { // process toplevel form ptls->world_age = jl_world_counter; - form = jl_expand(jl_array_ptr_ref(exprs, i)); + form = jl_expand(jl_array_ptr_ref(exprs, i), newm); ptls->world_age = jl_world_counter; - (void)jl_toplevel_eval_flex(form, 1, 1); + (void)jl_toplevel_eval_flex(newm, form, 1, 1); } } JL_CATCH { @@ -241,7 +240,7 @@ jl_value_t *jl_eval_module_expr(jl_expr_t *ex) arraylist_push(&module_stack, newm); - if (outermost == NULL || ptls->current_module == jl_main_module) { + if (outermost == NULL || parent_module == jl_main_module) { JL_TRY { size_t i, l = module_stack.len; for (i = stackidx; i < l; i++) { @@ -343,25 +342,26 @@ static int jl_eval_expr_with_compiler_p(jl_value_t *e, int compileloops, jl_modu static jl_value_t *require_func=NULL; -static jl_module_t *eval_import_path_(jl_array_t *args, int retrying) +static jl_module_t *eval_import_path_(jl_module_t *from, jl_array_t *args, int retrying) { - jl_ptls_t ptls = jl_get_ptls_states(); // in .A.B.C, first find a binding for A in the chain of module scopes // following parent links. then evaluate the rest of the path from there. // in A.B, look for A in Main first. - jl_sym_t *var = (jl_sym_t*)jl_array_ptr_ref(args,0); - size_t i=1; - if (!jl_is_symbol(var)) jl_type_error("import or using", (jl_value_t*)jl_sym_type, (jl_value_t*)var); - jl_module_t *m; + jl_sym_t *var = (jl_sym_t*)jl_array_ptr_ref(args, 0); + size_t i = 1; + if (!jl_is_symbol(var)) + jl_type_error("import or using", (jl_value_t*)jl_sym_type, (jl_value_t*)var); + jl_module_t *m; if (var != dot_sym) { m = jl_main_module; } else { - m = ptls->current_module; + m = from; while (1) { - var = (jl_sym_t*)jl_array_ptr_ref(args,i); - if (!jl_is_symbol(var)) jl_type_error("import or using", (jl_value_t*)jl_sym_type, (jl_value_t*)var); + var = (jl_sym_t*)jl_array_ptr_ref(args, i); + if (!jl_is_symbol(var)) + jl_type_error("import or using", (jl_value_t*)jl_sym_type, (jl_value_t*)var); i++; if (var != dot_sym) { if (i == jl_array_len(args)) @@ -401,13 +401,14 @@ static jl_module_t *eval_import_path_(jl_array_t *args, int retrying) if (require_func != NULL) { jl_value_t *reqargs[2] = {require_func, (jl_value_t*)var}; jl_apply(reqargs, 2); - return eval_import_path_(args, 1); + return eval_import_path_(from, args, 1); } } } if (retrying && require_func) { - jl_printf(JL_STDERR, "WARNING: requiring \"%s\" in module \"%s\" did not define a corresponding module.\n", jl_symbol_name(var), - jl_symbol_name(ptls->current_module->name)); + jl_printf(JL_STDERR, "WARNING: requiring \"%s\" in module \"%s\" did not define a corresponding module.\n", + jl_symbol_name(var), + jl_symbol_name(from->name)); return NULL; } else { @@ -425,12 +426,12 @@ static jl_module_t *eval_import_path_(jl_array_t *args, int retrying) return m; } -static jl_module_t *eval_import_path(jl_array_t *args) +static jl_module_t *eval_import_path(jl_module_t *from, jl_array_t *args) { - return eval_import_path_(args, 0); + return eval_import_path_(from, args, 0); } -jl_value_t *jl_toplevel_eval_body(jl_array_t *stmts); +jl_value_t *jl_toplevel_eval_body(jl_module_t *m, jl_array_t *stmts); int jl_is_toplevel_only_expr(jl_value_t *e) { @@ -450,6 +451,7 @@ static jl_method_instance_t *jl_new_thunk(jl_code_info_t *src, jl_module_t *modu jl_method_instance_t *li = jl_new_method_instance_uninit(); li->inferred = (jl_value_t*)src; li->specTypes = (jl_value_t*)jl_emptytuple_type; + li->def.module = module; jl_array_t *stmts = (jl_array_t*)src->code; size_t i, l; JL_GC_PUSH1(&li); @@ -460,7 +462,7 @@ static jl_method_instance_t *jl_new_thunk(jl_code_info_t *src, jl_module_t *modu return li; } -jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast, int expanded) +jl_value_t *jl_toplevel_eval_flex(jl_module_t *m, jl_value_t *e, int fast, int expanded) { jl_ptls_t ptls = jl_get_ptls_states(); if (!jl_is_expr(e)) { @@ -468,59 +470,62 @@ jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast, int expanded) jl_lineno = jl_linenode_line(e); return jl_nothing; } - return jl_interpret_toplevel_expr(e); + return jl_interpret_toplevel_expr_in(m, e, NULL, NULL); } jl_expr_t *ex = (jl_expr_t*)e; if (ex->head == error_sym || ex->head == jl_incomplete_sym) { // expression types simple enough not to need expansion - return jl_interpret_toplevel_expr(e); + return jl_interpret_toplevel_expr_in(m, e, NULL, NULL); } else if (ex->head == module_sym) { - return jl_eval_module_expr(ex); + return jl_eval_module_expr(m, ex); } else if (ex->head == importall_sym) { - jl_module_t *m = eval_import_path(ex->args); - if (m==NULL) return jl_nothing; - jl_sym_t *name = (jl_sym_t*)jl_array_ptr_ref(ex->args, jl_array_len(ex->args)-1); + jl_module_t *import = eval_import_path(m, ex->args); + if (import == NULL) + return jl_nothing; + jl_sym_t *name = (jl_sym_t*)jl_array_ptr_ref(ex->args, jl_array_len(ex->args) - 1); if (!jl_is_symbol(name)) jl_error("syntax: malformed \"importall\" statement"); - m = (jl_module_t*)jl_eval_global_var(m, name); - if (!jl_is_module(m)) + import = (jl_module_t*)jl_eval_global_var(import, name); + if (!jl_is_module(import)) jl_errorf("invalid %s statement: name exists but does not refer to a module", jl_symbol_name(ex->head)); - jl_module_importall(ptls->current_module, m); + jl_module_importall(m, import); return jl_nothing; } else if (ex->head == using_sym) { - jl_module_t *m = eval_import_path(ex->args); - if (m==NULL) return jl_nothing; - jl_sym_t *name = (jl_sym_t*)jl_array_ptr_ref(ex->args, jl_array_len(ex->args)-1); + jl_module_t *import = eval_import_path(m, ex->args); + if (import == NULL) + return jl_nothing; + jl_sym_t *name = (jl_sym_t*)jl_array_ptr_ref(ex->args, jl_array_len(ex->args) - 1); if (!jl_is_symbol(name)) jl_error("syntax: malformed \"using\" statement"); - jl_module_t *u = (jl_module_t*)jl_eval_global_var(m, name); + jl_module_t *u = (jl_module_t*)jl_eval_global_var(import, name); if (jl_is_module(u)) { - jl_module_using(ptls->current_module, u); + jl_module_using(m, u); } else { - jl_module_use(ptls->current_module, m, name); + jl_module_use(m, import, name); } return jl_nothing; } else if (ex->head == import_sym) { - jl_module_t *m = eval_import_path(ex->args); - if (m==NULL) return jl_nothing; - jl_sym_t *name = (jl_sym_t*)jl_array_ptr_ref(ex->args, jl_array_len(ex->args)-1); + jl_module_t *import = eval_import_path(m, ex->args); + if (import == NULL) + return jl_nothing; + jl_sym_t *name = (jl_sym_t*)jl_array_ptr_ref(ex->args, jl_array_len(ex->args) - 1); if (!jl_is_symbol(name)) jl_error("syntax: malformed \"import\" statement"); - jl_module_import(ptls->current_module, m, name); + jl_module_import(m, import, name); return jl_nothing; } else if (ex->head == export_sym) { - for(size_t i=0; i < jl_array_len(ex->args); i++) { + for (size_t i = 0; i < jl_array_len(ex->args); i++) { jl_sym_t *name = (jl_sym_t*)jl_array_ptr_ref(ex->args, i); if (!jl_is_symbol(name)) jl_error("syntax: malformed \"export\" statement"); - jl_module_export(ptls->current_module, name); + jl_module_export(m, name); } return jl_nothing; } @@ -538,7 +543,7 @@ jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast, int expanded) if (!expanded && ex->head != body_sym && ex->head != thunk_sym && ex->head != return_sym && ex->head != method_sym && ex->head != toplevel_sym) { // not yet expanded - ex = (jl_expr_t*)jl_expand(e); + ex = (jl_expr_t*)jl_expand(e, m); } jl_sym_t *head = jl_is_expr(ex) ? ex->head : NULL; @@ -548,7 +553,7 @@ jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast, int expanded) int i; for (i = 0; i < jl_array_len(ex->args); i++) { ptls->world_age = jl_world_counter; // eval each statement in the newest world age - res = jl_toplevel_eval_flex(jl_array_ptr_ref(ex->args, i), fast, 0); + res = jl_toplevel_eval_flex(m, jl_array_ptr_ref(ex->args, i), fast, 0); } ptls->world_age = last_age; JL_GC_POP(); @@ -559,22 +564,22 @@ jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast, int expanded) thk = (jl_code_info_t*)jl_exprarg(ex,0); assert(jl_is_code_info(thk)); assert(jl_typeis(thk->code, jl_array_any_type)); - ewc = jl_eval_with_compiler_p(thk, (jl_array_t*)thk->code, fast, ptls->current_module); + ewc = jl_eval_with_compiler_p(thk, (jl_array_t*)thk->code, fast, m); } else { - if (head && jl_eval_expr_with_compiler_p((jl_value_t*)ex, fast, ptls->current_module)) { + if (head && jl_eval_expr_with_compiler_p((jl_value_t*)ex, fast, m)) { thk = jl_wrap_expr((jl_value_t*)ex); ewc = 1; } else { if (head == body_sym) { - result = jl_toplevel_eval_body(ex->args); + result = jl_toplevel_eval_body(m, ex->args); } else if (jl_is_toplevel_only_expr((jl_value_t*)ex)) { - result = jl_toplevel_eval((jl_value_t*)ex); + result = jl_toplevel_eval(m, (jl_value_t*)ex); } else { - result = jl_interpret_toplevel_expr((jl_value_t*)ex); + result = jl_interpret_toplevel_expr_in(m, (jl_value_t*)ex, NULL, NULL); } JL_GC_POP(); return result; @@ -582,28 +587,27 @@ jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast, int expanded) } if (ewc) { - li = jl_new_thunk(thk, ptls->current_module); + li = jl_new_thunk(thk, m); size_t world = jl_get_ptls_states()->world_age; jl_type_infer(&li, world, 0); jl_value_t *dummy_f_arg = NULL; result = jl_call_method_internal(li, &dummy_f_arg, 1); } else { - result = jl_interpret_toplevel_thunk(thk); + result = jl_interpret_toplevel_thunk(m, thk); } JL_GC_POP(); return result; } -JL_DLLEXPORT jl_value_t *jl_toplevel_eval(jl_value_t *v) +JL_DLLEXPORT jl_value_t *jl_toplevel_eval(jl_module_t *m, jl_value_t *v) { - return jl_toplevel_eval_flex(v, 1, 0); + return jl_toplevel_eval_flex(m, v, 1, 0); } -JL_DLLEXPORT jl_value_t *jl_load(const char *fname) +JL_DLLEXPORT jl_value_t *jl_load(jl_module_t *module, const char *fname) { - jl_ptls_t ptls = jl_get_ptls_states(); - if (ptls->current_module->istopmod) { + if (module->istopmod) { jl_printf(JL_STDOUT, "%s\r\n", fname); #ifdef _OS_WINDOWS_ uv_run(uv_default_loop(), (uv_run_mode)1); @@ -613,14 +617,14 @@ JL_DLLEXPORT jl_value_t *jl_load(const char *fname) if (jl_stat(fname, (char*)&stbuf) != 0 || (stbuf.st_mode & S_IFMT) != S_IFREG) { jl_errorf("could not open file %s", fname); } - return jl_parse_eval_all(fname, NULL, 0); + return jl_parse_eval_all(fname, NULL, 0, module); } // load from filename given as a String object -JL_DLLEXPORT jl_value_t *jl_load_(jl_value_t *str) +JL_DLLEXPORT jl_value_t *jl_load_(jl_module_t *module, jl_value_t *str) { // assume String has a hidden '\0' at the end - return jl_load((const char*)jl_string_data(str)); + return jl_load(module, (const char*)jl_string_data(str)); } #ifdef __cplusplus diff --git a/test/broadcast.jl b/test/broadcast.jl index 4368462f4e7b5..b9b07c11f54fc 100644 --- a/test/broadcast.jl +++ b/test/broadcast.jl @@ -312,12 +312,12 @@ end # make sure scalars are inlined, which causes f.(x,scalar) to lower to a "thunk" import Base.Meta: isexpr -@test isexpr(expand(:(f.(x,y))), :call) -@test isexpr(expand(:(f.(x,1))), :thunk) -@test isexpr(expand(:(f.(x,1.0))), :thunk) -@test isexpr(expand(:(f.(x,$π))), :thunk) -@test isexpr(expand(:(f.(x,"hello"))), :thunk) -@test isexpr(expand(:(f.(x,$("hello")))), :thunk) +@test isexpr(expand(Main, :(f.(x,y))), :call) +@test isexpr(expand(Main, :(f.(x,1))), :thunk) +@test isexpr(expand(Main, :(f.(x,1.0))), :thunk) +@test isexpr(expand(Main, :(f.(x,$π))), :thunk) +@test isexpr(expand(Main, :(f.(x,"hello"))), :thunk) +@test isexpr(expand(Main, :(f.(x,$("hello")))), :thunk) # PR #17623: Fused binary operators @test [true] .* [true] == [true] diff --git a/test/cmdlineargs.jl b/test/cmdlineargs.jl index 7278d6c214b41..7af3336c3fd98 100644 --- a/test/cmdlineargs.jl +++ b/test/cmdlineargs.jl @@ -406,9 +406,9 @@ for precomp in ("yes", "no") @test contains(bt, "include_from_node1") if ((is_windows() && Sys.WORD_SIZE == 32) || (is_bsd() && !is_apple())) && precomp == "yes" # FIXME: Issue #17251 (Windows), #20798 (FreeBSD) - @test_broken contains(bt, "include_from_node1(::String) at $(joinpath(".","loading.jl"))") + @test_broken contains(bt, "include_from_node1(::Module, ::String) at $(joinpath(".", "loading.jl"))") else - @test contains(bt, "include_from_node1(::String) at $(joinpath(".","loading.jl"))") + @test contains(bt, "include_from_node1(::Module, ::String) at $(joinpath(".", "loading.jl"))") end lno = match(r"at \.[\/\\]loading\.jl:(\d+)", bt) @test length(lno.captures) == 1 diff --git a/test/core.jl b/test/core.jl index a75ca32ee8b4c..32d0f73a1d23d 100644 --- a/test/core.jl +++ b/test/core.jl @@ -376,7 +376,7 @@ begin function f7234_b() global f7234_cnt += 1 glob_x2 += 1 - global f7235_cnt += -10000 + global f7234_cnt += -10000 end end @test_throws UndefVarError f7234_b() @@ -499,8 +499,8 @@ end bar21900 = foo21900 + 1 end end -@test !isdefined(:foo21900) -@test !isdefined(:bar21900) +@test !@isdefined(foo21900) +@test !@isdefined(bar21900) bar21900 = 0 @test_throws UndefVarError @eval begin for i21900 = 1:10 @@ -512,7 +512,7 @@ bar21900 = 0 end end @test bar21900 == -1 -@test !isdefined(:foo21900) +@test !@isdefined foo21900 foo21900 = 0 @test nothing === @eval begin for i21900 = 1:10 @@ -739,6 +739,7 @@ end let didthrow = try include_string( + @__MODULE__, """ module TestInitError __init__() = error() @@ -1413,7 +1414,8 @@ let g4505{X}(::X) = 0 @test g4505(0) == 0 end -@test !isdefined(:g4505) +@test !@isdefined g4505 +@test !isdefined(@__MODULE__, :g4505) # issue #4681 # ccall should error if convert() returns something of the wrong type @@ -1711,9 +1713,15 @@ test5536(a::Union{Real, AbstractArray}) = "Non-splatting" @test test5536(5) == "Non-splatting" # multiline comments (#6139 and others raised in #6128) and embedded NUL chars (#10994) -@test 3 == include_string("1 + 2") == include_string("1 + #==# 2") == include_string("1 + #===# 2") == include_string("1 + #= #= blah =# =# 2") == include_string("1 + #= #= #= nested =# =# =# 2") == include_string("1 + #= \0 =# 2") -@test_throws LoadError include_string("#=") -@test_throws LoadError include_string("#= #= #= =# =# =") +@test 3 == + include_string(@__MODULE__, "1 + 2") == + include_string(@__MODULE__, "1 + #==# 2") == + include_string(@__MODULE__, "1 + #===# 2") == + include_string(@__MODULE__, "1 + #= #= blah =# =# 2") == + include_string(@__MODULE__, "1 + #= #= #= nested =# =# =# 2") == + include_string(@__MODULE__, "1 + #= \0 =# 2") +@test_throws LoadError include_string(@__MODULE__, "#=") +@test_throws LoadError include_string(@__MODULE__, "#= #= #= =# =# =") # issue #6142 import Base: + @@ -1829,7 +1837,7 @@ macro m20524(ex) end @m20524 ((a,(b20524,c)) = (8,(1,5)); (a,b20524,c)) @test f20524() === (8,1,5) -@test !isdefined(:b20524) # should not assign to a global +@test !@isdefined b20524 # should not assign to a global # issue #6387 primitive type Date6387{C} 64 end @@ -3734,7 +3742,7 @@ let k15283 = j15283+=1 end @test j15283 == 1 -@test !isdefined(:k15283) +@test !@isdefined k15283 # issue #15264 module Test15264 diff --git a/test/distributed_exec.jl b/test/distributed_exec.jl index 4583fbf237d31..d54763101d6dd 100644 --- a/test/distributed_exec.jl +++ b/test/distributed_exec.jl @@ -1599,7 +1599,7 @@ function setup_syms(n, pids) eval(:(global $sym = rand())) for p in pids eval(:(@test $sym == remotecall_fetch(()->$sym, $p))) - eval(:(@test remotecall_fetch(isdefined, $p, Symbol($symstr)))) + eval(:(@test remotecall_fetch(isdefined, $p, Main, Symbol($symstr)))) end push!(syms, sym) end diff --git a/test/docs.jl b/test/docs.jl index eadd59e65cad1..e91238c2781d0 100644 --- a/test/docs.jl +++ b/test/docs.jl @@ -495,7 +495,8 @@ end # Issue #16359. Error message for invalid doc syntax. -let __source__ = LineNumberNode(0) +let __source__ = LineNumberNode(0), + __module__ = @__MODULE__ for each in [ # valid syntax :(f()), :(f(x)), @@ -504,14 +505,14 @@ let __source__ = LineNumberNode(0) :(f(x = 1)), :(f(; x = 1)) ] - @test Meta.isexpr(Docs.docm(__source__, "...", each), :block) + @test Meta.isexpr(Docs.docm(__source__, __module__, "...", each), :block) end for each in [ # invalid syntax :(f("...")), :(f(1, 2)), :(f(() -> ())) ] - result = Docs.docm(__source__, "...", each) + result = Docs.docm(__source__, __module__, "...", each) @test Meta.isexpr(result, :call) @test result.args[1] === error end @@ -705,7 +706,7 @@ end ) # Issue #13905. -@test macroexpand(:(@doc "" f() = @x)) == Expr(:error, UndefVarError(Symbol("@x"))) +@test @macroexpand(@doc "" f() = @x) == Expr(:error, UndefVarError(Symbol("@x"))) # Undocumented DataType Summaries. @@ -978,8 +979,8 @@ dynamic_test.x = "test 2" @test @doc(dynamic_test) == "test 2 Union{}" @test @doc(dynamic_test(::String)) == "test 2 Tuple{String}" -@test Docs._repl(:(dynamic_test(1.0))) == Expr(:macrocall, Symbol("@doc"), LineNumberNode(204, doc_util_path), esc(:(dynamic_test(::typeof(1.0))))) -@test Docs._repl(:(dynamic_test(::String))) == Expr(:macrocall, Symbol("@doc"), LineNumberNode(204, doc_util_path), esc(:(dynamic_test(::String)))) +@test Docs._repl(:(dynamic_test(1.0))) == Expr(:macrocall, Symbol("@doc"), LineNumberNode(206, doc_util_path), esc(:(dynamic_test(::typeof(1.0))))) +@test Docs._repl(:(dynamic_test(::String))) == Expr(:macrocall, Symbol("@doc"), LineNumberNode(206, doc_util_path), esc(:(dynamic_test(::String)))) # Equality testing diff --git a/test/fastmath.jl b/test/fastmath.jl index 80120e7c7b2fd..bac571c5bf2ab 100644 --- a/test/fastmath.jl +++ b/test/fastmath.jl @@ -4,12 +4,12 @@ # check expansions -@test macroexpand(:(@fastmath 1+2)) == :(Base.FastMath.add_fast(1,2)) -@test macroexpand(:(@fastmath +)) == :(Base.FastMath.add_fast) -@test macroexpand(:(@fastmath min(1))) == :(Base.FastMath.min_fast(1)) -@test macroexpand(:(@fastmath min)) == :(Base.FastMath.min_fast) -@test macroexpand(:(@fastmath x.min)) == :(x.min) -@test macroexpand(:(@fastmath sincos(x))) == :(Base.FastMath.sincos_fast(x)) +@test macroexpand(Main, :(@fastmath 1+2)) == :(Base.FastMath.add_fast(1,2)) +@test macroexpand(Main, :(@fastmath +)) == :(Base.FastMath.add_fast) +@test macroexpand(Main, :(@fastmath min(1))) == :(Base.FastMath.min_fast(1)) +@test macroexpand(Main, :(@fastmath min)) == :(Base.FastMath.min_fast) +@test macroexpand(Main, :(@fastmath x.min)) == :(x.min) +@test macroexpand(Main, :(@fastmath sincos(x))) == :(Base.FastMath.sincos_fast(x)) # basic arithmetic diff --git a/test/inline.jl b/test/inline.jl index 3a7d7cc76ac8b..769ea452d8a17 100644 --- a/test/inline.jl +++ b/test/inline.jl @@ -113,8 +113,8 @@ let a = read21311() end @testset "issue #19122: [no]inline of short func. def. with return type annotation" begin - exf19122 = macroexpand(:(@inline f19122()::Bool = true)) - exg19122 = macroexpand(:(@noinline g19122()::Bool = true)) + exf19122 = @macroexpand(@inline f19122()::Bool = true) + exg19122 = @macroexpand(@noinline g19122()::Bool = true) @test exf19122.args[2].args[1].args[1] == :inline @test exg19122.args[2].args[1].args[1] == :noinline diff --git a/test/loading.jl b/test/loading.jl index a39e094061859..a7d29f31cabc1 100644 --- a/test/loading.jl +++ b/test/loading.jl @@ -33,9 +33,9 @@ end include("test_sourcepath.jl") thefname = "the fname!//\\&\1*" -include_string_test_func = include_string("include_string_test() = @__FILE__", thefname) +include_string_test_func = include_string(@__MODULE__, "include_string_test() = @__FILE__", thefname) @test include_string_test_func() == thefname -@test include_string("Base.source_path()", thefname) == Base.source_path() +@test include_string(@__MODULE__, "Base.source_path()", thefname) == Base.source_path() @test basename(@__FILE__) == "loading.jl" @test isabspath(@__FILE__) diff --git a/test/misc.jl b/test/misc.jl index 599aadf854064..fd39d9f903e2c 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -269,7 +269,7 @@ end # test that they don't introduce global vars global v11801, t11801, names_before_timing -names_before_timing = names(current_module(), true) +names_before_timing = names(@__MODULE__, true) let t = @elapsed 1+1 @test isa(t, Real) && t >= 0 @@ -288,7 +288,7 @@ v11801, t11801 = @timed sin(1) @test v11801 == sin(1) @test isa(t11801,Real) && t11801 >= 0 -@test names(current_module(), true) == names_before_timing +@test names(@__MODULE__, true) == names_before_timing # interactive utilities diff --git a/test/parse.jl b/test/parse.jl index 5fd78b99d476f..d07c558179be9 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -495,7 +495,7 @@ test_parseerror("0x0.1", "hex float literal must contain \"p\" or \"P\"") test_parseerror("0x1.0p", "invalid numeric constant \"0x1.0\"") # issue #15798 -@test expand(Base.parse_input_line(""" +@test expand(Main, Base.parse_input_line(""" try = "No" """)) == Expr(:error, "unexpected \"=\"") @@ -524,10 +524,10 @@ test_parseerror("if\nfalse\nend", "missing condition in \"if\" at none:1") test_parseerror("if false\nelseif\nend", "missing condition in \"elseif\" at none:2") # issue #15828 -@test expand(parse("x...")) == Expr(:error, "\"...\" expression outside call") +@test expand(Main, parse("x...")) == Expr(:error, "\"...\" expression outside call") # issue #15830 -@test expand(parse("foo(y = (global x)) = y")) == Expr(:error, "misplaced \"global\" declaration") +@test expand(Main, parse("foo(y = (global x)) = y")) == Expr(:error, "misplaced \"global\" declaration") # issue #15844 function f15844(x) @@ -558,11 +558,11 @@ add_method_to_glob_fn!() @test_throws ParseError parse("function finally() end") # PR #16170 -@test expand(parse("true(x) = x")) == Expr(:error, "invalid function name \"true\"") -@test expand(parse("false(x) = x")) == Expr(:error, "invalid function name \"false\"") +@test expand(Main, parse("true(x) = x")) == Expr(:error, "invalid function name \"true\"") +@test expand(Main, parse("false(x) = x")) == Expr(:error, "invalid function name \"false\"") # issue #16355 -@test expand(:(f(d:Int...)=nothing)) == Expr(:error, "\"d:Int\" is not a valid function argument name") +@test expand(Main, :(f(d:Int...) = nothing)) == Expr(:error, "\"d:Int\" is not a valid function argument name") # issue #16517 @test (try error(); catch 0; end) === 0 @@ -642,7 +642,7 @@ end # issue #16720 let err = try - include_string("module A + include_string(@__MODULE__, "module A function broken() @@ -707,27 +707,27 @@ let m_error, error_out, filename = Base.source_path() end # issue #7272 -@test expand(parse("let +@test expand(Main, parse("let global x = 2 local x = 1 end")) == Expr(:error, "variable \"x\" declared both local and global") -@test expand(parse("let +@test expand(Main, parse("let local x = 2 local x = 1 end")) == Expr(:error, "local \"x\" declared twice") -@test expand(parse("let x +@test expand(Main, parse("let x local x = 1 end")) == Expr(:error, "local \"x\" declared twice") -@test expand(parse("let x = 2 +@test expand(Main, parse("let x = 2 local x = 1 end")) == Expr(:error, "local \"x\" declared twice") # make sure front end can correctly print values to error messages -let ex = expand(parse("\"a\"=1")) +let ex = expand(Main, parse("\"a\"=1")) @test ex == Expr(:error, "invalid assignment location \"\"a\"\"") end @@ -747,20 +747,23 @@ for (str, tag) in Dict("" => :none, "\"" => :string, "#=" => :comment, "'" => :c end # meta nodes for optional positional arguments -@test expand(:(@inline f(p::Int=2) = 3)).args[2].args[3].inlineable +@test expand(Main, :(@inline f(p::Int=2) = 3)).args[2].args[3].inlineable # issue #16096 module M16096 macro iter() - quote + return quote @inline function foo(sub) it = 1 end end end end -let ex = expand(:(@M16096.iter)) - @test !(isa(ex,Expr) && ex.head === :error) +let ex = expand(@__MODULE__, :(@M16096.iter)) + @test isa(ex, Expr) && ex.head === :thunk +end +let ex = expand(Main, :($M16096.@iter)) + @test isa(ex, Expr) && ex.head === :thunk end macro f16096() quote @@ -791,12 +794,12 @@ module B15838 end @test A15838.@f() === nothing @test A15838.@f(1) === :b -let nometh = expand(:(A15838.@f(1, 2))), __source__ = LineNumberNode(@__LINE__, Symbol(@__FILE__)) +let nometh = expand(@__MODULE__, :(A15838.@f(1, 2))), __source__ = LineNumberNode(@__LINE__, Symbol(@__FILE__)) @test (nometh::Expr).head === :error @test length(nometh.args) == 1 e = nometh.args[1]::MethodError @test e.f === getfield(A15838, Symbol("@f")) - @test e.args === (__source__, 1, 2) + @test e.args === (__source__, @__MODULE__, 1, 2) end # issue 10046 @@ -805,11 +808,11 @@ for op in ["+", "-", "\$", "|", ".+", ".-", "*", ".*"] end # issue #17701 -@test expand(:(i==3 && i+=1)) == Expr(:error, "invalid assignment location \"==(i,3)&&i\"") +@test expand(Main, :(i==3 && i+=1)) == Expr(:error, "invalid assignment location \"==(i,3)&&i\"") # issue #18667 -@test expand(:(true = 1)) == Expr(:error, "invalid assignment location \"true\"") -@test expand(:(false = 1)) == Expr(:error, "invalid assignment location \"false\"") +@test expand(Main, :(true = 1)) == Expr(:error, "invalid assignment location \"true\"") +@test expand(Main, :(false = 1)) == Expr(:error, "invalid assignment location \"false\"") # PR #15592 let str = "[1] [2]" @@ -869,7 +872,7 @@ macro m2() 1 end end -include_string(""" +include_string(@__MODULE__, """ macro m3() quote @m1 @@ -881,10 +884,10 @@ macro m4() end end """, "another_file.jl") -m1_exprs = get_expr_list(expand(:(@m1))) -m2_exprs = get_expr_list(expand(:(@m2))) -m3_exprs = get_expr_list(expand(:(@m3))) -m4_exprs = get_expr_list(expand(:(@m4))) +m1_exprs = get_expr_list(expand(@__MODULE__, :(@m1))) +m2_exprs = get_expr_list(expand(@__MODULE__, :(@m2))) +m3_exprs = get_expr_list(expand(@__MODULE__, :(@m3))) +m4_exprs = get_expr_list(expand(@__MODULE__, :(@m4))) # Check the expanded expresion has expected number of matching push/pop # and the return is handled correctly @@ -967,7 +970,7 @@ end @test parse("Foo{T} = Bar{T}") == Expr(:(=), Expr(:curly, :Foo, :T), Expr(:curly, :Bar, :T)) # don't insert push_loc for filename `none` at the top level -let ex = expand(parse(""" +let ex = expand(Main, parse(""" begin x = 1 end""")) @@ -1026,8 +1029,8 @@ end let global const (c8925, d8925) = (3, 4) end -@test c8925 == 3 && isconst(:c8925) -@test d8925 == 4 && isconst(:d8925) +@test c8925 == 3 && isconst(@__MODULE__, :c8925) +@test d8925 == 4 && isconst(@__MODULE__, :d8925) # issue #18754: parse ccall as a regular function @test parse("ccall([1], 2)[3]") == Expr(:ref, Expr(:call, :ccall, Expr(:vect, 1), 2), 3) @@ -1054,8 +1057,8 @@ end # issue #20541 @test parse("[a .!b]") == Expr(:hcat, :a, Expr(:call, :(.!), :b)) -@test expand(:(a{1} = b)) == Expr(:error, "invalid type parameter name \"1\"") -@test expand(:(a{2<:Any} = b)) == Expr(:error, "invalid type parameter name \"2\"") +@test expand(Main, :(a{1} = b)) == Expr(:error, "invalid type parameter name \"1\"") +@test expand(Main, :(a{2<:Any} = b)) == Expr(:error, "invalid type parameter name \"2\"") # issue #20653 @test_throws UndefVarError Base.call(::Int) = 1 @@ -1076,14 +1079,14 @@ macro m20729() return ex end -@test_throws ErrorException eval(:(@m20729)) -@test expand(:(@m20729)) == Expr(:error, "undefined reference in AST") +@test_throws ErrorException eval(@__MODULE__, :(@m20729)) +@test expand(@__MODULE__, :(@m20729)) == Expr(:error, "undefined reference in AST") macro err20000() return Expr(:error, "oops!") end -@test expand(:(@err20000)) == Expr(:error, "oops!") +@test expand(@__MODULE__, :(@err20000)) == Expr(:error, "oops!") # issue #20000 @test parse("@m(a; b=c)") == Expr(:macrocall, Symbol("@m"), LineNumberNode(1, :none), @@ -1101,8 +1104,8 @@ g21054(>:) = >:2 @test g21054(-) == -2 # issue #21168 -@test expand(:(a.[1])) == Expr(:error, "invalid syntax a.[1]") -@test expand(:(a.{1})) == Expr(:error, "invalid syntax a.{1}") +@test expand(Main, :(a.[1])) == Expr(:error, "invalid syntax a.[1]") +@test expand(Main, :(a.{1})) == Expr(:error, "invalid syntax a.{1}") # Issue #21225 let abstr = parse("abstract type X end") @@ -1209,8 +1212,8 @@ module Test21607 end # issue #16937 -@test expand(:(f(2, a=1, w=3, c=3, w=4, b=2))) == Expr(:error, - "keyword argument \"w\" repeated in call to \"f\"") +@test expand(Main, :(f(2, a=1, w=3, c=3, w=4, b=2))) == + Expr(:error, "keyword argument \"w\" repeated in call to \"f\"") let f(x) = g(x) = 1 diff --git a/test/reflection.jl b/test/reflection.jl index 0e00763f70c26..5a85bb31c729f 100644 --- a/test/reflection.jl +++ b/test/reflection.jl @@ -88,7 +88,7 @@ tag = Base.have_color ? Base.error_color() : "ARRAY{FLOAT64,N}" # Make sure emphasis is not used for other functions tag = Base.have_color ? Base.error_color() : "ANY" iob = IOBuffer() -show(iob, expand(:(x->x^2))) +show(iob, expand(Main, :(x -> x^2))) str = String(take!(iob)) @test isempty(search(str, tag)) @@ -151,11 +151,11 @@ i10165{T,n}(::Type{AbstractArray{T,n}}) = 1 const a_const = 1 not_const = 1 -@test isconst(:a_const) == true +@test isconst(@__MODULE__, :a_const) == true @test isconst(Base, :pi) == true -@test isconst(:pi) == true -@test isconst(:not_const) == false -@test isconst(:is_not_defined) == false +@test isconst(@__MODULE__, :pi) == true +@test isconst(@__MODULE__, :not_const) == false +@test isconst(@__MODULE__, :is_not_defined) == false @test isimmutable(1) == true @test isimmutable([]) == false @@ -188,22 +188,21 @@ module TestModSub9475 b9475 = 7 foo9475(x) = x let - @test Base.binding_module(:a9475) == current_module() - @test Base.binding_module(:c7648) == TestMod7648 - @test Base.module_name(current_module()) == :TestModSub9475 - @test Base.fullname(current_module()) == (curmod_name..., :TestMod7648, - :TestModSub9475) - @test Base.module_parent(current_module()) == TestMod7648 + @test Base.binding_module(@__MODULE__, :a9475) == @__MODULE__ + @test Base.binding_module(@__MODULE__, :c7648) == TestMod7648 + @test Base.module_name(@__MODULE__) == :TestModSub9475 + @test Base.fullname(@__MODULE__) == (curmod_name..., :TestMod7648, :TestModSub9475) + @test Base.module_parent(@__MODULE__) == TestMod7648 end end # module TestModSub9475 using .TestModSub9475 let - @test Base.binding_module(:d7648) == current_module() - @test Base.binding_module(:a9475) == TestModSub9475 - @test Base.module_name(current_module()) == :TestMod7648 - @test Base.module_parent(current_module()) == curmod + @test Base.binding_module(@__MODULE__, :d7648) == @__MODULE__ + @test Base.binding_module(@__MODULE__, :a9475) == TestModSub9475 + @test Base.module_name(@__MODULE__) == :TestMod7648 + @test Base.module_parent(@__MODULE__) == curmod end end # module TestMod7648 @@ -214,18 +213,19 @@ let @test Set(names(TestMod7648))==Set([:TestMod7648, :a9475, :foo9475, :c7648, :foo7648, :foo7648_nomethods, :Foo7648]) @test Set(names(TestMod7648, true)) == Set([:TestMod7648, :TestModSub9475, :a9475, :foo9475, :c7648, :d7648, :f7648, :foo7648, Symbol("#foo7648"), :foo7648_nomethods, Symbol("#foo7648_nomethods"), - :Foo7648, :eval, Symbol("#eval")]) + :Foo7648, :eval, Symbol("#eval"), :include, Symbol("#include")]) @test Set(names(TestMod7648, true, true)) == Set([:TestMod7648, :TestModSub9475, :a9475, :foo9475, :c7648, :d7648, :f7648, :foo7648, Symbol("#foo7648"), :foo7648_nomethods, Symbol("#foo7648_nomethods"), - :Foo7648, :eval, Symbol("#eval"), :convert, :curmod_name, :curmod]) + :Foo7648, :eval, Symbol("#eval"), :include, Symbol("#include"), + :convert, :curmod_name, :curmod]) @test isconst(TestMod7648, :c7648) @test !isconst(TestMod7648, :d7648) end let using .TestMod7648 - @test Base.binding_module(:a9475) == TestMod7648.TestModSub9475 - @test Base.binding_module(:c7648) == TestMod7648 + @test Base.binding_module(@__MODULE__, :a9475) == TestMod7648.TestModSub9475 + @test Base.binding_module(@__MODULE__, :c7648) == TestMod7648 @test Base.function_name(foo7648) == :foo7648 @test Base.function_module(foo7648, (Any,)) == TestMod7648 @test Base.function_module(foo7648) == TestMod7648 @@ -254,11 +254,14 @@ export this_is_not_defined @test_throws ErrorException which(:this_is_not_defined) @test_throws ErrorException @which this_is_not_defined @test_throws ErrorException which(:this_is_not_exported) -@test isexported(current_module(), :this_is_not_defined) -@test !isexported(current_module(), :this_is_not_exported) +@test isexported(@__MODULE__, :this_is_not_defined) +@test !isexported(@__MODULE__, :this_is_not_exported) const a_value = 1 -@test which(:a_value) == current_module() -@test !isexported(current_module(), :a_value) +@test Base.which_module(@__MODULE__, :a_value) === @__MODULE__ +@test @which(a_value) === @__MODULE__ +@test_throws ErrorException which(:a_value) +@test which(:Core) === Main +@test !isexported(@__MODULE__, :a_value) end # issue #13264 @@ -365,11 +368,11 @@ end let using .MacroTest a = 1 - m = getfield(current_module(), Symbol("@macrotest")) - @test which(m, Tuple{LineNumberNode, Int, Symbol}) == @which @macrotest 1 a - @test which(m, Tuple{LineNumberNode, Int, Int}) == @which @macrotest 1 1 + m = getfield(@__MODULE__, Symbol("@macrotest")) + @test which(m, Tuple{LineNumberNode, Module, Int, Symbol}) == @which @macrotest 1 a + @test which(m, Tuple{LineNumberNode, Module, Int, Int}) == @which @macrotest 1 1 - @test first(methods(m, Tuple{LineNumberNode, Int, Int})) == @which MacroTest.@macrotest 1 1 + @test first(methods(m, Tuple{LineNumberNode, Module, Int, Int})) == @which MacroTest.@macrotest 1 1 @test functionloc(@which @macrotest 1 1) == @functionloc @macrotest 1 1 end diff --git a/test/repl.jl b/test/repl.jl index 65b27398db249..028cc02540f37 100644 --- a/test/repl.jl +++ b/test/repl.jl @@ -592,7 +592,7 @@ end # let exename # issue #19864: mutable struct Error19864 <: Exception; end function test19864() - @eval current_module() Base.showerror(io::IO, e::Error19864) = print(io, "correct19864") + @eval Base.showerror(io::IO, e::Error19864) = print(io, "correct19864") buf = IOBuffer() REPL.print_response(buf, Error19864(), [], false, false, nothing) return String(take!(buf)) diff --git a/test/replutil.jl b/test/replutil.jl index ac4bec2258976..d8c63b3b276bc 100644 --- a/test/replutil.jl +++ b/test/replutil.jl @@ -375,8 +375,8 @@ let err_str, "(::Type{$(curmod_prefix)EightBitTypeT{T}})() where T in $curmod_str at $sp:$(method_defs_lineno + 5)" @test sprint(show, which(reinterpret(EightBitTypeT{Int32}, 0x54), Tuple{})) == "(::$(curmod_prefix)EightBitTypeT)() in $curmod_str at $sp:$(method_defs_lineno + 6)" - @test startswith(sprint(show, which(getfield(Base, Symbol("@doc")), Tuple{LineNumberNode, Vararg{Any}})), - "@doc(__source__::LineNumberNode, x...) in Core at boot.jl:") + @test startswith(sprint(show, which(getfield(Base, Symbol("@doc")), Tuple{LineNumberNode, Module, Vararg{Any}})), + "@doc(__source__::LineNumberNode, __module__::Module, x...) in Core at boot.jl:") @test startswith(sprint(show, which(FunctionLike(), Tuple{})), "(::$(curmod_prefix)FunctionLike)() in $curmod_str at $sp:$(method_defs_lineno + 7)") @test stringmime("text/plain", FunctionLike()) == "(::FunctionLike) (generic function with 1 method)" @@ -476,8 +476,8 @@ macro seven_dollar(ex) end let - @test (@macroexpand @macroexpand x) == macroexpand(:(@macroexpand x)) - @test (@macroexpand :(1+$y) ) == macroexpand(:( :(1+ $y))) + @test (@macroexpand @macroexpand x) == macroexpand(@__MODULE__, :(@macroexpand x)) + @test (@macroexpand :(1+$y) ) == macroexpand(@__MODULE__, :( :(1+ $y) )) @test (@macroexpand @fastmath 1+2 ) == :(Base.FastMath.add_fast(1,2)) @test (@macroexpand @fastmath + ) == :(Base.FastMath.add_fast) @test (@macroexpand @fastmath min(1) ) == :(Base.FastMath.min_fast(1)) diff --git a/test/stacktraces.jl b/test/stacktraces.jl index 19e23aa0f18f1..8ad2eed101095 100644 --- a/test/stacktraces.jl +++ b/test/stacktraces.jl @@ -98,12 +98,13 @@ for (frame, func, inlined) in zip(trace, [g,h,f], (can_inline, can_inline, false end end -let src = expand(quote let x = 1 end end).args[1]::CodeInfo, +let src = expand(Main, quote let x = 1 end end).args[1]::CodeInfo, li = ccall(:jl_new_method_instance_uninit, Ref{Core.MethodInstance}, ()), sf li.inferred = src li.specTypes = Tuple{} + li.def = @__MODULE__ sf = StackFrame(:a, :b, 3, li, false, false, 0) repr = string(sf) @test repr == "Toplevel MethodInstance thunk at b:3" diff --git a/test/strings/basic.jl b/test/strings/basic.jl index 551d46305d0f8..bf1fb7741c862 100644 --- a/test/strings/basic.jl +++ b/test/strings/basic.jl @@ -53,7 +53,7 @@ let sym = Symbol(Char(0xdcdb)) @test string(sym) == string(Char(0xdcdb)) @test String(sym) == string(Char(0xdcdb)) - @test expand(sym) === sym + @test expand(Main, sym) === sym res = string(parse(string(Char(0xdcdb)," = 1"),1,raise=false)[1]) @test res == """\$(Expr(:error, "invalid character \\\"\\udcdb\\\"\"))""" end diff --git a/test/testenv.jl b/test/testenv.jl index 871999c759536..6447d6e342d09 100644 --- a/test/testenv.jl +++ b/test/testenv.jl @@ -5,7 +5,7 @@ # This file can be included multiple times in the same module if necessary, # which can happen with unisolated test runs. -if !isdefined(:testenv_defined) +if !@isdefined(testenv_defined) const testenv_defined = true if haskey(ENV, "JULIA_TEST_EXEFLAGS") const test_exeflags = `$(Base.shell_split(ENV["JULIA_TEST_EXEFLAGS"]))` @@ -28,7 +28,7 @@ if !isdefined(:testenv_defined) addprocs_with_testenv(X; kwargs...) = addprocs(X; exename=test_exename, exeflags=test_exeflags, kwargs...) - const curmod = current_module() + const curmod = @__MODULE__ const curmod_name = fullname(curmod) const curmod_str = curmod === Main ? "Main" : join(curmod_name, ".") const curmod_prefix = "$(["$m." for m in curmod_name]...)" diff --git a/test/threads.jl b/test/threads.jl index 878db358f0456..a93c336795b29 100644 --- a/test/threads.jl +++ b/test/threads.jl @@ -136,7 +136,7 @@ threaded_gc_locked(Mutex) # Issue 14726 # Make sure that eval'ing in a different module doesn't mess up other threads -orig_curmodule14726 = current_module() +orig_curmodule14726 = @__MODULE__ main_var14726 = 1 module M14726 module_var14726 = 1 @@ -147,15 +147,15 @@ end @eval M14726 module_var14726 = $j end end -@test isdefined(:orig_curmodule14726) -@test isdefined(:main_var14726) -@test current_module() == orig_curmodule14726 +@test @isdefined(orig_curmodule14726) +@test @isdefined(main_var14726) +@test @__MODULE__() == orig_curmodule14726 @threads for i in 1:100 # Make sure current module is not null. # The @test might not be particularly meaningful currently since the # thread infrastructures swallows the error. (Same below) - @test current_module() == orig_curmodule14726 + @test @__MODULE__() == orig_curmodule14726 end module M14726_2 @@ -166,7 +166,7 @@ using Base.Threads # pushes the work onto the threads. # The @test might not be particularly meaningful currently since the # thread infrastructures swallows the error. (See also above) - @test current_module() == M14726_2 + @test @__MODULE__() == M14726_2 end end diff --git a/test/workspace.jl b/test/workspace.jl index 44a315c6fbf5d..3cd95121fbed0 100644 --- a/test/workspace.jl +++ b/test/workspace.jl @@ -6,26 +6,34 @@ script = """ # Issue #11948 f(x) = x+1 workspace() -@assert !isdefined(:f) -LastMain.f(2) +@assert @__MODULE__() === Main +@assert isdefined(Main, :f) +@assert !@isdefined LastMain +@eval Core.Main begin + @assert @__MODULE__() === Main + @assert !isdefined(Main, :f) + LastMain.f(2) -# PR #12990 -io = IOBuffer() -show(io, Pair) -@assert String(take!(io)) == "Pair" -@assert !Base.inbase(LastMain) + # PR #12990 + io = IOBuffer() + show(io, Pair) + @assert String(take!(io)) == "Pair" + @assert !Base.inbase(LastMain) +end """ exename = Base.julia_cmd() -run(`$exename --startup-file=no -e $script`) +@test success(pipeline(`$exename --startup-file=no -e $script`, stdout=STDOUT, stderr=STDERR)) # issue #17764 script2 = """ mutable struct Foo end workspace() -mutable struct Foo end -@assert Tuple{Type{LastMain.Foo}} !== Tuple{Type{Main.Foo}} +@eval Core.Main begin + mutable struct Foo end + @assert Tuple{Type{LastMain.Foo}} !== Tuple{Type{Main.Foo}} +end """ -run(`$exename --startup-file=no -e $script2`) +@test success(pipeline(`$exename --startup-file=no -e $script2`, stdout=STDOUT, stderr=STDERR)) # Issue #22101 mktempdir() do dir diff --git a/ui/repl.c b/ui/repl.c index 0ae1580f7cda0..2355675b2fa53 100644 --- a/ui/repl.c +++ b/ui/repl.c @@ -46,7 +46,7 @@ static int exec_program(char *program) { jl_ptls_t ptls = jl_get_ptls_states(); JL_TRY { - jl_load(program); + jl_load(jl_main_module, program); } JL_CATCH { jl_value_t *errs = jl_stderr_obj();