Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Compiler/src/Compiler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ using Base: @_foldable_meta, @_gc_preserve_begin, @_gc_preserve_end, @nospeciali
structdiff, tls_world_age, unconstrain_vararg_length, unionlen, uniontype_layout,
uniontypes, unsafe_convert, unwrap_unionall, unwrapva, vect, widen_diagonal,
_uncompressed_ir, maybe_add_binding_backedge!, datatype_min_ninitialized,
partialstruct_init_undefs, fieldcount_noerror
partialstruct_init_undefs, fieldcount_noerror, _eval_import, _eval_using
using Base.Order

import Base: ==, _topmod, append!, convert, copy, copy!, findall, first, get, get!,
Expand Down
4 changes: 4 additions & 0 deletions base/Base_compiler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

module Base

Core._import(Base, Core, :_eval_import, :_eval_import, true)
Core._import(Base, Core, :_eval_using, :_eval_using, true)

using .Core.Intrinsics, .Core.IR

# to start, we're going to use a very simple definition of `include`
Expand Down Expand Up @@ -340,6 +343,7 @@ include("ordering.jl")
using .Order

include("coreir.jl")
include("module.jl")
include("invalidation.jl")

BUILDROOT::String = ""
Expand Down
48 changes: 48 additions & 0 deletions base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,54 @@ function Symbol(a::Array{UInt8, 1})
end
Symbol(s::Symbol) = s

# Minimal implementations of using/import for bootstrapping (supports only
# `import .M: a, b, c, ...`, little error checking)
let
fail() = throw(ArgumentError("unsupported import/using while bootstrapping"))
length(a::Array{T, 1}) where {T} = getfield(getfield(a, :size), 1)
function getindex(A::Array, i::Int)
Intrinsics.ult_int(Intrinsics.bitcast(UInt, Intrinsics.sub_int(i, 1)), Intrinsics.bitcast(UInt, length(A))) || fail()
memoryrefget(memoryrefnew(getfield(A, :ref), i, false), :not_atomic, false)
end
x == y = Intrinsics.eq_int(x, y)
x + y = Intrinsics.add_int(x, y)
x <= y = Intrinsics.sle_int(x, y)

global function _eval_import(explicit::Bool, to::Module, from::Union{Expr, Nothing}, paths::Expr...)
from isa Expr || fail()
if length(from.args) == 2 && getindex(from.args, 1) === :.
from = getglobal(to, getindex(from.args, 2))
elseif length(from.args) == 1 && getindex(from.args, 1) === :Core
from = Core
elseif length(from.args) == 1 && getindex(from.args, 1) === :Base
from = Main.Base
else
fail()
end
from isa Module || fail()
i = 1
while i <= nfields(paths)
a = getfield(paths, i).args
length(a) == 1 || fail()
s = getindex(a, 1)
Core._import(to, from, s, s, explicit)
i += 1
end
end

global function _eval_using(to::Module, path::Expr)
getindex(path.args, 1) === :. || fail()
from = getglobal(to, getindex(path.args, 2))
i = 3
while i <= length(path.args)
from = getfield(from, getindex(path.args, i))
i += 1
end
from isa Module || fail()
Core._using(to, from)
end
end

# module providing the IR object model
module IR

Expand Down
2 changes: 1 addition & 1 deletion base/c.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# definitions related to C interface

import Core.Intrinsics: cglobal
import .Intrinsics: cglobal

"""
cglobal((symbol, library) [, type=Cvoid])
Expand Down
5 changes: 3 additions & 2 deletions base/checked.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ export checked_neg, checked_abs, checked_add, checked_sub, checked_mul,
checked_div, checked_rem, checked_fld, checked_mod, checked_cld, checked_pow,
checked_length, add_with_overflow, sub_with_overflow, mul_with_overflow

import Core.Intrinsics:
import Core: Intrinsics
import .Intrinsics:
checked_sadd_int, checked_ssub_int, checked_smul_int, checked_sdiv_int,
checked_srem_int,
checked_uadd_int, checked_usub_int, checked_umul_int, checked_udiv_int,
checked_urem_int
import ..no_op_err, ..@inline, ..@noinline, ..checked_length
import Base: no_op_err, @inline, @noinline, checked_length

# define promotion behavior for checked operations
checked_add(x::Integer, y::Integer) = checked_add(promote(x,y)...)
Expand Down
19 changes: 19 additions & 0 deletions base/docs/basedocs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2753,6 +2753,25 @@ See also [`setpropertyonce!`](@ref Base.setpropertyonce!) and [`setglobal!`](@re
"""
setglobalonce!

"""
_import(to::Module, from::Module, asname::Symbol, [sym::Symbol, imported::Bool])

With all five arguments, imports `sym` from module `from` into `to` with name
`asname`. `imported` is true for bindings created with `import` (set it to
false for `using A: ...`).

With only the first three arguments, creates a binding for the module `from`
with name `asname` in `to`.
"""
Core._import

"""
_using(to::Module, from::Module)

Add `from` to the usings list of `to`.
"""
Core._using

"""
typeof(x)

Expand Down
12 changes: 6 additions & 6 deletions base/iterators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Methods for working with Iterators.
baremodule Iterators

# small dance to make this work from Base or Intrinsics
import ..@__MODULE__, ..parentmodule
import Base: @__MODULE__, parentmodule
const Base = parentmodule(@__MODULE__)
using .Base:
@inline, Pair, Pairs, AbstractDict, IndexLinear, IndexStyle, AbstractVector, Vector,
Expand All @@ -17,14 +17,14 @@ using .Base:
any, _counttuple, eachindex, ntuple, zero, prod, reduce, in, firstindex, lastindex,
tail, fieldtypes, min, max, minimum, zero, oneunit, promote, promote_shape, LazyString,
afoldl
using Core
using .Core
using Core: @doc

using .Base:
cld, fld, resize!, IndexCartesian
using .Base.Checked: checked_mul
using Base:
cld, fld, resize!, IndexCartesian, Checked
using .Checked: checked_mul

import .Base:
import Base:
first, last,
isempty, length, size, axes, ndims,
eltype, IteratorSize, IteratorEltype, promote_typejoin,
Expand Down
2 changes: 1 addition & 1 deletion base/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2331,7 +2331,7 @@ function require(into::Module, mod::Symbol)
if world == typemax(UInt)
world = get_world_counter()
end
return invoke_in_world(world, __require, into, mod)
return Compiler.@zone "LOAD_Require" invoke_in_world(world, __require, into, mod)
end

function check_for_hint(into, mod)
Expand Down
143 changes: 143 additions & 0 deletions base/module.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

# Full-featured versions of _eval_import and _eval_using

for m in methods(_eval_import)
delete_method(m)
end
for m in methods(_eval_using)
delete_method(m)
end

function eval_import_path(at::Module, from::Union{Module, Nothing}, path::Expr, keyword::String)
isempty(path.args) && error("malformed import statement")

i::Int = 1
function next!()
i <= length(path.args) || error("invalid module path")
v = path.args[i]
i += 1
v isa Symbol || throw(TypeError(Symbol(keyword), "", Symbol, v))
v
end
v = next!()
m = nothing

if from !== nothing
m = from
elseif v !== :.
# `A.B`: call the loader to obtain the root A in the current environment.
if v === :Core
m = Core
elseif v === :Base
m = Base
else
m = require(at, v)
m isa Module || error("failed to load module $v")
end
i > lastindex(path.args) && return m, nothing
v = next!()
else
# `.A.B.C`: strip off leading dots by following parent links
m = at
while (v = next!()) === :.
m = parentmodule(m)
end
end

while true
v === :. && error("invalid $keyword path: \".\" in identifier path")
i > lastindex(path.args) && break
m = getglobal(m, v)
m isa Module || error("invalid $keyword path: \"$v\" does not name a module")
v = next!()
end
m, v
end

function eval_import_path_all(at::Module, path::Expr, keyword::String)
m, v = eval_import_path(at, nothing, path, keyword)
if v !== nothing
m = getglobal(m, v)
m isa Module || error("invalid $keyword path: \"$v\" does not name a module")
end
m
end

function check_macro_rename(from::Symbol, to::Symbol, keyword::String)
c1(sym) = bitcast(Char, UInt32(unsafe_load(unsafe_convert(Ptr{UInt8}, sym))) << 24)
from_c, to_c = c1(from), c1(to)
if from_c == '@' && to_c != '@'
error("cannot rename macro \"$from\" to non-macro \"$to\" in \"$keyword\"")
end
if from_c != '@' && to_c == '@'
error("cannot rename non-macro \"$from\" to macro \"$to\" in \"$keyword\"")
end
end

"""
_eval_import(imported::Bool, to::Module, from::Union{Expr, Nothing}, paths::Expr...)

Evaluate the import paths, calling `Core._import` for each name to be imported.
`imported` imports are created with `import`, `using A: x` sets this to false.
The `from` is the part of the import path before the `:`. This is the lowered
form of `import`, `import ...:`, and `using ...:`.

```
import A => _eval_import(true, Main, nothing, Expr(:., :A))
import A.b => _eval_import(true, Main, nothing, Expr(:., :A, :b))
import A.b as c => _eval_import(true, Main, nothing, Expr(:as, Expr(:., :A, :b), :c))
import A.B: C.d, e => _eval_import(true, Main, Expr(:., :A, :B), Expr(:., :C, :d), Expr(:., :e))
import A.B: C.d as e => _eval_import(true, Main, Expr(:., :A, :B), Expr(:as, Expr(:., :C, :d), :e))
using A.B: C.d, e => _eval_import(false, Main, Expr(:., :A, :B), Expr(:., :C, :d), Expr(:., :e))

See also [`_import`](@ref Core._import).
```
"""
function _eval_import(imported::Bool, to::Module, from::Union{Expr, Nothing}, paths::Expr...)
keyword = imported ? "import" : "using"
fail() = error("malformed \"$keyword\" statement")
from = from !== nothing ? eval_import_path_all(to, from, keyword) : nothing

for path in paths
path isa Expr || fail()
asname = nothing
if path.head === :as && length(path.args) == 2
path, asname = path.args
elseif path.head !== :.
fail()
end
old_from = from
from, name = eval_import_path(to, from, path, keyword)

if name !== nothing
asname = asname === nothing ? name : asname
check_macro_rename(name, asname, keyword)
Core._import(to, from, asname, name, imported)
else
Core._import(to, from, asname === nothing ? nameof(from) : asname)
end
end
end

"""
_eval_using(to::Module, path::Expr)

Evaluate the import path to a module and call [`Core._using`](@ref) on it,
making its exports available to the `to` module; this is the lowered form of
`using A`.

```
using A.B => _module_using(Main, Expr(:., :A, :B))
```

See also [`_using`](@ref Core._using).
"""
function _eval_using(to::Module, path::Expr)
from = eval_import_path_all(to, path, "using")
Core._using(to, from)
is_package = length(path.args) == 1 && path.args[1] !== :.
if to == Main && is_package
Core._import(to, from, nameof(from))
end
end
2 changes: 1 addition & 1 deletion base/ordering.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
module Order


import ..@__MODULE__, ..parentmodule
import Base: @__MODULE__, parentmodule
const Base = parentmodule(@__MODULE__)
import .Base:
AbstractVector, @propagate_inbounds, isless, identity, getindex, reverse,
Expand Down
4 changes: 0 additions & 4 deletions src/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ JL_DLLEXPORT jl_sym_t *jl_module_sym;
JL_DLLEXPORT jl_sym_t *jl_slot_sym;
JL_DLLEXPORT jl_sym_t *jl_export_sym;
JL_DLLEXPORT jl_sym_t *jl_public_sym;
JL_DLLEXPORT jl_sym_t *jl_import_sym;
JL_DLLEXPORT jl_sym_t *jl_toplevel_sym;
JL_DLLEXPORT jl_sym_t *jl_quote_sym;
JL_DLLEXPORT jl_sym_t *jl_line_sym;
Expand All @@ -51,7 +50,6 @@ JL_DLLEXPORT jl_sym_t *jl_pop_exception_sym;
JL_DLLEXPORT jl_sym_t *jl_exc_sym;
JL_DLLEXPORT jl_sym_t *jl_error_sym;
JL_DLLEXPORT jl_sym_t *jl_new_sym;
JL_DLLEXPORT jl_sym_t *jl_using_sym;
JL_DLLEXPORT jl_sym_t *jl_splatnew_sym;
JL_DLLEXPORT jl_sym_t *jl_block_sym;
JL_DLLEXPORT jl_sym_t *jl_new_opaque_closure_sym;
Expand Down Expand Up @@ -349,8 +347,6 @@ void jl_init_common_symbols(void)
jl_module_sym = jl_symbol("module");
jl_export_sym = jl_symbol("export");
jl_public_sym = jl_symbol("public");
jl_import_sym = jl_symbol("import");
jl_using_sym = jl_symbol("using");
jl_assign_sym = jl_symbol("=");
jl_method_sym = jl_symbol("method");
jl_exc_sym = jl_symbol("the_exception");
Expand Down
2 changes: 2 additions & 0 deletions src/builtin_proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ extern "C" {
XX(_defaultctors,"_defaultctors") \
XX(_equiv_typedef,"_equiv_typedef") \
XX(_expr,"_expr") \
XX(_import, "_import") \
XX(_primitivetype,"_primitivetype") \
XX(_setsuper,"_setsuper!") \
XX(_structtype,"_structtype") \
XX(_svec_ref,"_svec_ref") \
XX(_typebody,"_typebody!") \
XX(_typevar,"_typevar") \
XX(_using, "_using") \
XX(applicable,"applicable") \
XX(apply_type,"apply_type") \
XX(compilerbarrier,"compilerbarrier") \
Expand Down
Loading