@@ -77,31 +77,31 @@ Its fields are as follows:
77
77
- `pending_styles::Vector{Tuple{UnitRange{Int}, Union{Symbol, Expr, Pair{Symbol, Any}}}}`,
78
78
A list of styles that have been terminated, and so are known to occur over a certain range,
79
79
but have yet to be applied.
80
- - `offset::RefValue{ Int} `, a record of the between the `content` index and the index in the resulting
80
+ - `offset::Int`, a record of the between the `content` index and the index in the resulting
81
81
styled string, as markup structures are absorbed.
82
- - `point::RefValue{ Int} `, the current index in `content`.
83
- - `escape::RefValue{ Bool} `, whether the last character seen was an escape character.
84
- - `interpolated::RefValue{ Bool} `, whether any interpolated values have been seen. Knowing whether or not
82
+ - `point::Int`, the current index in `content`.
83
+ - `escape::Bool`, whether the last character seen was an escape character.
84
+ - `interpolated::Bool`, whether any interpolated values have been seen. Knowing whether or not
85
85
anything needs to be evaluated allows the resulting string to be computed at macroexpansion time,
86
86
when possible.
87
87
- `errors::Vector`, any errors raised during parsing. We collect them instead of immediately throwing
88
88
so that we can list as many issues as possible at once, instead of forcing the author of the invalid
89
89
styled markup to resolve each issue one at a time. This is expected to be populated by invocations of
90
90
`styerr!`.
91
91
"""
92
- struct State
93
- content:: String
94
- bytes:: Vector{UInt8}
95
- s:: Iterators.Stateful
96
- mod:: Union{Module, Nothing}
97
- parts:: Vector{Any}
98
- active_styles:: Vector {Vector{Tuple{Int, Int, Union{Symbol, Expr, Pair{Symbol, Any}}}}}
99
- pending_styles:: Vector {Tuple{UnitRange{Int}, Union{Symbol, Expr, Pair{Symbol, Any}}}}
100
- offset:: Base.RefValue{ Int}
101
- point:: Base.RefValue{ Int}
102
- escape:: Base.RefValue{ Bool}
103
- interpolated:: Base.RefValue{ Bool}
104
- errors:: Vector
92
+ mutable struct State
93
+ const content:: String
94
+ const bytes:: Vector{UInt8}
95
+ const s:: Iterators.Stateful
96
+ const mod:: Union{Module, Nothing}
97
+ const parts:: Vector{Any}
98
+ const active_styles:: Vector {Vector{Tuple{Int, Int, Union{Symbol, Expr, Pair{Symbol, Any}}}}}
99
+ const pending_styles:: Vector {Tuple{UnitRange{Int}, Union{Symbol, Expr, Pair{Symbol, Any}}}}
100
+ offset:: Int
101
+ point:: Int
102
+ escape:: Bool
103
+ interpolated:: Bool
104
+ const errors:: Vector
105
105
end
106
106
107
107
function State (content:: AbstractString , mod:: Union{Module, Nothing} = nothing )
@@ -110,8 +110,8 @@ function State(content::AbstractString, mod::Union{Module, Nothing}=nothing)
110
110
Any[], # parts
111
111
Vector{Tuple{Int, Int, Union{Symbol, Expr, Pair{Symbol, Any}}}}[], # active_styles
112
112
Tuple{UnitRange{Int}, Union{Symbol, Expr, Pair{Symbol, Any}}}[], # pending_styles
113
- Ref ( 0 ), Ref ( 1 ) , # offset, point
114
- Ref ( false ), Ref ( false ) , # escape, interpolated
113
+ 0 , 1 , # offset, point
114
+ false , false , # escape, interpolated
115
115
NamedTuple{(:message , :position , :hint ), # errors
116
116
Tuple{AnnotatedString{String}, <: Union{Int, Nothing} , String}}[])
117
117
end
@@ -192,11 +192,11 @@ This consumes all the content between `state.point` and `stop`, and shifts
192
192
`state.point` to be the index after `stop`.
193
193
"""
194
194
function addpart! (state:: State , stop:: Int )
195
- if state. point[] > stop+ state. offset[] + ncodeunits (state. content[stop])- 1
196
- return state. point[] = nextind (state. content, stop) + state. offset[]
195
+ if state. point > stop+ state. offset+ ncodeunits (state. content[stop])- 1
196
+ return state. point = nextind (state. content, stop) + state. offset
197
197
end
198
198
str = String (state. bytes[
199
- state. point[] : stop+ state. offset[] + ncodeunits (state. content[stop])- 1 ])
199
+ state. point: stop+ state. offset+ ncodeunits (state. content[stop])- 1 ])
200
200
sty_type, tupl = if ismacro (state)
201
201
Expr, (a, b) -> Expr (:tuple , a, b)
202
202
else
@@ -210,15 +210,15 @@ function addpart!(state::State, stop::Int)
210
210
sort! (state. pending_styles, by = (r -> (first (r), - last (r))) ∘ first) # Prioritise the most specific styles
211
211
for (range, annot) in state. pending_styles
212
212
if ! isempty (range)
213
- push! (styles, tupl (range .- state. point[] , annot))
213
+ push! (styles, tupl (range .- state. point, annot))
214
214
end
215
215
end
216
216
empty! (state. pending_styles)
217
217
relevant_styles = Iterators. filter (
218
- (_, start, _):: Tuple -> start <= stop + state. offset[] + 1 ,
218
+ (_, start, _):: Tuple -> start <= stop + state. offset + 1 ,
219
219
Iterators. flatten (map (reverse, state. active_styles)))
220
220
for (_, start, annot) in relevant_styles
221
- range = (start - state. point[] ): (stop - state. point[] + state. offset[] + 1 )
221
+ range = (start - state. point): (stop - state. point + state. offset + 1 )
222
222
push! (styles, tupl (range, annot))
223
223
end
224
224
if isempty (styles)
@@ -229,7 +229,7 @@ function addpart!(state::State, stop::Int)
229
229
:(AnnotatedString ($ str, $ (Expr (:vect , styles... ))))
230
230
end
231
231
end )
232
- state. point[] = nextind (state. content, stop) + state. offset[]
232
+ state. point = nextind (state. content, stop) + state. offset
233
233
end
234
234
235
235
"""
@@ -239,7 +239,7 @@ Create a new part based on (the eventual evaluation of) `expr`, running from
239
239
`start` to `stop`, taking the currently active styles into account.
240
240
"""
241
241
function addpart! (state:: State , start:: Int , expr, stop:: Int )
242
- if state. point[] < start
242
+ if state. point < start
243
243
addpart! (state, start)
244
244
end
245
245
if isempty (state. active_styles)
@@ -270,7 +270,7 @@ function addpart!(state::State, start::Int, expr, stop::Int)
270
270
end
271
271
end ))
272
272
end
273
- map! .((i, _, annot):: Tuple -> (i, stop + state. offset[] + 1 , annot),
273
+ map! .((i, _, annot):: Tuple -> (i, stop + state. offset + 1 , annot),
274
274
state. active_styles, state. active_styles)
275
275
end
276
276
end
@@ -282,8 +282,8 @@ Parse the escaped character `char`, at index `i`, into `state`
282
282
"""
283
283
function escaped! (state:: State , i:: Int , char:: Char )
284
284
if char in (' {' , ' }' , ' \\ ' ) || (char == ' $' && ismacro (state))
285
- deleteat! (state. bytes, i + state. offset[] - 1 )
286
- state. offset[] -= ncodeunits (' \\ ' )
285
+ deleteat! (state. bytes, i + state. offset - 1 )
286
+ state. offset -= ncodeunits (' \\ ' )
287
287
elseif char ∈ (' \n ' , ' \r ' ) && ! isempty (state. s)
288
288
skipped = 0
289
289
if char == ' \r ' && isnextchar (state, ' \n ' )
@@ -294,10 +294,10 @@ function escaped!(state::State, i::Int, char::Char)
294
294
popfirst! (state. s)
295
295
skipped += 1
296
296
end
297
- deleteat! (state. bytes, i+ state. offset[] - 1 : i+ skipped+ state. offset[] )
298
- state. offset[] -= skipped + ncodeunits (" \\\n " )
297
+ deleteat! (state. bytes, i+ state. offset- 1 : i+ skipped+ state. offset)
298
+ state. offset -= skipped + ncodeunits (" \\\n " )
299
299
end
300
- state. escape[] = false
300
+ state. escape = false
301
301
end
302
302
303
303
"""
@@ -307,11 +307,11 @@ Interpolate the expression starting at `i`, and add it as a part to `state`.
307
307
"""
308
308
function interpolated! (state:: State , i:: Int , _)
309
309
expr, nexti = readexpr! (state, i + ncodeunits (' $' ))
310
- deleteat! (state. bytes, i + state. offset[] )
311
- state. offset[] -= ncodeunits (' $' )
310
+ deleteat! (state. bytes, i + state. offset)
311
+ state. offset -= ncodeunits (' $' )
312
312
addpart! (state, i, esc (expr), nexti)
313
- state. point[] = nexti + state. offset[]
314
- state. interpolated[] = true
313
+ state. point = nexti + state. offset
314
+ state. interpolated = true
315
315
end
316
316
317
317
"""
@@ -408,8 +408,8 @@ function begin_style!(state::State, i::Int, char::Char)
408
408
# style declaration(s).
409
409
if ! isempty (state. s)
410
410
nexti = first (peek (state. s))
411
- deleteat! (state. bytes, i+ state. offset[] : nexti+ state. offset[] - 1 )
412
- state. offset[] -= nexti - i
411
+ deleteat! (state. bytes, i+ state. offset: nexti+ state. offset- 1 )
412
+ state. offset -= nexti - i
413
413
end
414
414
end
415
415
@@ -420,10 +420,10 @@ Close of the most recent active style in `state`, making it a pending style.
420
420
"""
421
421
function end_style! (state:: State , i:: Int , char:: Char )
422
422
for (_, start, annot) in pop! (state. active_styles)
423
- pushfirst! (state. pending_styles, (start: i+ state. offset[] , annot))
423
+ pushfirst! (state. pending_styles, (start: i+ state. offset, annot))
424
424
end
425
- deleteat! (state. bytes, i + state. offset[] )
426
- state. offset[] -= ncodeunits (' }' )
425
+ deleteat! (state. bytes, i + state. offset)
426
+ state. offset -= ncodeunits (' }' )
427
427
end
428
428
429
429
"""
@@ -511,7 +511,7 @@ function read_inlineface!(state::State, i::Int, char::Char, newstyles)
511
511
elseif isnextchar (state, ' $' ) && ismacro (state)
512
512
expr, _ = readexpr! (state)
513
513
lastchar = last (popfirst! (state. s))
514
- state. interpolated[] = true
514
+ state. interpolated = true
515
515
needseval = true
516
516
esc (expr)
517
517
else
@@ -525,7 +525,7 @@ function read_inlineface!(state::State, i::Int, char::Char, newstyles)
525
525
if isnextchar (state, ' $' ) && ismacro (state)
526
526
expr, _ = readexpr! (state)
527
527
lastchar = last (popfirst! (state. s))
528
- state. interpolated[] = true
528
+ state. interpolated = true
529
529
needseval = true
530
530
ustyle = esc (expr)
531
531
else
@@ -639,7 +639,7 @@ function read_inlineface!(state::State, i::Int, char::Char, newstyles)
639
639
val = if ismacro (state) && isnextchar (state, ' $' )
640
640
expr, _ = readexpr! (state)
641
641
lastchar = last (popfirst! (state. s))
642
- state. interpolated[] = true
642
+ state. interpolated = true
643
643
needseval = true
644
644
esc (expr)
645
645
elseif key == :font
@@ -724,7 +724,7 @@ function read_inlineface!(state::State, i::Int, char::Char, newstyles)
724
724
end
725
725
face = Expr (:call , Face, kwargs... )
726
726
push! (newstyles,
727
- (i, i + state. offset[] + 1 ,
727
+ (i, i + state. offset + 1 ,
728
728
if ! ismacro (state)
729
729
Pair {Symbol, Any} (:face , Face (; NamedTuple (kwargs)... ))
730
730
elseif needseval
@@ -766,7 +766,7 @@ function read_face_or_keyval!(state::State, i::Int, char::Char, newstyles)
766
766
# this isn't the 'last' char yet, but it will be
767
767
key = if ismacro (state) && last (peek (state. s)) == ' $'
768
768
expr, _ = readexpr! (state)
769
- state. interpolated[] = true
769
+ state. interpolated = true
770
770
needseval = true
771
771
esc (expr)
772
772
else
@@ -788,7 +788,7 @@ function read_face_or_keyval!(state::State, i::Int, char::Char, newstyles)
788
788
read_curlywrapped! (state)
789
789
elseif ismacro (state) && nextchar == ' $'
790
790
expr, _ = readexpr! (state)
791
- state. interpolated[] = true
791
+ state. interpolated = true
792
792
needseval = true
793
793
esc (expr)
794
794
else
@@ -800,7 +800,7 @@ function read_face_or_keyval!(state::State, i::Int, char::Char, newstyles)
800
800
String (chars)
801
801
end
802
802
push! (newstyles,
803
- (i, i + state. offset[] + ncodeunits (' {' ),
803
+ (i, i + state. offset + ncodeunits (' {' ),
804
804
if key isa String && ! (value isa Symbol || value isa Expr)
805
805
Pair {Symbol, Any} (Symbol (key), value)
806
806
elseif key isa Expr || key isa Symbol
@@ -811,7 +811,7 @@ function read_face_or_keyval!(state::State, i::Int, char::Char, newstyles)
811
811
end ))
812
812
elseif key != = " "
813
813
push! (newstyles,
814
- (i, i + state. offset[] + ncodeunits (' {' ),
814
+ (i, i + state. offset + ncodeunits (' {' ),
815
815
if key isa Symbol || key isa Expr
816
816
:(Pair {Symbol, Any} (:face , $ key))
817
817
else # Face symbol
@@ -836,8 +836,8 @@ function run_state_machine!(state::State)
836
836
# Run the state machine
837
837
for (i, char) in state. s
838
838
if char == ' \\ '
839
- state. escape[] = true
840
- elseif state. escape[]
839
+ state. escape = true
840
+ elseif state. escape
841
841
escaped! (state, i, char)
842
842
elseif ismacro (state) && char == ' $'
843
843
interpolated! (state, i, char)
@@ -852,7 +852,7 @@ function run_state_machine!(state::State)
852
852
end
853
853
end
854
854
# Ensure that any trailing unstyled content is added
855
- if state. point[] <= lastindex (state. content) + state. offset[]
855
+ if state. point <= lastindex (state. content) + state. offset
856
856
addpart! (state, lastindex (state. content))
857
857
end
858
858
for incomplete in Iterators. flatten (state. active_styles)
@@ -988,7 +988,7 @@ macro styled_str(raw_content::String)
988
988
run_state_machine! (state)
989
989
if ! isempty (state. errors)
990
990
throw (MalformedStylingMacro (state. content, state. errors))
991
- elseif state. interpolated[]
991
+ elseif state. interpolated
992
992
:(annotatedstring ($ (state. parts... )) |> annotatedstring_optimize!)
993
993
else
994
994
annotatedstring (map (Base. Fix1 (hygienic_eval, state), state. parts)... ) |> annotatedstring_optimize!
0 commit comments