Skip to content

Commit a60c0f3

Browse files
mlechuc42f
andcommitted
Updates to const and global lowering; add K"constdecl"; omit wrap
JuliaLang/julia#54773, JuliaLang/julia#56713, JuliaLang/julia#57470. Some changes omitted from `expand-decls` and `expand-assignment`. Note that the two-argument IR "const" is K"constdecl", whereas the one-argument K"const" only appears in the AST. Also note that the `wrap` parameter is omitted throughout assignment desugaring. As far as I'm aware, all this plumbing was just to support `const a,b,c = 1,2,3` having `b` and `c` inherit the `const`. TODO: find a better way of doing the same thing (a ScopedValue might be a clean solution; we currently throw an error). The check for `let; const x = 1; end`, (which should throw) is in scope analysis (lisp has it in `compile`). Co-authored-by: Claire Foster <[email protected]>
1 parent 874f75c commit a60c0f3

File tree

6 files changed

+161
-41
lines changed

6 files changed

+161
-41
lines changed

src/closure_conversion.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -344,11 +344,11 @@ function _convert_closures(ctx::ClosureConversionCtx, ex)
344344
@assert kind(ex[1]) == K"BindingId"
345345
binfo = lookup_binding(ctx, ex[1])
346346
if binfo.kind == :global
347-
@ast ctx ex [K"call"
348-
"set_binding_type!"::K"core"
349-
binfo.mod::K"Value"
350-
binfo.name::K"Symbol"
347+
@ast ctx ex [
348+
K"globaldecl"
349+
ex[1]
351350
_convert_closures(ctx, ex[2])
351+
# TODO (null)?
352352
]
353353
else
354354
makeleaf(ctx, ex, K"TOMBSTONE")

src/desugaring.jl

Lines changed: 101 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,16 +1165,21 @@ end
11651165
# Expand assignments
11661166

11671167
# Expand UnionAll definitions, eg `X{T} = Y{T,T}`
1168-
function expand_unionall_def(ctx, srcref, lhs, rhs)
1168+
function expand_unionall_def(ctx, srcref, lhs, rhs, is_const=true)
11691169
if numchildren(lhs) <= 1
11701170
throw(LoweringError(lhs, "empty type parameter list in type alias"))
11711171
end
11721172
name = lhs[1]
1173-
@ast ctx srcref [K"block"
1174-
[K"const_if_global" name]
1175-
unionall_type := expand_forms_2(ctx, [K"where" rhs lhs[2:end]...])
1176-
expand_forms_2(ctx, [K"=" name unionall_type])
1177-
]
1173+
rr = ssavar(ctx, srcref)
1174+
expand_forms_2(
1175+
ctx,
1176+
@ast ctx srcref [
1177+
K"block"
1178+
[K"=" rr [K"where" rhs lhs[2:end]...]]
1179+
[is_const ? K"constdecl" : K"assign_const_if_global" name rr]
1180+
rr
1181+
]
1182+
)
11781183
end
11791184

11801185
# Expand general assignment syntax, including
@@ -1184,13 +1189,13 @@ end
11841189
# * Assignments to array elements
11851190
# * Destructuring
11861191
# * Typed variable declarations
1187-
function expand_assignment(ctx, ex)
1192+
function expand_assignment(ctx, ex, is_const=false)
11881193
@chk numchildren(ex) == 2
11891194
lhs = ex[1]
11901195
rhs = ex[2]
11911196
kl = kind(lhs)
11921197
if kl == K"curly"
1193-
expand_unionall_def(ctx, ex, lhs, rhs)
1198+
expand_unionall_def(ctx, ex, lhs, rhs, is_const)
11941199
elseif kind(rhs) == K"="
11951200
# Expand chains of assignments
11961201
# a = b = c ==> b=c; a=c
@@ -1207,7 +1212,9 @@ function expand_assignment(ctx, ex)
12071212
tmp_rhs = ssavar(ctx, rhs, "rhs")
12081213
rr = tmp_rhs
12091214
end
1210-
for i in 1:length(stmts)
1215+
# In const a = b = c, only a is const
1216+
stmts[1] = @ast ctx ex [(is_const ? K"constdecl" : K"=") stmts[1] rr]
1217+
for i in 2:length(stmts)
12111218
stmts[i] = @ast ctx ex [K"=" stmts[i] rr]
12121219
end
12131220
if !isnothing(tmp_rhs)
@@ -1220,9 +1227,20 @@ function expand_assignment(ctx, ex)
12201227
]
12211228
)
12221229
elseif is_identifier_like(lhs)
1223-
sink_assignment(ctx, ex, lhs, expand_forms_2(ctx, rhs))
1230+
if is_const
1231+
rr = ssavar(ctx, rhs)
1232+
@ast ctx ex [
1233+
K"block"
1234+
sink_assignment(ctx, ex, rr, expand_forms_2(ctx, rhs))
1235+
[K"constdecl" lhs rr]
1236+
[K"removable" rr]
1237+
]
1238+
else
1239+
sink_assignment(ctx, ex, lhs, expand_forms_2(ctx, rhs))
1240+
end
12241241
elseif kl == K"."
12251242
# a.b = rhs ==> setproperty!(a, :b, rhs)
1243+
@chk !is_const (ex, "cannot declare `.` form const")
12261244
@chk numchildren(lhs) == 2
12271245
a = lhs[1]
12281246
b = lhs[2]
@@ -1250,16 +1268,24 @@ function expand_assignment(ctx, ex)
12501268
end
12511269
elseif kl == K"ref"
12521270
# a[i1, i2] = rhs
1271+
@chk !is_const (ex, "cannot declare ref form const")
12531272
expand_forms_2(ctx, expand_setindex(ctx, ex))
12541273
elseif kl == K"::" && numchildren(lhs) == 2
12551274
x = lhs[1]
12561275
T = lhs[2]
1257-
res = if is_identifier_like(x)
1276+
res = if is_const
1277+
expand_forms_2(ctx, @ast ctx ex [
1278+
K"const"
1279+
[K"="
1280+
lhs[1]
1281+
convert_for_type_decl(ctx, ex, rhs, T, true)
1282+
]])
1283+
elseif is_identifier_like(x)
12581284
# Identifer in lhs[1] is a variable type declaration, eg
12591285
# x::T = rhs
12601286
@ast ctx ex [K"block"
12611287
[K"decl" lhs[1] lhs[2]]
1262-
[K"=" lhs[1] rhs]
1288+
is_const ? [K"const" [K"=" lhs[1] rhs]] : [K"=" lhs[1] rhs]
12631289
]
12641290
else
12651291
# Otherwise just a type assertion, eg
@@ -1271,6 +1297,7 @@ function expand_assignment(ctx, ex)
12711297
# needs to be detected somewhere but won't be detected here. Maybe
12721298
# it shows that remove_argument_side_effects() is not the ideal
12731299
# solution here?
1300+
# TODO: handle underscore?
12741301
@ast ctx ex [K"block"
12751302
stmts...
12761303
[K"::" l1 lhs[2]]
@@ -2097,9 +2124,8 @@ function strip_decls!(ctx, stmts, declkind, declkind2, declmeta, ex)
20972124
end
20982125
end
20992126

2100-
# local x, (y=2), z ==> local x; local y; y = 2; local z
2101-
# const x = 1 ==> const x; x = 1
2102-
# global x::T = 1 ==> (block (global x) (decl x T) (x = 1))
2127+
# local x, (y=2), z ==> local x; local z; y = 2
2128+
# Note there are differences from lisp (evaluation order?)
21032129
function expand_decls(ctx, ex)
21042130
declkind = kind(ex)
21052131
declmeta = get(ex, :meta, nothing)
@@ -2129,6 +2155,58 @@ function expand_decls(ctx, ex)
21292155
makenode(ctx, ex, K"block", stmts)
21302156
end
21312157

2158+
# Return all the names that will be bound by the assignment LHS, including
2159+
# curlies and calls.
2160+
function lhs_bound_names(ex)
2161+
k = kind(ex)
2162+
if k == K"Placeholder"
2163+
[]
2164+
elseif is_identifier_like(ex)
2165+
[ex]
2166+
elseif k in KSet"call curly where ::"
2167+
lhs_bound_names(ex[1])
2168+
elseif k in KSet"tuple parameters"
2169+
vcat(map(lhs_bound_names, children(ex))...)
2170+
else
2171+
[]
2172+
end
2173+
end
2174+
2175+
function expand_const_decl(ctx, ex)
2176+
function check_assignment(asgn)
2177+
@chk (kind(asgn) == K"=") (ex, "expected assignment after `const`")
2178+
end
2179+
2180+
k = kind(ex[1])
2181+
if numchildren(ex) == 2
2182+
@ast ctx ex [
2183+
K"constdecl"
2184+
ex[1]
2185+
expand_forms_2(ctx, ex[2])
2186+
]
2187+
elseif k == K"global"
2188+
asgn = ex[1][1]
2189+
check_assignment(asgn)
2190+
globals = map(lhs_bound_names(asgn[1])) do x
2191+
@ast ctx ex [K"global" x]
2192+
end
2193+
@ast ctx ex [
2194+
K"block"
2195+
globals...
2196+
expand_assignment(ctx, ex[1], true)
2197+
]
2198+
elseif k == K"="
2199+
if numchildren(ex[1]) >= 1 && kind(ex[1][1]) == K"tuple"
2200+
throw(LoweringError(ex[1][1], "unsupported `const` tuple"))
2201+
end
2202+
expand_assignment(ctx, ex[1], true)
2203+
elseif k == K"local"
2204+
throw(LoweringError(ex, "unsupported `const local` declaration"))
2205+
else
2206+
throw(LoweringError(ex, "expected assignment after `const`"))
2207+
end
2208+
end
2209+
21322210
#-------------------------------------------------------------------------------
21332211
# Expansion of function definitions
21342212

@@ -3318,14 +3396,13 @@ function expand_abstract_or_primitive_type(ctx, ex)
33183396
]
33193397
[K"assert" "toplevel_only"::K"Symbol" [K"inert" ex] ]
33203398
[K"global" name]
3321-
[K"const" name]
33223399
[K"if"
33233400
[K"&&"
33243401
[K"isdefined" name]
33253402
[K"call" "_equiv_typedef"::K"core" name newtype_var]
33263403
]
33273404
nothing_(ctx, ex)
3328-
[K"=" name newtype_var]
3405+
[K"constdecl" name newtype_var]
33293406
]
33303407
nothing_(ctx, ex)
33313408
]
@@ -3827,9 +3904,10 @@ function expand_struct_def(ctx, ex, docs)
38273904
@ast ctx ex [K"block"
38283905
[K"assert" "toplevel_only"::K"Symbol" [K"inert" ex] ]
38293906
[K"scope_block"(scope_type=:hard)
3907+
# Needed for later constdecl to work, though plain global form may be removed soon.
3908+
[K"global" global_struct_name]
38303909
[K"block"
38313910
[K"global" global_struct_name]
3832-
[K"const" global_struct_name]
38333911
[K"local" struct_name]
38343912
[K"always_defined" struct_name]
38353913
typevar_stmts...
@@ -3868,9 +3946,9 @@ function expand_struct_def(ctx, ex, docs)
38683946
end
38693947
]
38703948
# Otherwise do an assignment to trigger an error
3871-
[K"=" global_struct_name struct_name]
3949+
[K"const" global_struct_name struct_name]
38723950
]
3873-
[K"=" global_struct_name struct_name]
3951+
[K"const" global_struct_name struct_name]
38743952
]
38753953
[K"call"(type_body)
38763954
"_typebody!"::K"core"
@@ -4271,7 +4349,9 @@ function expand_forms_2(ctx::DesugaringContext, ex::SyntaxTree, docs=nothing)
42714349
]
42724350
elseif k == K"let"
42734351
expand_forms_2(ctx, expand_let(ctx, ex))
4274-
elseif k == K"local" || k == K"global" || k == K"const"
4352+
elseif k == K"const"
4353+
expand_const_decl(ctx, ex)
4354+
elseif k == K"local" || k == K"global"
42754355
if numchildren(ex) == 1 && kind(ex[1]) == K"Identifier"
42764356
# Don't recurse when already simplified - `local x`, etc
42774357
ex

src/eval.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,9 +298,10 @@ function to_lowered_expr(mod, ex, ssa_offset=0)
298298
k == K"splatnew" ? :splatnew :
299299
k == K"=" ? :(=) :
300300
k == K"global" ? :global :
301-
k == K"const" ? :const :
301+
k == K"constdecl" ? :const :
302302
k == K"leave" ? :leave :
303303
k == K"isdefined" ? :isdefined :
304+
k == K"globaldecl" ? :globaldecl :
304305
k == K"pop_exception" ? :pop_exception :
305306
k == K"captured_local" ? :captured_local :
306307
k == K"gc_preserve_begin" ? :gc_preserve_begin :

src/kinds.jl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ function _register_kinds()
9696
"_opaque_closure"
9797
# The enclosed statements must be executed at top level
9898
"toplevel_butfirst"
99-
"const_if_global"
99+
"assign_const_if_global"
100100
"moved_local"
101101
"label"
102102
"trycatchelse"
@@ -121,8 +121,12 @@ function _register_kinds()
121121
"slot"
122122
# Static parameter to a `CodeInfo` code object ("type parameters" to methods)
123123
"static_parameter"
124-
# Reference to a global variable within a module
124+
# References/declares a global variable within a module
125125
"globalref"
126+
"globaldecl"
127+
# Two-argument constant declaration and assignment.
128+
# Translated to :const in the IR for now (we use K"const" already in parsing).
129+
"constdecl"
126130
# Unconditional goto
127131
"goto"
128132
# Conditional goto

src/linear_ir.jl

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -336,18 +336,35 @@ function emit_break(ctx, ex)
336336
emit_jump(ctx, ex, target)
337337
end
338338

339-
function emit_assignment(ctx, srcref, lhs, rhs)
339+
# `op` may also be K"constdecl"
340+
function emit_assignment_or_setglobal(ctx, srcref, lhs, rhs, op=K"=")
341+
# (const (globalref _ _) _) does not use setglobal!
342+
binfo = lookup_binding(ctx, lhs.var_id)
343+
if binfo.kind == :global && op == K"="
344+
emit(ctx, @ast ctx srcref [
345+
K"call"
346+
"setglobal!"::K"top"
347+
binfo.mod::K"Value"
348+
binfo.name::K"Symbol"
349+
rhs
350+
])
351+
else
352+
emit(ctx, srcref, op, lhs, rhs)
353+
end
354+
end
355+
356+
function emit_assignment(ctx, srcref, lhs, rhs, op=K"=")
340357
if !isnothing(rhs)
341358
if is_valid_ir_rvalue(ctx, lhs, rhs)
342-
emit(ctx, srcref, K"=", lhs, rhs)
359+
emit_assignment_or_setglobal(ctx, srcref, lhs, rhs, op)
343360
else
344361
r = emit_assign_tmp(ctx, rhs)
345-
emit(ctx, srcref, K"=", lhs, r)
362+
emit_assignment_or_setglobal(ctx, srcref, lhs, r, op)
346363
end
347364
else
348365
# in unreachable code (such as after return); still emit the assignment
349366
# so that the structure of those uses is preserved
350-
emit(ctx, @ast ctx srcref [K"=" lhs "nothing"::K"core"])
367+
emit_assignment_or_setglobal(ctx, srcref, lhs, @ast ctx srcref "nothing"::K"core", op)
351368
nothing
352369
end
353370
end
@@ -642,7 +659,7 @@ function compile(ctx::LinearIRContext, ex, needs_value, in_tail_pos)
642659
emit(ctx, callex)
643660
nothing
644661
end
645-
elseif k == K"="
662+
elseif k == K"=" || k == K"constdecl"
646663
lhs = ex[1]
647664
if kind(lhs) == K"Placeholder"
648665
compile(ctx, ex[2], needs_value, in_tail_pos)
@@ -651,14 +668,14 @@ function compile(ctx::LinearIRContext, ex, needs_value, in_tail_pos)
651668
# TODO look up arg-map for renaming if lhs was reassigned
652669
if needs_value && !isnothing(rhs)
653670
r = emit_assign_tmp(ctx, rhs)
654-
emit(ctx, ex, K"=", lhs, r)
671+
emit_assignment_or_setglobal(ctx, ex, lhs, r, k)
655672
if in_tail_pos
656673
emit_return(ctx, ex, r)
657674
else
658675
r
659676
end
660677
else
661-
emit_assignment(ctx, ex, lhs, rhs)
678+
emit_assignment(ctx, ex, lhs, rhs, k)
662679
end
663680
end
664681
elseif k == K"block" || k == K"scope_block"
@@ -813,7 +830,7 @@ function compile(ctx::LinearIRContext, ex, needs_value, in_tail_pos)
813830
end
814831
elseif k == K"gc_preserve_begin"
815832
makenode(ctx, ex, k, compile_args(ctx, children(ex)))
816-
elseif k == K"gc_preserve_end" || k == K"global" || k == K"const"
833+
elseif k == K"gc_preserve_end" || k == K"global"
817834
if needs_value
818835
throw(LoweringError(ex, "misplaced kind $k in value position"))
819836
end
@@ -864,6 +881,17 @@ function compile(ctx::LinearIRContext, ex, needs_value, in_tail_pos)
864881
# TODO: also exclude deleted vars
865882
emit(ctx, ex)
866883
end
884+
elseif k == K"globaldecl"
885+
if needs_value
886+
throw(LoweringError(ex, "misplaced global declaration"))
887+
end
888+
if numchildren(ex) == 1 || is_identifier_like(ex[2])
889+
emit(ctx, ex)
890+
else
891+
rr = ssavar(ctx, ex[2])
892+
emit(ctx, @ast ctx ex [K"=" rr ex[2]])
893+
emit(ctx, @ast ctx ex [K"globaldecl" ex[1] rr])
894+
end
867895
else
868896
throw(LoweringError(ex, "Invalid syntax; $(repr(k))"))
869897
end

0 commit comments

Comments
 (0)