From f0f535f8c44df5b4bd504407d353319529ac0fa7 Mon Sep 17 00:00:00 2001 From: Chris Foster Date: Thu, 9 Apr 2020 16:52:24 +1000 Subject: [PATCH] Move more of _include implementation to julia --- base/loading.jl | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/base/loading.jl b/base/loading.jl index 1aba17ff21653..bfe3471cb7642 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -1081,10 +1081,37 @@ The optional first argument `mapexpr` can be used to transform the included code it is evaluated: for each parsed expression `expr` in `code`, the `include_string` function actually evaluates `mapexpr(expr)`. If it is omitted, `mapexpr` defaults to [`identity`](@ref). """ -function include_string(mapexpr::Function, m::Module, txt_::AbstractString, fname::AbstractString="string") - txt = String(txt_) - ccall(:jl_parse_eval_all, Any, (Any, Any, Any, Any), - m, txt, String(fname), mapexpr === identity ? nothing : mapexpr) +function include_string(mapexpr::Function, mod::Module, code::AbstractString, + filename::AbstractString="string") + loc = LineNumberNode(1, Symbol(filename)) + try + ast = Meta.parseall(code, filename=filename) + @assert Meta.isexpr(ast, :toplevel) + result = nothing + line_and_ex = Expr(:toplevel, loc, nothing) + for ex in ast.args + if ex isa LineNumberNode + loc = ex + line_and_ex.args[1] = ex + continue + end + ex = mapexpr(ex) + # Wrap things to be eval'd in a :toplevel expr to carry line + # information as part of the expr. + line_and_ex.args[2] = ex + # Macro expand, lower, and evaluate successive top-level statements + # in the latest world. + # + # TODO: Separate macro expansion and lowering steps from the final + # evaluation step, and make these throw their own error types which + # carry the full source location. + result = invokelatest(Core.eval, mod, line_and_ex) + end + return result + catch exc + # TODO: Remove LoadError! + throw(LoadError(String(loc.file), loc.line, exc)) + end end include_string(m::Module, txt::AbstractString, fname::AbstractString="string") = @@ -1121,18 +1148,16 @@ actually evaluates `mapexpr(expr)`. If it is omitted, `mapexpr` defaults to [`i Base.include # defined in Base.jl # Full include() implementation which is used after bootstrap -# Hidden for nicer backtraces in include() function _include(mapexpr::Function, mod::Module, _path::AbstractString) path, prev = _include_dependency(mod, _path) for callback in include_callbacks # to preserve order, must come before Core.include invokelatest(callback, mod, path) end + code = read(path, String) tls = task_local_storage() tls[:SOURCE_PATH] = path - local result try - result = ccall(:jl_load_rewrite, Any, (Any, Any, Any), mod, path, - mapexpr === identity ? nothing : mapexpr) + include_string(mapexpr, mod, code, path) finally if prev === nothing delete!(tls, :SOURCE_PATH) @@ -1140,7 +1165,6 @@ function _include(mapexpr::Function, mod::Module, _path::AbstractString) tls[:SOURCE_PATH] = prev end end - return result end """