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))
2
4
3
5
# Adaptor for the API/ABI expected by the Julia runtime code.
4
6
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)
5
26
try
6
27
# TODO : Check that we do all this input wrangling without copying the
7
28
# code buffer
@@ -10,13 +31,13 @@ function core_parser_hook(code, filename, lineno, offset, options)
10
31
(ptr,len) = code
11
32
code = String (unsafe_wrap (Array, ptr, len))
12
33
end
13
- if ! isnothing (_debug_log)
14
- print (_debug_log, """
34
+ if ! isnothing (_debug_log[] )
35
+ print (_debug_log[] , """
15
36
#-#-#-------------------------------
16
37
# ENTER filename=$filename , lineno=$lineno , offset=$offset , options=$options "
17
38
#-#-#-------------------------------
18
39
""" )
19
- write (_debug_log, code)
40
+ write (_debug_log[] , code)
20
41
end
21
42
22
43
io = IOBuffer (code)
@@ -58,8 +79,8 @@ function core_parser_hook(code, filename, lineno, offset, options)
58
79
# of one cancel here.
59
80
last_offset = last_byte (stream)
60
81
61
- if ! isnothing (_debug_log)
62
- println (_debug_log, """
82
+ if ! isnothing (_debug_log[] )
83
+ println (_debug_log[] , """
63
84
#-#-#-
64
85
# EXIT last_offset=$last_offset
65
86
#-#-#-
@@ -69,19 +90,25 @@ function core_parser_hook(code, filename, lineno, offset, options)
69
90
# Rewrap result in an svec for use by the C code
70
91
return Core. svec (ex, last_offset)
71
92
catch exc
93
+ if ! isnothing (_debug_log[])
94
+ println (_debug_log[], """
95
+ #-#-#-
96
+ # ERROR EXIT
97
+ # $exc
98
+ #-#-#-
99
+ """ )
100
+ end
72
101
@error (" JuliaSyntax parser failed — falling back to flisp!" ,
73
102
exception= (exc,catch_backtrace ()),
74
103
offset= offset,
75
104
code= code)
76
- end
77
- return Core. Compiler. fl_parse (code, filename, offset, options)
78
- end
79
105
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
85
112
end
86
113
87
114
# Hack:
@@ -92,19 +119,27 @@ Base.Meta.ParseError(e::JuliaSyntax.ParseError) = e
92
119
const _default_parser = Core. _parse
93
120
94
121
"""
122
+ enable_in_core!([enable=true; freeze_world_age, debug_filename])
123
+
95
124
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)`.
97
128
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"]`).
99
134
"""
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)
103
138
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
108
143
end
109
144
parser = enable ? core_parser_hook : _default_parser
110
145
Base. eval (Core, :(_parse = $ parser))
0 commit comments