Skip to content

Commit 82b9705

Browse files
authored
Remove many unnecessary allocations (#96)
* Eliminate the use of Ref to communicate values out of the anonymous function passed to parse_brackets(). It seems this forces unnecessary allocation of the Ref captured by the closure. * Force specialization on `down` in `parse_assignment_with_initial_ex` to avoid an unnecessary generic dispatch there. This should probably bring down the total number of allocations during parsing to around O(log(N) + M) in the length of the file N and depth, M, of the AST.
1 parent b15e079 commit 82b9705

File tree

1 file changed

+26
-27
lines changed

1 file changed

+26
-27
lines changed

src/parser.jl

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,7 @@ function parse_assignment(ps::ParseState, down, equals_is_kw::Bool)
540540
parse_assignment_with_initial_ex(ps, mark, down, equals_is_kw)
541541
end
542542

543-
function parse_assignment_with_initial_ex(ps::ParseState, mark, down, equals_is_kw::Bool)
543+
function parse_assignment_with_initial_ex(ps::ParseState, mark, down::T, equals_is_kw::Bool) where {T} # where => specialize on `down`
544544
t = peek_token(ps)
545545
k = kind(t)
546546
if !is_prec_assignment(k)
@@ -1169,19 +1169,18 @@ function parse_unary_call(ps::ParseState)
11691169
mark_before_paren = position(ps)
11701170
bump(ps, TRIVIA_FLAG) # (
11711171
initial_semi = peek(ps) == K";"
1172-
is_call = Ref(false)
1173-
is_block = Ref(false)
1174-
parse_brackets(ps, K")") do had_commas, had_splat, num_semis, num_subexprs
1175-
is_call[] = had_commas || had_splat || initial_semi
1176-
is_block[] = !is_call[] && num_semis > 0
1177-
return (needs_parameters=is_call[],
1178-
eq_is_kw_before_semi=is_call[],
1179-
eq_is_kw_after_semi=is_call[])
1172+
opts = parse_brackets(ps, K")") do had_commas, had_splat, num_semis, num_subexprs
1173+
is_call = had_commas || had_splat || initial_semi
1174+
return (needs_parameters=is_call,
1175+
eq_is_kw_before_semi=is_call,
1176+
eq_is_kw_after_semi=is_call,
1177+
is_call=is_call,
1178+
is_block=!is_call && num_semis > 0)
11801179
end
11811180

11821181
# The precedence between unary + and any following infix ^ depends on
11831182
# whether the parens are a function call or not
1184-
if is_call[]
1183+
if opts.is_call
11851184
if preceding_whitespace(t2)
11861185
# Whitespace not allowed before prefix function call bracket
11871186
# + (a,b) ==> (call + (error) a b)
@@ -1203,7 +1202,7 @@ function parse_unary_call(ps::ParseState)
12031202
parse_factor_with_initial_ex(ps, mark)
12041203
else
12051204
# Unary function calls with brackets as grouping, not an arglist
1206-
if is_block[]
1205+
if opts.is_block
12071206
# +(a;b) ==> (call + (block a b))
12081207
emit(ps, mark_before_paren, K"block")
12091208
end
@@ -1995,14 +1994,14 @@ function parse_function(ps::ParseState)
19951994
# distinguish the cases here.
19961995
bump(ps, TRIVIA_FLAG)
19971996
is_empty_tuple = peek(ps, skip_newlines=true) == K")"
1998-
_is_anon_func = Ref(is_anon_func)
1999-
parse_brackets(ps, K")") do _, _, _, _
2000-
_is_anon_func[] = peek(ps, 2) != K"("
2001-
return (needs_parameters = _is_anon_func[],
2002-
eq_is_kw_before_semi = _is_anon_func[],
2003-
eq_is_kw_after_semi = _is_anon_func[])
1997+
opts = parse_brackets(ps, K")") do _, _, _, _
1998+
_is_anon_func = peek(ps, 2) != K"("
1999+
return (needs_parameters = _is_anon_func,
2000+
eq_is_kw_before_semi = _is_anon_func,
2001+
eq_is_kw_after_semi = _is_anon_func,
2002+
is_anon_func=_is_anon_func)
20042003
end
2005-
is_anon_func = _is_anon_func[]
2004+
is_anon_func = opts.is_anon_func
20062005
if is_anon_func
20072006
# function (x) body end ==> (function (tuple x) (block body))
20082007
# function (x,y) end ==> (function (tuple x y) (block))
@@ -2859,17 +2858,16 @@ function parse_paren(ps::ParseState, check_identifiers=true)
28592858
# Deal with all other cases of tuple or block syntax via the generic
28602859
# parse_brackets
28612860
initial_semi = peek(ps) == K";"
2862-
is_tuple = Ref(false)
2863-
is_block = Ref(false)
2864-
parse_brackets(ps, K")") do had_commas, had_splat, num_semis, num_subexprs
2865-
is_tuple[] = had_commas || (had_splat && num_semis >= 1) ||
2861+
opts = parse_brackets(ps, K")") do had_commas, had_splat, num_semis, num_subexprs
2862+
is_tuple = had_commas || (had_splat && num_semis >= 1) ||
28662863
(initial_semi && (num_semis == 1 || num_subexprs > 0))
2867-
is_block[] = num_semis > 0
2868-
return (needs_parameters=is_tuple[],
2864+
return (needs_parameters=is_tuple,
28692865
eq_is_kw_before_semi=false,
2870-
eq_is_kw_after_semi=is_tuple[])
2866+
eq_is_kw_after_semi=is_tuple,
2867+
is_tuple=is_tuple,
2868+
is_block=num_semis > 0)
28712869
end
2872-
if is_tuple[]
2870+
if opts.is_tuple
28732871
# Tuple syntax with commas
28742872
# (x,) ==> (tuple x)
28752873
# (x,y) ==> (tuple x y)
@@ -2886,7 +2884,7 @@ function parse_paren(ps::ParseState, check_identifiers=true)
28862884
# (a; b; c,d) ==> (tuple a (parameters b (parameters c d)))
28872885
# (a=1, b=2; c=3) ==> (tuple (= a 1) (= b 2) (parameters (kw c 3)))
28882886
emit(ps, mark, K"tuple")
2889-
elseif is_block[]
2887+
elseif opts.is_block
28902888
# Blocks
28912889
# (;;) ==> (block)
28922890
# (a=1;) ==> (block (= a 1))
@@ -3016,6 +3014,7 @@ function parse_brackets(after_parse::Function,
30163014
release_positions(ps.stream, params_marks)
30173015
release_positions(ps.stream, eq_positions)
30183016
bump_closing_token(ps, closing_kind)
3017+
return actions
30193018
end
30203019

30213020
is_indentation(b::UInt8) = (b == UInt8(' ') || b == UInt8('\t'))

0 commit comments

Comments
 (0)