Skip to content

Commit d105724

Browse files
committed
Freeze world age by default in enable_in_core!()
A fixed world age for the parser prevents the need for recompilation of the parser due to any user-defined methods.
1 parent ffd3e47 commit d105724

File tree

1 file changed

+58
-23
lines changed

1 file changed

+58
-23
lines changed

src/hooks.jl

Lines changed: 58 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,28 @@
1-
_debug_log = nothing
1+
# World age which the parser will be invoked in.
2+
# Set to typemax(UInt) to invoke in the world of the caller.
3+
const _parser_world_age = Ref{UInt}(typemax(UInt))
24

35
# Adaptor for the API/ABI expected by the Julia runtime code.
46
function core_parser_hook(code, filename, lineno, offset, options)
7+
if _parser_world_age[] != typemax(UInt)
8+
Base.invoke_in_world(_parser_world_age[], _core_parser_hook,
9+
code, filename, lineno, offset, options)
10+
else
11+
_core_parser_hook(code, filename, lineno, offset, options)
12+
end
13+
end
14+
15+
# Core._parse gained a `lineno` argument in
16+
# https://github.com/JuliaLang/julia/pull/43876
17+
# Prior to this, the following signature was needed:
18+
function core_parser_hook(code, filename, offset, options)
19+
core_parser_hook(code, filename, LineNumberNode(0), offset, options)
20+
end
21+
22+
# Debug log file for dumping parsed code
23+
const _debug_log = Ref{Union{Nothing,IO}}(nothing)
24+
25+
function _core_parser_hook(code, filename, lineno, offset, options)
526
try
627
# TODO: Check that we do all this input wrangling without copying the
728
# code buffer
@@ -10,13 +31,13 @@ function core_parser_hook(code, filename, lineno, offset, options)
1031
(ptr,len) = code
1132
code = String(unsafe_wrap(Array, ptr, len))
1233
end
13-
if !isnothing(_debug_log)
14-
print(_debug_log, """
34+
if !isnothing(_debug_log[])
35+
print(_debug_log[], """
1536
#-#-#-------------------------------
1637
# ENTER filename=$filename, lineno=$lineno, offset=$offset, options=$options"
1738
#-#-#-------------------------------
1839
""")
19-
write(_debug_log, code)
40+
write(_debug_log[], code)
2041
end
2142

2243
io = IOBuffer(code)
@@ -58,8 +79,8 @@ function core_parser_hook(code, filename, lineno, offset, options)
5879
# of one cancel here.
5980
last_offset = last_byte(stream)
6081

61-
if !isnothing(_debug_log)
62-
println(_debug_log, """
82+
if !isnothing(_debug_log[])
83+
println(_debug_log[], """
6384
#-#-#-
6485
# EXIT last_offset=$last_offset
6586
#-#-#-
@@ -69,19 +90,25 @@ function core_parser_hook(code, filename, lineno, offset, options)
6990
# Rewrap result in an svec for use by the C code
7091
return Core.svec(ex, last_offset)
7192
catch exc
93+
if !isnothing(_debug_log[])
94+
println(_debug_log[], """
95+
#-#-#-
96+
# ERROR EXIT
97+
# $exc
98+
#-#-#-
99+
""")
100+
end
72101
@error("JuliaSyntax parser failed — falling back to flisp!",
73102
exception=(exc,catch_backtrace()),
74103
offset=offset,
75104
code=code)
76-
end
77-
return Core.Compiler.fl_parse(code, filename, offset, options)
78-
end
79105

80-
# Core._parse gained a `lineno` argument in
81-
# https://github.com/JuliaLang/julia/pull/43876
82-
# Prior to this, the following signature was needed:
83-
function core_parser_hook(code, filename, offset, options)
84-
core_parser_hook(code, filename, LineNumberNode(0), offset, options)
106+
if VERSION >= v"1.8.0-DEV.1370" # https://github.com/JuliaLang/julia/pull/43876
107+
return Core.Compiler.fl_parse(code, filename, lineno, offset, options)
108+
else
109+
return Core.Compiler.fl_parse(code, filename, offset, options)
110+
end
111+
end
85112
end
86113

87114
# Hack:
@@ -92,19 +119,27 @@ Base.Meta.ParseError(e::JuliaSyntax.ParseError) = e
92119
const _default_parser = Core._parse
93120

94121
"""
122+
enable_in_core!([enable=true; freeze_world_age, debug_filename])
123+
95124
Connect the JuliaSyntax parser to the Julia runtime so that it replaces the
96-
flisp parser for all parsing work.
125+
flisp parser for all parsing work. That is, JuliaSyntax will be used for
126+
`include()` `Meta.parse()`, the REPL, etc. To disable, set use
127+
`enable_in_core!(false)`.
97128
98-
That is, JuliaSyntax will be used for `include()` `Meta.parse()`, the REPL, etc.
129+
Keyword arguments:
130+
* `freeze_world_age` - Use a fixed world age for the parser to prevent
131+
recompilation of the parser due to any user-defined methods (default `true`).
132+
* `debug_filename` - File name of parser debug log (defaults to `nothing` or
133+
the value of `ENV["JULIA_SYNTAX_DEBUG_FILE"]`).
99134
"""
100-
function enable_in_core!(enable=true)
101-
debug_filename = get(ENV, "JULIA_SYNTAX_DEBUG_FILE", nothing)
102-
global _debug_log
135+
function enable_in_core!(enable=true; freeze_world_age = true,
136+
debug_filename = get(ENV, "JULIA_SYNTAX_DEBUG_FILE", nothing))
137+
_parser_world_age[] = freeze_world_age ? Base.get_world_counter() : typemax(UInt)
103138
if enable && !isnothing(debug_filename)
104-
_debug_log = open(debug_filename, "w")
105-
elseif !enable && !isnothing(_debug_log)
106-
close(_debug_log)
107-
_debug_log = nothing
139+
_debug_log[] = open(debug_filename, "w")
140+
elseif !enable && !isnothing(_debug_log[])
141+
close(_debug_log[])
142+
_debug_log[] = nothing
108143
end
109144
parser = enable ? core_parser_hook : _default_parser
110145
Base.eval(Core, :(_parse = $parser))

0 commit comments

Comments
 (0)